OSDN Git Service

Change to encode reply messages with Kanji code of filenames.
[ffftp/ffftp.git] / socket.c
index b3d4163..f004036 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -38,6 +38,8 @@
 \r
 #include "common.h"\r
 #include "resource.h"\r
+// UTF-8対応\r
+#include "punycode.h"\r
 \r
 #define USE_THIS       1\r
 #define DBG_MSG                0\r
@@ -92,6 +94,8 @@ static int RegistAsyncTable(SOCKET s);
 static int RegistAsyncTableDbase(HANDLE Async);\r
 static int UnRegistAsyncTable(SOCKET s);\r
 static int UnRegistAsyncTableDbase(HANDLE Async);\r
+// UTF-8対応\r
+static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen);\r
 \r
 \r
 /*===== 外部参照 =====*/\r
@@ -271,6 +275,8 @@ static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LP
                        break;\r
 \r
                case WM_ASYNC_DBASE :\r
+                       // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり\r
+                       RegistAsyncTableDbase((HANDLE)wParam);\r
                        // スレッド衝突のバグ修正\r
                        WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
                        for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
@@ -291,31 +297,6 @@ static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LP
                                        break;\r
                                }\r
                        }\r
-                       // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり\r
-                       if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
-                       {\r
-                               for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
-                               {\r
-                                       if(SignalDbase[Pos].Async == 0)\r
-                                       {\r
-                                               SignalDbase[Pos].Async = (HANDLE)wParam;\r
-                                               SignalDbase[Pos].Done = 0;\r
-                                               SignalDbase[Pos].ErrorDb = 0;\r
-                                               if(HIWORD(lParam) != 0)\r
-                                               {\r
-                                                       SignalDbase[Pos].ErrorDb = 1;\r
-#if DBG_MSG\r
-                                                       DoPrintf("##### SignalDatabase: error");\r
-#endif\r
-                                               }\r
-                                               SignalDbase[Pos].Done = 1;\r
-#if DBG_MSG\r
-                                               DoPrintf("##### SignalDatabase: Done");\r
-#endif\r
-                                               break;\r
-                                       }\r
-                               }\r
-                       }\r
                        // スレッド衝突のバグ修正\r
                        ReleaseMutex(hAsyncTblAccMutex);\r
                        break;\r
@@ -676,9 +657,12 @@ struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *Canc
        DoPrintf("# Start gethostbyname");\r
 #endif\r
        Ret = NULL;\r
-       *CancelCheckWork = NO;\r
+       // 同時接続対応\r
+//     *CancelCheckWork = NO;\r
 \r
-       hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
+       // UTF-8対応\r
+//     hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
+       hAsync = WSAAsyncGetHostByNameM(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
        if(hAsync != NULL)\r
        {\r
                RegistAsyncTableDbase(hAsync);\r
@@ -738,6 +722,9 @@ int do_closesocket(SOCKET s)
 #endif\r
        CancelCheckWork = NO;\r
 \r
+       // スレッド衝突のバグ修正\r
+       WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
+       UnRegistAsyncTable(s);\r
        // FTPS対応\r
 //     Ret = closesocket(s);\r
        Ret = closesocketS(s);\r
@@ -755,10 +742,12 @@ int do_closesocket(SOCKET s)
                        Ret = 0;\r
        }\r
 \r
-       WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
+       // スレッド衝突のバグ修正\r
+//     WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
        if(BackgrndMessageProc() == YES)\r
                CancelCheckWork = YES;\r
-       UnRegistAsyncTable(s);\r
+       // スレッド衝突のバグ修正\r
+//     UnRegistAsyncTable(s);\r
 \r
 #if DBG_MSG\r
        DoPrintf("# Exit close");\r
@@ -783,7 +772,8 @@ int do_connect(SOCKET s, const struct sockaddr *name, int namelen, int *CancelCh
 #if DBG_MSG\r
        DoPrintf("# Start connect (S=%x)", s);\r
 #endif\r
-       *CancelCheckWork = NO;\r
+       // 同時接続対応\r
+//     *CancelCheckWork = NO;\r
 \r
 #if DBG_MSG\r
        DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
@@ -791,12 +781,7 @@ int do_connect(SOCKET s, const struct sockaddr *name, int namelen, int *CancelCh
        Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
        if(Ret != SOCKET_ERROR)\r
        {\r
-               // FTPS対応\r
-//             Ret = connect(s, name, namelen);\r
-               if(AskCryptMode() == CRYPT_FTPIS)\r
-                       Ret = connectS(s, name, namelen);\r
-               else\r
-                       Ret = connect(s, name, namelen);\r
+               Ret = connect(s, name, namelen);\r
                if(Ret == SOCKET_ERROR)\r
                {\r
                        do\r
@@ -890,12 +875,7 @@ SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
        {\r
                do\r
                {\r
-                       // FTPS対応\r
-//                     Ret2 = accept(s, addr, addrlen);\r
-                       if(AskCryptMode() == CRYPT_FTPIS)\r
-                               Ret2 = acceptS(s, addr, addrlen);\r
-                       else\r
-                               Ret2 = accept(s, addr, addrlen);\r
+                       Ret2 = accept(s, addr, addrlen);\r
                        if(Ret2 != INVALID_SOCKET)\r
                        {\r
 #if DBG_MSG\r
@@ -957,7 +937,8 @@ int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *Cance
        DoPrintf("# Start recv (S=%x)", s);\r
 #endif\r
        *TimeOutErr = NO;\r
-       *CancelCheckWork = NO;\r
+       // 同時接続対応\r
+//     *CancelCheckWork = NO;\r
        Ret = SOCKET_ERROR;\r
        Error = 0;\r
 \r
@@ -1054,7 +1035,8 @@ int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int
        DoPrintf("# Start send (S=%x)", s);\r
 #endif\r
        *TimeOutErr = NO;\r
-       *CancelCheckWork = NO;\r
+       // 同時接続対応\r
+//     *CancelCheckWork = NO;\r
        Ret = SOCKET_ERROR;\r
        Error = 0;\r
 \r
@@ -1064,36 +1046,40 @@ int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int
 #if DBG_MSG\r
        DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
 #endif\r
-       WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
+       // Windows 2000でFD_WRITEが通知されないことがあるバグ修正\r
+       // 毎回通知されたのはNT 4.0までのバグであり仕様ではない\r
+       // XP以降は互換性のためか毎回通知される\r
+//     WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
        if(BackgrndMessageProc() == YES)\r
                *CancelCheckWork = YES;\r
 \r
        // FTPS対応\r
        // 送信バッファの空き確認には影響しないが念のため\r
 //     while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
-       while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
-       {\r
-               if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
-               {\r
-                       Error = 1;\r
-                       break;\r
-               }\r
-\r
-               Sleep(1);\r
-               if(BackgrndMessageProc() == YES)\r
-                       *CancelCheckWork = YES;\r
-               else if(TimeOut != 0)\r
-               {\r
-                       time(&ElapseTime);\r
-                       ElapseTime -= StartTime;\r
-                       if(ElapseTime >= TimeOut)\r
-                       {\r
-                               DoPrintf("do_write timed out");\r
-                               *TimeOutErr = YES;\r
-                               *CancelCheckWork = YES;\r
-                       }\r
-               }\r
-       }\r
+       // Windows 2000でFD_WRITEが通知されないことがあるバグ修正\r
+//     while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
+//     {\r
+//             if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
+//             {\r
+//                     Error = 1;\r
+//                     break;\r
+//             }\r
+//\r
+//             Sleep(1);\r
+//             if(BackgrndMessageProc() == YES)\r
+//                     *CancelCheckWork = YES;\r
+//             else if(TimeOut != 0)\r
+//             {\r
+//                     time(&ElapseTime);\r
+//                     ElapseTime -= StartTime;\r
+//                     if(ElapseTime >= TimeOut)\r
+//                     {\r
+//                             DoPrintf("do_write timed out");\r
+//                             *TimeOutErr = YES;\r
+//                             *CancelCheckWork = YES;\r
+//                     }\r
+//             }\r
+//     }\r
 \r
        if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
        {\r
@@ -1151,6 +1137,20 @@ int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int
 }\r
 \r
 \r
+// 同時接続対応\r
+void RemoveReceivedData(SOCKET s)\r
+{\r
+       char buf[1024];\r
+       int len;\r
+       int Error;\r
+       while((len = recvS(s, buf, sizeof(buf), MSG_PEEK)) >= 0)\r
+       {\r
+               AskAsyncDone(s, &Error, FD_READ_BIT);\r
+               recvS(s, buf, len, 0);\r
+       }\r
+}\r
+\r
+\r
 /*----- \r
 *\r
 *      Parameter\r
@@ -1177,3 +1177,124 @@ int CheckClosedAndReconnect(void)
 \r
 \r
 \r
+// UTF-8対応\r
+\r
+static BOOL ConvertStringToPunycode(LPSTR Output, DWORD Count, LPCSTR Input)\r
+{\r
+       BOOL bResult;\r
+       punycode_uint* pUnicode;\r
+       punycode_uint* p;\r
+       BOOL bNeeded;\r
+       LPCSTR InputString;\r
+       punycode_uint Length;\r
+       punycode_uint OutputLength;\r
+       bResult = FALSE;\r
+       if(pUnicode = malloc(sizeof(punycode_uint) * strlen(Input)))\r
+       {\r
+               p = pUnicode;\r
+               bNeeded = FALSE;\r
+               InputString = Input;\r
+               Length = 0;\r
+               while(*InputString != '\0')\r
+               {\r
+                       *p = 0;\r
+                       if((*InputString & 0x80) == 0x00)\r
+                               *p |= (punycode_uint)*InputString & 0x7f;\r
+                       else if((*InputString & 0xe0) == 0xc0)\r
+                               *p |= (punycode_uint)*InputString & 0x1f;\r
+                       else if((*InputString & 0xf0) == 0xe0)\r
+                               *p |= (punycode_uint)*InputString & 0x0f;\r
+                       else if((*InputString & 0xf8) == 0xf0)\r
+                               *p |= (punycode_uint)*InputString & 0x07;\r
+                       else if((*InputString & 0xfc) == 0xf8)\r
+                               *p |= (punycode_uint)*InputString & 0x03;\r
+                       else if((*InputString & 0xfe) == 0xfc)\r
+                               *p |= (punycode_uint)*InputString & 0x01;\r
+                       InputString++;\r
+                       while((*InputString & 0xc0) == 0x80)\r
+                       {\r
+                               *p = *p << 6;\r
+                               *p |= (punycode_uint)*InputString & 0x3f;\r
+                               InputString++;\r
+                       }\r
+                       if(*p >= 0x80)\r
+                               bNeeded = TRUE;\r
+                       p++;\r
+                       Length++;\r
+               }\r
+               if(bNeeded)\r
+               {\r
+                       if(Count >= strlen("xn--") + 1)\r
+                       {\r
+                               strcpy(Output, "xn--");\r
+                               OutputLength = Count - strlen("xn--");\r
+                               if(punycode_encode(Length, pUnicode, NULL, (punycode_uint*)&OutputLength, Output + strlen("xn--")) == punycode_success)\r
+                               {\r
+                                       Output[strlen("xn--") + OutputLength] = '\0';\r
+                                       bResult = TRUE;\r
+                               }\r
+                       }\r
+               }\r
+               free(pUnicode);\r
+       }\r
+       if(!bResult)\r
+       {\r
+               if(Count >= strlen(Input) + 1)\r
+               {\r
+                       strcpy(Output, Input);\r
+                       bResult = TRUE;\r
+               }\r
+       }\r
+       return bResult;\r
+}\r
+\r
+static BOOL ConvertNameToPunycode(LPSTR Output, LPCSTR Input)\r
+{\r
+       BOOL bResult;\r
+       DWORD Length;\r
+       char* pm0;\r
+       char* pm1;\r
+       char* p;\r
+       char* pNext;\r
+       bResult = FALSE;\r
+       Length = strlen(Input);\r
+       if(pm0 = AllocateStringM(Length + 1))\r
+       {\r
+               if(pm1 = AllocateStringM(Length * 4 + 1))\r
+               {\r
+                       strcpy(pm0, Input);\r
+                       p = pm0;\r
+                       while(p)\r
+                       {\r
+                               if(pNext = strchr(p, '.'))\r
+                               {\r
+                                       *pNext = '\0';\r
+                                       pNext++;\r
+                               }\r
+                               if(ConvertStringToPunycode(pm1, Length * 4, p))\r
+                                       strcat(Output, pm1);\r
+                               if(pNext)\r
+                                       strcat(Output, ".");\r
+                               p = pNext;\r
+                       }\r
+                       bResult = TRUE;\r
+                       FreeDuplicatedString(pm1);\r
+               }\r
+               FreeDuplicatedString(pm0);\r
+       }\r
+       return bResult;\r
+}\r
+\r
+static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen)\r
+{\r
+       HANDLE r = NULL;\r
+       char* pa0 = NULL;\r
+       if(pa0 = AllocateStringA(strlen(name) * 4))\r
+       {\r
+               if(ConvertNameToPunycode(pa0, name))\r
+                       r = WSAAsyncGetHostByName(hWnd, wMsg, pa0, buf, buflen);\r
+       }\r
+       FreeDuplicatedString(pa0);\r
+       return r;\r
+}\r
+\r