OSDN Git Service

Fix bugs of character code conversion of filenames.
[ffftp/ffftp.git] / remote.c
1 /*=============================================================================\r
2 *\r
3 *                                                       リモート側のファイル操作\r
4 *\r
5 ===============================================================================\r
6 / Copyright (C) 1997-2007 Sota. All rights reserved.\r
7 /\r
8 / Redistribution and use in source and binary forms, with or without \r
9 / modification, are permitted provided that the following conditions \r
10 / are met:\r
11 /\r
12 /  1. Redistributions of source code must retain the above copyright \r
13 /     notice, this list of conditions and the following disclaimer.\r
14 /  2. Redistributions in binary form must reproduce the above copyright \r
15 /     notice, this list of conditions and the following disclaimer in the \r
16 /     documentation and/or other materials provided with the distribution.\r
17 /\r
18 / THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR \r
19 / IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES \r
20 / OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
21 / IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, \r
22 / INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
23 / BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF \r
24 / USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
25 / ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
26 / (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF \r
27 / THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
28 /============================================================================*/\r
29 \r
30 /* このソースは一部、WS_FTP Version 93.12.05 のソースを参考にしました。 */\r
31 \r
32 #define STRICT\r
33 #include <stdio.h>\r
34 #include <stdlib.h>\r
35 #include <stdarg.h>\r
36 #include <string.h>\r
37 #include <mbstring.h>\r
38 #include <time.h>\r
39 #include <winsock.h>\r
40 #include <windowsx.h>\r
41 #include <commctrl.h>\r
42 \r
43 #include "common.h"\r
44 #include "resource.h"\r
45 \r
46 #define PWD_XPWD                0\r
47 #define PWD_PWD                 1\r
48 \r
49 /*===== プロトタイプ =====*/\r
50 \r
51 static int DoPWD(char *Buf);\r
52 static int ReadOneLine(SOCKET cSkt, char *Buf, int Max, int *CancelCheckWork);\r
53 static int DoDirList(HWND hWnd, SOCKET cSkt, char *AddOpt, char *Path, int Num, int *CancelCheckWork);\r
54 static void ChangeSepaLocal2Remote(char *Fname);\r
55 static void ChangeSepaRemote2Local(char *Fname);\r
56 \r
57 /*===== 外部参照 =====*/\r
58 \r
59 extern TRANSPACKET MainTransPkt;\r
60 \r
61 /* 設定値 */\r
62 extern int TimeOut;\r
63 extern int SendQuit;\r
64 \r
65 // 同時接続対応\r
66 extern int CancelFlg;\r
67 \r
68 /*===== ローカルなワーク =====*/\r
69 \r
70 static int PwdCommandType;\r
71 \r
72 // 同時接続対応\r
73 //static int CheckCancelFlg = NO;\r
74 \r
75 \r
76 \r
77 /*----- リモート側のカレントディレクトリ変更 ----------------------------------\r
78 *\r
79 *       Parameter\r
80 *               char *Path : パス名\r
81 *               int Disp : ディレクトリリストにパス名を表示するかどうか(YES/NO)\r
82 *               int ForceGet : 失敗してもカレントディレクトリを取得する\r
83 *               int ErrorBell : エラー事の音を鳴らすかどうか(YES/NO)\r
84 *\r
85 *       Return Value\r
86 *               int 応答コードの1桁目\r
87 *----------------------------------------------------------------------------*/\r
88 \r
89 int DoCWD(char *Path, int Disp, int ForceGet, int ErrorBell)\r
90 {\r
91         int Sts;\r
92         char Buf[FMAX_PATH+1];\r
93 \r
94         Sts = FTP_COMPLETE * 100;\r
95 \r
96         if(strcmp(Path, "..") == 0)\r
97                 Sts = CommandProcCmd(NULL, "CDUP");\r
98         else if(strcmp(Path, "") != 0)\r
99         {\r
100                 if((AskHostType() != HTYPE_VMS) || (strchr(Path, '[') != NULL))\r
101                         Sts = CommandProcCmd(NULL, "CWD %s", Path);\r
102                 else\r
103                         Sts = CommandProcCmd(NULL, "CWD [.%s]", Path);  /* VMS用 */\r
104         }\r
105 \r
106         if((Sts/100 >= FTP_CONTINUE) && (ErrorBell == YES))\r
107                 SoundPlay(SND_ERROR);\r
108 \r
109         if((Sts/100 == FTP_COMPLETE) ||\r
110            (ForceGet == YES))\r
111         {\r
112                 if(Disp == YES)\r
113                 {\r
114                         if(DoPWD(Buf) != FTP_COMPLETE)\r
115                         {\r
116                                 /*===== PWDが使えなかった場合 =====*/\r
117 \r
118                                 if(*Path == '/')\r
119                                         strcpy(Buf, Path);\r
120                                 else\r
121                                 {\r
122                                         AskRemoteCurDir(Buf, FMAX_PATH);\r
123                                         if(strlen(Buf) == 0)\r
124                                                 strcpy(Buf, "/");\r
125 \r
126                                         while(*Path != NUL)\r
127                                         {\r
128                                                 if(strcmp(Path, ".") == 0)\r
129                                                         Path++;\r
130                                                 else if(strncmp(Path, "./", 2) == 0)\r
131                                                         Path += 2;\r
132                                                 else if(strcmp(Path, "..") == 0)\r
133                                                 {\r
134                                                         GetUpperDir(Buf);\r
135                                                         Path += 2;\r
136                                                 }\r
137                                                 else if(strncmp(Path, "../", 2) == 0)\r
138                                                 {\r
139                                                         GetUpperDir(Buf);\r
140                                                         Path += 3;\r
141                                                 }\r
142                                                 else\r
143                                                 {\r
144                                                         SetSlashTail(Buf);\r
145                                                         strcat(Buf, Path);\r
146                                                         break;\r
147                                                 }\r
148                                         }\r
149                                 }\r
150                         }\r
151                         SetRemoteDirHist(Buf);\r
152                 }\r
153         }\r
154         return(Sts/100);\r
155 }\r
156 \r
157 \r
158 \r
159 \r
160 /*----- リモート側のカレントディレクトリ変更(その2)-------------------------\r
161 *\r
162 *       Parameter\r
163 *               char *Path : パス名\r
164 *               char *Cur : カレントディレクトリ\r
165 *\r
166 *       Return Value\r
167 *               int 応答コードの1桁目\r
168 *\r
169 *       Note\r
170 *               パス名は "xxx/yyy/zzz" の形式\r
171 *               ディレクトリ変更が失敗したら、カレントディレクトリに戻しておく\r
172 *----------------------------------------------------------------------------*/\r
173 \r
174 int DoCWDStepByStep(char *Path, char *Cur)\r
175 {\r
176         int Sts;\r
177         char *Set;\r
178         char *Set2;\r
179         char Tmp[FMAX_PATH+2];\r
180 \r
181         Sts = FTP_COMPLETE;\r
182 \r
183         memset(Tmp, NUL, FMAX_PATH+2);\r
184         strcpy(Tmp, Path);\r
185         Set = Tmp;\r
186         while(*Set != NUL)\r
187         {\r
188                 if((Set2 = strchr(Set, '/')) != NULL)\r
189                         *Set2 = NUL;\r
190                 if((Sts = DoCWD(Set, NO, NO, NO)) != FTP_COMPLETE)\r
191                         break;\r
192                 if(Set2 == NULL)\r
193                         break;\r
194                 Set = Set2 + 1;\r
195         }\r
196 \r
197         if(Sts != FTP_COMPLETE)\r
198                 DoCWD(Cur, NO, NO, NO);\r
199 \r
200         return(Sts);\r
201 }\r
202 \r
203 \r
204 /*----- リモート側のカレントディレクトリ取得 ----------------------------------\r
205 *\r
206 *       Parameter\r
207 *               char *Buf : パス名を返すバッファ\r
208 *\r
209 *       Return Value\r
210 *               int 応答コードの1桁目\r
211 *----------------------------------------------------------------------------*/\r
212 \r
213 static int DoPWD(char *Buf)\r
214 {\r
215         char *Pos;\r
216         char Tmp[1024];\r
217         int Sts;\r
218 \r
219         if(PwdCommandType == PWD_XPWD)\r
220         {\r
221                 Sts = CommandProcCmd(Tmp, "XPWD");\r
222                 if(Sts/100 != FTP_COMPLETE)\r
223                         PwdCommandType = PWD_PWD;\r
224         }\r
225         if(PwdCommandType == PWD_PWD)\r
226                 Sts = CommandProcCmd(Tmp, "PWD");\r
227 \r
228         if(Sts/100 == FTP_COMPLETE)\r
229         {\r
230                 if((Pos = strchr(Tmp, '"')) != NULL)\r
231                 {\r
232                         memmove(Tmp, Pos+1, strlen(Pos+1)+1);\r
233                         if((Pos = strchr(Tmp, '"')) != NULL)\r
234                                 *Pos = NUL;\r
235                 }\r
236                 else\r
237                         memmove(Tmp, Tmp+4, strlen(Tmp+4)+1);\r
238 \r
239                 if(strlen(Tmp) < FMAX_PATH)\r
240                 {\r
241                         strcpy(Buf, Tmp);\r
242                         // 0x5Cが含まれる文字列を扱えないバグ修正\r
243 //                      ReplaceAll(Buf, '\\', '/');\r
244                         ChangeSepaRemote2Local(Buf);\r
245                         ChangeFnameRemote2Local(Buf, FMAX_PATH);\r
246                         // 0x5Cが含まれる文字列を扱えないバグ修正\r
247                         ReplaceAll(Buf, '\\', '/');\r
248                 }\r
249                 else\r
250                         Sts = FTP_ERROR*100;\r
251         }\r
252         return(Sts/100);\r
253 }\r
254 \r
255 \r
256 /*----- PWDコマンドのタイプを初期化する ---------------------------------------\r
257 *\r
258 *       Parameter\r
259 *               なし\r
260 *\r
261 *       Return Value\r
262 *               なし\r
263 *----------------------------------------------------------------------------*/\r
264 \r
265 void InitPWDcommand()\r
266 {\r
267         PwdCommandType = PWD_XPWD;\r
268 }\r
269 \r
270 \r
271 /*----- リモート側のディレクトリ作成 ----------------------------------------\r
272 *\r
273 *       Parameter\r
274 *               char *Path : パス名\r
275 *\r
276 *       Return Value\r
277 *               int 応答コードの1桁目\r
278 *----------------------------------------------------------------------------*/\r
279 \r
280 int DoMKD(char *Path)\r
281 {\r
282         int Sts;\r
283 \r
284         Sts = CommandProcCmd(NULL, "MKD %s", Path);\r
285 \r
286         if(Sts/100 >= FTP_CONTINUE)\r
287                 SoundPlay(SND_ERROR);\r
288 \r
289         return(Sts/100);\r
290 }\r
291 \r
292 \r
293 /*----- リモート側のディレクトリ削除 ------------------------------------------\r
294 *\r
295 *       Parameter\r
296 *               char *Path : パス名\r
297 *\r
298 *       Return Value\r
299 *               int 応答コードの1桁目\r
300 *----------------------------------------------------------------------------*/\r
301 \r
302 int DoRMD(char *Path)\r
303 {\r
304         int Sts;\r
305 \r
306         Sts = CommandProcCmd(NULL, "RMD %s", Path);\r
307 \r
308         if(Sts/100 >= FTP_CONTINUE)\r
309                 SoundPlay(SND_ERROR);\r
310 \r
311         return(Sts/100);\r
312 }\r
313 \r
314 \r
315 /*----- リモート側のファイル削除 ----------------------------------------------\r
316 *\r
317 *       Parameter\r
318 *               char *Path : パス名\r
319 *\r
320 *       Return Value\r
321 *               int 応答コードの1桁目\r
322 *----------------------------------------------------------------------------*/\r
323 \r
324 int DoDELE(char *Path)\r
325 {\r
326         int Sts;\r
327 \r
328         Sts = CommandProcCmd(NULL, "DELE %s", Path);\r
329 \r
330         if(Sts/100 >= FTP_CONTINUE)\r
331                 SoundPlay(SND_ERROR);\r
332 \r
333         return(Sts/100);\r
334 }\r
335 \r
336 \r
337 /*----- リモート側のファイル名変更 --------------------------------------------\r
338 *\r
339 *       Parameter\r
340 *               char *Src : 元ファイル名\r
341 *               char *Dst : 変更後のファイル名\r
342 *\r
343 *       Return Value\r
344 *               int 応答コードの1桁目\r
345 *----------------------------------------------------------------------------*/\r
346 \r
347 int DoRENAME(char *Src, char *Dst)\r
348 {\r
349         int Sts;\r
350 \r
351         Sts = CommandProcCmd(NULL, "RNFR %s", Src);\r
352         if(Sts == 350)\r
353                 // 同時接続対応\r
354 //              Sts = command(AskCmdCtrlSkt(), NULL, &CheckCancelFlg, "RNTO %s", Dst);\r
355                 Sts = command(AskCmdCtrlSkt(), NULL, &CancelFlg, "RNTO %s", Dst);\r
356 \r
357         if(Sts/100 >= FTP_CONTINUE)\r
358                 SoundPlay(SND_ERROR);\r
359 \r
360         return(Sts/100);\r
361 }\r
362 \r
363 \r
364 /*----- リモート側のファイルの属性変更 ----------------------------------------\r
365 *\r
366 *       Parameter\r
367 *               char *Path : パス名\r
368 *               char *Mode : モード文字列\r
369 *\r
370 *       Return Value\r
371 *               int 応答コードの1桁目\r
372 *----------------------------------------------------------------------------*/\r
373 \r
374 int DoCHMOD(char *Path, char *Mode)\r
375 {\r
376         int Sts;\r
377 \r
378         Sts = CommandProcCmd(NULL, "%s %s %s", AskHostChmodCmd(), Mode, Path);\r
379 \r
380         if(Sts/100 >= FTP_CONTINUE)\r
381                 SoundPlay(SND_ERROR);\r
382 \r
383         return(Sts/100);\r
384 }\r
385 \r
386 \r
387 /*----- リモート側のファイルのサイズを取得(転送ソケット使用)-----------------\r
388 *\r
389 *       Parameter\r
390 *               char *Path : パス名\r
391 *               LONGLONG *Size : ファイルのサイズを返すワーク\r
392 *\r
393 *       Return Value\r
394 *               int 応答コードの1桁目\r
395 *\r
396 *       Note\r
397 *               ★★転送ソケットを使用する★★\r
398 *               サイズが選られない時は Size = -1 を返す\r
399 *----------------------------------------------------------------------------*/\r
400 \r
401 // 同時接続対応\r
402 //int DoSIZE(char *Path, LONGLONG *Size)\r
403 int DoSIZE(SOCKET cSkt, char *Path, LONGLONG *Size, int *CancelCheckWork)\r
404 {\r
405         int Sts;\r
406         char Tmp[1024];\r
407 \r
408         // 同時接続対応\r
409 //      Sts = CommandProcTrn(Tmp, "SIZE %s", Path);\r
410         Sts = CommandProcTrn(cSkt, Tmp, CancelCheckWork, "SIZE %s", Path);\r
411 \r
412         *Size = -1;\r
413         if((Sts/100 == FTP_COMPLETE) && (strlen(Tmp) > 4) && IsDigit(Tmp[4]))\r
414                 *Size = _atoi64(&Tmp[4]);\r
415 \r
416         return(Sts/100);\r
417 }\r
418 \r
419 \r
420 /*----- リモート側のファイルの日付を取得(転送ソケット使用)-------------------\r
421 *\r
422 *       Parameter\r
423 *               char *Path : パス名\r
424 *               FILETIME *Time : 日付を返すワーク\r
425 *\r
426 *       Return Value\r
427 *               int 応答コードの1桁目\r
428 *\r
429 *       Note\r
430 *               ★★転送ソケットを使用する★★\r
431 *               日付が選られない時は Time = 0 を返す\r
432 *----------------------------------------------------------------------------*/\r
433 \r
434 // 同時接続対応\r
435 //int DoMDTM(char *Path, FILETIME *Time)\r
436 int DoMDTM(SOCKET cSkt, char *Path, FILETIME *Time, int *CancelCheckWork)\r
437 {\r
438         int Sts;\r
439         char Tmp[1024];\r
440         SYSTEMTIME sTime;\r
441 \r
442     Time->dwLowDateTime = 0;\r
443     Time->dwHighDateTime = 0;\r
444 \r
445         // 同時接続対応\r
446 //      Sts = CommandProcTrn(Tmp, "MDTM %s", Path);\r
447         Sts = CommandProcTrn(cSkt, Tmp, CancelCheckWork, "MDTM %s", Path);\r
448         if(Sts/100 == FTP_COMPLETE)\r
449         {\r
450                 sTime.wMilliseconds = 0;\r
451                 if(sscanf(Tmp+4, "%04d%02d%02d%02d%02d%02d",\r
452                         &sTime.wYear, &sTime.wMonth, &sTime.wDay,\r
453                         &sTime.wHour, &sTime.wMinute, &sTime.wSecond) == 6)\r
454                 {\r
455                         SystemTimeToFileTime(&sTime, Time);\r
456                         SpecificLocalFileTime2FileTime(Time, AskHostTimeZone());\r
457 \r
458                 }\r
459         }\r
460         return(Sts/100);\r
461 }\r
462 \r
463 \r
464 /*----- リモート側のコマンドを実行 --------------------------------------------\r
465 *\r
466 *       Parameter\r
467 *               char *CmdStr : コマンド文字列\r
468 *\r
469 *       Return Value\r
470 *               int 応答コードの1桁目\r
471 *----------------------------------------------------------------------------*/\r
472 \r
473 int DoQUOTE(char *CmdStr)\r
474 {\r
475         int Sts;\r
476 \r
477         Sts = CommandProcCmd(NULL, "%s", CmdStr);\r
478 \r
479         if(Sts/100 >= FTP_CONTINUE)\r
480                 SoundPlay(SND_ERROR);\r
481 \r
482         return(Sts/100);\r
483 }\r
484 \r
485 \r
486 /*----- ソケットを閉じる ------------------------------------------------------\r
487 *\r
488 *       Parameter\r
489 *               なし\r
490 *\r
491 *       Return Value\r
492 *               SOCKET 閉じた後のソケット\r
493 *----------------------------------------------------------------------------*/\r
494 \r
495 SOCKET DoClose(SOCKET Sock)\r
496 {\r
497         if(Sock != INVALID_SOCKET)\r
498         {\r
499 //              if(WSAIsBlocking())\r
500 //              {\r
501 //                      DoPrintf("Skt=%u : Cancelled blocking call", Sock);\r
502 //                      WSACancelBlockingCall();\r
503 //              }\r
504                 do_closesocket(Sock);\r
505                 DoPrintf("Skt=%u : Socket closed.", Sock);\r
506                 Sock = INVALID_SOCKET;\r
507         }\r
508         if(Sock != INVALID_SOCKET)\r
509                 DoPrintf("Skt=%u : Failed to close socket.", Sock);\r
510 \r
511         return(Sock);\r
512 }\r
513 \r
514 \r
515 /*----- ホストからログアウトする ----------------------------------------------\r
516 *\r
517 *       Parameter\r
518 *               kSOCKET ctrl_skt : ソケット\r
519 *\r
520 *       Return Value\r
521 *               int 応答コードの1桁目\r
522 *----------------------------------------------------------------------------*/\r
523 \r
524 int DoQUIT(SOCKET ctrl_skt)\r
525 {\r
526         int Ret;\r
527 \r
528         Ret = FTP_COMPLETE;\r
529         if(SendQuit == YES)\r
530                 // 同時接続対応\r
531 //              Ret = command(ctrl_skt, NULL, &CheckCancelFlg, "QUIT") / 100;\r
532                 Ret = command(ctrl_skt, NULL, &CancelFlg, "QUIT") / 100;\r
533 \r
534         return(Ret);\r
535 }\r
536 \r
537 \r
538 /*----- リモート側のディレクトリリストを取得(コマンドコントロールソケットを使用)\r
539 *\r
540 *       Parameter\r
541 *               char *AddOpt : 追加のオプション\r
542 *               char *Path : パス名\r
543 *               int Num : ファイル名番号\r
544 *\r
545 *       Return Value\r
546 *               int 応答コードの1桁目\r
547 *----------------------------------------------------------------------------*/\r
548 \r
549 int DoDirListCmdSkt(char *AddOpt, char *Path, int Num, int *CancelCheckWork)\r
550 {\r
551         int Sts;\r
552 \r
553         if(AskTransferNow() == YES)\r
554                 SktShareProh();\r
555 \r
556 //      if((Sts = DoDirList(NULL, AskCmdCtrlSkt(), AddOpt, Path, Num)) == 429)\r
557 //      {\r
558 //              ReConnectCmdSkt();\r
559                 Sts = DoDirList(NULL, AskCmdCtrlSkt(), AddOpt, Path, Num, CancelCheckWork);\r
560 \r
561                 if(Sts/100 >= FTP_CONTINUE)\r
562                         SoundPlay(SND_ERROR);\r
563 //      }\r
564         return(Sts/100);\r
565 }\r
566 \r
567 \r
568 /*----- リモート側のディレクトリリストを取得 ----------------------------------\r
569 *\r
570 *       Parameter\r
571 *               HWND hWnd : 転送中ダイアログのウインドウハンドル\r
572 *               SOCKET cSkt : コントロールソケット\r
573 *               char *AddOpt : 追加のオプション\r
574 *               char *Path : パス名 (""=カレントディレクトリ)\r
575 *               int Num : ファイル名番号\r
576 *\r
577 *       Return Value\r
578 *               int 応答コード\r
579 *----------------------------------------------------------------------------*/\r
580 \r
581 static int DoDirList(HWND hWnd, SOCKET cSkt, char *AddOpt, char *Path, int Num, int *CancelCheckWork)\r
582 {\r
583         char Tmp[FMAX_PATH];\r
584         int Sts;\r
585 \r
586 //#pragma aaa\r
587 //DoPrintf("===== DoDirList %d = %s", Num, Path);\r
588 \r
589         MakeCacheFileName(Num, Tmp);\r
590 //      MainTransPkt.ctrl_skt = cSkt;\r
591 \r
592         if(AskListCmdMode() == NO)\r
593         {\r
594                 strcpy(MainTransPkt.Cmd, "NLST");\r
595                 if(strlen(AskHostLsName()) > 0)\r
596                 {\r
597                         strcat(MainTransPkt.Cmd, " ");\r
598                         if((AskHostType() == HTYPE_ACOS) || (AskHostType() == HTYPE_ACOS_4))\r
599                                 strcat(MainTransPkt.Cmd, "'");\r
600                         strcat(MainTransPkt.Cmd, AskHostLsName());\r
601                         if((AskHostType() == HTYPE_ACOS) || (AskHostType() == HTYPE_ACOS_4))\r
602                                 strcat(MainTransPkt.Cmd, "'");\r
603                 }\r
604                 if(strlen(AddOpt) > 0)\r
605                         strcat(MainTransPkt.Cmd, AddOpt);\r
606         }\r
607         else\r
608         {\r
609                 // MLSD対応\r
610 //              strcpy(MainTransPkt.Cmd, "LIST");\r
611                 if(AskUseMLSD() && (AskHostFeature() & FEATURE_MLSD))\r
612                         strcpy(MainTransPkt.Cmd, "MLSD");\r
613                 else\r
614                         strcpy(MainTransPkt.Cmd, "LIST");\r
615                 if(strlen(AddOpt) > 0)\r
616                 {\r
617                         strcat(MainTransPkt.Cmd, " -");\r
618                         strcat(MainTransPkt.Cmd, AddOpt);\r
619                 }\r
620         }\r
621 \r
622         if(strlen(Path) > 0)\r
623                 strcat(MainTransPkt.Cmd, " ");\r
624 \r
625         strcpy(MainTransPkt.RemoteFile, Path);\r
626         strcpy(MainTransPkt.LocalFile, Tmp);\r
627         MainTransPkt.Type = TYPE_A;\r
628         MainTransPkt.Size = -1;\r
629         /* ファイルリストの中の漢字のファイル名は、別途   */\r
630         /* ChangeFnameRemote2Local で変換する                      */\r
631         MainTransPkt.KanjiCode = KANJI_NOCNV;\r
632         MainTransPkt.KanaCnv = YES;\r
633         MainTransPkt.Mode = EXIST_OVW;\r
634         MainTransPkt.ExistSize = 0;\r
635         MainTransPkt.hWndTrans = hWnd;\r
636         MainTransPkt.Next = NULL;\r
637 \r
638         Sts = DoDownLoad(cSkt, &MainTransPkt, YES, CancelCheckWork);\r
639 \r
640 //#pragma aaa\r
641 //DoPrintf("===== DoDirList Done.");\r
642 \r
643         return(Sts);\r
644 }\r
645 \r
646 \r
647 /*----- リモート側へコマンドを送りリプライを待つ(コマンドソケット)-----------\r
648 *\r
649 *       Parameter\r
650 *               char *Reply : リプライのコピー先 (NULL=コピーしない)\r
651 *               char *fmt : フォーマット文字列\r
652 *               ... : パラメータ\r
653 *\r
654 *       Return Value\r
655 *               int 応答コード\r
656 *\r
657 *       Note\r
658 *               コマンドコントロールソケットを使う\r
659 *----------------------------------------------------------------------------*/\r
660 \r
661 int CommandProcCmd(char *Reply, char *fmt, ...)\r
662 {\r
663         va_list Args;\r
664         char Cmd[1024];\r
665         int Sts;\r
666 \r
667         va_start(Args, fmt);\r
668         wvsprintf(Cmd, fmt, Args);\r
669         va_end(Args);\r
670 \r
671         if(AskTransferNow() == YES)\r
672                 SktShareProh();\r
673 \r
674 //#pragma aaa\r
675 //DoPrintf("**CommandProcCmd : %s", Cmd);\r
676 \r
677 //      if((Sts = command(AskCmdCtrlSkt(), Reply, "%s", Cmd)) == 429)\r
678 //      {\r
679 //              if(ReConnectCmdSkt() == FFFTP_SUCCESS)\r
680 //              {\r
681                         // 同時接続対応\r
682 //                      Sts = command(AskCmdCtrlSkt(), Reply, &CheckCancelFlg, "%s", Cmd);\r
683                         Sts = command(AskCmdCtrlSkt(), Reply, &CancelFlg, "%s", Cmd);\r
684 //              }\r
685 //      }\r
686         return(Sts);\r
687 }\r
688 \r
689 \r
690 /*----- リモート側へコマンドを送りリプライを待つ(転送ソケット)---------------\r
691 *\r
692 *       Parameter\r
693 *               char *Reply : リプライのコピー先 (NULL=コピーしない)\r
694 *               char *fmt : フォーマット文字列\r
695 *               ... : パラメータ\r
696 *\r
697 *       Return Value\r
698 *               int 応答コード\r
699 *\r
700 *       Note\r
701 *               転送コントロールソケットを使う\r
702 *----------------------------------------------------------------------------*/\r
703 \r
704 // 同時接続対応\r
705 //int CommandProcTrn(char *Reply, char *fmt, ...)\r
706 int CommandProcTrn(SOCKET cSkt, char *Reply, int* CancelCheckWork, char *fmt, ...)\r
707 {\r
708         va_list Args;\r
709         char Cmd[1024];\r
710         int Sts;\r
711 \r
712         va_start(Args, fmt);\r
713         wvsprintf(Cmd, fmt, Args);\r
714         va_end(Args);\r
715 \r
716 //#pragma aaa\r
717 //DoPrintf("**CommandProcTrn : %s", Cmd);\r
718 \r
719 //      if((Sts = command(AskTrnCtrlSkt(), Reply, "%s", Cmd)) == 429)\r
720 //      {\r
721 //              if(ReConnectTrnSkt() == FFFTP_SUCCESS)\r
722 //                      Sts = command(AskTrnCtrlSkt(), Reply, &CheckCancelFlg, "%s", Cmd);\r
723                         Sts = command(cSkt, Reply, CancelCheckWork, "%s", Cmd);\r
724 //      }\r
725         return(Sts);\r
726 }\r
727 \r
728 \r
729 /*----- コマンドを送りリプライを待つ ------------------------------------------\r
730 *\r
731 *       Parameter\r
732 *               SOCKET cSkt : コントロールソケット\r
733 *               char *Reply : リプライのコピー先 (NULL=コピーしない)\r
734 *               char *fmt : フォーマット文字列\r
735 *               ... : パラメータ\r
736 *\r
737 *       Return Value\r
738 *               int 応答コード\r
739 *\r
740 *       Note\r
741 *               ホストのファイル名の漢字コードに応じて、ここで漢字コードの変換を行なう\r
742 *----------------------------------------------------------------------------*/\r
743 \r
744 //#pragma aaa\r
745 //static int cntcnt = 0;\r
746 \r
747 int command(SOCKET cSkt, char *Reply, int *CancelCheckWork, char *fmt, ...)\r
748 {\r
749         va_list Args;\r
750         char Cmd[FMAX_PATH*2];\r
751         int Sts;\r
752         char TmpBuf[ONELINE_BUF_SIZE];\r
753 \r
754         if(cSkt != INVALID_SOCKET)\r
755         {\r
756                 va_start(Args, fmt);\r
757                 wvsprintf(Cmd, fmt, Args);\r
758                 va_end(Args);\r
759 \r
760                 if(strncmp(Cmd, "PASS ", 5) == 0)\r
761                         SetTaskMsg(">PASS [xxxxxx]");\r
762                 else if((strncmp(Cmd, "USER ", 5) == 0) ||\r
763                                 (strncmp(Cmd, "OPEN ", 5) == 0))\r
764                 {\r
765                         SetTaskMsg(">%s", Cmd);\r
766                 }\r
767                 else\r
768                 {\r
769                         ChangeSepaLocal2Remote(Cmd);\r
770                         SetTaskMsg(">%s", Cmd);\r
771                         ChangeFnameLocal2Remote(Cmd, FMAX_PATH*2);\r
772                 }\r
773 \r
774 //              DoPrintf("SEND : %s", Cmd);\r
775                 strcat(Cmd, "\x0D\x0A");\r
776 \r
777                 if(Reply != NULL)\r
778                         strcpy(Reply, "");\r
779 \r
780                 Sts = 429;\r
781                 if(SendData(cSkt, Cmd, strlen(Cmd), 0, CancelCheckWork) == FFFTP_SUCCESS)\r
782                 {\r
783                         Sts = ReadReplyMessage(cSkt, Reply, 1024, CancelCheckWork, TmpBuf);\r
784                 }\r
785 \r
786 //#pragma aaa\r
787 //if(Reply != NULL)\r
788 //      DoPrintf("%x : %x : %s : %s", cSkt, &TmpBuf, Cmd, Reply);\r
789 //else\r
790 //      DoPrintf("%x : %x : %s : NULL", cSkt, &TmpBuf, Cmd);\r
791 \r
792 //              DoPrintf("command() RET=%d", Sts);\r
793         }\r
794         else\r
795                 Sts = 429;\r
796 \r
797         return(Sts);\r
798 }\r
799 \r
800 \r
801 /*----- データを送る ----------------------------------------------------------\r
802 *\r
803 *       Parameter\r
804 *               SOCKET Skt : ソケット\r
805 *               char *Data : データ\r
806 *               int Size : 送るデータのサイズ\r
807 *               int Mode : コールモード\r
808 *\r
809 *       Return Value\r
810 *               int ステータス\r
811 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
812 *----------------------------------------------------------------------------*/\r
813 \r
814 int SendData(SOCKET Skt, char *Data, int Size, int Mode, int *CancelCheckWork)\r
815 {\r
816         int Sts;\r
817         int Tmp;\r
818 //      fd_set SendFds;\r
819 //      struct timeval Tout;\r
820 //      struct timeval *ToutPtr;\r
821         int TimeOutErr;\r
822 \r
823         Sts = FFFTP_FAIL;\r
824         if(Skt != INVALID_SOCKET)\r
825         {\r
826                 Sts = FFFTP_SUCCESS;\r
827                 while(Size > 0)\r
828                 {\r
829 //                      FD_ZERO(&SendFds);\r
830 //                      FD_SET(Skt, &SendFds);\r
831 //                      ToutPtr = NULL;\r
832 //                      if(TimeOut != 0)\r
833 //                      {\r
834 //                              Tout.tv_sec = TimeOut;\r
835 //                              Tout.tv_usec = 0;\r
836 //                              ToutPtr = &Tout;\r
837 //                      }\r
838 //                      Tmp = select(0, NULL, &SendFds, NULL, ToutPtr);\r
839 //                      if(Tmp == SOCKET_ERROR)\r
840 //                      {\r
841 //                              Sts = FFFTP_FAIL;\r
842 //                              ReportWSError("select", WSAGetLastError());\r
843 //                              break;\r
844 //                      }\r
845 //                      else if(Tmp == 0)\r
846 //                      {\r
847 //                              Sts = FFFTP_FAIL;\r
848 //                              SetTaskMsg(MSGJPN241);\r
849 //                              break;\r
850 //                      }\r
851 \r
852                         Tmp = do_send(Skt, Data, Size, Mode, &TimeOutErr, CancelCheckWork);\r
853                         if(TimeOutErr == YES)\r
854                         {\r
855                                 Sts = FFFTP_FAIL;\r
856                                 SetTaskMsg(MSGJPN241);\r
857                                 break;\r
858                         }\r
859                         else if(Tmp == SOCKET_ERROR)\r
860                         {\r
861                                 Sts = FFFTP_FAIL;\r
862                                 ReportWSError("send", WSAGetLastError());\r
863                                 break;\r
864                         }\r
865 \r
866                         Size -= Tmp;\r
867                         Data += Tmp;\r
868                 }\r
869         }\r
870         return(Sts);\r
871 }\r
872 \r
873 \r
874 /*----- 応答メッセージを受け取る ----------------------------------------------\r
875 *\r
876 *       Parameter\r
877 *               SOCKET cSkt : コントロールソケット\r
878 *               char *Buf : メッセージを受け取るバッファ (NULL=コピーしない)\r
879 *               int Max : バッファのサイズ\r
880 *               int *CancelCheckWork :\r
881 *               char *Tmp : テンポラリワーク\r
882 *\r
883 *       Return Value\r
884 *               int 応答コード\r
885 *----------------------------------------------------------------------------*/\r
886 \r
887 int ReadReplyMessage(SOCKET cSkt, char *Buf, int Max, int *CancelCheckWork, char *Tmp)\r
888 {\r
889         int iRetCode;\r
890         int iContinue;\r
891         int FirstCode;\r
892         int Lines;\r
893         int i;\r
894 \r
895         if(Buf != NULL)\r
896                 memset(Buf, NUL, Max);\r
897         Max--;\r
898 \r
899         FirstCode = 0;\r
900         if(cSkt != INVALID_SOCKET)\r
901         {\r
902                 Lines = 0;\r
903                 do\r
904                 {\r
905                         iContinue = NO;\r
906                         iRetCode = ReadOneLine(cSkt, Tmp, ONELINE_BUF_SIZE, CancelCheckWork);\r
907 \r
908                         SetTaskMsg("%s", Tmp);\r
909 \r
910                         if(Buf != NULL)\r
911                         {\r
912                                 // 2行目以降の応答コードは消す\r
913                                 if(Lines > 0)\r
914                                 {\r
915                                         for(i = 0; ; i++)\r
916                                         {\r
917                                                 if(IsDigit(Tmp[i]) == 0)\r
918                                                         break;\r
919                                                 Tmp[i] = ' ';\r
920                                         }\r
921                                 }\r
922                                 strncat(Buf, Tmp, Max);\r
923                                 Max = max1(0, Max-strlen(Tmp));\r
924 \r
925 //                              strncpy(Buf, Tmp, Max);\r
926                         }\r
927 \r
928                         if((iRetCode != 421) && (iRetCode != 429))\r
929                         {\r
930                                 if((FirstCode == 0) &&\r
931                                    (iRetCode >= 100) && (iRetCode <= 599))\r
932                                 {\r
933                                         FirstCode = iRetCode;\r
934                                 }\r
935 \r
936                                 if((iRetCode < 100) || (iRetCode > 599) ||\r
937                                    (*(Tmp + 3) == '-') ||\r
938                                    ((FirstCode > 0) && (iRetCode != FirstCode)))\r
939                                 {\r
940                                         iContinue = YES;\r
941                                 }\r
942                         }\r
943                         else\r
944                                 FirstCode = iRetCode;\r
945 \r
946                         Lines++;\r
947                 }\r
948                 while(iContinue == YES);\r
949         }\r
950         return(FirstCode);\r
951 }\r
952 \r
953 \r
954 /*----- 1行分のデータを受け取る ----------------------------------------------\r
955 *\r
956 *       Parameter\r
957 *               SOCKET cSkt : コントロールソケット\r
958 *               char *Buf : メッセージを受け取るバッファ\r
959 *               int Max : バッファのサイズ\r
960 *               int *CancelCheckWork : \r
961 *\r
962 *       Return Value\r
963 *               int 応答コード\r
964 *----------------------------------------------------------------------------*/\r
965 \r
966 static int ReadOneLine(SOCKET cSkt, char *Buf, int Max, int *CancelCheckWork)\r
967 {\r
968         char *Pos;\r
969         int SizeOnce;\r
970         int CopySize;\r
971         int ResCode;\r
972         int i;\r
973 //      fd_set ReadFds;\r
974 //      struct timeval Tout;\r
975 //      struct timeval *ToutPtr;\r
976         char Tmp[1024];\r
977         int TimeOutErr;\r
978 \r
979         ResCode = 0;\r
980         if(cSkt != INVALID_SOCKET)\r
981         {\r
982                 memset(Buf, NUL, Max);\r
983                 Max--;                                  /* 末尾のNULLのぶん */\r
984                 Pos = Buf;\r
985 \r
986                 for(;;)\r
987                 {\r
988 //                      FD_ZERO(&ReadFds);\r
989 //                      FD_SET(cSkt, &ReadFds);\r
990 //                      ToutPtr = NULL;\r
991 //                      if(TimeOut != 0)\r
992 //                      {\r
993 //                              Tout.tv_sec = TimeOut;\r
994 //                              Tout.tv_usec = 0;\r
995 //                              ToutPtr = &Tout;\r
996 //                      }\r
997 //                      i = select(0, &ReadFds, NULL, NULL, ToutPtr);\r
998 //                      if(i == SOCKET_ERROR)\r
999 //                      {\r
1000 //                              ReportWSError("select", WSAGetLastError());\r
1001 //                              SizeOnce = -1;\r
1002 //                              break;\r
1003 //                      }\r
1004 //                      else if(i == 0)\r
1005 //                      {\r
1006 //                              SetTaskMsg(MSGJPN242);\r
1007 //                              SizeOnce = -2;\r
1008 //                              break;\r
1009 //                      }\r
1010 \r
1011                         /* LFまでを受信するために、最初はPEEKで受信 */\r
1012                         if((SizeOnce = do_recv(cSkt, (LPSTR)Tmp, 1024, MSG_PEEK, &TimeOutErr, CancelCheckWork)) <= 0)\r
1013                         {\r
1014                                 if(TimeOutErr == YES)\r
1015                                 {\r
1016                                         SetTaskMsg(MSGJPN242);\r
1017                                         SizeOnce = -2;\r
1018                                 }\r
1019                                 else if(SizeOnce == SOCKET_ERROR)\r
1020                                 {\r
1021                                         SizeOnce = -1;\r
1022                                 }\r
1023                                 break;\r
1024                         }\r
1025 \r
1026                         /* LFを探して、あったらそこまでの長さをセット */\r
1027                         for(i = 0; i < SizeOnce ; i++)\r
1028                         {\r
1029                                 if(*(Tmp + i) == NUL || *(Tmp + i) == 0x0A)\r
1030                                 {\r
1031                                         SizeOnce = i + 1;\r
1032                                         break;\r
1033                                 }\r
1034                         }\r
1035 \r
1036                         /* 本受信 */\r
1037                         if((SizeOnce = do_recv(cSkt, Tmp, SizeOnce, 0, &TimeOutErr, CancelCheckWork)) <= 0)\r
1038                                 break;\r
1039 \r
1040                         CopySize = min1(Max, SizeOnce);\r
1041                         memcpy(Pos, Tmp, CopySize);\r
1042                         Pos += CopySize;\r
1043                         Max -= CopySize;\r
1044 \r
1045                         /* データがLFで終わっていたら1行終わり */\r
1046                         if(*(Tmp + SizeOnce - 1) == 0x0A)\r
1047                                 break;\r
1048                 }\r
1049                 *Pos = NUL;\r
1050 \r
1051                 if(SizeOnce <= 0)\r
1052                 {\r
1053                         ResCode = 429;\r
1054                         memset(Buf, 0, Max);\r
1055 \r
1056                         if((SizeOnce == -2) || (AskTransferNow() == YES))\r
1057                         // 転送中に全て中止を行うと不正なデータが得られる場合のバグ修正\r
1058 //                              DisconnectSet();\r
1059                                 cSkt = DoClose(cSkt);\r
1060                 }\r
1061                 else\r
1062                 {\r
1063                         if(IsDigit(*Buf) && IsDigit(*(Buf+1)) && IsDigit(*(Buf+2)))\r
1064                         {\r
1065                                 memset(Tmp, NUL, 4);\r
1066                                 strncpy(Tmp, Buf, 3);\r
1067                                 ResCode = atoi(Tmp);\r
1068                         }\r
1069 \r
1070                         /* 末尾の CR,LF,スペースを取り除く */\r
1071                         while((i=strlen(Buf))>2 &&\r
1072                                   (Buf[i-1]==0x0a || Buf[i-1]==0x0d || Buf[i-1]==' '))\r
1073                                 Buf[i-1]=0;\r
1074                 }\r
1075         }\r
1076         return(ResCode);\r
1077 }\r
1078 \r
1079 \r
1080 /*----- 固定長データを受け取る ------------------------------------------------\r
1081 *\r
1082 *       Parameter\r
1083 *               SOCKET cSkt : コントロールソケット\r
1084 *               char *Buf : メッセージを受け取るバッファ\r
1085 *               int Size : バイト数\r
1086 *               int *CancelCheckWork : \r
1087 *\r
1088 *       Return Value\r
1089 *               int ステータス\r
1090 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1091 *----------------------------------------------------------------------------*/\r
1092 \r
1093 int ReadNchar(SOCKET cSkt, char *Buf, int Size, int *CancelCheckWork)\r
1094 {\r
1095 //      struct timeval Tout;\r
1096 //      struct timeval *ToutPtr;\r
1097 //      fd_set ReadFds;\r
1098 //      int i;\r
1099         int SizeOnce;\r
1100         int Sts;\r
1101         int TimeOutErr;\r
1102 \r
1103         Sts = FFFTP_FAIL;\r
1104         if(cSkt != INVALID_SOCKET)\r
1105         {\r
1106                 Sts = FFFTP_SUCCESS;\r
1107                 while(Size > 0)\r
1108                 {\r
1109 //                      FD_ZERO(&ReadFds);\r
1110 //                      FD_SET(cSkt, &ReadFds);\r
1111 //                      ToutPtr = NULL;\r
1112 //                      if(TimeOut != 0)\r
1113 //                      {\r
1114 //                              Tout.tv_sec = TimeOut;\r
1115 //                              Tout.tv_usec = 0;\r
1116 //                              ToutPtr = &Tout;\r
1117 //                      }\r
1118 //                      i = select(0, &ReadFds, NULL, NULL, ToutPtr);\r
1119 //                      if(i == SOCKET_ERROR)\r
1120 //                      {\r
1121 //                              ReportWSError("select", WSAGetLastError());\r
1122 //                              Sts = FFFTP_FAIL;\r
1123 //                              break;\r
1124 //                      }\r
1125 //                      else if(i == 0)\r
1126 //                      {\r
1127 //                              SetTaskMsg(MSGJPN243);\r
1128 //                              Sts = FFFTP_FAIL;\r
1129 //                              break;\r
1130 //                      }\r
1131 \r
1132                         if((SizeOnce = do_recv(cSkt, Buf, Size, 0, &TimeOutErr, CancelCheckWork)) <= 0)\r
1133                         {\r
1134                                 if(TimeOutErr == YES)\r
1135                                         SetTaskMsg(MSGJPN243);\r
1136                                 Sts = FFFTP_FAIL;\r
1137                                 break;\r
1138                         }\r
1139 \r
1140                         Buf += SizeOnce;\r
1141                         Size -= SizeOnce;\r
1142                 }\r
1143         }\r
1144 \r
1145         if(Sts == FFFTP_FAIL)\r
1146                 SetTaskMsg(MSGJPN244);\r
1147 \r
1148         return(Sts);\r
1149 }\r
1150 \r
1151 \r
1152 /*----- エラー文字列を取得 ----------------------------------------------------\r
1153 *\r
1154 *       Parameter\r
1155 *               UINT Error : エラー番号\r
1156 *\r
1157 *       Return Value\r
1158 *               char *エラー文字列\r
1159 *----------------------------------------------------------------------------*/\r
1160 \r
1161 char *ReturnWSError(UINT Error)\r
1162 {\r
1163         static char Msg[128];\r
1164         char *Str;\r
1165 \r
1166         switch(Error)\r
1167         {\r
1168                 case WSAVERNOTSUPPORTED:\r
1169                         Str = "version of WinSock not supported";\r
1170                         break;\r
1171 \r
1172                 case WSASYSNOTREADY:\r
1173                         Str = "WinSock not present or not responding";\r
1174                         break;\r
1175 \r
1176                 case WSAEINVAL:\r
1177                         Str = "app version not supported by DLL";\r
1178                         break;\r
1179 \r
1180                 case WSAHOST_NOT_FOUND:\r
1181                         Str = "Authoritive: Host not found";\r
1182                         break;\r
1183 \r
1184                 case WSATRY_AGAIN:\r
1185                         Str = "Non-authoritive: host not found or server failure";\r
1186                         break;\r
1187 \r
1188                 case WSANO_RECOVERY:\r
1189                         Str = "Non-recoverable: refused or not implemented";\r
1190                         break;\r
1191 \r
1192                 case WSANO_DATA:\r
1193                         Str = "Valid name, no data record for type";\r
1194                         break;\r
1195 \r
1196 #if 0\r
1197                 case WSANO_ADDRESS:\r
1198                         Str = "Valid name, no MX record";\r
1199                         break;\r
1200 #endif\r
1201 \r
1202                 case WSANOTINITIALISED:\r
1203                         Str = "WSA Startup not initialized";\r
1204                         break;\r
1205 \r
1206                 case WSAENETDOWN:\r
1207                         Str = "Network subsystem failed";\r
1208                         break;\r
1209 \r
1210                 case WSAEINPROGRESS:\r
1211                         Str = "Blocking operation in progress";\r
1212                         break;\r
1213 \r
1214                 case WSAEINTR:\r
1215                         Str = "Blocking call cancelled";\r
1216                         break;\r
1217 \r
1218                 case WSAEAFNOSUPPORT:\r
1219                         Str = "address family not supported";\r
1220                         break;\r
1221 \r
1222                 case WSAEMFILE:\r
1223                         Str = "no file descriptors available";\r
1224                         break;\r
1225 \r
1226                 case WSAENOBUFS:\r
1227                         Str = "no buffer space available";\r
1228                         break;\r
1229 \r
1230                 case WSAEPROTONOSUPPORT:\r
1231                         Str = "specified protocol not supported";\r
1232                         break;\r
1233 \r
1234                 case WSAEPROTOTYPE:\r
1235                         Str = "protocol wrong type for this socket";\r
1236                         break;\r
1237 \r
1238                 case WSAESOCKTNOSUPPORT:\r
1239                         Str = "socket type not supported for address family";\r
1240                         break;\r
1241 \r
1242                 case WSAENOTSOCK:\r
1243                         Str = "descriptor is not a socket";\r
1244                         break;\r
1245 \r
1246                 case WSAEWOULDBLOCK:\r
1247                         Str = "socket marked as non-blocking and SO_LINGER set not 0";\r
1248                         break;\r
1249 \r
1250                 case WSAEADDRINUSE:\r
1251                         Str = "address already in use";\r
1252                         break;\r
1253 \r
1254                 case WSAECONNABORTED:\r
1255                         Str = "connection aborted";\r
1256                         break;\r
1257 \r
1258                 case WSAECONNRESET:\r
1259                         Str = "connection reset";\r
1260                         break;\r
1261 \r
1262                 case WSAENOTCONN:\r
1263                         Str = "not connected";\r
1264                         break;\r
1265 \r
1266                 case WSAETIMEDOUT:\r
1267                         Str = "connection timed out";\r
1268                         break;\r
1269 \r
1270                 case WSAECONNREFUSED:\r
1271                         Str = "connection refused";\r
1272                         break;\r
1273 \r
1274                 case WSAEHOSTDOWN:\r
1275                         Str = "host down";\r
1276                         break;\r
1277 \r
1278                 case WSAEHOSTUNREACH:\r
1279                         Str = "host unreachable";\r
1280                         break;\r
1281 \r
1282                 case WSAEADDRNOTAVAIL:\r
1283                         Str = "address not available";\r
1284                         break;\r
1285 \r
1286                 default:\r
1287                         sprintf(Msg, "error %u", Error);\r
1288                         return(Msg);\r
1289         }\r
1290         return(Str);\r
1291 }\r
1292 \r
1293 \r
1294 /*----- デバッグコンソールにエラーを表示 --------------------------------------\r
1295 *\r
1296 *       Parameter\r
1297 *               char *Msg : エラーの前に表示するメッセージ\r
1298 *               UINT Error : エラー番号\r
1299 *\r
1300 *       Return Value\r
1301 *               なし\r
1302 *----------------------------------------------------------------------------*/\r
1303 \r
1304 void ReportWSError(char *Msg, UINT Error)\r
1305 {\r
1306         if(Msg != NULL)\r
1307                 DoPrintf("[[%s : %s]]", Msg, ReturnWSError(Error));\r
1308         else\r
1309                 DoPrintf("[[%s]]", ReturnWSError(Error));\r
1310 }\r
1311 \r
1312 \r
1313 /*----- ファイル名をローカル側で扱えるように変換する --------------------------\r
1314 *\r
1315 *       Parameter\r
1316 *               char *Fname : ファイル名\r
1317 *               int Max : 最大長\r
1318 *\r
1319 *       Return Value\r
1320 *               int ステータス\r
1321 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1322 *----------------------------------------------------------------------------*/\r
1323 \r
1324 int ChangeFnameRemote2Local(char *Fname, int Max)\r
1325 {\r
1326         int Sts;\r
1327         char *Buf;\r
1328         char *Pos;\r
1329         CODECONVINFO cInfo;\r
1330         // バッファ上書きバグ対策\r
1331         char *Buf2;\r
1332 \r
1333         Sts = FFFTP_FAIL;\r
1334         if((Buf = malloc(Max)) != NULL)\r
1335         {\r
1336         // バッファ上書きバグ対策\r
1337         if((Buf2 = malloc(strlen(Fname) + 1)) != NULL)\r
1338         {\r
1339                 InitCodeConvInfo(&cInfo);\r
1340                 cInfo.KanaCnv = NO;                     //AskHostNameKana();\r
1341                 // バッファ上書きバグ対策\r
1342 //              cInfo.Str = Fname;\r
1343                 strcpy(Buf2, Fname);\r
1344                 cInfo.Str = Buf2;\r
1345                 cInfo.StrLen = strlen(Fname);\r
1346                 cInfo.Buf = Buf;\r
1347                 cInfo.BufSize = Max - 1;\r
1348 \r
1349                 // ここで全てUTF-8へ変換する\r
1350                 // TODO: SJIS以外も直接UTF-8へ変換\r
1351                 switch(AskHostNameKanji())\r
1352                 {\r
1353                         case KANJI_SJIS :\r
1354                                 ConvSJIStoUTF8N(&cInfo);\r
1355                                 *(Buf + cInfo.OutLen) = NUL;\r
1356                                 strcpy(Fname, Buf);\r
1357                                 Pos = strchr(Fname, NUL);\r
1358                                 FlushRestData(&cInfo);\r
1359                                 *(Buf + cInfo.OutLen) = NUL;\r
1360                                 strcpy(Pos, Buf);\r
1361                                 break;\r
1362 \r
1363                         case KANJI_JIS :\r
1364                                 ConvJIStoSJIS(&cInfo);\r
1365                                 *(Buf + cInfo.OutLen) = NUL;\r
1366                                 strcpy(Fname, Buf);\r
1367                                 Pos = strchr(Fname, NUL);\r
1368                                 FlushRestData(&cInfo);\r
1369                                 *(Buf + cInfo.OutLen) = NUL;\r
1370                                 strcpy(Pos, Buf);\r
1371                                 // TODO\r
1372                                 InitCodeConvInfo(&cInfo);\r
1373                                 cInfo.KanaCnv = NO;\r
1374                                 cInfo.Str = Fname;\r
1375                                 cInfo.StrLen = strlen(Fname);\r
1376                                 cInfo.Buf = Buf;\r
1377                                 cInfo.BufSize = Max - 1;\r
1378                                 ConvSJIStoUTF8N(&cInfo);\r
1379                                 *(Buf + cInfo.OutLen) = NUL;\r
1380                                 strcpy(Fname, Buf);\r
1381                                 Pos = strchr(Fname, NUL);\r
1382                                 FlushRestData(&cInfo);\r
1383                                 *(Buf + cInfo.OutLen) = NUL;\r
1384                                 strcpy(Pos, Buf);\r
1385                                 break;\r
1386 \r
1387                         case KANJI_EUC :\r
1388                                 ConvEUCtoSJIS(&cInfo);\r
1389                                 *(Buf + cInfo.OutLen) = NUL;\r
1390                                 strcpy(Fname, Buf);\r
1391                                 Pos = strchr(Fname, NUL);\r
1392                                 FlushRestData(&cInfo);\r
1393                                 *(Buf + cInfo.OutLen) = NUL;\r
1394                                 strcpy(Pos, Buf);\r
1395                                 // TODO\r
1396                                 InitCodeConvInfo(&cInfo);\r
1397                                 cInfo.KanaCnv = NO;\r
1398                                 cInfo.Str = Fname;\r
1399                                 cInfo.StrLen = strlen(Fname);\r
1400                                 cInfo.Buf = Buf;\r
1401                                 cInfo.BufSize = Max - 1;\r
1402                                 ConvSJIStoUTF8N(&cInfo);\r
1403                                 *(Buf + cInfo.OutLen) = NUL;\r
1404                                 strcpy(Fname, Buf);\r
1405                                 Pos = strchr(Fname, NUL);\r
1406                                 FlushRestData(&cInfo);\r
1407                                 *(Buf + cInfo.OutLen) = NUL;\r
1408                                 strcpy(Pos, Buf);\r
1409                                 break;\r
1410 \r
1411                         case KANJI_SMB_HEX :\r
1412                         case KANJI_SMB_CAP :\r
1413                                 ConvSMBtoSJIS(&cInfo);\r
1414                                 *(Buf + cInfo.OutLen) = NUL;\r
1415                                 strcpy(Fname, Buf);\r
1416                                 Pos = strchr(Fname, NUL);\r
1417                                 FlushRestData(&cInfo);\r
1418                                 *(Buf + cInfo.OutLen) = NUL;\r
1419                                 strcpy(Pos, Buf);\r
1420                                 // TODO\r
1421                                 InitCodeConvInfo(&cInfo);\r
1422                                 cInfo.KanaCnv = NO;\r
1423                                 cInfo.Str = Fname;\r
1424                                 cInfo.StrLen = strlen(Fname);\r
1425                                 cInfo.Buf = Buf;\r
1426                                 cInfo.BufSize = Max - 1;\r
1427                                 ConvSJIStoUTF8N(&cInfo);\r
1428                                 *(Buf + cInfo.OutLen) = NUL;\r
1429                                 strcpy(Fname, Buf);\r
1430                                 Pos = strchr(Fname, NUL);\r
1431                                 FlushRestData(&cInfo);\r
1432                                 *(Buf + cInfo.OutLen) = NUL;\r
1433                                 strcpy(Pos, Buf);\r
1434                                 break;\r
1435 \r
1436 //                      case KANJI_UTF8N :\r
1437 //                              ConvUTF8NtoSJIS(&cInfo);\r
1438 //                              *(Buf + cInfo.OutLen) = NUL;\r
1439 //                              strcpy(Fname, Buf);\r
1440 //                              Pos = strchr(Fname, NUL);\r
1441 //                              FlushRestData(&cInfo);\r
1442 //                              *(Buf + cInfo.OutLen) = NUL;\r
1443 //                              strcpy(Pos, Buf);\r
1444 //                              break;\r
1445                 }\r
1446                 // バッファ上書きバグ対策\r
1447                 free(Buf2);\r
1448                 Sts = FFFTP_SUCCESS;\r
1449                 }\r
1450                 free(Buf);\r
1451                 // バッファ上書きバグ対策\r
1452 //              Sts = FFFTP_SUCCESS;\r
1453         }\r
1454         return(Sts);\r
1455 }\r
1456 \r
1457 \r
1458 /*----- ファイル名をリモート側で扱えるように変換する --------------------------\r
1459 *\r
1460 *       Parameter\r
1461 *               char *Fname : ファイル名\r
1462 *               int Max : 最大長\r
1463 *\r
1464 *       Return Value\r
1465 *               int ステータス\r
1466 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1467 *----------------------------------------------------------------------------*/\r
1468 \r
1469 int ChangeFnameLocal2Remote(char *Fname, int Max)\r
1470 {\r
1471         int Sts;\r
1472         char *Buf;\r
1473         char *Pos;\r
1474         CODECONVINFO cInfo;\r
1475         // バッファ上書きバグ対策\r
1476         char *Buf2;\r
1477 \r
1478         Sts = FFFTP_FAIL;\r
1479         if((Buf = malloc(Max)) != NULL)\r
1480         {\r
1481         // バッファ上書きバグ対策\r
1482         if((Buf2 = malloc(strlen(Fname) + 1)) != NULL)\r
1483         {\r
1484                 InitCodeConvInfo(&cInfo);\r
1485                 cInfo.KanaCnv = AskHostNameKana();\r
1486                 // バッファ上書きバグ対策\r
1487 //              cInfo.Str = Fname;\r
1488                 strcpy(Buf2, Fname);\r
1489                 cInfo.Str = Buf2;\r
1490                 cInfo.StrLen = strlen(Fname);\r
1491                 cInfo.Buf = Buf;\r
1492                 cInfo.BufSize = Max - 1;\r
1493 \r
1494                 // ここで全てUTF-8から変換する\r
1495                 // TODO: SJIS以外も直接UTF-8から変換\r
1496                 switch(AskHostNameKanji())\r
1497                 {\r
1498                         case KANJI_SJIS :\r
1499                                 ConvUTF8NtoSJIS(&cInfo);\r
1500                                 *(Buf + cInfo.OutLen) = NUL;\r
1501                                 strcpy(Fname, Buf);\r
1502                                 Pos = strchr(Fname, NUL);\r
1503                                 FlushRestData(&cInfo);\r
1504                                 *(Buf + cInfo.OutLen) = NUL;\r
1505                                 strcpy(Pos, Buf);\r
1506                                 break;\r
1507 \r
1508                         case KANJI_JIS :\r
1509                                 ConvUTF8NtoSJIS(&cInfo);\r
1510                                 *(Buf + cInfo.OutLen) = NUL;\r
1511                                 strcpy(Fname, Buf);\r
1512                                 Pos = strchr(Fname, NUL);\r
1513                                 FlushRestData(&cInfo);\r
1514                                 *(Buf + cInfo.OutLen) = NUL;\r
1515                                 strcpy(Pos, Buf);\r
1516                                 // TODO\r
1517                                 InitCodeConvInfo(&cInfo);\r
1518                                 cInfo.KanaCnv = NO;\r
1519                                 cInfo.Str = Fname;\r
1520                                 cInfo.StrLen = strlen(Fname);\r
1521                                 cInfo.Buf = Buf;\r
1522                                 cInfo.BufSize = Max - 1;\r
1523                                 ConvSJIStoJIS(&cInfo);\r
1524                                 *(Buf + cInfo.OutLen) = NUL;\r
1525                                 strcpy(Fname, Buf);\r
1526                                 Pos = strchr(Fname, NUL);\r
1527                                 FlushRestData(&cInfo);\r
1528                                 *(Buf + cInfo.OutLen) = NUL;\r
1529                                 strcpy(Pos, Buf);\r
1530                                 break;\r
1531 \r
1532                         case KANJI_EUC :\r
1533                                 ConvUTF8NtoSJIS(&cInfo);\r
1534                                 *(Buf + cInfo.OutLen) = NUL;\r
1535                                 strcpy(Fname, Buf);\r
1536                                 Pos = strchr(Fname, NUL);\r
1537                                 FlushRestData(&cInfo);\r
1538                                 *(Buf + cInfo.OutLen) = NUL;\r
1539                                 strcpy(Pos, Buf);\r
1540                                 // TODO\r
1541                                 InitCodeConvInfo(&cInfo);\r
1542                                 cInfo.KanaCnv = NO;\r
1543                                 cInfo.Str = Fname;\r
1544                                 cInfo.StrLen = strlen(Fname);\r
1545                                 cInfo.Buf = Buf;\r
1546                                 cInfo.BufSize = Max - 1;\r
1547                                 ConvSJIStoEUC(&cInfo);\r
1548                                 *(Buf + cInfo.OutLen) = NUL;\r
1549                                 strcpy(Fname, Buf);\r
1550                                 Pos = strchr(Fname, NUL);\r
1551                                 FlushRestData(&cInfo);\r
1552                                 *(Buf + cInfo.OutLen) = NUL;\r
1553                                 strcpy(Pos, Buf);\r
1554                                 break;\r
1555 \r
1556                         case KANJI_SMB_HEX :\r
1557                                 ConvUTF8NtoSJIS(&cInfo);\r
1558                                 *(Buf + cInfo.OutLen) = NUL;\r
1559                                 strcpy(Fname, Buf);\r
1560                                 Pos = strchr(Fname, NUL);\r
1561                                 FlushRestData(&cInfo);\r
1562                                 *(Buf + cInfo.OutLen) = NUL;\r
1563                                 strcpy(Pos, Buf);\r
1564                                 // TODO\r
1565                                 InitCodeConvInfo(&cInfo);\r
1566                                 cInfo.KanaCnv = NO;\r
1567                                 cInfo.Str = Fname;\r
1568                                 cInfo.StrLen = strlen(Fname);\r
1569                                 cInfo.Buf = Buf;\r
1570                                 cInfo.BufSize = Max - 1;\r
1571                                 ConvSJIStoSMB_HEX(&cInfo);\r
1572                                 *(Buf + cInfo.OutLen) = NUL;\r
1573                                 strcpy(Fname, Buf);\r
1574                                 Pos = strchr(Fname, NUL);\r
1575                                 FlushRestData(&cInfo);\r
1576                                 *(Buf + cInfo.OutLen) = NUL;\r
1577                                 strcpy(Pos, Buf);\r
1578                                 break;\r
1579 \r
1580                         case KANJI_SMB_CAP :\r
1581                                 ConvUTF8NtoSJIS(&cInfo);\r
1582                                 *(Buf + cInfo.OutLen) = NUL;\r
1583                                 strcpy(Fname, Buf);\r
1584                                 Pos = strchr(Fname, NUL);\r
1585                                 FlushRestData(&cInfo);\r
1586                                 *(Buf + cInfo.OutLen) = NUL;\r
1587                                 strcpy(Pos, Buf);\r
1588                                 // TODO\r
1589                                 InitCodeConvInfo(&cInfo);\r
1590                                 cInfo.KanaCnv = NO;\r
1591                                 cInfo.Str = Fname;\r
1592                                 cInfo.StrLen = strlen(Fname);\r
1593                                 cInfo.Buf = Buf;\r
1594                                 cInfo.BufSize = Max - 1;\r
1595                                 ConvSJIStoSMB_CAP(&cInfo);\r
1596                                 *(Buf + cInfo.OutLen) = NUL;\r
1597                                 strcpy(Fname, Buf);\r
1598                                 Pos = strchr(Fname, NUL);\r
1599                                 FlushRestData(&cInfo);\r
1600                                 *(Buf + cInfo.OutLen) = NUL;\r
1601                                 strcpy(Pos, Buf);\r
1602                                 break;\r
1603 \r
1604 //                      case KANJI_UTF8N :\r
1605 //                              ConvSJIStoUTF8N(&cInfo);\r
1606 //                              *(Buf + cInfo.OutLen) = NUL;\r
1607 //                              strcpy(Fname, Buf);\r
1608 //                              Pos = strchr(Fname, NUL);\r
1609 //                              FlushRestData(&cInfo);\r
1610 //                              *(Buf + cInfo.OutLen) = NUL;\r
1611 //                              strcpy(Pos, Buf);\r
1612 //                              break;\r
1613                 }\r
1614                 // バッファ上書きバグ対策\r
1615                 free(Buf2);\r
1616                 Sts = FFFTP_SUCCESS;\r
1617                 }\r
1618                 free(Buf);\r
1619                 // バッファ上書きバグ対策\r
1620 //              Sts = FFFTP_SUCCESS;\r
1621         }\r
1622         return(Sts);\r
1623 }\r
1624 \r
1625 \r
1626 /*----- パスの区切り文字をホストに合わせて変更する ----------------------------\r
1627 *\r
1628 *       Parameter\r
1629 *               char *Fname : ファイル名\r
1630 *\r
1631 *       Return Value\r
1632 *               なし\r
1633 *----------------------------------------------------------------------------*/\r
1634 static void ChangeSepaLocal2Remote(char *Fname)\r
1635 {\r
1636         if(AskHostType() == HTYPE_STRATUS)\r
1637         {\r
1638                 ReplaceAll(Fname, '/', '>');\r
1639         }\r
1640         return;\r
1641 }\r
1642 \r
1643 \r
1644 /*----- パスの区切り文字をローカルに合わせて変更する --------------------------\r
1645 *\r
1646 *       Parameter\r
1647 *               char *Fname : ファイル名\r
1648 *\r
1649 *       Return Value\r
1650 *               なし\r
1651 *----------------------------------------------------------------------------*/\r
1652 static void ChangeSepaRemote2Local(char *Fname)\r
1653 {\r
1654         if(AskHostType() == HTYPE_STRATUS)\r
1655         {\r
1656                 ReplaceAll(Fname, '>', '/');\r
1657         }\r
1658         return;\r
1659 }\r
1660 \r
1661 \r
1662 \r
1663 \r
1664 \r
1665 \r
1666 \r