OSDN Git Service

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