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