OSDN Git Service

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