예제 #1
0
파일: pathfn.cpp 프로젝트: BITINT/DEFCON2
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
{
  const wchar *DestPtr=SrcPath;
  for (const wchar *s=DestPtr;*s!=0;s++)
    if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
      DestPtr=s+4;
  while (*DestPtr)
  {
    const wchar *s=DestPtr;
    if (s[0] && IsDriveDiv(s[1]))
      s+=2;
    if (s[0]=='\\' && s[1]=='\\')
    {
      const wchar *Slash=strchrw(s+2,'\\');
      if (Slash!=NULL && (Slash=strchrw(Slash+1,'\\'))!=NULL)
        s=Slash+1;
    }
    for (const wchar *t=s;*t!=0;t++)
      if (IsPathDiv(*t))
        s=t+1;
      else
        if (*t!='.')
          break;
    if (s==DestPtr)
      break;
    DestPtr=s;
  }
  if (DestPath!=NULL)
  {
    wchar TmpStr[NM];
    strncpyw(TmpStr,DestPtr,sizeof(TmpStr)/sizeof(TmpStr[0])-1);
    strcpyw(DestPath,TmpStr);
  }
  return((wchar *)DestPtr);
}
예제 #2
0
void MakeNameUsable(char *Name,bool Extended)
{
#ifdef _WIN_ALL
  // In Windows we also need to convert characters not defined in current
  // code page. This double conversion changes them to '?', which is
  // catched by code below.
  size_t NameLength=strlen(Name);
  wchar NameW[NM];
  CharToWide(Name,NameW,ASIZE(NameW));
  WideToChar(NameW,Name,NameLength+1);
  Name[NameLength]=0;
#endif
  for (char *s=Name;*s!=0;s=charnext(s))
  {
    if (strchr(Extended ? "?*<>|\"":"?*",*s)!=NULL || Extended && (byte)*s<32)
      *s='_';
#ifdef _EMX
    if (*s=='=')
      *s='_';
#endif
#ifndef _UNIX
    if (s-Name>1 && *s==':')
      *s='_';
    // Remove ' ' and '.' before path separator, but allow .\ and ..\.
    if ((*s==' ' || *s=='.' && s>Name && !IsPathDiv(s[-1]) && s[-1]!='.') && IsPathDiv(s[1]))
      *s='_';
#endif
  }
}
예제 #3
0
// We should return 'true' even if resulting path is shorter than MAX_PATH,
// because we can also use this function to open files with non-standard
// characters, even if their path length is normal.
bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
{
  const wchar *Prefix=L"\\\\?\\";
  const size_t PrefixLength=4;
  bool FullPath=IsDiskLetter(Src) && IsPathDiv(Src[2]);
  size_t SrcLength=wcslen(Src);
  if (IsFullPath(Src)) // Paths in d:\path\name format.
  {
    if (IsDiskLetter(Src))
    {
      if (MaxSize<=PrefixLength+SrcLength)
        return false;
      wcsncpy(Dest,Prefix,PrefixLength);
      wcscpy(Dest+PrefixLength,Src);
      return true;
    }
    else
      if (Src[0]=='\\' && Src[1]=='\\')
      {
        if (MaxSize<=PrefixLength+SrcLength+2)
          return false;
        wcsncpy(Dest,Prefix,PrefixLength);
        wcscpy(Dest+PrefixLength,L"UNC");
        wcscpy(Dest+PrefixLength+3,Src+1);
        return true;
      }
    // We may be here only if we modify IsFullPath in the future.
    return false;
  }
  else
  {
    wchar CurDir[NM];
    DWORD DirCode=GetCurrentDirectory(ASIZE(CurDir)-1,CurDir);
    if (DirCode==0 || DirCode>ASIZE(CurDir)-1)
      return false;

    if (IsPathDiv(Src[0])) // Paths in \path\name format.
    {
      if (MaxSize<=PrefixLength+SrcLength+2)
        return false;
      wcsncpy(Dest,Prefix,PrefixLength);
      wcsncpy(Dest+PrefixLength,CurDir,2); // Copy drive letter 'd:'.
      wcscpy(Dest+PrefixLength+2,Src);
      return true;
    }
    else  // Paths in path\name format.
    {
      AddEndSlash(CurDir,ASIZE(CurDir));
      if (MaxSize<=PrefixLength+wcslen(CurDir)+SrcLength)
        return false;
      wcsncpy(Dest,Prefix,PrefixLength);
      wcscpy(Dest+PrefixLength,CurDir);
      wcsncatz(Dest,Src,MaxSize);
      return true;
    }
  }
  return false;
}
예제 #4
0
파일: pathfn.cpp 프로젝트: BITINT/DEFCON2
bool IsFullPath(const char *Path)
{
  char PathOnly[NM];
  GetFilePath(Path,PathOnly);
  if (IsWildcard(PathOnly))
    return(true);
#if defined(_WIN_32) || defined(_EMX)
  return(Path[0]=='\\' && Path[1]=='\\' ||
         IsDiskLetter(Path) && IsPathDiv(Path[2]));
#else
  return(IsPathDiv(Path[0]));
#endif
}
예제 #5
0
bool IsFullPath(const wchar *Path)
{
/*
  wchar PathOnly[NM];
  GetFilePath(Path,PathOnly,ASIZE(PathOnly));
  if (IsWildcard(PathOnly))
    return true;
*/
#if defined(_WIN_ALL) || defined(_EMX)
  return Path[0]=='\\' && Path[1]=='\\' || IsDiskLetter(Path) && IsPathDiv(Path[2]);
#else
  return IsPathDiv(Path[0]);
#endif
}
예제 #6
0
파일: filefn.cpp 프로젝트: 1ldk/mpc-hc
bool CreatePath(const wchar *Path,bool SkipLastName)
{
  if (Path==NULL || *Path==0)
    return false;

#if defined(_WIN_ALL) || defined(_EMX)
  uint DirAttr=0;
#else
  uint DirAttr=0777;
#endif
  
  bool Success=true;

  for (const wchar *s=Path;*s!=0;s++)
  {
    wchar DirName[NM];
    if (s-Path>=ASIZE(DirName))
      break;

    // Process all kinds of path separators, so user can enter Unix style
    // path in Windows or Windows in Unix. s>Path check avoids attempting
    // creating an empty directory for paths starting from path separator.
    if (IsPathDiv(*s) && s>Path)
    {
#ifdef _WIN_ALL
      // We must not attempt to create "D:" directory, because first
      // CreateDirectory will fail, so we'll use \\?\D:, which forces Wine
      // to create "D:" directory.
      if (s==Path+2 && Path[1]==':')
        continue;
#endif
      wcsncpy(DirName,Path,s-Path);
      DirName[s-Path]=0;

      Success=MakeDir(DirName,true,DirAttr)==MKDIR_SUCCESS;
#ifndef GUI
      if (Success)
      {
        mprintf(St(MCreatDir),DirName);
        mprintf(L" %s",St(MOk));
      }
#endif
    }
  }
  if (!SkipLastName && !IsPathDiv(*PointToLastChar(Path)))
    Success=MakeDir(Path,true,DirAttr)==MKDIR_SUCCESS;
  return Success;
}
예제 #7
0
void ConvertNameToFull(const char *Src,char *Dest)
{
#ifdef _WIN_32
#ifndef _WIN_CE
  char FullName[NM],*NamePtr;
  if (GetFullPathName(Src,sizeof(FullName),FullName,&NamePtr))
    strcpy(Dest,FullName);
  else
#endif
    if (Src!=Dest)
      strcpy(Dest,Src);
#else
  char FullName[NM];
  if (IsPathDiv(*Src) || IsDiskLetter(Src))
    strcpy(FullName,Src);
  else
  {
    if (getcwd(FullName,sizeof(FullName))==NULL)
      *FullName=0;
    else
      AddEndSlash(FullName);
    strcat(FullName,Src);
  }
  strcpy(Dest,FullName);
#endif
}
예제 #8
0
파일: pathfn.cpp 프로젝트: BITINT/DEFCON2
wchar* PointToName(const wchar *Path)
{
  for (int I=strlenw(Path)-1;I>=0;I--)
    if (IsPathDiv(Path[I]))
      return (wchar*)&Path[I+1];
  return (wchar*)((*Path && IsDriveDiv(Path[1])) ? Path+2:Path);
}
예제 #9
0
파일: extinfo.cpp 프로젝트: XhmikosR/mpc-hc
// Calculate a number of path components except \. and \..
static int CalcAllowedDepth(const wchar *Name)
{
  int AllowedDepth=0;
  while (*Name!=0)
  {
    if (IsPathDiv(Name[0]) && Name[1]!=0 && !IsPathDiv(Name[1]))
    {
      bool Dot=Name[1]=='.' && (IsPathDiv(Name[2]) || Name[2]==0);
      bool Dot2=Name[1]=='.' && Name[2]=='.' && (IsPathDiv(Name[3]) || Name[3]==0);
      if (!Dot && !Dot2)
        AllowedDepth++;
    }
    Name++;
  }
  return AllowedDepth;
}
예제 #10
0
bool ScanTree::GetNextMask()
{
  if (!GetFilteredMask())
    return false;
#ifdef _WIN_ALL
  UnixSlashToDos(CurMask,CurMask,ASIZE(CurMask));
#endif

  // We wish to scan entire disk if mask like c:\ is specified
  // regardless of recursion mode. Use c:\*.* mask when need to scan only 
  // the root directory.
  ScanEntireDisk=IsDriveLetter(CurMask) && IsPathDiv(CurMask[2]) && CurMask[3]==0;

  wchar *Name=PointToName(CurMask);
  if (*Name==0)
    wcsncatz(CurMask,MASKALL,ASIZE(CurMask));
  if (Name[0]=='.' && (Name[1]==0 || Name[1]=='.' && Name[2]==0))
  {
    AddEndSlash(CurMask,ASIZE(CurMask));
    wcsncatz(CurMask,MASKALL,ASIZE(CurMask));
  }
  SpecPathLength=Name-CurMask;
  Depth=0;

  wcsncpyz(OrigCurMask,CurMask,ASIZE(OrigCurMask));

  return true;
}
예제 #11
0
파일: filefn.cpp 프로젝트: 1ibraheem/xbmc
void ConvertNameToFull(const char *Src,char *Dest)
{
#ifdef _WIN_32
//#ifndef _WIN_CE
#if !defined(_WIN_CE) && !defined(_LINUX)
  char FullName[NM],*NamePtr;
  if (GetFullPathName(Src,sizeof(FullName),FullName,&NamePtr))
    strcpy(Dest,FullName);
  else
#endif
    if (Src!=Dest)
      strcpy(Dest,Src);
#else
  char FullName[NM];
  if (IsPathDiv(*Src) || IsDiskLetter(Src))
    strcpy(FullName,Src);
  else
  {
    if (getcwd(FullName,sizeof(FullName)))
    {
      AddEndSlash(FullName);
      strcat(FullName,Src);
    }
  }
  strcpy(Dest,FullName);
#endif
}
예제 #12
0
char* ConvertPath(const char *SrcPath,char *DestPath)
{
  const char *DestPtr=SrcPath;

  // Prevent \..\ in any part of path string.
  for (const char *s=DestPtr;*s!=0;s++)
    if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
      DestPtr=s+4;

  // Remove any sequence of . and \ in the beginning of path string.
  while (*DestPtr)
  {
    const char *s=DestPtr;
    if (s[0] && IsDriveDiv(s[1]))
      s+=2;
    else
      if (s[0]=='\\' && s[1]=='\\')
      {
        const char *Slash=strchr(s+2,'\\');
        if (Slash!=NULL && (Slash=strchr(Slash+1,'\\'))!=NULL)
          s=Slash+1;
      }
    for (const char *t=s;*t!=0;t++)
      if (IsPathDiv(*t))
        s=t+1;
      else
        if (*t!='.')
          break;
    if (s==DestPtr)
      break;
    DestPtr=s;
  }

  // Code above does not remove last "..", doing here.
  if (DestPtr[0]=='.' && DestPtr[1]=='.' && DestPtr[2]==0)
    DestPtr+=2;

  if (DestPath!=NULL)
  {
    // SrcPath and DestPath can point to same memory area,
    // so we use the temporary buffer for copying.
    char TmpStr[NM];
    strncpyz(TmpStr,DestPtr,ASIZE(TmpStr));
    strcpy(DestPath,TmpStr);
  }
  return((char *)DestPtr);
}
예제 #13
0
void MakeNameUsable(wchar *Name,bool Extended)
{
  for (wchar *s=Name;*s!=0;s++)
  {
    if (wcschr(Extended ? L"?*<>|\"":L"?*",*s)!=NULL || Extended && (uint)*s<32)
      *s='_';
#ifndef _UNIX
    if (s-Name>1 && *s==':')
      *s='_';
#if 0  // We already can create such files.
    // Remove ' ' and '.' before path separator, but allow .\ and ..\.
    if (IsPathDiv(s[1]) && (*s==' ' || *s=='.' && s>Name &&
        !IsPathDiv(s[-1]) && (s[-1]!='.' || s>Name+1 && !IsPathDiv(s[-2]))))
      *s='_';
#endif
#endif
  }
}
예제 #14
0
파일: pathfn.cpp 프로젝트: 1ibraheem/xbmc
char* PointToName(const char *Path)
{
  //const char *Found=NULL;
  for (const char *s=&Path[strlen(Path)-1];s>=Path;s--)
    if (IsPathDiv(*s))
      return (char*)(s+1);
//  if (Found!=NULL)
  //  return((char*)Found);
  return (char*)((*Path && IsDriveDiv(Path[1]) && charnext(Path)==Path+1) ? Path+2:Path);
}
예제 #15
0
파일: pathfn.cpp 프로젝트: BITINT/DEFCON2
char* PointToName(const char *Path)
{
  const char *Found=NULL;
  for (const char *s=Path;*s!=0;s=charnext(s))
    if (IsPathDiv(*s))
      Found=(char*)(s+1);
  if (Found!=NULL)
    return((char*)Found);
  return (char*)((*Path && IsDriveDiv(Path[1]) && charnext(Path)==Path+1) ? Path+2:Path);
}
예제 #16
0
bool ScanTree::PrepareMasks()
{
    ScanEntireDisk=false;
    if (!FileMasks->GetString(CurMask,CurMaskW,sizeof(CurMask)))
        return(false);
    CurMask[ASIZE(CurMask)-1]=0;
    CurMaskW[ASIZE(CurMaskW)-1]=0;
#ifdef _WIN_32
    UnixSlashToDos(CurMask);
#endif

    // We wish to scan entire disk if mask like c:\ is specified
    // regardless of recursion mode. Use c:\*.* mask when need to scan only
    // the root directory.
    ScanEntireDisk=IsDiskLetter(CurMask) && IsPathDiv(CurMask[2]) && CurMask[3]==0;

    char *Name=PointToName(CurMask);
    if (*Name==0)
        strcat(CurMask,MASKALL);
    if (Name[0]=='.' && (Name[1]==0 || Name[1]=='.' && Name[2]==0))
    {
        AddEndSlash(CurMask);
        strcat(CurMask,MASKALL);
    }
    SpecPathLength=Name-CurMask;
//  if (SpecPathLength>1)
//    SpecPathLength--;

    bool WideName=(*CurMaskW!=0);

    if (WideName)
    {
        wchar *NameW=PointToName(CurMaskW);
        if (*NameW==0)
            strcatw(CurMaskW,MASKALLW);
        if (NameW[0]=='.' && (NameW[1]==0 || NameW[1]=='.' && NameW[2]==0))
        {
            AddEndSlash(CurMaskW);
            strcatw(CurMaskW,MASKALLW);
        }
        SpecPathLengthW=NameW-CurMaskW;
    }
    else
    {
        wchar WideMask[NM];
        CharToWide(CurMask,WideMask);
        SpecPathLengthW=PointToName(WideMask)-WideMask;
    }
    Depth=0;

    strcpy(OrigCurMask,CurMask);
    strcpyw(OrigCurMaskW,CurMaskW);

    return(true);
}
예제 #17
0
파일: extinfo.cpp 프로젝트: Blitzker/mpc-hc
bool IsRelativeSymlinkSafe(const wchar *SrcName,const wchar *TargetName)
{
  if (IsFullRootPath(SrcName))
    return false;
  int AllowedDepth=0;
  while (*SrcName!=0)
  {
    if (IsPathDiv(SrcName[0]) && SrcName[1]!=0 && !IsPathDiv(SrcName[1]))
    {
      bool Dot=SrcName[1]=='.' && (IsPathDiv(SrcName[2]) || SrcName[2]==0);
      bool Dot2=SrcName[1]=='.' && SrcName[2]=='.' && (IsPathDiv(SrcName[3]) || SrcName[3]==0);
      if (!Dot && !Dot2)
        AllowedDepth++;
    }
    SrcName++;
  }
  if (IsFullRootPath(TargetName)) // Catch root dir based /path/file paths.
    return false;
  for (int Pos=0;*TargetName!=0;Pos++)
  {
    bool Dot2=TargetName[0]=='.' && TargetName[1]=='.' && 
              (IsPathDiv(TargetName[2]) || TargetName[2]==0) &&
              (Pos==0 || IsPathDiv(*(TargetName-1)));
    if (Dot2)
      AllowedDepth--;
    TargetName++;
  }
  return AllowedDepth>=0;
}
예제 #18
0
파일: extinfo.cpp 프로젝트: XhmikosR/mpc-hc
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName)
{
  // Catch root dir based /path/file paths also as stuff like \\?\.
  // Do not check PrepSrcName here, it can be root based if destination path
  // is a root based.
  if (IsFullRootPath(SrcName) || IsFullRootPath(TargetName))
    return false;
  
  // We could check just prepared src name, but for extra safety
  // we check both original (as from archive header) and prepared
  // (after applying the destination path and -ep switches) names.

  int AllowedDepth=CalcAllowedDepth(SrcName); // Original name depth.

  // Remove the destination path from prepared name if any. We should not
  // count the destination path depth, because the link target must point
  // inside of this path, not outside of it.
  size_t ExtrPathLength=wcslen(Cmd->ExtrPath);
  if (ExtrPathLength>0 && wcsncmp(PrepSrcName,Cmd->ExtrPath,ExtrPathLength)==0)
  {
    PrepSrcName+=ExtrPathLength;
    while (IsPathDiv(*PrepSrcName))
      PrepSrcName++;
  }
  int PrepAllowedDepth=CalcAllowedDepth(PrepSrcName);

  // Number of ".." in link target.
  int UpLevels=0;
  for (int Pos=0;*TargetName!=0;Pos++)
  {
    bool Dot2=TargetName[0]=='.' && TargetName[1]=='.' && 
              (IsPathDiv(TargetName[2]) || TargetName[2]==0) &&
              (Pos==0 || IsPathDiv(*(TargetName-1)));
    if (Dot2)
      UpLevels++;
    TargetName++;
  }
  return AllowedDepth>=UpLevels && PrepAllowedDepth>=UpLevels;
}
예제 #19
0
void MakeNameUsable(wchar *Name,bool Extended)
{
  for (wchar *s=Name;*s!=0;s++)
  {
    if (wcschr(Extended ? L"?*<>|\"":L"?*",*s)!=NULL || Extended && (uint)*s<32)
      *s='_';
#ifndef _UNIX
    if (s-Name>1 && *s==':')
      *s='_';
    if ((*s==' ' || *s=='.') && IsPathDiv(s[1]))
      *s='_';
#endif
  }
}
예제 #20
0
bool IsNameUsable(const wchar *Name)
{
#ifndef _UNIX
  if (Name[0] && Name[1] && wcschr(Name+2,':')!=NULL)
    return false;
  for (const wchar *s=Name;*s!=0;s++)
  {
    if ((uint)*s<32)
      return false;
    if ((*s==' ' || *s=='.') && IsPathDiv(s[1]))
      return false;
  }
#endif
  return *Name!=0 && wcspbrk(Name,L"?*<>|\"")==NULL;
}
예제 #21
0
bool IsNameUsable(const char *Name)
{
#ifndef _UNIX
  if (Name[0] && Name[1] && strchr(Name+2,':')!=NULL)
    return(false);
  for (const char *s=Name;*s!=0;s=charnext(s))
  {
    if ((byte)*s<32)
      return(false);
    if (*s==' ' && IsPathDiv(s[1]))
      return(false);
  }
#endif
  return(*Name!=0 && strpbrk(Name,"?*<>|\"")==NULL);
}
예제 #22
0
// For masks like dir1\dir2*\*.ext in non-recursive mode.
bool ScanTree::ExpandFolderMask()
{
  bool WildcardFound=false;
  uint SlashPos=0;
  for (int I=0;CurMask[I]!=0;I++)
  {
    if (CurMask[I]=='?' || CurMask[I]=='*')
      WildcardFound=true;
    if (WildcardFound && IsPathDiv(CurMask[I]))
    {
      // First path separator position after folder wildcard mask.
      // In case of dir1\dir2*\dir3\name.ext mask it may point not to file
      // name, so we cannot use PointToName() here.
      SlashPos=I; 
      break;
    }
  }

  wchar Mask[NM];
  wcsncpyz(Mask,CurMask,ASIZE(Mask));
  Mask[SlashPos]=0;

  // Prepare the list of all folders matching the wildcard mask.
  ExpandedFolderList.Reset();
  FindFile Find;
  Find.SetMask(Mask);
  FindData FD;
  while (Find.Next(&FD))
    if (FD.IsDir)
    {
      wcsncatz(FD.Name,CurMask+SlashPos,ASIZE(FD.Name));

      // Treat dir*\* or dir*\*.* as dir, so empty 'dir' is also matched
      // by such mask. Skipping empty dir with dir*\*.* confused some users.
      wchar *LastMask=PointToName(FD.Name);
      if (wcscmp(LastMask,L"*")==0 || wcscmp(LastMask,L"*.*")==0)
        RemoveNameFromPath(FD.Name);

      ExpandedFolderList.AddString(FD.Name);
    }
  if (ExpandedFolderList.ItemsCount()==0)
    return false;
  // Return the first matching folder name now.
  ExpandedFolderList.GetString(CurMask,ASIZE(CurMask));
  return true;
}
예제 #23
0
void MakeNameUsable(char *Name,bool Extended)
{
  for (char *s=Name;*s!=0;s=charnext(s))
  {
    if (strchr(Extended ? "?*<>|\"":"?*",*s)!=NULL || Extended && (byte)*s<32)
      *s='_';
#ifdef _EMX
    if (*s=='=')
      *s='_';
#endif
#ifndef _UNIX
    if (s-Name>1 && *s==':')
      *s='_';
    if (*s==' ' && IsPathDiv(s[1]))
      *s='_';
#endif
  }
}
예제 #24
0
bool CreatePath(const wchar *Path,bool SkipLastName)
{
  if (Path==NULL || *Path==0)
    return(false);

#if defined(_WIN_ALL) || defined(_EMX)
  uint DirAttr=0;
#else
  uint DirAttr=0777;
#endif
  
  bool Success=true;

  for (const wchar *s=Path;*s!=0;s++)
  {
    if (s-Path>=NM)
      break;

    if (*s==CPATHDIVIDER)
    {
      wchar DirName[NM];
      wcsncpy(DirName,Path,s-Path);
      DirName[s-Path]=0;

      if (MakeDir(NULL,DirName,true,DirAttr)==MKDIR_SUCCESS)
      {
#ifndef GUI
        char DirNameA[NM];
        WideToChar(DirName,DirNameA,ASIZE(DirNameA));
        DirNameA[ASIZE(DirNameA)-1]=0;
        mprintf(St(MCreatDir),DirNameA);
        mprintf(" %s",St(MOk));
#endif
      }
      else
        Success=false;
    }
  }
  if (!SkipLastName)
    if (!IsPathDiv(*PointToLastChar(Path)))
      if (MakeDir(NULL,Path,true,DirAttr)!=MKDIR_SUCCESS)
        Success=false;
  return(Success);
}
예제 #25
0
// Return 'true' if we need to exclude the directory from archiving as result
// of -x switch. We do not want -x*. switch to exclude all directories,
// so when archiving we process exclusion arguments for directories specially.
bool CommandData::ExclCheckDir(char *CheckName)
{
  // If exclusion mask and directory name match exactly, return true.
  if (ExclCheckArgs(ExclArgs,CheckName,true,MATCH_EXACT))
    return(true);

  // Now we want to allow wildcards in exclusion mask only if it has
  // '\' at the end. So 'dir*\' will exclude all dir* directories.
  // We append '\' to directory name, so it will match only masks having
  // '\' at the end.
  char DirName[NM+1];
  ConvertPath(CheckName,DirName);
  AddEndSlash(DirName);

  char *CurMask;
  ExclArgs->Rewind();
  while ((CurMask=ExclArgs->GetString())!=NULL)
    if (IsPathDiv(*PointToLastChar(CurMask)))
      if (CmpName(CurMask,DirName,MATCH_SUBPATH))
        return(true);
  
  return(false);
}
예제 #26
0
// For masks like dir1\dir2*\file.ext this function sets 'dir1' recursive mask
// and '*\dir2*\file.ext' filter. Masks without folder wildcards are
// returned as is.
bool ScanTree::GetFilteredMask()
{
  // If we have some matching folders left for non-recursive folder wildcard
  // mask, we return it here.
  if (ExpandedFolderList.ItemsCount()>0 && ExpandedFolderList.GetString(CurMask,ASIZE(CurMask)))
    return true;

  FolderWildcards=false;
  FilterList.Reset();
  if (!FileMasks->GetString(CurMask,ASIZE(CurMask)))
    return false;

  // Check if folder wildcards present.
  bool WildcardFound=false;
  uint FolderWildcardCount=0;
  uint SlashPos=0;
  for (int I=0;CurMask[I]!=0;I++)
  {
    if (CurMask[I]=='?' || CurMask[I]=='*')
      WildcardFound=true;
    if (IsPathDiv(CurMask[I]) || IsDriveDiv(CurMask[I]))
    {
      if (WildcardFound)
      {
        // Calculate a number of folder wildcards in current mask.
        FolderWildcardCount++;
        WildcardFound=false;
      }
      if (FolderWildcardCount==0)
        SlashPos=I; // Slash position before first folder wildcard mask.
    }
  }
  if (FolderWildcardCount==0)
    return true;
  FolderWildcards=true; // Global folder wildcards flag.

  // If we have only one folder wildcard component and -r is missing or -r-
  // is specified, prepare matching folders in non-recursive mode.
  // We assume -r for masks like dir1*\dir2*\file*, because it is complicated
  // to fast find them using OS file find API call.
  if ((Recurse==RECURSE_NONE || Recurse==RECURSE_DISABLE) && FolderWildcardCount==1)
    return ExpandFolderMask();

  wchar Filter[NM];
  // Convert path\dir*\ to *\dir filter to search for 'dir' in all 'path' subfolders.
  wcscpy(Filter,L"*");
  AddEndSlash(Filter,ASIZE(Filter));
  // SlashPos might point or not point to path separator for masks like 'dir*', '\dir*' or 'd:dir*'
  wchar *WildName=IsPathDiv(CurMask[SlashPos]) || IsDriveDiv(CurMask[SlashPos]) ? CurMask+SlashPos+1 : CurMask+SlashPos;
  wcsncatz(Filter,WildName,ASIZE(Filter));

  // Treat dir*\* or dir*\*.* as dir\, so empty 'dir' is also matched
  // by such mask. Skipping empty dir with dir*\*.* confused some users.
  wchar *LastMask=PointToName(Filter);
  if (wcscmp(LastMask,L"*")==0 || wcscmp(LastMask,L"*.*")==0)
    *LastMask=0;

  FilterList.AddString(Filter);

  bool RelativeDrive=IsDriveDiv(CurMask[SlashPos]);
  if (RelativeDrive)
    SlashPos++; // Use "d:" instead of "d" for d:* mask.

  CurMask[SlashPos]=0;

  if (!RelativeDrive) // Keep d: mask as is, not convert to d:\*
  {
    // We need to append "\*" both for -ep1 to work correctly and to
    // convert d:\* masks previously truncated to d: back to original form.
    AddEndSlash(CurMask,ASIZE(CurMask));
    wcsncatz(CurMask,MASKALL,ASIZE(CurMask));
  }
  return true;
}
예제 #27
0
파일: extract.cpp 프로젝트: KastB/OpenCPN
void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *DestName,size_t DestSize)
{
  wcsncpyz(DestName,Cmd->ExtrPath,DestSize);

  // We need IsPathDiv check here to correctly handle Unix forward slash
  // in the end of destination path in Windows: rar x arc dest/
  if (*Cmd->ExtrPath!=0 && !IsPathDiv(*PointToLastChar(Cmd->ExtrPath)))
  {
    // Destination path can be without trailing slash if it come from GUI shell.
    AddEndSlash(DestName,DestSize);
  }

#ifndef SFX_MODULE
  if (Cmd->AppendArcNameToPath)
  {
    wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize);
    SetExt(DestName,NULL,DestSize);
    AddEndSlash(DestName,DestSize);
  }
#endif

#ifndef SFX_MODULE
  size_t ArcPathLength=wcslen(Cmd->ArcPath);
  if (ArcPathLength>0)
  {
    size_t NameLength=wcslen(ArcFileName);
    ArcFileName+=Min(ArcPathLength,NameLength);
    while (*ArcFileName==CPATHDIVIDER)
      ArcFileName++;
    if (*ArcFileName==0) // Excessive -ap switch.
    {
      *DestName=0;
      return;
    }
  }
#endif

  wchar Command=Cmd->Command[0];
  // Use -ep3 only in systems, where disk letters are exist, not in Unix.
  bool AbsPaths=Cmd->ExclPath==EXCL_ABSPATH && Command=='X' && IsDriveDiv(':');

  // We do not use any user specified destination paths when extracting
  // absolute paths in -ep3 mode.
  if (AbsPaths)
    *DestName=0;

  if (Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
    wcsncatz(DestName,PointToName(ArcFileName),DestSize);
  else
    wcsncatz(DestName,ArcFileName,DestSize);

  wchar DiskLetter=toupperw(DestName[0]);

  if (AbsPaths)
  {
    if (DestName[1]=='_' && IsPathDiv(DestName[2]) &&
        DiskLetter>='A' && DiskLetter<='Z')
      DestName[1]=':';
    else
      if (DestName[0]=='_' && DestName[1]=='_')
      {
        // Convert __server\share to \\server\share.
        DestName[0]=CPATHDIVIDER;
        DestName[1]=CPATHDIVIDER;
      }
  }
}
예제 #28
0
void CommandData::ParseArg(char *Arg,wchar *ArgW)
{
  if (IsSwitch(*Arg) && !NoMoreSwitches)
    if (Arg[1]=='-')
      NoMoreSwitches=true;
    else
      ProcessSwitch(&Arg[1]);
  else
    if (*Command==0)
    {
      strncpy(Command,Arg,sizeof(Command));
      if (ArgW!=NULL)
        strncpyw(CommandW,ArgW,sizeof(CommandW)/sizeof(CommandW[0]));
      if (toupper(*Command)=='S')
      {
        const char *SFXName=Command[1] ? Command+1:DefSFXName;
        if (PointToName(SFXName)!=SFXName || FileExist(SFXName))
          strcpy(SFXModule,SFXName);
        else
          GetConfigName(SFXName,SFXModule,true);
      }
#ifndef GUI
      *Command=toupper(*Command);
      if (*Command!='I' && *Command!='S')
        strupper(Command);
#endif
    }
    else
      if (*ArcName==0)
      {
        strncpy(ArcName,Arg,sizeof(ArcName));
        if (ArgW!=NULL)
          strncpyw(ArcNameW,ArgW,sizeof(ArcNameW)/sizeof(ArcNameW[0]));
      }
      else
      {
        int Length=strlen(Arg);
        char EndChar=Arg[Length-1];
        char CmdChar=toupper(*Command);
        bool Add=strchr("AFUM",CmdChar)!=NULL;
        bool Extract=CmdChar=='X' || CmdChar=='E';
        if ((IsDriveDiv(EndChar) || IsPathDiv(EndChar)) && !Add)
          strcpy(ExtrPath,Arg);
        else
          if ((Add || CmdChar=='T') && *Arg!='@')
            FileArgs->AddString(Arg);
          else
          {
            struct FindData FileData;
            bool Found=FindFile::FastFind(Arg,NULL,&FileData);
            if (!Found && *Arg=='@' && !IsWildcard(Arg))
            {
              ReadTextFile(Arg+1,FileArgs,false,true,true,true,true);
              FileLists=true;
            }
            else
              if (Found && FileData.IsDir && Extract && *ExtrPath==0)
              {
                strcpy(ExtrPath,Arg);
                AddEndSlash(ExtrPath);
              }
              else
                FileArgs->AddString(Arg);
          }
      }
}
예제 #29
0
void CommandData::ParseArg(char *Arg,wchar *ArgW)
{
  if (IsSwitch(*Arg) && !NoMoreSwitches)
    if (Arg[1]=='-')
      NoMoreSwitches=true;
    else
      ProcessSwitch(Arg+1,(ArgW!=NULL && *ArgW!=0 ? ArgW+1:NULL));
  else
    if (*Command==0)
    {
      strncpyz(Command,Arg,ASIZE(Command));
      if (ArgW!=NULL)
        wcsncpy(CommandW,ArgW,ASIZE(CommandW));


#ifndef GUI
      *Command=etoupper(*Command);
      // 'I' and 'S' commands can contain case sensitive strings after
      // the first character, so we must not modify their case.
      // 'S' can contain SFX name, which case is important in Unix.
      if (*Command!='I' && *Command!='S')
        strupper(Command);
#endif
    }
    else
      if (*ArcName==0 && *ArcNameW==0)
      {
        strncpyz(ArcName,Arg,ASIZE(ArcName));
        if (ArgW!=NULL)
          wcsncpyz(ArcNameW,ArgW,ASIZE(ArcNameW));
      }
      else
      {
        bool EndSeparator; // If last character is the path separator.
        if (ArgW!=NULL)
        {
          size_t Length=wcslen(ArgW);
          wchar EndChar=Length==0 ? 0:ArgW[Length-1];
          EndSeparator=IsDriveDiv(EndChar) || IsPathDiv(EndChar);
        }
        else
        {
          size_t Length=strlen(Arg);
          char EndChar=Length==0 ? 0:Arg[Length-1];
          EndSeparator=IsDriveDiv(EndChar) || IsPathDiv(EndChar);
        }

        char CmdChar=etoupper(*Command);
        bool Add=strchr("AFUM",CmdChar)!=NULL;
        bool Extract=CmdChar=='X' || CmdChar=='E';
        if (EndSeparator && !Add)
        {
          strncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
          if (ArgW!=NULL)
            wcsncpyz(ExtrPathW,ArgW,ASIZE(ExtrPathW));
        }
        else
          if ((Add || CmdChar=='T') && *Arg!='@')
            FileArgs->AddString(Arg,ArgW);
          else
          {
            FindData FileData;
            bool Found=FindFile::FastFind(Arg,ArgW,&FileData);
            if (!Found && *Arg=='@' && !IsWildcard(Arg,ArgW))
            {
              FileLists=true;

              RAR_CHARSET Charset=FilelistCharset;

#if defined(_WIN_ALL) && !defined(GUI)
              // for compatibility reasons we use OEM encoding
              // in Win32 console version by default

              if (Charset==RCH_DEFAULT)
                Charset=RCH_OEM;
#endif

              wchar *WideArgName=(ArgW!=NULL && *ArgW!=0 ? ArgW+1:NULL);
              ReadTextFile(Arg+1,WideArgName,FileArgs.get(),false,true,Charset,true,true,true);

            }
            else
              if (Found && FileData.IsDir && Extract && *ExtrPath==0 && *ExtrPathW==0)
              {
                strncpyz(ExtrPath,Arg,ASIZE(ExtrPath)-1);
                AddEndSlash(ExtrPath);
                if (ArgW!=NULL)
                {
                  wcsncpyz(ExtrPathW,ArgW,ASIZE(ExtrPathW)-1);
                  AddEndSlash(ExtrPathW);
                }
              }
              else
                FileArgs->AddString(Arg,ArgW);
          }
      }
}
예제 #30
0
bool CommandData::ExclCheckArgs(StringList *Args,bool Dir,char *CheckName,bool CheckFullPath,int MatchMode)
{
  char *Name=ConvertPath(CheckName,NULL);
  char FullName[NM];
  char CurMask[NM+1]; // We reserve the space to append "*" to mask.
  *FullName=0;
  Args->Rewind();
  while (Args->GetString(CurMask,ASIZE(CurMask)-1))
  {
    char *LastMaskChar=PointToLastChar(CurMask);
    bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only.

    if (Dir)
    {
      // CheckName is a directory.
      if (DirMask)
      {
        // We process the directory and have the directory exclusion mask.
        // So let's convert "mask\" to "mask" and process it normally.
        
        *LastMaskChar=0;
      }
      else
      {
        // If mask has wildcards in name part and does not have the trailing
        // '\' character, we cannot use it for directories.
      
        if (IsWildcard(PointToName(CurMask)))
          continue;
      }
    }
    else
    {
      // If we process a file inside of directory excluded by "dirmask\".
      // we want to exclude such file too. So we convert "dirmask\" to
      // "dirmask\*". It is important for operations other than archiving.
      // When archiving, directory matched by "dirmask\" is excluded
      // from further scanning.

      if (DirMask)
        strcat(CurMask,"*");
    }

#ifndef SFX_MODULE
    if (CheckFullPath && IsFullPath(CurMask))
    {
      // We do not need to do the special "*\" processing here, because
      // onlike the "else" part of this "if", now we convert names to full
      // format, so they all include the path, which is matched by "*\"
      // correctly. Moreover, removing "*\" from mask would break
      // the comparison, because now all names have the path.

      if (*FullName==0)
        ConvertNameToFull(CheckName,FullName);
      if (CmpName(CurMask,FullName,MatchMode))
        return(true);
    }
    else
#endif
    {
      char NewName[NM+2],*CurName=Name;
      if (CurMask[0]=='*' && IsPathDiv(CurMask[1]))
      {
        // We want "*\name" to match 'name' not only in subdirectories,
        // but also in the current directory. We convert the name
        // from 'name' to '.\name' to be matched by "*\" part even if it is
        // in current directory.
        NewName[0]='.';
        NewName[1]=CPATHDIVIDER;
        strncpyz(NewName+2,Name,ASIZE(NewName)-2);
        CurName=NewName;
      }

      if (CmpName(ConvertPath(CurMask,NULL),CurName,MatchMode))
        return(true);
    }
  }
  return(false);
}