PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/ftp/Connect.cpp

https://bitbucket.org/regent/farmanager
C++ | 821 lines | 701 code | 116 blank | 4 comment | 108 complexity | 4219b9e95f695e29d59ee012cbc8bd83 MD5 | raw file
  1. #include <all_far.h>
  2. #pragma hdrstop
  3. #include "Int.h"
  4. cmd cmdtabdata[] =
  5. {
  6. /*00*/{ "account", 1, 1, 0 }, // [...]
  7. /*01*/{ "append", 1, 1, 2 }, // <local> [<remote>]
  8. /*02*/{ "ascii", 1, 1, 0 }, //
  9. /*03*/{ "binary", 1, 1, 0 }, //
  10. /*04*/{ "bye", 0, 0, 0 }, //
  11. /*05*/{ "cd", 1, 1, 1 }, // <path>
  12. /*06*/{ "cdup", 1, 1, 0 }, //
  13. /*07*/{ "chmod", 1, 1, 2 }, // <file> <mode>
  14. /*08*/{ "close", 1, 1, 0 }, //
  15. /*09*/{ "delete", 1, 1, 1 }, // <file>
  16. /*10*/{ "dir", 1, 1, 0 }, // [<path>]
  17. /*11*/{ "disconnect", 1, 1, 0 }, //
  18. /*12*/{ "get", 1, 1, 1 }, // <remote> [<local>]
  19. /*13*/{ "idle", 1, 1, 1 }, // <time>
  20. /*14*/{ "image", 1, 1, 0 }, //
  21. /*15*/{ "ls", 1, 1, 0 }, // [<path>]
  22. /*16*/{ "mkdir", 1, 1, 1 }, // <dir>
  23. /*17*/{ "modtime", 1, 1, 1 }, // <file> (get last modification time)
  24. /*18*/{ "newer", 1, 1, 1 }, // <remote> [<local>] (get files only if new)
  25. /*19*/{ "nlist", 1, 1, 0 }, // [<path>]
  26. /*20*/{ "open", 0, 1, 1 }, // <site> [<port> [<user> [<pwd>]]]
  27. /*21*/{ "proxy", 0, 1, 1 }, // <command> [<cmd params>] (exec cmd into proxy mode; tempror switch to proxy if not yet)
  28. /*22*/{ "sendport", 0, 0, 0 }, //
  29. /*23*/{ "put", 1, 1, 1 }, // <local> [<remote>]
  30. /*24*/{ "pwd", 1, 1, 0 }, //
  31. /*25*/{ "quit", 0, 0, 0 }, //
  32. /*26*/{ "quote", 1, 1, 1 }, // <command> [...]
  33. /*27*/{ "recv", 1, 1, 1 }, // <remote> [<local>]
  34. /*28*/{ "reget", 1, 1, 1 }, // <remote> [<local>]
  35. /*29*/{ "rstatus", 1, 1, 0 }, // [<command>]
  36. /*30*/{ "rhelp", 1, 1, 0 }, // [<command>]
  37. /*31*/{ "rename", 1, 1, 2 }, // <old name> <new name>
  38. /*32*/{ "reset", 1, 1, 0 }, // (read one server reply string)
  39. /*33*/{ "restart", 1, 1, 1 }, // <restart point> (set internal restart offset)
  40. /*34*/{ "rmdir", 1, 1, 1 }, // <dirname>
  41. /*35*/{ "runique", 0, 1, 0 }, // (set internal `runique` flag)
  42. /*36*/{ "send", 1, 1, 1 }, // <local> [<remote>]
  43. /*37*/{ "site", 1, 1, 1 }, // <command> [...]
  44. /*38*/{ "size", 1, 1, 1 }, // <file>
  45. /*39*/{ "system", 1, 1, 0 }, // (exec SYST command)
  46. /*40*/{ "sunique", 0, 1, 0 }, // (set internal `sunique` flag)
  47. /*41*/{ "user", 1, 1, 1 }, // <user> [<pwd>] [<account command>]
  48. /*42*/{ "umask", 1, 1, 1 }, // <umask>
  49. { 0 },
  50. };
  51. Connection::Connection()
  52. {
  53. cmdLineSize = 0;
  54. cmdSize = 0;
  55. CmdBuff = NULL;
  56. RplBuff = NULL;
  57. CmdMsg = NULL;
  58. cmdCount = 0;;
  59. *LastHost = 0;
  60. *LastMsg = 0;
  61. IOBuff = NULL;
  62. hIdle = NULL;
  63. memset(&proxstruct, 0, sizeof(proxstruct));
  64. memset(&tmpstruct, 0, sizeof(tmpstruct));
  65. brk_flag = FALSE;
  66. restart_point = 0;
  67. cin = 0;
  68. cout = 0;
  69. *hostname = 0;
  70. slrflag = 0;
  71. portnum = 0;
  72. sendport = 0;
  73. proxy = 0;
  74. proxflag = 0;
  75. sunique = 0;
  76. runique = 0;
  77. code = 0;
  78. *pasv = 0;
  79. altarg = NULL;
  80. stru = 0;
  81. *bytename=0;
  82. bytesize=0;
  83. stringbase = NULL;
  84. argbase = NULL;
  85. margc = 0;
  86. cpend = 0;
  87. mflag = 0;
  88. memset(ListCache,0,sizeof(ListCache));
  89. ListCachePos = 0;
  90. *UserName = 0;
  91. *UserPassword = 0;
  92. Output = NULL;
  93. OutputSize = 0;
  94. OutputPos = 0;
  95. LastUsedTableNum = 0;
  96. connected = 0;
  97. cmd_peer = 0;
  98. data_peer = 0;
  99. SocketError = 0;
  100. *SystemInfo = 0;
  101. SystemInfoFilled = 0;
  102. TableNum = 0;
  103. ErrorCode = 0;
  104. SysError = FALSE;
  105. Breakable = FALSE;
  106. *DirFile = 0;
  107. RetryCount = 0;
  108. TrafficInfo = NULL;
  109. CmdVisible = FALSE;
  110. ResumeSupport = FALSE;
  111. IOCallback = FALSE;
  112. LoginComplete = FALSE;
  113. SocketError = (int)INVALID_SOCKET;
  114. sendport = -1;
  115. cmd_peer = INVALID_SOCKET;
  116. data_peer = INVALID_SOCKET;
  117. LastUsedTableNum = 1;
  118. TrafficInfo = new FTPProgress;
  119. CurrentState = fcsNormal;
  120. Breakable = TRUE;
  121. Host.ServerType = FTP_TYPE_DETECT;
  122. }
  123. Connection::~Connection()
  124. {
  125. PROC(("Connection::~Connection","%p",this))
  126. int LastError = GetLastError();
  127. ResetOutput();
  128. CacheReset();
  129. AbortAllRequest(0);
  130. SetLastError(LastError);
  131. CloseIOBuff();
  132. delete TrafficInfo;
  133. CloseCmdBuff();
  134. }
  135. void Connection::ExecCmdTab(struct cmd *c,int argc,char *argv[])
  136. {
  137. PROC(("ExecCmdTab","%d [%s,%s,%s]",argc,(argc>=1)?argv[0]:"nil",(argc>=2)?argv[1]:"nil",(argc>=3)?argv[2]:"nil"));
  138. for(size_t I=0; I < ARRAYSIZE(cmdtabdata); I++)
  139. if(c==&cmdtabdata[I])
  140. {
  141. switch(I)
  142. {
  143. case 0:
  144. account(argc,argv);
  145. break;
  146. case 1:
  147. if(argc>2) argv[2] = FromOEMDup(argv[2]);
  148. put(argc,argv);
  149. break;
  150. case 2:
  151. setascii();
  152. break;
  153. case 3:
  154. setbinary();
  155. break;
  156. case 4:
  157. quit();
  158. break;
  159. case 5:
  160. argv[1] = FromOEMDup(argv[1]);
  161. cd(argc,argv);
  162. break;
  163. case 6:
  164. cdup();
  165. break;
  166. case 7:
  167. do_chmod(argc,argv);
  168. break;
  169. case 8:
  170. disconnect();
  171. break;
  172. case 9:
  173. argv[1] = FromOEMDup(argv[1]);
  174. deleteFile(argc,argv);
  175. break;
  176. case 10:
  177. if(argc > 1)
  178. argv[1] = FromOEMDup(argv[1]);
  179. ls(argc,argv);
  180. break;
  181. case 11:
  182. disconnect();
  183. break;
  184. case 12:
  185. argv[1] = FromOEMDup(argv[1]);
  186. get(argc,argv);
  187. break;
  188. case 13:
  189. idle(argc,argv);
  190. break;
  191. case 14:
  192. setbinary();
  193. break;
  194. case 15:
  195. if(argc>1) argv[1] = FromOEMDup(argv[1]);
  196. ls(argc,argv);
  197. break;
  198. case 16:
  199. argv[1] = FromOEMDup(argv[1]);
  200. makedir(argc,argv);
  201. break;
  202. case 17:
  203. modtime(argc,argv);
  204. break;
  205. case 18:
  206. newer(argc,argv);
  207. break;
  208. case 19:
  209. if(argc>1) argv[1] = FromOEMDup(argv[1]);
  210. ls(argc,argv);
  211. break;
  212. case 20:
  213. setpeer(argc,argv);
  214. break;
  215. case 21:
  216. doproxy(argc,argv);
  217. break;
  218. case 22:
  219. setport();
  220. break;
  221. case 23:
  222. if(argc>2) argv[2] = FromOEMDup(argv[2]);
  223. put(argc,argv);
  224. break;
  225. case 24:
  226. pwd();
  227. break;
  228. case 25:
  229. quit();
  230. break;
  231. case 26:
  232. quote(argc,argv);
  233. break;
  234. case 27:
  235. argv[1] = FromOEMDup(argv[1]);
  236. get(argc,argv);
  237. break;
  238. case 28:
  239. argv[1] = FromOEMDup(argv[1]);
  240. reget(argc,argv);
  241. break;
  242. case 29:
  243. rmtstatus(argc,argv);
  244. break;
  245. case 30:
  246. rmthelp(argc,argv);
  247. break;
  248. case 31:
  249. if(argc>1) argv[1] = FromOEMDup(argv[1]);
  250. if(argc>2) argv[2] = FromOEMDup(argv[2],1);
  251. renamefile(argc,argv);
  252. break;
  253. case 32:
  254. reset();
  255. break;
  256. case 33:
  257. restart(argc,argv);
  258. break;
  259. case 34:
  260. argv[1] = FromOEMDup(argv[1]);
  261. removedir(argc,argv);
  262. break;
  263. case 35:
  264. setrunique();
  265. break;
  266. case 36:
  267. if(argc>2) argv[2] = FromOEMDup(argv[2]);
  268. put(argc,argv);
  269. break;
  270. case 37:
  271. site(argc,argv);
  272. break;
  273. case 38:
  274. argv[1] = FromOEMDup(argv[1]);
  275. sizecmd(argc,argv);
  276. break;
  277. case 39:
  278. syst();
  279. break;
  280. case 40:
  281. setsunique();
  282. break;
  283. case 41:
  284. user(argc,argv);
  285. break;
  286. case 42:
  287. do_umask(argc,argv);
  288. break;
  289. }
  290. break;
  291. }
  292. }
  293. String Connection::SFromOEM(LPCSTR str)
  294. {
  295. String s(str);
  296. FromOEM(s);
  297. return s;
  298. }
  299. String Connection::SToOEM(LPCSTR str)
  300. {
  301. String s(str);
  302. ToOEM(s);
  303. return s;
  304. }
  305. char *Connection::FromOEMDup(LPCSTR str,int num)
  306. {
  307. static String nm[2];
  308. nm[num] = str;
  309. FromOEM(nm[num]);
  310. return nm[num].c_str();
  311. }
  312. char *Connection::ToOEMDup(LPCSTR str,int num)
  313. {
  314. static String nm[2];
  315. nm[num] = str;
  316. ToOEM(nm[num]);
  317. return nm[num].c_str();
  318. }
  319. void Connection::GetState(ConnectionState* p)
  320. {
  321. p->Inited = TRUE;
  322. p->Blocked = CmdVisible;
  323. p->RetryCount = RetryCount;
  324. p->TableNum = TableNum;
  325. p->Passive = Host.PassiveMode;
  326. p->Object = TrafficInfo->Object;
  327. TrafficInfo->Object = NULL;
  328. }
  329. void Connection::SetState(ConnectionState* p)
  330. {
  331. if(!p->Inited)
  332. return;
  333. CmdVisible = p->Blocked;
  334. RetryCount = p->RetryCount;
  335. TableNum = p->TableNum;
  336. Host.PassiveMode = p->Passive;
  337. TrafficInfo->Object = p->Object;
  338. TrafficInfo->SetConnection(this);
  339. }
  340. void Connection::InitData(FTPHost* p,int blocked /*=TRUE,FALSE,-1*/)
  341. {
  342. Host = *p;
  343. Host.Size = sizeof(Host);
  344. CmdVisible = TRUE;
  345. if(blocked != -1)
  346. CmdVisible = blocked == FALSE;
  347. }
  348. void Connection::AddOutput(BYTE *Data,int Size)
  349. {
  350. if(Size==0) return;
  351. BYTE *NewOutput=(BYTE*)realloc(Output,OutputSize+Size+1);
  352. if(NewOutput==NULL)
  353. {
  354. /*-*/Log(("!allocate output buffer %d",OutputSize+Size+1));
  355. return;
  356. }
  357. Output=NewOutput;
  358. memcpy(Output+OutputSize,Data,Size);
  359. OutputSize+=Size;
  360. }
  361. void Connection::GetOutput(String& s)
  362. {
  363. s.SetLength(0);
  364. if(OutputPos == 0)
  365. {
  366. if(Opt.LogOutput)
  367. {
  368. LogCmd(Message("--LISTING--(Current table: %d Last used: %d)--",TableNum,LastUsedTableNum), ldInt);
  369. LogCmd((LPCSTR)Output, ldRaw, OutputSize);
  370. LogCmd("--LISTING--", ldInt);
  371. }
  372. //ToOEM( Output,OutputSize );
  373. }
  374. while(OutputPos < OutputSize &&
  375. (Output[OutputPos]=='\n' || Output[OutputPos]=='\r'))
  376. OutputPos++;
  377. if(OutputPos >= OutputSize)
  378. return;
  379. while(OutputPos < OutputSize)
  380. {
  381. BOOL eol = Output[OutputPos] == '\n' || Output[OutputPos] == '\r';
  382. if(eol)
  383. {
  384. while(OutputPos < OutputSize && strchr("\n\r",Output[OutputPos]) != NULL)
  385. OutputPos++;
  386. if(Host.ServerType != FTP_TYPE_VMS)
  387. break;
  388. if(Output[OutputPos] != ' ')
  389. break;
  390. }
  391. s.Add((char)Output[OutputPos++]);
  392. }
  393. }
  394. void Connection::ResetOutput()
  395. {
  396. if(Output)
  397. free(Output);
  398. Output=NULL;
  399. OutputSize=0;
  400. OutputPos=0;
  401. }
  402. void Connection::CacheReset()
  403. {
  404. for(size_t I=0; I<ARRAYSIZE(ListCache); I++)
  405. {
  406. if(ListCache[I].Listing)
  407. free(ListCache[I].Listing);
  408. ListCache[I].Listing=NULL;
  409. ListCache[I].ListingSize=0;
  410. }
  411. ListCachePos=0;
  412. }
  413. int Connection::CacheGet()
  414. {
  415. if(DirFile[0])
  416. {
  417. HANDLE f = Fopen(DirFile,"r");
  418. if(f)
  419. {
  420. ResetOutput();
  421. OutputSize = (DWORD)Fsize(f);
  422. Output = (BYTE*)malloc(OutputSize+1);
  423. if(!Output)
  424. return FALSE;
  425. Fread(f, Output, OutputSize);
  426. Fclose(f);
  427. return TRUE;
  428. }
  429. }
  430. for(size_t I=0; I < ARRAYSIZE(ListCache); I++)
  431. if(ListCache[I].ListingSize > 0 &&
  432. CurDir.Cmp(ListCache[I].DirName))
  433. {
  434. ResetOutput();
  435. BYTE *NewOutput=(BYTE*)malloc(ListCache[I].ListingSize+1);
  436. if(NewOutput==NULL)
  437. return FALSE;
  438. Output = NewOutput;
  439. OutputSize = ListCache[I].ListingSize;
  440. memcpy(Output,ListCache[I].Listing,OutputSize);
  441. Output[OutputSize] = 0;
  442. return TRUE;
  443. }
  444. return FALSE;
  445. }
  446. void Connection::CacheAdd()
  447. {
  448. if(ListCache[ListCachePos].Listing)
  449. free(ListCache[ListCachePos].Listing);
  450. ListCache[ListCachePos].ListingSize = 0;
  451. ListCache[ListCachePos].Listing = (char*)malloc(OutputSize+1);
  452. if(ListCache[ListCachePos].Listing ==NULL)
  453. return;
  454. ListCache[ListCachePos].ListingSize = OutputSize;
  455. memcpy(ListCache[ListCachePos].Listing, Output, OutputSize);
  456. ListCache[ListCachePos].Listing[OutputSize] = 0;
  457. StrCpy(ListCache[ListCachePos].DirName, CurDir.c_str(), ARRAYSIZE(ListCache[ListCachePos].DirName));
  458. ListCachePos++;
  459. if(ListCachePos >= (int)(ARRAYSIZE(ListCache)))
  460. ListCachePos=0;
  461. }
  462. /* Returns if error happen
  463. */
  464. BOOL Connection::GetExitCode()
  465. {
  466. static struct
  467. {
  468. int Code;
  469. int WCode;
  470. } FtpErrCodes[] =
  471. {
  472. { 202, ERROR_CALL_NOT_IMPLEMENTED },
  473. { 421, ERROR_INTERNET_CONNECTION_ABORTED },
  474. { 451, 0 },
  475. { 450, ERROR_IO_INCOMPLETE },
  476. { 452, ERROR_DISK_FULL },
  477. { 500, ERROR_BAD_COMMAND },
  478. { 501, ERROR_BAD_COMMAND },
  479. { 502, ERROR_CALL_NOT_IMPLEMENTED },
  480. { 503, ERROR_BAD_COMMAND },
  481. { 504, ERROR_CALL_NOT_IMPLEMENTED },
  482. { 530, ERROR_INTERNET_LOGIN_FAILURE },
  483. { 532, ERROR_ACCESS_DENIED },
  484. { 550, ERROR_ACCESS_DENIED },
  485. { 551, 0 },
  486. { 552, ERROR_DISK_FULL },
  487. { 553, 0 }
  488. };
  489. if(ErrorCode != ERROR_SUCCESS)
  490. {
  491. SetLastError(ErrorCode);
  492. return FALSE;
  493. }
  494. if(code == RPL_ERROR ||
  495. code == RPL_TRANSFERERROR)
  496. {
  497. //SetLastError(ErrorCode);
  498. return FALSE;
  499. }
  500. for(size_t I=0; I < ARRAYSIZE(FtpErrCodes); I++)
  501. if(FtpErrCodes[I].Code == code)
  502. {
  503. if(FtpErrCodes[I].WCode)
  504. SetLastError(FtpErrCodes[I].WCode);
  505. return FALSE;
  506. }
  507. return TRUE;
  508. }
  509. int encode_UTF8(WCHAR *ws, int wsz, char *utf8s, int sz)
  510. {
  511. int i = 0, iw = 0;
  512. char *s;
  513. s = utf8s;
  514. while(iw<wsz && *ws && i<sz)
  515. {
  516. if(*ws <= 0x007F) /* 1 octet */
  517. {
  518. *s++ = (char)*ws;
  519. i++;
  520. }
  521. else if(*ws <= 0x07FF) /* 2 octets */
  522. {
  523. *s++ = 0xC0 | ((*ws >> 6) & 0x1F);
  524. *s++ = 0x80 | (*ws & 0x3F);
  525. i+=2;
  526. }
  527. else if(*ws <= 0xFFFF) /* 3 octets */
  528. {
  529. *s++ = 0xE0 | ((*ws >> 12) & 0x0F);
  530. *s++ = 0x80 | ((*ws >> 6) & 0x3F);
  531. *s++ = 0x80 | (*ws & 0x3F);
  532. i+=3;
  533. }
  534. else /* >= 4 octets -- not fit in UCS-2 */
  535. {
  536. *s++ = '_';
  537. i++;
  538. }
  539. ++ws;
  540. ++iw;
  541. }
  542. iw = i;
  543. while(iw < sz)
  544. {
  545. *s++ = 0;
  546. iw++;
  547. }
  548. return i;
  549. }
  550. int Connection::FromOEM(BYTE *Line,int _sz,int fsz)
  551. {
  552. CharTableSet TableSet;
  553. int TabNum = LastUsedTableNum;
  554. int sz = _sz;
  555. if(!Line || !sz) return 0;
  556. if(sz == -1)
  557. sz = static_cast<int>(strlen((char*)Line));
  558. else
  559. sz--;
  560. if(fsz == -1)
  561. fsz = sz;
  562. int ret = sz;
  563. if(TabNum == 2 ||
  564. TabNum > 3 && FP_Info->CharTable(TabNum-4,(char*)&TableSet,sizeof(TableSet)) == -1)
  565. {
  566. LogCmd(Message("Not working decode table %d used !!",TabNum), ldInt);
  567. TabNum = 1;
  568. }
  569. switch(TabNum)
  570. {
  571. case 0:
  572. OemToCharBuff((LPCSTR)Line, (char *)Line, sz);
  573. break;
  574. case 1:
  575. break;
  576. case 3:
  577. {
  578. WCHAR *tmp = (WCHAR *)malloc(sz*sizeof(WCHAR));
  579. MultiByteToWideChar(CP_OEMCP, 0, (LPCSTR)Line, sz, tmp, sz);
  580. ret = encode_UTF8(tmp, sz, (char *)Line, fsz);
  581. free(tmp);
  582. break;
  583. }
  584. default:
  585. for(int I=0; I < sz; I++)
  586. Line[I] = (BYTE)TableSet.EncodeTable[ Line[I] ];
  587. break;
  588. }
  589. return ret;
  590. }
  591. int decode_UTF8(unsigned char *utf8s, int sz, WCHAR *ws, int wsz)
  592. {
  593. int i = 0, iw = 0;
  594. WCHAR *wc;
  595. wc = ws;
  596. while(*utf8s && i<sz && iw<wsz)
  597. {
  598. if(!(*utf8s & 0x80))
  599. {
  600. *wc = *utf8s++; /* 1 octet */
  601. i++;
  602. }
  603. else if((*utf8s & 0xE0) == 0xC0) /* 2 octets */
  604. {
  605. *wc = (*utf8s++ & 0x1F) << 6; /* 1st */
  606. i++;
  607. if((*utf8s & 0xC0) == 0x80)
  608. {
  609. *wc |= *utf8s++ & 0x3F; /* 2nd */
  610. i++;
  611. }
  612. else
  613. *wc = *utf8s % 26 + 'a';
  614. }
  615. else if((*utf8s & 0xF0) == 0xE0) /* 3 octets */
  616. {
  617. *wc = (*utf8s++ & 0x0F) << 12; /* 1st */
  618. i++;
  619. if((*utf8s & 0xC0) == 0x80) /* 2nd */
  620. {
  621. *wc |= (*utf8s++ & 0x3F) << 6;
  622. i++;
  623. if((*utf8s & 0xC0) == 0x80)
  624. {
  625. *wc |= *utf8s++ & 0x3F; /* 3d */
  626. i++;
  627. }
  628. else
  629. *wc = *utf8s % 26 + 'a'; /* bad UTF-8 */
  630. }
  631. else *wc = *utf8s % 26 + 'a'; /* bad UTF-8 */
  632. }
  633. else if((*utf8s * 0xF0) == 0xF0) /* >= 4 octets -- not fit in UCS-2 */
  634. {
  635. ++utf8s;
  636. i++;
  637. while(*utf8s && ((*utf8s & 0xC0) == 0x80) && i<sz)
  638. {
  639. i++;
  640. ++utf8s;
  641. }
  642. *wc = '_';
  643. }
  644. else
  645. {
  646. *wc = *utf8s % 26 + 'a';
  647. ++utf8s;
  648. i++;
  649. }
  650. ++wc;
  651. iw++;
  652. }
  653. return iw;
  654. }
  655. int Connection::ToOEM(BYTE *Line,int _sz)
  656. {
  657. CharTableSet TableSet;
  658. int TabNum = TableNum;
  659. int sz = _sz;
  660. if(!Line || !sz) return 0;
  661. if(sz == -1)
  662. sz = static_cast<int>(strlen((char*)Line));
  663. else
  664. sz--;
  665. int ret = sz;
  666. if(TabNum > 3 && FP_Info->CharTable(TabNum-4,(char*)&TableSet,sizeof(TableSet)) == -1)
  667. {
  668. LogCmd(Message("Decode table set to %d, but does not exist. Switch to autodetect",TabNum), ldInt);
  669. TabNum = 2;
  670. }
  671. if(TabNum == 2)
  672. {
  673. TabNum = FP_Info->CharTable(FCT_DETECT,(char*)Line,sz);
  674. if(TabNum == -1 || FP_Info->CharTable(TabNum,(char*)&TableSet,sizeof(TableSet)) == -1)
  675. TabNum = 1;
  676. else
  677. TabNum = TabNum+4;
  678. LogCmd(Message("Autodetected table: %d",TabNum), ldInt);
  679. TableNum = TabNum;
  680. }
  681. switch(TabNum)
  682. {
  683. case 0:
  684. CharToOemBuff((LPCSTR)Line, (char *)Line, sz);
  685. break;
  686. case 1:
  687. break;
  688. case 3:
  689. {
  690. WCHAR *tmp = (WCHAR *)malloc(sz*sizeof(WCHAR));
  691. ret = decode_UTF8(Line, sz, tmp, sz);
  692. WideCharToMultiByte(CP_OEMCP, 0, tmp, ret, (LPSTR)Line, ret, NULL, NULL);
  693. for(int i=ret; i<sz; i++)
  694. Line[i] = 0;
  695. free(tmp);
  696. break;
  697. }
  698. default:
  699. for(int I=0; I < sz; I++)
  700. Line[I] = (BYTE)TableSet.DecodeTable[ Line[I] ];
  701. break;
  702. }
  703. LastUsedTableNum = TabNum;
  704. return ret;
  705. }