OSDN Git Service

Add support for simultaneous connection for file transfer (sometimes freezes).
[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                 strcpy(MainTransPkt.Cmd, "LIST");\r
597                 if(strlen(AddOpt) > 0)\r
598                 {\r
599                         strcat(MainTransPkt.Cmd, " -");\r
600                         strcat(MainTransPkt.Cmd, AddOpt);\r
601                 }\r
602         }\r
603 \r
604         if(strlen(Path) > 0)\r
605                 strcat(MainTransPkt.Cmd, " ");\r
606 \r
607         strcpy(MainTransPkt.RemoteFile, Path);\r
608         strcpy(MainTransPkt.LocalFile, Tmp);\r
609         MainTransPkt.Type = TYPE_A;\r
610         MainTransPkt.Size = -1;\r
611         /* ファイルリストの中の漢字のファイル名は、別途   */\r
612         /* ChangeFnameRemote2Local で変換する                      */\r
613         MainTransPkt.KanjiCode = KANJI_NOCNV;\r
614         MainTransPkt.KanaCnv = YES;\r
615         MainTransPkt.Mode = EXIST_OVW;\r
616         MainTransPkt.ExistSize = 0;\r
617         MainTransPkt.hWndTrans = hWnd;\r
618         MainTransPkt.Next = NULL;\r
619 \r
620         Sts = DoDownLoad(cSkt, &MainTransPkt, YES, CancelCheckWork);\r
621 \r
622 //#pragma aaa\r
623 //DoPrintf("===== DoDirList Done.");\r
624 \r
625         return(Sts);\r
626 }\r
627 \r
628 \r
629 /*----- リモート側へコマンドを送りリプライを待つ(コマンドソケット)-----------\r
630 *\r
631 *       Parameter\r
632 *               char *Reply : リプライのコピー先 (NULL=コピーしない)\r
633 *               char *fmt : フォーマット文字列\r
634 *               ... : パラメータ\r
635 *\r
636 *       Return Value\r
637 *               int 応答コード\r
638 *\r
639 *       Note\r
640 *               コマンドコントロールソケットを使う\r
641 *----------------------------------------------------------------------------*/\r
642 \r
643 int CommandProcCmd(char *Reply, char *fmt, ...)\r
644 {\r
645         va_list Args;\r
646         char Cmd[1024];\r
647         int Sts;\r
648 \r
649         va_start(Args, fmt);\r
650         wvsprintf(Cmd, fmt, Args);\r
651         va_end(Args);\r
652 \r
653         if(AskTransferNow() == YES)\r
654                 SktShareProh();\r
655 \r
656 //#pragma aaa\r
657 //DoPrintf("**CommandProcCmd : %s", Cmd);\r
658 \r
659 //      if((Sts = command(AskCmdCtrlSkt(), Reply, "%s", Cmd)) == 429)\r
660 //      {\r
661 //              if(ReConnectCmdSkt() == FFFTP_SUCCESS)\r
662 //              {\r
663                         Sts = command(AskCmdCtrlSkt(), Reply, &CheckCancelFlg, "%s", Cmd);\r
664 //              }\r
665 //      }\r
666         return(Sts);\r
667 }\r
668 \r
669 \r
670 /*----- リモート側へコマンドを送りリプライを待つ(転送ソケット)---------------\r
671 *\r
672 *       Parameter\r
673 *               char *Reply : リプライのコピー先 (NULL=コピーしない)\r
674 *               char *fmt : フォーマット文字列\r
675 *               ... : パラメータ\r
676 *\r
677 *       Return Value\r
678 *               int 応答コード\r
679 *\r
680 *       Note\r
681 *               転送コントロールソケットを使う\r
682 *----------------------------------------------------------------------------*/\r
683 \r
684 // 同時接続対応\r
685 //int CommandProcTrn(char *Reply, char *fmt, ...)\r
686 int CommandProcTrn(SOCKET cSkt, char *Reply, char *fmt, ...)\r
687 {\r
688         va_list Args;\r
689         char Cmd[1024];\r
690         int Sts;\r
691 \r
692         va_start(Args, fmt);\r
693         wvsprintf(Cmd, fmt, Args);\r
694         va_end(Args);\r
695 \r
696 //#pragma aaa\r
697 //DoPrintf("**CommandProcTrn : %s", Cmd);\r
698 \r
699 //      if((Sts = command(AskTrnCtrlSkt(), Reply, "%s", Cmd)) == 429)\r
700 //      {\r
701 //              if(ReConnectTrnSkt() == FFFTP_SUCCESS)\r
702 //                      Sts = command(AskTrnCtrlSkt(), Reply, &CheckCancelFlg, "%s", Cmd);\r
703                         Sts = command(cSkt, Reply, &CheckCancelFlg, "%s", Cmd);\r
704 //      }\r
705         return(Sts);\r
706 }\r
707 \r
708 \r
709 /*----- コマンドを送りリプライを待つ ------------------------------------------\r
710 *\r
711 *       Parameter\r
712 *               SOCKET cSkt : コントロールソケット\r
713 *               char *Reply : リプライのコピー先 (NULL=コピーしない)\r
714 *               char *fmt : フォーマット文字列\r
715 *               ... : パラメータ\r
716 *\r
717 *       Return Value\r
718 *               int 応答コード\r
719 *\r
720 *       Note\r
721 *               ホストのファイル名の漢字コードに応じて、ここで漢字コードの変換を行なう\r
722 *----------------------------------------------------------------------------*/\r
723 \r
724 //#pragma aaa\r
725 //static int cntcnt = 0;\r
726 \r
727 int command(SOCKET cSkt, char *Reply, int *CancelCheckWork, char *fmt, ...)\r
728 {\r
729         va_list Args;\r
730         char Cmd[FMAX_PATH*2];\r
731         int Sts;\r
732         char TmpBuf[ONELINE_BUF_SIZE];\r
733 \r
734         if(cSkt != INVALID_SOCKET)\r
735         {\r
736                 va_start(Args, fmt);\r
737                 wvsprintf(Cmd, fmt, Args);\r
738                 va_end(Args);\r
739 \r
740                 if(strncmp(Cmd, "PASS ", 5) == 0)\r
741                         SetTaskMsg(">PASS [xxxxxx]");\r
742                 else if((strncmp(Cmd, "USER ", 5) == 0) ||\r
743                                 (strncmp(Cmd, "OPEN ", 5) == 0))\r
744                 {\r
745                         SetTaskMsg(">%s", Cmd);\r
746                 }\r
747                 else\r
748                 {\r
749                         ChangeSepaLocal2Remote(Cmd);\r
750                         SetTaskMsg(">%s", Cmd);\r
751                         ChangeFnameLocal2Remote(Cmd, FMAX_PATH*2);\r
752                 }\r
753 \r
754 //              DoPrintf("SEND : %s", Cmd);\r
755                 strcat(Cmd, "\x0D\x0A");\r
756 \r
757                 if(Reply != NULL)\r
758                         strcpy(Reply, "");\r
759 \r
760                 Sts = 429;\r
761                 if(SendData(cSkt, Cmd, strlen(Cmd), 0, CancelCheckWork) == FFFTP_SUCCESS)\r
762                 {\r
763                         Sts = ReadReplyMessage(cSkt, Reply, 1024, CancelCheckWork, TmpBuf);\r
764                 }\r
765 \r
766 //#pragma aaa\r
767 //if(Reply != NULL)\r
768 //      DoPrintf("%x : %x : %s : %s", cSkt, &TmpBuf, Cmd, Reply);\r
769 //else\r
770 //      DoPrintf("%x : %x : %s : NULL", cSkt, &TmpBuf, Cmd);\r
771 \r
772 //              DoPrintf("command() RET=%d", Sts);\r
773         }\r
774         else\r
775                 Sts = 429;\r
776 \r
777         return(Sts);\r
778 }\r
779 \r
780 \r
781 /*----- データを送る ----------------------------------------------------------\r
782 *\r
783 *       Parameter\r
784 *               SOCKET Skt : ソケット\r
785 *               char *Data : データ\r
786 *               int Size : 送るデータのサイズ\r
787 *               int Mode : コールモード\r
788 *\r
789 *       Return Value\r
790 *               int ステータス\r
791 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
792 *----------------------------------------------------------------------------*/\r
793 \r
794 int SendData(SOCKET Skt, char *Data, int Size, int Mode, int *CancelCheckWork)\r
795 {\r
796         int Sts;\r
797         int Tmp;\r
798 //      fd_set SendFds;\r
799 //      struct timeval Tout;\r
800 //      struct timeval *ToutPtr;\r
801         int TimeOutErr;\r
802 \r
803         Sts = FFFTP_FAIL;\r
804         if(Skt != INVALID_SOCKET)\r
805         {\r
806                 Sts = FFFTP_SUCCESS;\r
807                 while(Size > 0)\r
808                 {\r
809 //                      FD_ZERO(&SendFds);\r
810 //                      FD_SET(Skt, &SendFds);\r
811 //                      ToutPtr = NULL;\r
812 //                      if(TimeOut != 0)\r
813 //                      {\r
814 //                              Tout.tv_sec = TimeOut;\r
815 //                              Tout.tv_usec = 0;\r
816 //                              ToutPtr = &Tout;\r
817 //                      }\r
818 //                      Tmp = select(0, NULL, &SendFds, NULL, ToutPtr);\r
819 //                      if(Tmp == SOCKET_ERROR)\r
820 //                      {\r
821 //                              Sts = FFFTP_FAIL;\r
822 //                              ReportWSError("select", WSAGetLastError());\r
823 //                              break;\r
824 //                      }\r
825 //                      else if(Tmp == 0)\r
826 //                      {\r
827 //                              Sts = FFFTP_FAIL;\r
828 //                              SetTaskMsg(MSGJPN241);\r
829 //                              break;\r
830 //                      }\r
831 \r
832                         Tmp = do_send(Skt, Data, Size, Mode, &TimeOutErr, CancelCheckWork);\r
833                         if(TimeOutErr == YES)\r
834                         {\r
835                                 Sts = FFFTP_FAIL;\r
836                                 SetTaskMsg(MSGJPN241);\r
837                                 break;\r
838                         }\r
839                         else if(Tmp == SOCKET_ERROR)\r
840                         {\r
841                                 Sts = FFFTP_FAIL;\r
842                                 ReportWSError("send", WSAGetLastError());\r
843                                 break;\r
844                         }\r
845 \r
846                         Size -= Tmp;\r
847                         Data += Tmp;\r
848                 }\r
849         }\r
850         return(Sts);\r
851 }\r
852 \r
853 \r
854 /*----- 応答メッセージを受け取る ----------------------------------------------\r
855 *\r
856 *       Parameter\r
857 *               SOCKET cSkt : コントロールソケット\r
858 *               char *Buf : メッセージを受け取るバッファ (NULL=コピーしない)\r
859 *               int Max : バッファのサイズ\r
860 *               int *CancelCheckWork :\r
861 *               char *Tmp : テンポラリワーク\r
862 *\r
863 *       Return Value\r
864 *               int 応答コード\r
865 *----------------------------------------------------------------------------*/\r
866 \r
867 int ReadReplyMessage(SOCKET cSkt, char *Buf, int Max, int *CancelCheckWork, char *Tmp)\r
868 {\r
869         int iRetCode;\r
870         int iContinue;\r
871         int FirstCode;\r
872         int Lines;\r
873         int i;\r
874 \r
875         if(Buf != NULL)\r
876                 memset(Buf, NUL, Max);\r
877         Max--;\r
878 \r
879         FirstCode = 0;\r
880         if(cSkt != INVALID_SOCKET)\r
881         {\r
882                 Lines = 0;\r
883                 do\r
884                 {\r
885                         iContinue = NO;\r
886                         iRetCode = ReadOneLine(cSkt, Tmp, ONELINE_BUF_SIZE, CancelCheckWork);\r
887 \r
888                         SetTaskMsg("%s", Tmp);\r
889 \r
890                         if(Buf != NULL)\r
891                         {\r
892                                 // 2行目以降の応答コードは消す\r
893                                 if(Lines > 0)\r
894                                 {\r
895                                         for(i = 0; ; i++)\r
896                                         {\r
897                                                 if(IsDigit(Tmp[i]) == 0)\r
898                                                         break;\r
899                                                 Tmp[i] = ' ';\r
900                                         }\r
901                                 }\r
902                                 strncat(Buf, Tmp, Max);\r
903                                 Max = max1(0, Max-strlen(Tmp));\r
904 \r
905 //                              strncpy(Buf, Tmp, Max);\r
906                         }\r
907 \r
908                         if((iRetCode != 421) && (iRetCode != 429))\r
909                         {\r
910                                 if((FirstCode == 0) &&\r
911                                    (iRetCode >= 100) && (iRetCode <= 599))\r
912                                 {\r
913                                         FirstCode = iRetCode;\r
914                                 }\r
915 \r
916                                 if((iRetCode < 100) || (iRetCode > 599) ||\r
917                                    (*(Tmp + 3) == '-') ||\r
918                                    ((FirstCode > 0) && (iRetCode != FirstCode)))\r
919                                 {\r
920                                         iContinue = YES;\r
921                                 }\r
922                         }\r
923                         else\r
924                                 FirstCode = iRetCode;\r
925 \r
926                         Lines++;\r
927                 }\r
928                 while(iContinue == YES);\r
929         }\r
930         return(FirstCode);\r
931 }\r
932 \r
933 \r
934 /*----- 1行分のデータを受け取る ----------------------------------------------\r
935 *\r
936 *       Parameter\r
937 *               SOCKET cSkt : コントロールソケット\r
938 *               char *Buf : メッセージを受け取るバッファ\r
939 *               int Max : バッファのサイズ\r
940 *               int *CancelCheckWork : \r
941 *\r
942 *       Return Value\r
943 *               int 応答コード\r
944 *----------------------------------------------------------------------------*/\r
945 \r
946 static int ReadOneLine(SOCKET cSkt, char *Buf, int Max, int *CancelCheckWork)\r
947 {\r
948         char *Pos;\r
949         int SizeOnce;\r
950         int CopySize;\r
951         int ResCode;\r
952         int i;\r
953 //      fd_set ReadFds;\r
954 //      struct timeval Tout;\r
955 //      struct timeval *ToutPtr;\r
956         char Tmp[1024];\r
957         int TimeOutErr;\r
958 \r
959         ResCode = 0;\r
960         if(cSkt != INVALID_SOCKET)\r
961         {\r
962                 memset(Buf, NUL, Max);\r
963                 Max--;                                  /* 末尾のNULLのぶん */\r
964                 Pos = Buf;\r
965 \r
966                 for(;;)\r
967                 {\r
968 //                      FD_ZERO(&ReadFds);\r
969 //                      FD_SET(cSkt, &ReadFds);\r
970 //                      ToutPtr = NULL;\r
971 //                      if(TimeOut != 0)\r
972 //                      {\r
973 //                              Tout.tv_sec = TimeOut;\r
974 //                              Tout.tv_usec = 0;\r
975 //                              ToutPtr = &Tout;\r
976 //                      }\r
977 //                      i = select(0, &ReadFds, NULL, NULL, ToutPtr);\r
978 //                      if(i == SOCKET_ERROR)\r
979 //                      {\r
980 //                              ReportWSError("select", WSAGetLastError());\r
981 //                              SizeOnce = -1;\r
982 //                              break;\r
983 //                      }\r
984 //                      else if(i == 0)\r
985 //                      {\r
986 //                              SetTaskMsg(MSGJPN242);\r
987 //                              SizeOnce = -2;\r
988 //                              break;\r
989 //                      }\r
990 \r
991                         /* LFまでを受信するために、最初はPEEKで受信 */\r
992                         if((SizeOnce = do_recv(cSkt, (LPSTR)Tmp, 1024, MSG_PEEK, &TimeOutErr, CancelCheckWork)) <= 0)\r
993                         {\r
994                                 if(TimeOutErr == YES)\r
995                                 {\r
996                                         SetTaskMsg(MSGJPN242);\r
997                                         SizeOnce = -2;\r
998                                 }\r
999                                 else if(SizeOnce == SOCKET_ERROR)\r
1000                                 {\r
1001                                         SizeOnce = -1;\r
1002                                 }\r
1003                                 break;\r
1004                         }\r
1005 \r
1006                         /* LFを探して、あったらそこまでの長さをセット */\r
1007                         for(i = 0; i < SizeOnce ; i++)\r
1008                         {\r
1009                                 if(*(Tmp + i) == NUL || *(Tmp + i) == 0x0A)\r
1010                                 {\r
1011                                         SizeOnce = i + 1;\r
1012                                         break;\r
1013                                 }\r
1014                         }\r
1015 \r
1016                         /* 本受信 */\r
1017                         if((SizeOnce = do_recv(cSkt, Tmp, SizeOnce, 0, &TimeOutErr, CancelCheckWork)) <= 0)\r
1018                                 break;\r
1019 \r
1020                         CopySize = min1(Max, SizeOnce);\r
1021                         memcpy(Pos, Tmp, CopySize);\r
1022                         Pos += CopySize;\r
1023                         Max -= CopySize;\r
1024 \r
1025                         /* データがLFで終わっていたら1行終わり */\r
1026                         if(*(Tmp + SizeOnce - 1) == 0x0A)\r
1027                                 break;\r
1028                 }\r
1029                 *Pos = NUL;\r
1030 \r
1031                 if(SizeOnce <= 0)\r
1032                 {\r
1033                         ResCode = 429;\r
1034                         memset(Buf, 0, Max);\r
1035 \r
1036                         if((SizeOnce == -2) || (AskTransferNow() == YES))\r
1037                         // 転送中に全て中止を行うと不正なデータが得られる場合のバグ修正\r
1038                         // エラーの種類によっては無限ループとスタックオーバーフローの可能性あり\r
1039 //                              DisconnectSet();\r
1040                         {\r
1041                                 if(SizeOnce == -1)\r
1042                                         ReConnectTrnSkt(&cSkt);\r
1043                                 else\r
1044                                         DisconnectSet();\r
1045                         }\r
1046                 }\r
1047                 else\r
1048                 {\r
1049                         if(IsDigit(*Buf) && IsDigit(*(Buf+1)) && IsDigit(*(Buf+2)))\r
1050                         {\r
1051                                 memset(Tmp, NUL, 4);\r
1052                                 strncpy(Tmp, Buf, 3);\r
1053                                 ResCode = atoi(Tmp);\r
1054                         }\r
1055 \r
1056                         /* 末尾の CR,LF,スペースを取り除く */\r
1057                         while((i=strlen(Buf))>2 &&\r
1058                                   (Buf[i-1]==0x0a || Buf[i-1]==0x0d || Buf[i-1]==' '))\r
1059                                 Buf[i-1]=0;\r
1060                 }\r
1061         }\r
1062         return(ResCode);\r
1063 }\r
1064 \r
1065 \r
1066 /*----- 固定長データを受け取る ------------------------------------------------\r
1067 *\r
1068 *       Parameter\r
1069 *               SOCKET cSkt : コントロールソケット\r
1070 *               char *Buf : メッセージを受け取るバッファ\r
1071 *               int Size : バイト数\r
1072 *               int *CancelCheckWork : \r
1073 *\r
1074 *       Return Value\r
1075 *               int ステータス\r
1076 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1077 *----------------------------------------------------------------------------*/\r
1078 \r
1079 int ReadNchar(SOCKET cSkt, char *Buf, int Size, int *CancelCheckWork)\r
1080 {\r
1081 //      struct timeval Tout;\r
1082 //      struct timeval *ToutPtr;\r
1083 //      fd_set ReadFds;\r
1084 //      int i;\r
1085         int SizeOnce;\r
1086         int Sts;\r
1087         int TimeOutErr;\r
1088 \r
1089         Sts = FFFTP_FAIL;\r
1090         if(cSkt != INVALID_SOCKET)\r
1091         {\r
1092                 Sts = FFFTP_SUCCESS;\r
1093                 while(Size > 0)\r
1094                 {\r
1095 //                      FD_ZERO(&ReadFds);\r
1096 //                      FD_SET(cSkt, &ReadFds);\r
1097 //                      ToutPtr = NULL;\r
1098 //                      if(TimeOut != 0)\r
1099 //                      {\r
1100 //                              Tout.tv_sec = TimeOut;\r
1101 //                              Tout.tv_usec = 0;\r
1102 //                              ToutPtr = &Tout;\r
1103 //                      }\r
1104 //                      i = select(0, &ReadFds, NULL, NULL, ToutPtr);\r
1105 //                      if(i == SOCKET_ERROR)\r
1106 //                      {\r
1107 //                              ReportWSError("select", WSAGetLastError());\r
1108 //                              Sts = FFFTP_FAIL;\r
1109 //                              break;\r
1110 //                      }\r
1111 //                      else if(i == 0)\r
1112 //                      {\r
1113 //                              SetTaskMsg(MSGJPN243);\r
1114 //                              Sts = FFFTP_FAIL;\r
1115 //                              break;\r
1116 //                      }\r
1117 \r
1118                         if((SizeOnce = do_recv(cSkt, Buf, Size, 0, &TimeOutErr, CancelCheckWork)) <= 0)\r
1119                         {\r
1120                                 if(TimeOutErr == YES)\r
1121                                         SetTaskMsg(MSGJPN243);\r
1122                                 Sts = FFFTP_FAIL;\r
1123                                 break;\r
1124                         }\r
1125 \r
1126                         Buf += SizeOnce;\r
1127                         Size -= SizeOnce;\r
1128                 }\r
1129         }\r
1130 \r
1131         if(Sts == FFFTP_FAIL)\r
1132                 SetTaskMsg(MSGJPN244);\r
1133 \r
1134         return(Sts);\r
1135 }\r
1136 \r
1137 \r
1138 /*----- エラー文字列を取得 ----------------------------------------------------\r
1139 *\r
1140 *       Parameter\r
1141 *               UINT Error : エラー番号\r
1142 *\r
1143 *       Return Value\r
1144 *               char *エラー文字列\r
1145 *----------------------------------------------------------------------------*/\r
1146 \r
1147 char *ReturnWSError(UINT Error)\r
1148 {\r
1149         static char Msg[128];\r
1150         char *Str;\r
1151 \r
1152         switch(Error)\r
1153         {\r
1154                 case WSAVERNOTSUPPORTED:\r
1155                         Str = "version of WinSock not supported";\r
1156                         break;\r
1157 \r
1158                 case WSASYSNOTREADY:\r
1159                         Str = "WinSock not present or not responding";\r
1160                         break;\r
1161 \r
1162                 case WSAEINVAL:\r
1163                         Str = "app version not supported by DLL";\r
1164                         break;\r
1165 \r
1166                 case WSAHOST_NOT_FOUND:\r
1167                         Str = "Authoritive: Host not found";\r
1168                         break;\r
1169 \r
1170                 case WSATRY_AGAIN:\r
1171                         Str = "Non-authoritive: host not found or server failure";\r
1172                         break;\r
1173 \r
1174                 case WSANO_RECOVERY:\r
1175                         Str = "Non-recoverable: refused or not implemented";\r
1176                         break;\r
1177 \r
1178                 case WSANO_DATA:\r
1179                         Str = "Valid name, no data record for type";\r
1180                         break;\r
1181 \r
1182 #if 0\r
1183                 case WSANO_ADDRESS:\r
1184                         Str = "Valid name, no MX record";\r
1185                         break;\r
1186 #endif\r
1187 \r
1188                 case WSANOTINITIALISED:\r
1189                         Str = "WSA Startup not initialized";\r
1190                         break;\r
1191 \r
1192                 case WSAENETDOWN:\r
1193                         Str = "Network subsystem failed";\r
1194                         break;\r
1195 \r
1196                 case WSAEINPROGRESS:\r
1197                         Str = "Blocking operation in progress";\r
1198                         break;\r
1199 \r
1200                 case WSAEINTR:\r
1201                         Str = "Blocking call cancelled";\r
1202                         break;\r
1203 \r
1204                 case WSAEAFNOSUPPORT:\r
1205                         Str = "address family not supported";\r
1206                         break;\r
1207 \r
1208                 case WSAEMFILE:\r
1209                         Str = "no file descriptors available";\r
1210                         break;\r
1211 \r
1212                 case WSAENOBUFS:\r
1213                         Str = "no buffer space available";\r
1214                         break;\r
1215 \r
1216                 case WSAEPROTONOSUPPORT:\r
1217                         Str = "specified protocol not supported";\r
1218                         break;\r
1219 \r
1220                 case WSAEPROTOTYPE:\r
1221                         Str = "protocol wrong type for this socket";\r
1222                         break;\r
1223 \r
1224                 case WSAESOCKTNOSUPPORT:\r
1225                         Str = "socket type not supported for address family";\r
1226                         break;\r
1227 \r
1228                 case WSAENOTSOCK:\r
1229                         Str = "descriptor is not a socket";\r
1230                         break;\r
1231 \r
1232                 case WSAEWOULDBLOCK:\r
1233                         Str = "socket marked as non-blocking and SO_LINGER set not 0";\r
1234                         break;\r
1235 \r
1236                 case WSAEADDRINUSE:\r
1237                         Str = "address already in use";\r
1238                         break;\r
1239 \r
1240                 case WSAECONNABORTED:\r
1241                         Str = "connection aborted";\r
1242                         break;\r
1243 \r
1244                 case WSAECONNRESET:\r
1245                         Str = "connection reset";\r
1246                         break;\r
1247 \r
1248                 case WSAENOTCONN:\r
1249                         Str = "not connected";\r
1250                         break;\r
1251 \r
1252                 case WSAETIMEDOUT:\r
1253                         Str = "connection timed out";\r
1254                         break;\r
1255 \r
1256                 case WSAECONNREFUSED:\r
1257                         Str = "connection refused";\r
1258                         break;\r
1259 \r
1260                 case WSAEHOSTDOWN:\r
1261                         Str = "host down";\r
1262                         break;\r
1263 \r
1264                 case WSAEHOSTUNREACH:\r
1265                         Str = "host unreachable";\r
1266                         break;\r
1267 \r
1268                 case WSAEADDRNOTAVAIL:\r
1269                         Str = "address not available";\r
1270                         break;\r
1271 \r
1272                 default:\r
1273                         sprintf(Msg, "error %u", Error);\r
1274                         return(Msg);\r
1275         }\r
1276         return(Str);\r
1277 }\r
1278 \r
1279 \r
1280 /*----- デバッグコンソールにエラーを表示 --------------------------------------\r
1281 *\r
1282 *       Parameter\r
1283 *               char *Msg : エラーの前に表示するメッセージ\r
1284 *               UINT Error : エラー番号\r
1285 *\r
1286 *       Return Value\r
1287 *               なし\r
1288 *----------------------------------------------------------------------------*/\r
1289 \r
1290 void ReportWSError(char *Msg, UINT Error)\r
1291 {\r
1292         if(Msg != NULL)\r
1293                 DoPrintf("[[%s : %s]]", Msg, ReturnWSError(Error));\r
1294         else\r
1295                 DoPrintf("[[%s]]", ReturnWSError(Error));\r
1296 }\r
1297 \r
1298 \r
1299 /*----- ファイル名をローカル側で扱えるように変換する --------------------------\r
1300 *\r
1301 *       Parameter\r
1302 *               char *Fname : ファイル名\r
1303 *               int Max : 最大長\r
1304 *\r
1305 *       Return Value\r
1306 *               int ステータス\r
1307 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1308 *----------------------------------------------------------------------------*/\r
1309 \r
1310 int ChangeFnameRemote2Local(char *Fname, int Max)\r
1311 {\r
1312         int Sts;\r
1313         char *Buf;\r
1314         char *Pos;\r
1315         CODECONVINFO cInfo;\r
1316 \r
1317         Sts = FFFTP_FAIL;\r
1318         if((Buf = malloc(Max)) != NULL)\r
1319         {\r
1320                 InitCodeConvInfo(&cInfo);\r
1321                 cInfo.KanaCnv = NO;                     //AskHostNameKana();\r
1322                 cInfo.Str = Fname;\r
1323                 cInfo.StrLen = strlen(Fname);\r
1324                 cInfo.Buf = Buf;\r
1325                 cInfo.BufSize = Max - 1;\r
1326 \r
1327                 // ここで全てUTF-8へ変換する\r
1328                 // TODO: SJIS以外も直接UTF-8へ変換\r
1329                 switch(AskHostNameKanji())\r
1330                 {\r
1331                         case KANJI_SJIS :\r
1332                                 ConvSJIStoUTF8N(&cInfo);\r
1333                                 *(Buf + cInfo.OutLen) = NUL;\r
1334                                 strcpy(Fname, Buf);\r
1335                                 Pos = strchr(Fname, NUL);\r
1336                                 FlushRestData(&cInfo);\r
1337                                 *(Buf + cInfo.OutLen) = NUL;\r
1338                                 strcpy(Pos, Buf);\r
1339                                 break;\r
1340 \r
1341                         case KANJI_JIS :\r
1342                                 ConvJIStoSJIS(&cInfo);\r
1343                                 *(Buf + cInfo.OutLen) = NUL;\r
1344                                 strcpy(Fname, Buf);\r
1345                                 Pos = strchr(Fname, NUL);\r
1346                                 FlushRestData(&cInfo);\r
1347                                 *(Buf + cInfo.OutLen) = NUL;\r
1348                                 strcpy(Pos, Buf);\r
1349                                 // TODO\r
1350                                 InitCodeConvInfo(&cInfo);\r
1351                                 cInfo.KanaCnv = NO;\r
1352                                 cInfo.Str = Fname;\r
1353                                 cInfo.StrLen = strlen(Fname);\r
1354                                 cInfo.Buf = Buf;\r
1355                                 cInfo.BufSize = Max - 1;\r
1356                                 ConvSJIStoUTF8N(&cInfo);\r
1357                                 *(Buf + cInfo.OutLen) = NUL;\r
1358                                 strcpy(Fname, Buf);\r
1359                                 Pos = strchr(Fname, NUL);\r
1360                                 FlushRestData(&cInfo);\r
1361                                 *(Buf + cInfo.OutLen) = NUL;\r
1362                                 strcpy(Pos, Buf);\r
1363                                 break;\r
1364 \r
1365                         case KANJI_EUC :\r
1366                                 ConvEUCtoSJIS(&cInfo);\r
1367                                 *(Buf + cInfo.OutLen) = NUL;\r
1368                                 strcpy(Fname, Buf);\r
1369                                 Pos = strchr(Fname, NUL);\r
1370                                 FlushRestData(&cInfo);\r
1371                                 *(Buf + cInfo.OutLen) = NUL;\r
1372                                 strcpy(Pos, Buf);\r
1373                                 // TODO\r
1374                                 InitCodeConvInfo(&cInfo);\r
1375                                 cInfo.KanaCnv = NO;\r
1376                                 cInfo.Str = Fname;\r
1377                                 cInfo.StrLen = strlen(Fname);\r
1378                                 cInfo.Buf = Buf;\r
1379                                 cInfo.BufSize = Max - 1;\r
1380                                 ConvSJIStoUTF8N(&cInfo);\r
1381                                 *(Buf + cInfo.OutLen) = NUL;\r
1382                                 strcpy(Fname, Buf);\r
1383                                 Pos = strchr(Fname, NUL);\r
1384                                 FlushRestData(&cInfo);\r
1385                                 *(Buf + cInfo.OutLen) = NUL;\r
1386                                 strcpy(Pos, Buf);\r
1387                                 break;\r
1388 \r
1389                         case KANJI_SMB_HEX :\r
1390                         case KANJI_SMB_CAP :\r
1391                                 ConvSMBtoSJIS(&cInfo);\r
1392                                 *(Buf + cInfo.OutLen) = NUL;\r
1393                                 strcpy(Fname, Buf);\r
1394                                 Pos = strchr(Fname, NUL);\r
1395                                 FlushRestData(&cInfo);\r
1396                                 *(Buf + cInfo.OutLen) = NUL;\r
1397                                 strcpy(Pos, Buf);\r
1398                                 // TODO\r
1399                                 InitCodeConvInfo(&cInfo);\r
1400                                 cInfo.KanaCnv = NO;\r
1401                                 cInfo.Str = Fname;\r
1402                                 cInfo.StrLen = strlen(Fname);\r
1403                                 cInfo.Buf = Buf;\r
1404                                 cInfo.BufSize = Max - 1;\r
1405                                 ConvSJIStoUTF8N(&cInfo);\r
1406                                 *(Buf + cInfo.OutLen) = NUL;\r
1407                                 strcpy(Fname, Buf);\r
1408                                 Pos = strchr(Fname, NUL);\r
1409                                 FlushRestData(&cInfo);\r
1410                                 *(Buf + cInfo.OutLen) = NUL;\r
1411                                 strcpy(Pos, Buf);\r
1412                                 break;\r
1413 \r
1414 //                      case KANJI_UTF8N :\r
1415 //                              ConvUTF8NtoSJIS(&cInfo);\r
1416 //                              *(Buf + cInfo.OutLen) = NUL;\r
1417 //                              strcpy(Fname, Buf);\r
1418 //                              Pos = strchr(Fname, NUL);\r
1419 //                              FlushRestData(&cInfo);\r
1420 //                              *(Buf + cInfo.OutLen) = NUL;\r
1421 //                              strcpy(Pos, Buf);\r
1422 //                              break;\r
1423                 }\r
1424                 free(Buf);\r
1425                 Sts = FFFTP_SUCCESS;\r
1426         }\r
1427         return(Sts);\r
1428 }\r
1429 \r
1430 \r
1431 /*----- ファイル名をリモート側で扱えるように変換する --------------------------\r
1432 *\r
1433 *       Parameter\r
1434 *               char *Fname : ファイル名\r
1435 *               int Max : 最大長\r
1436 *\r
1437 *       Return Value\r
1438 *               int ステータス\r
1439 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1440 *----------------------------------------------------------------------------*/\r
1441 \r
1442 int ChangeFnameLocal2Remote(char *Fname, int Max)\r
1443 {\r
1444         int Sts;\r
1445         char *Buf;\r
1446         char *Pos;\r
1447         CODECONVINFO cInfo;\r
1448 \r
1449         Sts = FFFTP_FAIL;\r
1450         if((Buf = malloc(Max)) != NULL)\r
1451         {\r
1452                 InitCodeConvInfo(&cInfo);\r
1453                 cInfo.KanaCnv = AskHostNameKana();\r
1454                 cInfo.Str = Fname;\r
1455                 cInfo.StrLen = strlen(Fname);\r
1456                 cInfo.Buf = Buf;\r
1457                 cInfo.BufSize = Max - 1;\r
1458 \r
1459                 // ここで全てUTF-8から変換する\r
1460                 // TODO: SJIS以外も直接UTF-8から変換\r
1461                 switch(AskHostNameKanji())\r
1462                 {\r
1463                         case KANJI_SJIS :\r
1464                                 ConvUTF8NtoSJIS(&cInfo);\r
1465                                 *(Buf + cInfo.OutLen) = NUL;\r
1466                                 strcpy(Fname, Buf);\r
1467                                 Pos = strchr(Fname, NUL);\r
1468                                 FlushRestData(&cInfo);\r
1469                                 *(Buf + cInfo.OutLen) = NUL;\r
1470                                 strcpy(Pos, Buf);\r
1471                                 break;\r
1472 \r
1473                         case KANJI_JIS :\r
1474                                 ConvUTF8NtoSJIS(&cInfo);\r
1475                                 *(Buf + cInfo.OutLen) = NUL;\r
1476                                 strcpy(Fname, Buf);\r
1477                                 Pos = strchr(Fname, NUL);\r
1478                                 FlushRestData(&cInfo);\r
1479                                 *(Buf + cInfo.OutLen) = NUL;\r
1480                                 strcpy(Pos, Buf);\r
1481                                 // TODO\r
1482                                 InitCodeConvInfo(&cInfo);\r
1483                                 cInfo.KanaCnv = NO;\r
1484                                 cInfo.Str = Fname;\r
1485                                 cInfo.StrLen = strlen(Fname);\r
1486                                 cInfo.Buf = Buf;\r
1487                                 cInfo.BufSize = Max - 1;\r
1488                                 ConvSJIStoJIS(&cInfo);\r
1489                                 *(Buf + cInfo.OutLen) = NUL;\r
1490                                 strcpy(Fname, Buf);\r
1491                                 Pos = strchr(Fname, NUL);\r
1492                                 FlushRestData(&cInfo);\r
1493                                 *(Buf + cInfo.OutLen) = NUL;\r
1494                                 strcpy(Pos, Buf);\r
1495                                 break;\r
1496 \r
1497                         case KANJI_EUC :\r
1498                                 ConvUTF8NtoSJIS(&cInfo);\r
1499                                 *(Buf + cInfo.OutLen) = NUL;\r
1500                                 strcpy(Fname, Buf);\r
1501                                 Pos = strchr(Fname, NUL);\r
1502                                 FlushRestData(&cInfo);\r
1503                                 *(Buf + cInfo.OutLen) = NUL;\r
1504                                 strcpy(Pos, Buf);\r
1505                                 // TODO\r
1506                                 InitCodeConvInfo(&cInfo);\r
1507                                 cInfo.KanaCnv = NO;\r
1508                                 cInfo.Str = Fname;\r
1509                                 cInfo.StrLen = strlen(Fname);\r
1510                                 cInfo.Buf = Buf;\r
1511                                 cInfo.BufSize = Max - 1;\r
1512                                 ConvSJIStoEUC(&cInfo);\r
1513                                 *(Buf + cInfo.OutLen) = NUL;\r
1514                                 strcpy(Fname, Buf);\r
1515                                 Pos = strchr(Fname, NUL);\r
1516                                 FlushRestData(&cInfo);\r
1517                                 *(Buf + cInfo.OutLen) = NUL;\r
1518                                 strcpy(Pos, Buf);\r
1519                                 break;\r
1520 \r
1521                         case KANJI_SMB_HEX :\r
1522                                 ConvUTF8NtoSJIS(&cInfo);\r
1523                                 *(Buf + cInfo.OutLen) = NUL;\r
1524                                 strcpy(Fname, Buf);\r
1525                                 Pos = strchr(Fname, NUL);\r
1526                                 FlushRestData(&cInfo);\r
1527                                 *(Buf + cInfo.OutLen) = NUL;\r
1528                                 strcpy(Pos, Buf);\r
1529                                 // TODO\r
1530                                 InitCodeConvInfo(&cInfo);\r
1531                                 cInfo.KanaCnv = NO;\r
1532                                 cInfo.Str = Fname;\r
1533                                 cInfo.StrLen = strlen(Fname);\r
1534                                 cInfo.Buf = Buf;\r
1535                                 cInfo.BufSize = Max - 1;\r
1536                                 ConvSJIStoSMB_HEX(&cInfo);\r
1537                                 *(Buf + cInfo.OutLen) = NUL;\r
1538                                 strcpy(Fname, Buf);\r
1539                                 Pos = strchr(Fname, NUL);\r
1540                                 FlushRestData(&cInfo);\r
1541                                 *(Buf + cInfo.OutLen) = NUL;\r
1542                                 strcpy(Pos, Buf);\r
1543                                 break;\r
1544 \r
1545                         case KANJI_SMB_CAP :\r
1546                                 ConvUTF8NtoSJIS(&cInfo);\r
1547                                 *(Buf + cInfo.OutLen) = NUL;\r
1548                                 strcpy(Fname, Buf);\r
1549                                 Pos = strchr(Fname, NUL);\r
1550                                 FlushRestData(&cInfo);\r
1551                                 *(Buf + cInfo.OutLen) = NUL;\r
1552                                 strcpy(Pos, Buf);\r
1553                                 // TODO\r
1554                                 InitCodeConvInfo(&cInfo);\r
1555                                 cInfo.KanaCnv = NO;\r
1556                                 cInfo.Str = Fname;\r
1557                                 cInfo.StrLen = strlen(Fname);\r
1558                                 cInfo.Buf = Buf;\r
1559                                 cInfo.BufSize = Max - 1;\r
1560                                 ConvSJIStoSMB_CAP(&cInfo);\r
1561                                 *(Buf + cInfo.OutLen) = NUL;\r
1562                                 strcpy(Fname, Buf);\r
1563                                 Pos = strchr(Fname, NUL);\r
1564                                 FlushRestData(&cInfo);\r
1565                                 *(Buf + cInfo.OutLen) = NUL;\r
1566                                 strcpy(Pos, Buf);\r
1567                                 break;\r
1568 \r
1569 //                      case KANJI_UTF8N :\r
1570 //                              ConvSJIStoUTF8N(&cInfo);\r
1571 //                              *(Buf + cInfo.OutLen) = NUL;\r
1572 //                              strcpy(Fname, Buf);\r
1573 //                              Pos = strchr(Fname, NUL);\r
1574 //                              FlushRestData(&cInfo);\r
1575 //                              *(Buf + cInfo.OutLen) = NUL;\r
1576 //                              strcpy(Pos, Buf);\r
1577 //                              break;\r
1578                 }\r
1579                 free(Buf);\r
1580                 Sts = FFFTP_SUCCESS;\r
1581         }\r
1582         return(Sts);\r
1583 }\r
1584 \r
1585 \r
1586 /*----- パスの区切り文字をホストに合わせて変更する ----------------------------\r
1587 *\r
1588 *       Parameter\r
1589 *               char *Fname : ファイル名\r
1590 *\r
1591 *       Return Value\r
1592 *               なし\r
1593 *----------------------------------------------------------------------------*/\r
1594 static void ChangeSepaLocal2Remote(char *Fname)\r
1595 {\r
1596         if(AskHostType() == HTYPE_STRATUS)\r
1597         {\r
1598                 ReplaceAll(Fname, '/', '>');\r
1599         }\r
1600         return;\r
1601 }\r
1602 \r
1603 \r
1604 /*----- パスの区切り文字をローカルに合わせて変更する --------------------------\r
1605 *\r
1606 *       Parameter\r
1607 *               char *Fname : ファイル名\r
1608 *\r
1609 *       Return Value\r
1610 *               なし\r
1611 *----------------------------------------------------------------------------*/\r
1612 static void ChangeSepaRemote2Local(char *Fname)\r
1613 {\r
1614         if(AskHostType() == HTYPE_STRATUS)\r
1615         {\r
1616                 ReplaceAll(Fname, '>', '/');\r
1617         }\r
1618         return;\r
1619 }\r
1620 \r
1621 \r
1622 \r
1623 \r
1624 \r
1625 \r
1626 \r