Merge pull request #4011 from fritsch/vdpau-settings
[vuplus_xbmc] / lib / UnrarXLib / pathfn.cpp
1 // THIS FILE IS MODIFIED TO WORK WITH XBMC
2
3 #include "rar.hpp"
4 #include "utils/URIUtils.h"
5
6 char* PointToName(const char *Path)
7 {
8   //const char *Found=NULL;
9   for (const char *s=&Path[strlen(Path)-1];s>=Path;s--)
10     if (IsPathDiv(*s))
11       return (char*)(s+1);
12 //  if (Found!=NULL)
13   //  return((char*)Found);
14   return (char*)((*Path && IsDriveDiv(Path[1]) && charnext(Path)==Path+1) ? Path+2:Path);
15 }
16
17 /*
18 Dumbass broken routine!!
19 Not searching in reverse to strip off filename portion of path!
20 {
21   const char *Found=NULL;
22   for (const char *s=Path;*s!=0;s=charnext(s))
23     if (IsPathDiv(*s))
24       Found=(char*)(s+1);
25   if (Found!=NULL)
26     return((char*)Found);
27   return (char*)((*Path && IsDriveDiv(Path[1]) && charnext(Path)==Path+1) ? Path+2:Path);
28 }
29 */
30
31 wchar* PointToName(const wchar *Path)
32 {
33   for (int I=strlenw(Path)-1;I>=0;I--)
34     if (IsPathDiv(Path[I]))
35       return (wchar*)&Path[I+1];
36   return (wchar*)((*Path && IsDriveDiv(Path[1])) ? Path+2:Path);
37 }
38
39
40 char* PointToLastChar(const char *Path)
41 {
42   for (const char *s=Path,*p=Path;;p=s,s=charnext(s))
43     if (*s==0)
44       return((char *)p);
45 }
46
47
48 char* ConvertPath(const char *SrcPath,char *DestPath)
49 {
50   const char *DestPtr=SrcPath;
51   for (const char *s=DestPtr;*s!=0;s++)
52     if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
53       DestPtr=s+4;
54   while (*DestPtr)
55   {
56     const char *s=DestPtr;
57     if (s[0] && IsDriveDiv(s[1]))
58       s+=2;
59     if (s[0]=='\\' && s[1]=='\\')
60     {
61       const char *Slash=strchr(s+2,'\\');
62       if (Slash!=NULL && (Slash=strchr(Slash+1,'\\'))!=NULL)
63         s=Slash+1;
64     }
65     for (const char *t=s;*t!=0;t++)
66       if (IsPathDiv(*t))
67         s=t+1;
68       else
69         if (*t!='.')
70           break;
71     if (s==DestPtr)
72       break;
73     DestPtr=s;
74   }
75   if (DestPath!=NULL)
76   {
77     char TmpStr[NM];
78     strncpy(TmpStr,DestPtr,sizeof(TmpStr)-1);
79     strcpy(DestPath,TmpStr);
80   }
81   return((char *)DestPtr);
82 }
83
84
85 wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
86 {
87   const wchar *DestPtr=SrcPath;
88   for (const wchar *s=DestPtr;*s!=0;s++)
89     if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
90       DestPtr=s+4;
91   while (*DestPtr)
92   {
93     const wchar *s=DestPtr;
94     if (s[0] && IsDriveDiv(s[1]))
95       s+=2;
96     if (s[0]=='\\' && s[1]=='\\')
97     {
98       const wchar *Slash=strchrw(s+2,'\\');
99       if (Slash!=NULL && (Slash=strchrw(Slash+1,'\\'))!=NULL)
100         s=Slash+1;
101     }
102     for (const wchar *t=s;*t!=0;t++)
103       if (IsPathDiv(*t))
104         s=t+1;
105       else
106         if (*t!='.')
107           break;
108     if (s==DestPtr)
109       break;
110     DestPtr=s;
111   }
112   if (DestPath!=NULL)
113   {
114     wchar TmpStr[NM];
115     strncpyw(TmpStr,DestPtr,sizeof(TmpStr)/sizeof(TmpStr[0])-1);
116     strcpyw(DestPath,TmpStr);
117   }
118   return((wchar *)DestPtr);
119 }
120
121
122 void SetExt(char *Name,const char *NewExt)
123 {
124   char *Dot=GetExt(Name);
125   if (NewExt==NULL)
126   {
127     if (Dot!=NULL)
128       *Dot=0;
129   }
130   else
131     if (Dot==NULL)
132     {
133       strcat(Name,".");
134       strcat(Name,NewExt);
135     }
136     else
137       strcpy(Dot+1,NewExt);
138 }
139
140
141 #ifndef SFX_MODULE
142 void SetExt(wchar *Name,const wchar *NewExt)
143 {
144   if (Name==NULL || *Name==0)
145     return;
146   wchar *Dot=GetExt(Name);
147   if (NewExt==NULL)
148   {
149     if (Dot!=NULL)
150       *Dot=0;
151   }
152   else
153     if (Dot==NULL)
154     {
155       strcatw(Name,L".");
156       strcatw(Name,NewExt);
157     }
158     else
159       strcpyw(Dot+1,NewExt);
160 }
161 #endif
162
163
164 #ifndef SFX_MODULE
165 void SetSFXExt(char *SFXName)
166 {
167 #ifdef _UNIX
168   SetExt(SFXName,"sfx");
169 #endif
170
171 #if defined(_WIN_32) || defined(_EMX)
172   SetExt(SFXName,"exe");
173 #endif
174 }
175 #endif
176
177
178 #ifndef SFX_MODULE
179 void SetSFXExt(wchar *SFXName)
180 {
181   if (SFXName==NULL || *SFXName==0)
182     return;
183
184 #ifdef _UNIX
185   SetExt(SFXName,L"sfx");
186 #endif
187
188 #if defined(_WIN_32) || defined(_EMX)
189   SetExt(SFXName,L"exe");
190 #endif
191 }
192 #endif
193
194
195 char *GetExt(const char *Name)
196 {
197   CStdString strExtension = URIUtils::GetExtension(Name);
198   return((char *)strstr((char *)Name,strExtension.c_str()));
199 }
200
201 wchar *GetExt(const wchar *Name)
202 {
203   CStdString strExtension = URIUtils::GetExtension(Name);
204   return((wchar *)wcsstr((wchar_t *)Name,CStdStringW(strExtension).c_str()));
205 }
206
207
208 bool CmpExt(const char *Name,const char *Ext)
209 {
210   char *NameExt=GetExt(Name);
211   return(NameExt!=NULL && stricomp(NameExt+1,Ext)==0);
212 }
213
214
215 bool IsWildcard(const char *Str,const wchar *StrW)
216 {
217   if (StrW!=NULL && *StrW!=0)
218     return(strpbrkw(StrW,L"*?")!=NULL);
219   return(Str==NULL ? false:strpbrk(Str,"*?")!=NULL);
220 }
221
222
223 bool IsPathDiv(int Ch)
224 {
225 #if defined(_WIN_32) || defined(_EMX)
226   return(Ch=='\\' || Ch=='/');
227 #else
228   return(Ch==CPATHDIVIDER);
229 #endif
230 }
231
232
233 bool IsDriveDiv(int Ch)
234 {
235 #ifdef _UNIX
236   return(false);
237 #else
238   return(Ch==':');
239 #endif
240 }
241
242
243 int GetPathDisk(const char *Path)
244 {
245   if (IsDiskLetter(Path))
246     return(toupper(*Path)-'A');
247   else
248     return(-1);
249 }
250
251
252 void AddEndSlash(char *Path)
253 {
254   char *LastChar=PointToLastChar(Path);
255   if (*LastChar!=0 && *LastChar!=CPATHDIVIDER)
256     strcat(LastChar,PATHDIVIDER);
257 }
258
259
260 void AddEndSlash(wchar *Path)
261 {
262   int Length=strlenw(Path);
263   if (Length>0 && Path[Length-1]!=CPATHDIVIDER)
264     strcatw(Path,PATHDIVIDERW);
265 }
266
267
268 void GetFilePath(const char *FullName,char *Path)
269 {
270   int PathLength=PointToName(FullName)-FullName;
271   strncpy(Path,FullName,PathLength);
272   Path[PathLength]=0;
273 }
274
275
276 void GetFilePath(const wchar *FullName,wchar *Path)
277 {
278   const wchar *PathPtr=/*(*FullName && IsDriveDiv(FullName[1])) ? FullName+2:*/FullName;
279   int PathLength=PointToName(FullName)-FullName;
280   strncpyw(Path,PathPtr,PathLength);
281   Path[PathLength]=0;
282 }
283
284
285 void RemoveNameFromPath(char *Path)
286 {
287   char *Name=PointToName(Path);
288   if (Name>=Path+2 && (!IsDriveDiv(Path[1]) || Name>=Path+4))
289     Name--;
290   *Name=0;
291 }
292
293
294 #ifndef SFX_MODULE
295 void RemoveNameFromPath(wchar *Path)
296 {
297   wchar *Name=PointToName(Path);
298   if (Name>=Path+2 && (!IsDriveDiv(Path[1]) || Name>=Path+4))
299     Name--;
300   *Name=0;
301 }
302 #endif
303
304
305 #ifndef SFX_MODULE
306 bool EnumConfigPaths(char *Path,int Number)
307 {
308 #ifdef _EMX
309   static char RARFileName[NM];
310   if (Number==-1)
311     strcpy(RARFileName,Path);
312   if (Number!=0)
313     return(false);
314   if (_osmode==OS2_MODE)
315   {
316     PTIB ptib;
317     PPIB ppib;
318     DosGetInfoBlocks(&ptib, &ppib);
319     DosQueryModuleName(ppib->pib_hmte,NM,Path);
320   }
321   else
322     strcpy(Path,RARFileName);
323   RemoveNameFromPath(Path);
324   return(true);
325 #elif defined(_UNIX)
326   if (Number==0)
327   {
328     char *EnvStr=getenv("HOME");
329     if (EnvStr==NULL)
330       return(false);
331     strncpy(Path,EnvStr,NM);
332     Path[NM-1]=0;
333     return(true);
334   }
335   static const char *AltPath[]={
336     "/etc","/usr/lib","/usr/local/lib","/usr/local/etc"
337   };
338   Number--;
339   if (Number<0 || Number>=(int)(sizeof(AltPath)/sizeof(AltPath[0])))
340     return(false);
341   strcpy(Path,AltPath[Number]);
342   return(true);
343 #elif defined(_WIN_32)
344   if (Number!=0)
345     return(false);
346 #if !defined(TARGET_POSIX)
347   GetModuleFileName(NULL,Path,NM);
348   RemoveNameFromPath(Path);
349 #endif
350   return(true);
351 #else
352   return(false);
353 #endif
354 }
355 #endif
356
357
358 #ifndef SFX_MODULE
359 void GetConfigName(const char *Name,char *FullName, bool CheckExist)
360 {
361   for (int I=0;EnumConfigPaths(FullName,I);I++)
362   {
363     AddEndSlash(FullName);
364     strcat(FullName,Name);
365     if (!CheckExist || WildFileExist(FullName))
366       break;
367   }
368 }
369 #endif
370
371
372 char* GetVolNumPart(char *ArcName)
373 {
374   char *ChPtr=ArcName+strlen(ArcName)-1;
375   while (!isdigit(*ChPtr) && ChPtr>ArcName)
376     ChPtr--;
377   char *NumPtr=ChPtr;
378   while (isdigit(*NumPtr) && NumPtr>ArcName)
379     NumPtr--;
380   while (NumPtr>ArcName && *NumPtr!='.')
381   {
382     if (isdigit(*NumPtr))
383     {
384       char *Dot=strchrd(PointToName(ArcName),'.');
385       if (Dot!=NULL && Dot<NumPtr)
386         ChPtr=NumPtr;
387       break;
388     }
389     NumPtr--;
390   }
391   return(ChPtr);
392 }
393
394
395 void NextVolumeName(char *ArcName,bool OldNumbering)
396 {
397   char *ChPtr;
398   if ((ChPtr=GetExt(ArcName))==NULL)
399   {
400     strcat(ArcName,".rar");
401     ChPtr=GetExt(ArcName);
402   }
403   else
404     if (ChPtr[1]==0 || stricomp(ChPtr+1,"exe")==0 || stricomp(ChPtr+1,"sfx")==0)
405       strcpy(ChPtr+1,"rar");
406   if (!OldNumbering)
407   {
408     ChPtr=GetVolNumPart(ArcName);
409
410     while ((++(*ChPtr))=='9'+1)
411     {
412       *ChPtr='0';
413       ChPtr--;
414       if (ChPtr<ArcName || !isdigit(*ChPtr))
415       {
416         for (char *EndPtr=ArcName+strlen(ArcName);EndPtr!=ChPtr;EndPtr--)
417           *(EndPtr+1)=*EndPtr;
418         *(ChPtr+1)='1';
419         break;
420       }
421     }
422   }
423   else
424     if (!isdigit(*(ChPtr+2)) || !isdigit(*(ChPtr+3)))
425       strcpy(ChPtr+2,"00");
426     else
427     {
428       ChPtr+=3;
429       while ((++(*ChPtr))=='9'+1)
430         if (*(ChPtr-1)=='.')
431         {
432           *ChPtr='A';
433           break;
434         }
435         else
436         {
437           *ChPtr='0';
438           ChPtr--;
439         }
440     }
441 }
442
443
444 bool IsNameUsable(const char *Name)
445 {
446   // only for xbox
447   if ( Name == NULL) return false;
448   char cIllegalChars[] = "<>=?;\"*+,/|";
449   unsigned int iIllegalCharSize = strlen(cIllegalChars);
450   bool isIllegalChar;
451   unsigned int iSize = strlen(Name);
452   if(iSize > 42) return false;
453   
454   for (unsigned int i = 0; i < iSize; i++)
455   {
456     isIllegalChar = false;
457     // check for illegal chars
458     for (unsigned j = 0; j < iIllegalCharSize; j++)
459       if (Name[i] == cIllegalChars[j]) isIllegalChar = true;
460     // FATX only allows chars from 32 till 127
461     if (isIllegalChar == true || Name[i] < 32 || Name[i] > 126) return false;
462   }
463   return true;
464   /*
465 #ifndef _UNIX
466   if (Name[0] && Name[1] && strchr(Name+2,':')!=NULL)
467     return(false);
468 #endif
469   if (strlen(Name) < 43) return 1;
470   else return 0;
471   return(*Name!=0 && strpbrk(Name,"?*<>|")==NULL);
472   */
473 }
474
475
476 void MakeNameUsable(char *Name, bool bKeepExtension, bool IsFATX)
477 {
478   // Changed to be compatible with xbmc's MakeLegalFileName function
479   // (xbox only)
480
481   if ( Name == NULL) return;
482   char cIllegalChars[] = "<>=?;\"*+,/|";
483   unsigned int iIllegalCharSize = strlen(cIllegalChars);
484   bool isIllegalChar;
485   unsigned int iSize = strlen(Name);
486   unsigned int iNewStringSize = 0;
487   char* strNewString = new char[iSize + 1];
488
489   // only copy the legal characters to the new filename
490   for (unsigned int i = 0; i < iSize; i++)
491   {
492     isIllegalChar = false;
493     // check for illigal chars
494     for (unsigned j = 0; j < iIllegalCharSize; j++)
495       if (Name[i] == cIllegalChars[j]) isIllegalChar = true;
496     // FATX only allows chars from 32 till 127
497     if (isIllegalChar == false &&
498         Name[i] > 31 && Name[i] < 127) strNewString[iNewStringSize++] = Name[i];
499   }
500   strNewString[iNewStringSize] = '\0';
501
502   if (IsFATX)
503   {
504     // since we can only write to samba shares and hd, we assume this has to be a fatx filename
505     // thus we have to strip it down to 42 chars (samba doesn't have this limitation)
506   
507     char* FileName = PointToName(strNewString);
508     int iFileNameSize = strlen(FileName);
509     // no need to keep the extension, just strip it down to 42 characters
510     if (iFileNameSize > 42 && bKeepExtension == false) FileName[42] = '\0';
511
512     // we want to keep the extension
513     else if (iFileNameSize > 42 && bKeepExtension == true)
514     {
515       char strExtension[42];
516       unsigned int iExtensionLength = iFileNameSize - (strrchr(FileName, '.') - FileName);
517       strcpy(strExtension, (FileName + iFileNameSize - iExtensionLength));
518
519       strcpy(FileName + (42 - iExtensionLength), strExtension);
520     }
521   }
522
523   strcpy(Name, strNewString);
524   delete[] strNewString;
525 }
526
527 char* UnixSlashToDos(char *SrcName,char *DestName,uint MaxLength)
528 {
529   if (DestName!=NULL && DestName!=SrcName)
530     strcpy(DestName,SrcName);
531   for (char *s=SrcName;*s!=0;s=charnext(s))
532   {
533     if (*s=='/')
534     {
535       if (DestName==NULL)
536         *s='\\';
537       else
538         DestName[s-SrcName]='\\';
539     }
540   }
541   return(DestName==NULL ? SrcName:DestName);
542 }
543
544
545 char* DosSlashToUnix(char *SrcName,char *DestName,uint MaxLength)
546 {
547   if (DestName!=NULL && DestName!=SrcName)
548   {
549     if (strlen(SrcName)>=MaxLength)
550     {
551       *DestName=0;
552       return(DestName);
553     }
554     else
555       strcpy(DestName,SrcName);
556   }
557   for (char *s=SrcName;*s!=0;s=charnext(s))
558   {
559     if (*s=='\\')
560     {
561       if (DestName==NULL)
562         *s='/';
563       else
564         DestName[s-SrcName]='/';
565     }
566   }
567   return(DestName==NULL ? SrcName:DestName);
568 }
569
570
571 bool IsFullPath(const char *Path)
572 {
573   char PathOnly[NM];
574   GetFilePath(Path,PathOnly);
575   if (IsWildcard(PathOnly))
576     return(true);
577 #if defined(_WIN_32) || defined(_EMX)
578   return(Path[0]=='\\' && Path[1]=='\\' ||
579          IsDiskLetter(Path) && IsPathDiv(Path[2]));
580 #else
581   return(IsPathDiv(Path[0]));
582 #endif
583 }
584
585
586 bool IsDiskLetter(const char *Path)
587 {
588   char Letter=toupper(Path[0]);
589   return(Letter>='A' && Letter<='Z' && IsDriveDiv(Path[1]));
590 }
591
592
593 void GetPathRoot(const char *Path,char *Root)
594 {
595   *Root=0;
596   if (IsDiskLetter(Path))
597     sprintf(Root,"%c:\\",*Path);
598   else
599     if (Path[0]=='\\' && Path[1]=='\\')
600     {
601       const char *Slash=strchr(Path+2,'\\');
602       if (Slash!=NULL)
603       {
604         int Length;
605         if ((Slash=strchr(Slash+1,'\\'))!=NULL)
606           Length=Slash-Path+1;
607         else
608           Length=strlen(Path);
609         strncpy(Root,Path,Length);
610         Root[Length]=0;
611       }
612     }
613 }
614
615
616 int ParseVersionFileName(char *Name,wchar *NameW,bool Truncate)
617 {
618   int Version=0;
619   char *VerText=strrchrd(Name,';');
620   if (VerText!=NULL)
621   {
622     Version=atoi(VerText+1);
623     if (Truncate)
624       *VerText=0;
625   }
626   if (NameW!=NULL)
627   {
628     wchar *VerTextW=strrchrw(NameW,';');
629     if (VerTextW!=NULL)
630     {
631       if (Version==0)
632         Version=atoiw(VerTextW+1);
633       if (Truncate)
634         *VerTextW=0;
635     }
636   }
637   return(Version);
638 }
639
640
641 #ifndef SFX_MODULE
642 char* VolNameToFirstName(const char *VolName,char *FirstName,bool NewNumbering)
643 {
644   if (FirstName!=VolName)
645     strcpy(FirstName,VolName);
646   char *VolNumStart=FirstName;
647   if (NewNumbering)
648   {
649     int N='1';
650     for (char *ChPtr=GetVolNumPart(FirstName);ChPtr>FirstName;ChPtr--)
651       if (isdigit(*ChPtr))
652       {
653         *ChPtr=N;
654         N='0';
655       }
656       else
657         if (N=='0')
658         {
659           VolNumStart=ChPtr+1;
660           break;
661         }
662   }
663   else
664   {
665     SetExt(FirstName,"rar");
666     VolNumStart=GetExt(FirstName);
667   }
668   if (!FileExist(FirstName))
669   {
670     char Mask[NM];
671     strcpy(Mask,FirstName);
672     SetExt(Mask,"*");
673     FindFile Find;
674     Find.SetMask(Mask);
675     struct FindData FD;
676     while (Find.Next(&FD))
677     {
678       Archive Arc;
679       if (Arc.Open(FD.Name,FD.NameW) && Arc.IsArchive(true) && !Arc.NotFirstVolume)
680       {
681         strcpy(FirstName,FD.Name);
682         break;
683       }
684     }
685   }
686   return(VolNumStart);
687 }
688 #endif
689
690
691
692
693 wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW)
694 {
695   if (NameW!=NULL && *NameW!=0)
696   {
697     if (DestW!=NameW)
698       strcpyw(DestW,NameW);
699   }
700   else
701     CharToWide(Name,DestW);
702   return(DestW);
703 }
704
705
706
707
708