cmddata.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419
  1. #include "rar.hpp"
  2. CommandData::CommandData()
  3. {
  4. FileArgs=ExclArgs=InclArgs=StoreArgs=ArcNames=NULL;
  5. Init();
  6. }
  7. CommandData::~CommandData()
  8. {
  9. Close();
  10. }
  11. void CommandData::Init()
  12. {
  13. RAROptions::Init();
  14. Close();
  15. *Command=0;
  16. *CommandW=0;
  17. *ArcName=0;
  18. *ArcNameW=0;
  19. FileLists=false;
  20. NoMoreSwitches=false;
  21. ListMode=RCLM_AUTO;
  22. FileArgs=new StringList;
  23. ExclArgs=new StringList;
  24. InclArgs=new StringList;
  25. StoreArgs=new StringList;
  26. ArcNames=new StringList;
  27. }
  28. void CommandData::Close()
  29. {
  30. delete FileArgs;
  31. delete ExclArgs;
  32. delete InclArgs;
  33. delete StoreArgs;
  34. delete ArcNames;
  35. FileArgs=ExclArgs=InclArgs=StoreArgs=ArcNames=NULL;
  36. NextVolSizes.Reset();
  37. }
  38. #ifdef CUSTOM_CMDLINE_PARSER
  39. // Return the pointer to next position in the string and store dynamically
  40. // allocated command line parameters in Unicode and ASCII in ParW and ParA.
  41. static const wchar *AllocCmdParam(const wchar *CmdLine,wchar **ParW,char **ParA)
  42. {
  43. const wchar *NextCmd=GetCmdParam(CmdLine,NULL,0);
  44. if (NextCmd==NULL)
  45. return NULL;
  46. size_t ParSize=NextCmd-CmdLine+2; // Parameter size including the trailing zero.
  47. *ParW=(wchar *)malloc(ParSize*sizeof(wchar));
  48. if (*ParW==NULL)
  49. return NULL;
  50. CmdLine=GetCmdParam(CmdLine,*ParW,ParSize);
  51. size_t ParSizeA=ParSize*2; // One Unicode char can be converted to several MBCS chars.
  52. *ParA=(char *)malloc(ParSizeA);
  53. if (*ParA==NULL)
  54. {
  55. free(*ParW);
  56. return NULL;
  57. }
  58. GetAsciiName(*ParW,*ParA,ParSizeA);
  59. return CmdLine;
  60. }
  61. #endif
  62. #ifndef SFX_MODULE
  63. void CommandData::PreprocessCommandLine(int argc, char *argv[])
  64. {
  65. #ifdef CUSTOM_CMDLINE_PARSER
  66. // In Windows we may prefer to implement our own command line parser
  67. // to avoid replacing \" by " in standard parser. Such replacing corrupts
  68. // destination paths like "dest path\" in extraction commands.
  69. const wchar *CmdLine=GetCommandLine();
  70. wchar *ParW;
  71. char *ParA;
  72. for (bool FirstParam=true;;FirstParam=false)
  73. {
  74. if ((CmdLine=AllocCmdParam(CmdLine,&ParW,&ParA))==NULL)
  75. break;
  76. bool Code=FirstParam ? true:PreprocessSwitch(ParA);
  77. free(ParW);
  78. free(ParA);
  79. if (!Code)
  80. break;
  81. }
  82. #else
  83. for (int I=1;I<argc;I++)
  84. if (!PreprocessSwitch(argv[I]))
  85. break;
  86. #endif
  87. }
  88. #endif
  89. #ifndef SFX_MODULE
  90. void CommandData::ParseCommandLine(int argc, char *argv[])
  91. {
  92. #ifdef CUSTOM_CMDLINE_PARSER
  93. // In Windows we may prefer to implement our own command line parser
  94. // to avoid replacing \" by " in standard parser. Such replacing corrupts
  95. // destination paths like "dest path\" in extraction commands.
  96. const wchar *CmdLine=GetCommandLine();
  97. wchar *ParW;
  98. char *ParA;
  99. for (bool FirstParam=true;;FirstParam=false)
  100. {
  101. if ((CmdLine=AllocCmdParam(CmdLine,&ParW,&ParA))==NULL)
  102. break;
  103. if (!FirstParam) // First parameter is the executable name.
  104. ParseArg(ParA,ParW);
  105. free(ParW);
  106. free(ParA);
  107. }
  108. #else
  109. for (int I=1;I<argc;I++)
  110. ParseArg(argv[I],NULL);
  111. #endif
  112. ParseDone();
  113. }
  114. #endif
  115. #ifndef SFX_MODULE
  116. void CommandData::ParseArg(char *Arg,wchar *ArgW)
  117. {
  118. if (IsSwitch(*Arg) && !NoMoreSwitches)
  119. if (Arg[1]=='-')
  120. NoMoreSwitches=true;
  121. else
  122. ProcessSwitch(Arg+1,(ArgW!=NULL && *ArgW!=0 ? ArgW+1:NULL));
  123. else
  124. if (*Command==0)
  125. {
  126. strncpyz(Command,Arg,ASIZE(Command));
  127. if (ArgW!=NULL)
  128. wcsncpy(CommandW,ArgW,ASIZE(CommandW));
  129. #ifndef GUI
  130. *Command=etoupper(*Command);
  131. // 'I' and 'S' commands can contain case sensitive strings after
  132. // the first character, so we must not modify their case.
  133. // 'S' can contain SFX name, which case is important in Unix.
  134. if (*Command!='I' && *Command!='S')
  135. strupper(Command);
  136. #endif
  137. }
  138. else
  139. if (*ArcName==0 && *ArcNameW==0)
  140. {
  141. strncpyz(ArcName,Arg,ASIZE(ArcName));
  142. if (ArgW!=NULL)
  143. wcsncpyz(ArcNameW,ArgW,ASIZE(ArcNameW));
  144. }
  145. else
  146. {
  147. bool EndSeparator; // If last character is the path separator.
  148. if (ArgW!=NULL)
  149. {
  150. size_t Length=wcslen(ArgW);
  151. wchar EndChar=Length==0 ? 0:ArgW[Length-1];
  152. EndSeparator=IsDriveDiv(EndChar) || IsPathDiv(EndChar);
  153. }
  154. else
  155. {
  156. size_t Length=strlen(Arg);
  157. char EndChar=Length==0 ? 0:Arg[Length-1];
  158. EndSeparator=IsDriveDiv(EndChar) || IsPathDiv(EndChar);
  159. }
  160. char CmdChar=etoupper(*Command);
  161. bool Add=strchr("AFUM",CmdChar)!=NULL;
  162. bool Extract=CmdChar=='X' || CmdChar=='E';
  163. if (EndSeparator && !Add)
  164. {
  165. strncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
  166. if (ArgW!=NULL)
  167. wcsncpyz(ExtrPathW,ArgW,ASIZE(ExtrPathW));
  168. }
  169. else
  170. if ((Add || CmdChar=='T') && (*Arg!='@' || ListMode==RCLM_REJECT_LISTS))
  171. FileArgs->AddString(Arg,ArgW);
  172. else
  173. {
  174. FindData FileData;
  175. bool Found=FindFile::FastFind(Arg,ArgW,&FileData);
  176. if ((!Found || ListMode==RCLM_ACCEPT_LISTS) &&
  177. ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg,ArgW))
  178. {
  179. FileLists=true;
  180. RAR_CHARSET Charset=FilelistCharset;
  181. #if defined(_WIN_ALL) && !defined(GUI)
  182. // for compatibility reasons we use OEM encoding
  183. // in Win32 console version by default
  184. if (Charset==RCH_DEFAULT)
  185. Charset=RCH_OEM;
  186. #endif
  187. wchar *WideArgName=(ArgW!=NULL && *ArgW!=0 ? ArgW+1:NULL);
  188. ReadTextFile(Arg+1,WideArgName,FileArgs,false,true,Charset,true,true,true);
  189. }
  190. else
  191. if (Found && FileData.IsDir && Extract && *ExtrPath==0 && *ExtrPathW==0)
  192. {
  193. strncpyz(ExtrPath,Arg,ASIZE(ExtrPath)-1);
  194. AddEndSlash(ExtrPath);
  195. if (ArgW!=NULL)
  196. {
  197. wcsncpyz(ExtrPathW,ArgW,ASIZE(ExtrPathW)-1);
  198. AddEndSlash(ExtrPathW);
  199. }
  200. }
  201. else
  202. FileArgs->AddString(Arg,ArgW);
  203. }
  204. }
  205. }
  206. #endif
  207. void CommandData::ParseDone()
  208. {
  209. if (FileArgs->ItemsCount()==0 && !FileLists)
  210. FileArgs->AddString(MASKALL);
  211. char CmdChar=etoupper(*Command);
  212. bool Extract=CmdChar=='X' || CmdChar=='E' || CmdChar=='P';
  213. if (Test && Extract)
  214. Test=false; // Switch '-t' is senseless for 'X', 'E', 'P' commands.
  215. BareOutput=(CmdChar=='L' || CmdChar=='V') && Command[1]=='B';
  216. }
  217. #if !defined(SFX_MODULE) && !defined(_WIN_CE)
  218. void CommandData::ParseEnvVar()
  219. {
  220. char *EnvStr=getenv("RAR");
  221. if (EnvStr!=NULL)
  222. ProcessSwitchesString(EnvStr);
  223. }
  224. #endif
  225. #ifndef SFX_MODULE
  226. // Preprocess those parameters, which must be processed before the rest of
  227. // command line. Return 'false' to stop further processing.
  228. bool CommandData::PreprocessSwitch(const char *Switch)
  229. {
  230. if (IsSwitch(Switch[0]))
  231. {
  232. Switch++;
  233. if (stricomp(Switch,"-")==0) // Switch "--".
  234. return false;
  235. if (stricomp(Switch,"cfg-")==0)
  236. ConfigDisabled=true;
  237. #ifndef GUI
  238. if (strnicomp(Switch,"ilog",4)==0)
  239. {
  240. // Ensure that correct log file name is already set
  241. // if we need to report an error when processing the command line.
  242. ProcessSwitch(Switch);
  243. InitLogOptions(LogName);
  244. }
  245. #endif
  246. if (strnicomp(Switch,"sc",2)==0)
  247. {
  248. // Process -sc before reading any file lists.
  249. ProcessSwitch(Switch);
  250. }
  251. }
  252. return true;
  253. }
  254. #endif
  255. #if !defined(GUI) && !defined(SFX_MODULE)
  256. void CommandData::ReadConfig()
  257. {
  258. StringList List;
  259. if (ReadTextFile(DefConfigName,NULL,&List,true))
  260. {
  261. char *Str;
  262. while ((Str=List.GetString())!=NULL)
  263. {
  264. while (IsSpace(*Str))
  265. Str++;
  266. if (strnicomp(Str,"switches=",9)==0)
  267. ProcessSwitchesString(Str+9);
  268. }
  269. }
  270. }
  271. #endif
  272. #if !defined(SFX_MODULE) && !defined(_WIN_CE)
  273. void CommandData::ProcessSwitchesString(char *Str)
  274. {
  275. while (*Str)
  276. {
  277. while (!IsSwitch(*Str) && *Str!=0)
  278. Str++;
  279. if (*Str==0)
  280. break;
  281. char *Next=Str;
  282. while (!(Next[0]==' ' && IsSwitch(Next[1])) && *Next!=0)
  283. Next++;
  284. char NextChar=*Next;
  285. *Next=0;
  286. ProcessSwitch(Str+1);
  287. *Next=NextChar;
  288. Str=Next;
  289. }
  290. }
  291. #endif
  292. #if !defined(SFX_MODULE)
  293. void CommandData::ProcessSwitch(const char *Switch,const wchar *SwitchW)
  294. {
  295. bool WidePresent=SwitchW!=NULL && *SwitchW!=0; // If 'true', SwitchW is not empty.
  296. switch(etoupper(Switch[0]))
  297. {
  298. case '@':
  299. ListMode=Switch[1]=='+' ? RCLM_ACCEPT_LISTS:RCLM_REJECT_LISTS;
  300. break;
  301. case 'I':
  302. if (strnicomp(&Switch[1],"LOG",3)==0)
  303. {
  304. strncpyz(LogName,Switch[4] ? Switch+4:DefLogName,ASIZE(LogName));
  305. break;
  306. }
  307. if (stricomp(&Switch[1],"SND")==0)
  308. {
  309. Sound=true;
  310. break;
  311. }
  312. if (stricomp(&Switch[1],"ERR")==0)
  313. {
  314. MsgStream=MSG_STDERR;
  315. break;
  316. }
  317. if (strnicomp(&Switch[1],"EML",3)==0)
  318. {
  319. strncpyz(EmailTo,Switch[4] ? Switch+4:"@",ASIZE(EmailTo));
  320. EmailTo[sizeof(EmailTo)-1]=0;
  321. break;
  322. }
  323. if (stricomp(&Switch[1],"NUL")==0)
  324. {
  325. MsgStream=MSG_NULL;
  326. break;
  327. }
  328. if (etoupper(Switch[1])=='D')
  329. {
  330. for (int I=2;Switch[I]!=0;I++)
  331. switch(etoupper(Switch[I]))
  332. {
  333. case 'Q':
  334. MsgStream=MSG_ERRONLY;
  335. break;
  336. case 'C':
  337. DisableCopyright=true;
  338. break;
  339. case 'D':
  340. DisableDone=true;
  341. break;
  342. case 'P':
  343. DisablePercentage=true;
  344. break;
  345. }
  346. break;
  347. }
  348. if (stricomp(&Switch[1],"OFF")==0)
  349. {
  350. Shutdown=true;
  351. break;
  352. }
  353. break;
  354. case 'T':
  355. switch(etoupper(Switch[1]))
  356. {
  357. case 'K':
  358. ArcTime=ARCTIME_KEEP;
  359. break;
  360. case 'L':
  361. ArcTime=ARCTIME_LATEST;
  362. break;
  363. case 'O':
  364. FileTimeBefore.SetAgeText(Switch+2);
  365. break;
  366. case 'N':
  367. FileTimeAfter.SetAgeText(Switch+2);
  368. break;
  369. case 'B':
  370. FileTimeBefore.SetIsoText(Switch+2);
  371. break;
  372. case 'A':
  373. FileTimeAfter.SetIsoText(Switch+2);
  374. break;
  375. case 'S':
  376. {
  377. EXTTIME_MODE Mode=EXTTIME_HIGH3;
  378. bool CommonMode=Switch[2]>='0' && Switch[2]<='4';
  379. if (CommonMode)
  380. Mode=(EXTTIME_MODE)(Switch[2]-'0');
  381. if (Switch[2]=='-')
  382. Mode=EXTTIME_NONE;
  383. if (CommonMode || Switch[2]=='-' || Switch[2]=='+' || Switch[2]==0)
  384. xmtime=xctime=xatime=Mode;
  385. else
  386. {
  387. if (Switch[3]>='0' && Switch[3]<='4')
  388. Mode=(EXTTIME_MODE)(Switch[3]-'0');
  389. if (Switch[3]=='-')
  390. Mode=EXTTIME_NONE;
  391. switch(etoupper(Switch[2]))
  392. {
  393. case 'M':
  394. xmtime=Mode;
  395. break;
  396. case 'C':
  397. xctime=Mode;
  398. break;
  399. case 'A':
  400. xatime=Mode;
  401. break;
  402. case 'R':
  403. xarctime=Mode;
  404. break;
  405. }
  406. }
  407. }
  408. break;
  409. case '-':
  410. Test=false;
  411. break;
  412. case 0:
  413. Test=true;
  414. break;
  415. default:
  416. BadSwitch(Switch);
  417. break;
  418. }
  419. break;
  420. case 'A':
  421. switch(etoupper(Switch[1]))
  422. {
  423. case 'C':
  424. ClearArc=true;
  425. break;
  426. case 'D':
  427. AppendArcNameToPath=true;
  428. break;
  429. #ifndef SFX_MODULE
  430. case 'G':
  431. if (Switch[2]=='-' && Switch[3]==0)
  432. GenerateArcName=0;
  433. else
  434. {
  435. GenerateArcName=true;
  436. strncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
  437. }
  438. break;
  439. #endif
  440. case 'I':
  441. IgnoreGeneralAttr=true;
  442. break;
  443. case 'N': // Reserved for archive name.
  444. break;
  445. case 'O':
  446. AddArcOnly=true;
  447. break;
  448. case 'P':
  449. strcpy(ArcPath,Switch+2);
  450. if (WidePresent)
  451. wcscpy(ArcPathW,SwitchW+2);
  452. break;
  453. case 'S':
  454. SyncFiles=true;
  455. break;
  456. default:
  457. BadSwitch(Switch);
  458. break;
  459. }
  460. break;
  461. case 'D':
  462. if (Switch[2]==0)
  463. switch(etoupper(Switch[1]))
  464. {
  465. case 'S':
  466. DisableSortSolid=true;
  467. break;
  468. case 'H':
  469. OpenShared=true;
  470. break;
  471. case 'F':
  472. DeleteFiles=true;
  473. break;
  474. }
  475. break;
  476. case 'O':
  477. switch(etoupper(Switch[1]))
  478. {
  479. case '+':
  480. Overwrite=OVERWRITE_ALL;
  481. break;
  482. case '-':
  483. Overwrite=OVERWRITE_NONE;
  484. break;
  485. case 0:
  486. Overwrite=OVERWRITE_FORCE_ASK;
  487. break;
  488. case 'R':
  489. Overwrite=OVERWRITE_AUTORENAME;
  490. break;
  491. case 'W':
  492. ProcessOwners=true;
  493. break;
  494. #ifdef SAVE_LINKS
  495. case 'L':
  496. SaveLinks=true;
  497. break;
  498. #endif
  499. #ifdef _WIN_ALL
  500. case 'S':
  501. SaveStreams=true;
  502. break;
  503. case 'C':
  504. SetCompressedAttr=true;
  505. break;
  506. #endif
  507. default :
  508. BadSwitch(Switch);
  509. break;
  510. }
  511. break;
  512. case 'R':
  513. switch(etoupper(Switch[1]))
  514. {
  515. case 0:
  516. Recurse=RECURSE_ALWAYS;
  517. break;
  518. case '-':
  519. Recurse=RECURSE_DISABLE;
  520. break;
  521. case '0':
  522. Recurse=RECURSE_WILDCARDS;
  523. break;
  524. #ifndef _WIN_CE
  525. case 'I':
  526. {
  527. Priority=atoi(Switch+2);
  528. const char *ChPtr=strchr(Switch+2,':');
  529. if (ChPtr!=NULL)
  530. {
  531. SleepTime=atoi(ChPtr+1);
  532. InitSystemOptions(SleepTime);
  533. }
  534. SetPriority(Priority);
  535. }
  536. break;
  537. #endif
  538. }
  539. break;
  540. case 'Y':
  541. AllYes=true;
  542. break;
  543. case 'N':
  544. case 'X':
  545. if (Switch[1]!=0)
  546. {
  547. StringList *Args=etoupper(Switch[0])=='N' ? InclArgs:ExclArgs;
  548. if (Switch[1]=='@' && !IsWildcard(Switch))
  549. {
  550. RAR_CHARSET Charset=FilelistCharset;
  551. #if defined(_WIN_ALL) && !defined(GUI)
  552. // for compatibility reasons we use OEM encoding
  553. // in Win32 console version by default
  554. if (Charset==RCH_DEFAULT)
  555. Charset=RCH_OEM;
  556. #endif
  557. ReadTextFile(Switch+2,NULL,Args,false,true,Charset,true,true,true);
  558. }
  559. else
  560. Args->AddString(Switch+1);
  561. }
  562. break;
  563. case 'E':
  564. switch(etoupper(Switch[1]))
  565. {
  566. case 'P':
  567. switch(Switch[2])
  568. {
  569. case 0:
  570. ExclPath=EXCL_SKIPWHOLEPATH;
  571. break;
  572. case '1':
  573. ExclPath=EXCL_BASEPATH;
  574. break;
  575. case '2':
  576. ExclPath=EXCL_SAVEFULLPATH;
  577. break;
  578. case '3':
  579. ExclPath=EXCL_ABSPATH;
  580. break;
  581. }
  582. break;
  583. case 'E':
  584. ProcessEA=false;
  585. break;
  586. case 'N':
  587. NoEndBlock=true;
  588. break;
  589. default:
  590. if (Switch[1]=='+')
  591. {
  592. InclFileAttr=GetExclAttr(&Switch[2]);
  593. InclAttrSet=true;
  594. }
  595. else
  596. ExclFileAttr=GetExclAttr(&Switch[1]);
  597. break;
  598. }
  599. break;
  600. case 'P':
  601. if (Switch[1]==0)
  602. {
  603. GetPassword(PASSWORD_GLOBAL,NULL,NULL,Password,ASIZE(Password));
  604. eprintf("\n");
  605. }
  606. else
  607. {
  608. CharToWide(Switch+1,Password,ASIZE(Password));
  609. Password[ASIZE(Password)-1]=0;
  610. }
  611. break;
  612. case 'H':
  613. if (etoupper(Switch[1])=='P')
  614. {
  615. EncryptHeaders=true;
  616. if (Switch[2]!=0)
  617. {
  618. CharToWide(Switch+2,Password,ASIZE(Password));
  619. Password[ASIZE(Password)-1]=0;
  620. }
  621. else
  622. if (*Password==0)
  623. {
  624. GetPassword(PASSWORD_GLOBAL,NULL,NULL,Password,ASIZE(Password));
  625. eprintf("\n");
  626. }
  627. }
  628. break;
  629. case 'Z':
  630. if (Switch[1]==0 && (!WidePresent || SwitchW[1]==0))
  631. {
  632. #ifndef GUI // stdin is not supported by WinRAR.
  633. // If comment file is not specified, we read data from stdin.
  634. strcpy(CommentFile,"stdin");
  635. #endif
  636. }
  637. else
  638. {
  639. strncpyz(CommentFile,Switch+1,ASIZE(CommentFile));
  640. if (WidePresent)
  641. wcsncpyz(CommentFileW,SwitchW+1,ASIZE(CommentFileW));
  642. }
  643. break;
  644. case 'M':
  645. switch(etoupper(Switch[1]))
  646. {
  647. case 'C':
  648. {
  649. const char *Str=Switch+2;
  650. if (*Str=='-')
  651. for (int I=0;I<sizeof(FilterModes)/sizeof(FilterModes[0]);I++)
  652. FilterModes[I].State=FILTER_DISABLE;
  653. else
  654. while (*Str)
  655. {
  656. int Param1=0,Param2=0;
  657. FilterState State=FILTER_AUTO;
  658. FilterType Type=FILTER_NONE;
  659. if (IsDigit(*Str))
  660. {
  661. Param1=atoi(Str);
  662. while (IsDigit(*Str))
  663. Str++;
  664. }
  665. if (*Str==':' && IsDigit(Str[1]))
  666. {
  667. Param2=atoi(++Str);
  668. while (IsDigit(*Str))
  669. Str++;
  670. }
  671. switch(etoupper(*(Str++)))
  672. {
  673. case 'T': Type=FILTER_PPM; break;
  674. case 'E': Type=FILTER_E8; break;
  675. case 'D': Type=FILTER_DELTA; break;
  676. case 'A': Type=FILTER_AUDIO; break;
  677. case 'C': Type=FILTER_RGB; break;
  678. case 'I': Type=FILTER_ITANIUM; break;
  679. case 'L': Type=FILTER_UPCASETOLOW; break;
  680. }
  681. if (*Str=='+' || *Str=='-')
  682. State=*(Str++)=='+' ? FILTER_FORCE:FILTER_DISABLE;
  683. FilterModes[Type].State=State;
  684. FilterModes[Type].Param1=Param1;
  685. FilterModes[Type].Param2=Param2;
  686. }
  687. }
  688. break;
  689. case 'M':
  690. break;
  691. case 'D':
  692. {
  693. if ((WinSize=atoi(&Switch[2]))==0)
  694. WinSize=0x10000<<(etoupper(Switch[2])-'A');
  695. else
  696. WinSize*=1024;
  697. if (!CheckWinSize())
  698. BadSwitch(Switch);
  699. }
  700. break;
  701. case 'S':
  702. {
  703. char StoreNames[1024];
  704. strncpyz(StoreNames,(Switch[2]==0 ? DefaultStoreList:Switch+2),ASIZE(StoreNames));
  705. char *Names=StoreNames;
  706. while (*Names!=0)
  707. {
  708. char *End=strchr(Names,';');
  709. if (End!=NULL)
  710. *End=0;
  711. if (*Names=='.')
  712. Names++;
  713. char Mask[NM];
  714. if (strpbrk(Names,"*?.")==NULL)
  715. sprintf(Mask,"*.%s",Names);
  716. else
  717. strcpy(Mask,Names);
  718. StoreArgs->AddString(Mask);
  719. if (End==NULL)
  720. break;
  721. Names=End+1;
  722. }
  723. }
  724. break;
  725. #ifdef PACK_SMP
  726. case 'T':
  727. Threads=atoi(Switch+2);
  728. if (Threads>16)
  729. BadSwitch(Switch);
  730. else
  731. {
  732. }
  733. break;
  734. #endif
  735. default:
  736. Method=Switch[1]-'0';
  737. if (Method>5 || Method<0)
  738. BadSwitch(Switch);
  739. break;
  740. }
  741. break;
  742. case 'V':
  743. switch(etoupper(Switch[1]))
  744. {
  745. case 'N':
  746. OldNumbering=true;
  747. break;
  748. case 'P':
  749. VolumePause=true;
  750. break;
  751. case 'E':
  752. if (etoupper(Switch[2])=='R')
  753. VersionControl=atoi(Switch+3)+1;
  754. break;
  755. case '-':
  756. VolSize=0;
  757. break;
  758. default:
  759. VolSize=INT64NDF; // UnRAR -v switch for list command.
  760. break;
  761. }
  762. break;
  763. case 'F':
  764. if (Switch[1]==0)
  765. FreshFiles=true;
  766. else
  767. BadSwitch(Switch);
  768. break;
  769. case 'U':
  770. if (Switch[1]==0)
  771. UpdateFiles=true;
  772. else
  773. BadSwitch(Switch);
  774. break;
  775. case 'W':
  776. strncpyz(TempPath,&Switch[1],ASIZE(TempPath));
  777. AddEndSlash(TempPath);
  778. break;
  779. case 'S':
  780. if (IsDigit(Switch[1]))
  781. {
  782. Solid|=SOLID_COUNT;
  783. SolidCount=atoi(&Switch[1]);
  784. }
  785. else
  786. switch(etoupper(Switch[1]))
  787. {
  788. case 0:
  789. Solid|=SOLID_NORMAL;
  790. break;
  791. case '-':
  792. Solid=SOLID_NONE;
  793. break;
  794. case 'E':
  795. Solid|=SOLID_FILEEXT;
  796. break;
  797. case 'V':
  798. Solid|=Switch[2]=='-' ? SOLID_VOLUME_DEPENDENT:SOLID_VOLUME_INDEPENDENT;
  799. break;
  800. case 'D':
  801. Solid|=SOLID_VOLUME_DEPENDENT;
  802. break;
  803. case 'L':
  804. if (IsDigit(Switch[2]))
  805. FileSizeLess=atoil(Switch+2);
  806. break;
  807. case 'M':
  808. if (IsDigit(Switch[2]))
  809. FileSizeMore=atoil(Switch+2);
  810. break;
  811. case 'C':
  812. {
  813. // Switch is already found bad, avoid reporting it several times.
  814. bool AlreadyBad=false;
  815. RAR_CHARSET rch=RCH_DEFAULT;
  816. switch(etoupper(Switch[2]))
  817. {
  818. case 'A':
  819. rch=RCH_ANSI;
  820. break;
  821. case 'O':
  822. rch=RCH_OEM;
  823. break;
  824. case 'U':
  825. rch=RCH_UNICODE;
  826. break;
  827. default :
  828. BadSwitch(Switch);
  829. AlreadyBad=true;
  830. break;
  831. };
  832. if (!AlreadyBad)
  833. if (Switch[3]==0)
  834. CommentCharset=FilelistCharset=rch;
  835. else
  836. for (int I=3;Switch[I]!=0 && !AlreadyBad;I++)
  837. switch(etoupper(Switch[I]))
  838. {
  839. case 'C':
  840. CommentCharset=rch;
  841. break;
  842. case 'L':
  843. FilelistCharset=rch;
  844. break;
  845. default:
  846. BadSwitch(Switch);
  847. AlreadyBad=true;
  848. break;
  849. }
  850. }
  851. break;
  852. }
  853. break;
  854. case 'C':
  855. if (Switch[2]==0)
  856. switch(etoupper(Switch[1]))
  857. {
  858. case '-':
  859. DisableComment=true;
  860. break;
  861. case 'U':
  862. ConvertNames=NAMES_UPPERCASE;
  863. break;
  864. case 'L':
  865. ConvertNames=NAMES_LOWERCASE;
  866. break;
  867. }
  868. break;
  869. case 'K':
  870. switch(etoupper(Switch[1]))
  871. {
  872. case 'B':
  873. KeepBroken=true;
  874. break;
  875. case 0:
  876. Lock=true;
  877. break;
  878. }
  879. break;
  880. #ifndef GUI
  881. case '?' :
  882. OutHelp();
  883. break;
  884. #endif
  885. default :
  886. BadSwitch(Switch);
  887. break;
  888. }
  889. }
  890. #endif
  891. #ifndef SFX_MODULE
  892. void CommandData::BadSwitch(const char *Switch)
  893. {
  894. mprintf(St(MUnknownOption),Switch);
  895. ErrHandler.Exit(USER_ERROR);
  896. }
  897. #endif
  898. #ifndef GUI
  899. void CommandData::OutTitle()
  900. {
  901. if (BareOutput || DisableCopyright)
  902. return;
  903. #if defined(__GNUC__) && defined(SFX_MODULE)
  904. mprintf(St(MCopyrightS));
  905. #else
  906. #ifndef SILENT
  907. static bool TitleShown=false;
  908. if (TitleShown)
  909. return;
  910. TitleShown=true;
  911. char Version[50];
  912. int Beta=RARVER_BETA;
  913. if (Beta!=0)
  914. sprintf(Version,"%d.%02d %s %d",RARVER_MAJOR,RARVER_MINOR,St(MBeta),RARVER_BETA);
  915. else
  916. sprintf(Version,"%d.%02d",RARVER_MAJOR,RARVER_MINOR);
  917. #ifdef UNRAR
  918. mprintf(St(MUCopyright),Version,RARVER_YEAR);
  919. #else
  920. #endif
  921. #endif
  922. #endif
  923. }
  924. #endif
  925. inline bool CmpMSGID(MSGID i1,MSGID i2)
  926. {
  927. #ifdef MSGID_INT
  928. return(i1==i2);
  929. #else
  930. // If MSGID is const char*, we cannot compare pointers only.
  931. // Pointers to different instances of same strings can differ,
  932. // so we need to compare complete strings.
  933. return(strcmp(i1,i2)==0);
  934. #endif
  935. }
  936. void CommandData::OutHelp()
  937. {
  938. #if !defined(GUI) && !defined(SILENT)
  939. OutTitle();
  940. static MSGID Help[]={
  941. #ifdef SFX_MODULE
  942. // Console SFX switches definition.
  943. MCHelpCmd,MSHelpCmdE,MSHelpCmdT,MSHelpCmdV
  944. #elif defined(UNRAR)
  945. // UnRAR switches definition.
  946. MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL,
  947. MCHelpCmdP,MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm,
  948. MCHelpSwAT,MCHelpSwAC,MCHelpSwAD,MCHelpSwAG,MCHelpSwAI,MCHelpSwAP,
  949. MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,
  950. MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR,
  951. MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal,
  952. MCHelpSwO,MCHelpSwOC,MCHelpSwOR,MCHelpSwOW,MCHelpSwP,
  953. MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwSL,MCHelpSwSM,MCHelpSwTA,
  954. MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,MCHelpSwVUnr,
  955. MCHelpSwVER,MCHelpSwVP,MCHelpSwX,MCHelpSwXa,MCHelpSwXal,MCHelpSwY
  956. #else
  957. #endif
  958. };
  959. for (int I=0;I<sizeof(Help)/sizeof(Help[0]);I++)
  960. {
  961. #ifndef SFX_MODULE
  962. #ifdef DISABLEAUTODETECT
  963. if (Help[I]==MCHelpSwV)
  964. continue;
  965. #endif
  966. #ifndef _WIN_ALL
  967. static MSGID Win32Only[]={
  968. MCHelpSwIEML,MCHelpSwVD,MCHelpSwAO,MCHelpSwOS,MCHelpSwIOFF,
  969. MCHelpSwEP2,MCHelpSwOC,MCHelpSwDR,MCHelpSwRI
  970. };
  971. bool Found=false;
  972. for (int J=0;J<sizeof(Win32Only)/sizeof(Win32Only[0]);J++)
  973. if (CmpMSGID(Help[I],Win32Only[J]))
  974. {
  975. Found=true;
  976. break;
  977. }
  978. if (Found)
  979. continue;
  980. #endif
  981. #if !defined(_UNIX) && !defined(_WIN_ALL)
  982. if (CmpMSGID(Help[I],MCHelpSwOW))
  983. continue;
  984. #endif
  985. #if !defined(_WIN_ALL) && !defined(_EMX)
  986. if (CmpMSGID(Help[I],MCHelpSwAC))
  987. continue;
  988. #endif
  989. #ifndef SAVE_LINKS
  990. if (CmpMSGID(Help[I],MCHelpSwOL))
  991. continue;
  992. #endif
  993. #ifndef PACK_SMP
  994. if (CmpMSGID(Help[I],MCHelpSwMT))
  995. continue;
  996. #endif
  997. #ifndef _BEOS
  998. if (CmpMSGID(Help[I],MCHelpSwEE))
  999. {
  1000. #if defined(_EMX) && !defined(_DJGPP)
  1001. if (_osmode != OS2_MODE)
  1002. continue;
  1003. #else
  1004. continue;
  1005. #endif
  1006. }
  1007. #endif
  1008. #endif
  1009. mprintf(St(Help[I]));
  1010. }
  1011. mprintf("\n");
  1012. ErrHandler.Exit(USER_ERROR);
  1013. #endif
  1014. }
  1015. // Return 'true' if we need to exclude the file from processing as result
  1016. // of -x switch. If CheckInclList is true, we also check the file against
  1017. // the include list created with -n switch.
  1018. bool CommandData::ExclCheck(char *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList)
  1019. {
  1020. if (ExclCheckArgs(ExclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
  1021. return(true);
  1022. if (!CheckInclList || InclArgs->ItemsCount()==0)
  1023. return(false);
  1024. if (ExclCheckArgs(InclArgs,Dir,CheckName,false,MATCH_WILDSUBPATH))
  1025. return(false);
  1026. return(true);
  1027. }
  1028. bool CommandData::ExclCheckArgs(StringList *Args,bool Dir,char *CheckName,bool CheckFullPath,int MatchMode)
  1029. {
  1030. char *Name=ConvertPath(CheckName,NULL);
  1031. char FullName[NM];
  1032. char CurMask[NM+1]; // We reserve the space to append "*" to mask.
  1033. *FullName=0;
  1034. Args->Rewind();
  1035. while (Args->GetString(CurMask,ASIZE(CurMask)-1))
  1036. {
  1037. char *LastMaskChar=PointToLastChar(CurMask);
  1038. bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only.
  1039. if (Dir)
  1040. {
  1041. // CheckName is a directory.
  1042. if (DirMask)
  1043. {
  1044. // We process the directory and have the directory exclusion mask.
  1045. // So let's convert "mask\" to "mask" and process it normally.
  1046. *LastMaskChar=0;
  1047. }
  1048. else
  1049. {
  1050. // If mask has wildcards in name part and does not have the trailing
  1051. // '\' character, we cannot use it for directories.
  1052. if (IsWildcard(PointToName(CurMask)))
  1053. continue;
  1054. }
  1055. }
  1056. else
  1057. {
  1058. // If we process a file inside of directory excluded by "dirmask\".
  1059. // we want to exclude such file too. So we convert "dirmask\" to
  1060. // "dirmask\*". It is important for operations other than archiving.
  1061. // When archiving, directory matched by "dirmask\" is excluded
  1062. // from further scanning.
  1063. if (DirMask)
  1064. strcat(CurMask,"*");
  1065. }
  1066. #ifndef SFX_MODULE
  1067. if (CheckFullPath && IsFullPath(CurMask))
  1068. {
  1069. // We do not need to do the special "*\" processing here, because
  1070. // onlike the "else" part of this "if", now we convert names to full
  1071. // format, so they all include the path, which is matched by "*\"
  1072. // correctly. Moreover, removing "*\" from mask would break
  1073. // the comparison, because now all names have the path.
  1074. if (*FullName==0)
  1075. ConvertNameToFull(CheckName,FullName);
  1076. if (CmpName(CurMask,FullName,MatchMode))
  1077. return(true);
  1078. }
  1079. else
  1080. #endif
  1081. {
  1082. char NewName[NM+2],*CurName=Name;
  1083. if (CurMask[0]=='*' && IsPathDiv(CurMask[1]))
  1084. {
  1085. // We want "*\name" to match 'name' not only in subdirectories,
  1086. // but also in the current directory. We convert the name
  1087. // from 'name' to '.\name' to be matched by "*\" part even if it is
  1088. // in current directory.
  1089. NewName[0]='.';
  1090. NewName[1]=CPATHDIVIDER;
  1091. strncpyz(NewName+2,Name,ASIZE(NewName)-2);
  1092. CurName=NewName;
  1093. }
  1094. if (CmpName(ConvertPath(CurMask,NULL),CurName,MatchMode))
  1095. return(true);
  1096. }
  1097. }
  1098. return(false);
  1099. }
  1100. #ifndef SFX_MODULE
  1101. // Now this function performs only one task and only in Windows version:
  1102. // it skips symlinks to directories if -e1024 switch is specified.
  1103. // Symlinks are skipped in ScanTree class, so their entire contents
  1104. // is skipped too. Without this function we would check the attribute
  1105. // only directly before archiving, so we would skip the symlink record,
  1106. // but not the contents of symlinked directory.
  1107. bool CommandData::ExclDirByAttr(uint FileAttr)
  1108. {
  1109. #ifdef _WIN_ALL
  1110. if ((FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0 &&
  1111. (ExclFileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0)
  1112. return true;
  1113. #endif
  1114. return false;
  1115. }
  1116. #endif
  1117. #ifndef SFX_MODULE
  1118. // Return 'true' if we need to exclude the file from processing.
  1119. bool CommandData::TimeCheck(RarTime &ft)
  1120. {
  1121. if (FileTimeBefore.IsSet() && ft>=FileTimeBefore)
  1122. return(true);
  1123. if (FileTimeAfter.IsSet() && ft<=FileTimeAfter)
  1124. return(true);
  1125. return(false);
  1126. }
  1127. #endif
  1128. #ifndef SFX_MODULE
  1129. // Return 'true' if we need to exclude the file from processing.
  1130. bool CommandData::SizeCheck(int64 Size)
  1131. {
  1132. if (FileSizeLess!=INT64NDF && Size>=FileSizeLess)
  1133. return(true);
  1134. if (FileSizeMore!=INT64NDF && Size<=FileSizeMore)
  1135. return(true);
  1136. return(false);
  1137. }
  1138. #endif
  1139. int CommandData::IsProcessFile(FileHeader &NewLhd,bool *ExactMatch,int MatchType)
  1140. {
  1141. if (strlen(NewLhd.FileName)>=NM || wcslen(NewLhd.FileNameW)>=NM)
  1142. return(0);
  1143. bool Dir=(NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY;
  1144. if (ExclCheck(NewLhd.FileName,Dir,false,true))
  1145. return(0);
  1146. #ifndef SFX_MODULE
  1147. if (TimeCheck(NewLhd.mtime))
  1148. return(0);
  1149. if ((NewLhd.FileAttr & ExclFileAttr)!=0 || InclAttrSet && (NewLhd.FileAttr & InclFileAttr)==0)
  1150. return(0);
  1151. if (!Dir && SizeCheck(NewLhd.FullUnpSize))
  1152. return(0);
  1153. #endif
  1154. char *ArgName;
  1155. wchar *ArgNameW;
  1156. FileArgs->Rewind();
  1157. for (int StringCount=1;FileArgs->GetString(&ArgName,&ArgNameW);StringCount++)
  1158. {
  1159. #ifndef SFX_MODULE
  1160. bool Unicode=(NewLhd.Flags & LHD_UNICODE) || ArgNameW!=NULL && *ArgNameW!=0;
  1161. if (Unicode)
  1162. {
  1163. wchar NameW[NM],ArgW[NM],*NamePtr=NewLhd.FileNameW;
  1164. bool CorrectUnicode=true;
  1165. if (ArgNameW==NULL || *ArgNameW==0)
  1166. {
  1167. if (!CharToWide(ArgName,ArgW) || *ArgW==0)
  1168. CorrectUnicode=false;
  1169. ArgNameW=ArgW;
  1170. }
  1171. if ((NewLhd.Flags & LHD_UNICODE)==0)
  1172. {
  1173. if (!CharToWide(NewLhd.FileName,NameW) || *NameW==0)
  1174. CorrectUnicode=false;
  1175. NamePtr=NameW;
  1176. }
  1177. if (CmpName(ArgNameW,NamePtr,MatchType))
  1178. {
  1179. if (ExactMatch!=NULL)
  1180. *ExactMatch=wcsicompc(ArgNameW,NamePtr)==0;
  1181. return(StringCount);
  1182. }
  1183. if (CorrectUnicode)
  1184. continue;
  1185. }
  1186. #endif
  1187. if (CmpName(ArgName,NewLhd.FileName,MatchType))
  1188. {
  1189. if (ExactMatch!=NULL)
  1190. *ExactMatch=stricompc(ArgName,NewLhd.FileName)==0;
  1191. return(StringCount);
  1192. }
  1193. }
  1194. return(0);
  1195. }
  1196. #ifndef GUI
  1197. void CommandData::ProcessCommand()
  1198. {
  1199. #ifndef SFX_MODULE
  1200. const char *SingleCharCommands="FUADPXETK";
  1201. if (Command[0]!=0 && Command[1]!=0 && strchr(SingleCharCommands,*Command)!=NULL || *ArcName==0)
  1202. OutHelp();
  1203. #ifdef _UNIX
  1204. if (GetExt(ArcName)==NULL && (!FileExist(ArcName) || IsDir(GetFileAttr(ArcName))))
  1205. strncatz(ArcName,".rar",ASIZE(ArcName));
  1206. #else
  1207. if (GetExt(ArcName)==NULL)
  1208. strncatz(ArcName,".rar",ASIZE(ArcName));
  1209. #endif
  1210. if (strchr("AFUMD",*Command)==NULL)
  1211. {
  1212. if (GenerateArcName)
  1213. GenerateArchiveName(ArcName,ArcNameW,ASIZE(ArcName),GenerateMask,false);
  1214. StringList ArcMasks;
  1215. ArcMasks.AddString(ArcName);
  1216. ScanTree Scan(&ArcMasks,Recurse,SaveLinks,SCAN_SKIPDIRS);
  1217. FindData FindData;
  1218. while (Scan.GetNext(&FindData)==SCAN_SUCCESS)
  1219. AddArcName(FindData.Name,FindData.NameW);
  1220. }
  1221. else
  1222. AddArcName(ArcName,NULL);
  1223. #endif
  1224. switch(Command[0])
  1225. {
  1226. case 'P':
  1227. case 'X':
  1228. case 'E':
  1229. case 'T':
  1230. case 'I':
  1231. {
  1232. CmdExtract Extract;
  1233. Extract.DoExtract(this);
  1234. }
  1235. break;
  1236. #ifndef SILENT
  1237. case 'V':
  1238. case 'L':
  1239. ListArchive(this);
  1240. break;
  1241. default:
  1242. OutHelp();
  1243. #endif
  1244. }
  1245. if (!BareOutput)
  1246. mprintf("\n");
  1247. }
  1248. #endif
  1249. void CommandData::AddArcName(const char *Name,const wchar *NameW)
  1250. {
  1251. ArcNames->AddString(Name,NameW);
  1252. }
  1253. bool CommandData::GetArcName(char *Name,wchar *NameW,int MaxSize)
  1254. {
  1255. if (!ArcNames->GetString(Name,NameW,NM))
  1256. return(false);
  1257. return(true);
  1258. }
  1259. bool CommandData::IsSwitch(int Ch)
  1260. {
  1261. #if defined(_WIN_ALL) || defined(_EMX)
  1262. return(Ch=='-' || Ch=='/');
  1263. #else
  1264. return(Ch=='-');
  1265. #endif
  1266. }
  1267. #ifndef SFX_MODULE
  1268. uint CommandData::GetExclAttr(const char *Str)
  1269. {
  1270. if (IsDigit(*Str))
  1271. return(strtol(Str,NULL,0));
  1272. else
  1273. {
  1274. uint Attr;
  1275. for (Attr=0;*Str;Str++)
  1276. switch(etoupper(*Str))
  1277. {
  1278. #ifdef _UNIX
  1279. case 'D':
  1280. Attr|=S_IFDIR;
  1281. break;
  1282. case 'V':
  1283. Attr|=S_IFCHR;
  1284. break;
  1285. #elif defined(_WIN_ALL) || defined(_EMX)
  1286. case 'R':
  1287. Attr|=0x1;
  1288. break;
  1289. case 'H':
  1290. Attr|=0x2;
  1291. break;
  1292. case 'S':
  1293. Attr|=0x4;
  1294. break;
  1295. case 'D':
  1296. Attr|=0x10;
  1297. break;
  1298. case 'A':
  1299. Attr|=0x20;
  1300. break;
  1301. #endif
  1302. }
  1303. return(Attr);
  1304. }
  1305. }
  1306. #endif
  1307. #ifndef SFX_MODULE
  1308. bool CommandData::CheckWinSize()
  1309. {
  1310. static int ValidSize[]={
  1311. 0x10000,0x20000,0x40000,0x80000,0x100000,0x200000,0x400000
  1312. };
  1313. for (int I=0;I<sizeof(ValidSize)/sizeof(ValidSize[0]);I++)
  1314. if (WinSize==ValidSize[I])
  1315. return(true);
  1316. WinSize=0x400000;
  1317. return(false);
  1318. }
  1319. #endif