Exemple #1
0
static int UnzipFile (unzFile uf,
                      void* buffer,
                      const size_t bufferSize,
                      const char* outPath, 
                      const bool skipPaths,
                      const bool overwrite,
                      const char* password) {
  unz_global_info64 gi;
  uLong i;
  int res;

  if (unzGetGlobalInfo64(uf, &gi) != UNZ_OK) {
    return TRI_ERROR_INTERNAL;
  }
    
  for (i = 0; i < gi.number_entry; i++) {
    res = ExtractCurrentFile(uf, buffer, bufferSize, outPath, skipPaths, overwrite, password);

    if (res != TRI_ERROR_NO_ERROR) {
      break;
    }

    if ((i + 1) < gi.number_entry) {
      if (unzGoToNextFile(uf) != UNZ_OK) {
        res = TRI_ERROR_INTERNAL;
        break;
      }
    }
  }

  return res;
}
Exemple #2
0
extern "C" bool ArchGetFileW(HZIP hZip,WCHAR *pstrFile,byte **lpMem,int *dwSize)
{
    bool r=false;
    ZIPDECOMPRESSION *p=(ZIPDECOMPRESSION *)hZip;
    if ((hZip) && (p->bHandleType == HT_DECOMPRESSOR) && (pstrFile) && (lpMem) && (dwSize))
    {
        LPCSTR pFileName=UnicodeToOemEx(pstrFile,-1);
        unzGoToFirstFile(p->hZip);
        p->bExctractToMem=true;

        if (unzLocateFile(p->hZip,pFileName,CASESENSITIVITY) == UNZ_OK)
            r=(ExtractCurrentFile(hZip,true) > -1) ? true : false;
        else
        {
            ArchSetLastError(ARCH_FILE_NOT_FOUND);
            r=false;
        }
        MemFree((void*)pFileName);

        if (r)
        {
            *lpMem=(byte*)p->lpMem;
            *dwSize=p->dwSize;
        }
    }
    else
        ArchSetLastError(ARCH_INVALID_PARAMETER);
    return r;

}
Exemple #3
0
extern "C" bool ArchExtractFileW(HZIP hZip,WCHAR *pstrPath,WCHAR *lpstrFile)
{
    bool r=false;
    ZIPDECOMPRESSION *p=(ZIPDECOMPRESSION*)hZip;
    if ((hZip) && (p->bHandleType == HT_DECOMPRESSOR) && (pstrPath) && (lpstrFile))
    {
        LPCSTR pFileName=UnicodeToAnsiEx(lpstrFile,-1);
        lstrcpyW(p->strOutputDir,pstrPath);
        unzGoToFirstFile(p->hZip);
        if (unzLocateFile(p->hZip,pFileName,CASESENSITIVITY) == UNZ_OK)
            r=(ExtractCurrentFile(hZip,true) > -1) ? true : false;
        else
        {
            ArchSetLastError(ARCH_FILE_NOT_FOUND);
            r=false;
        }
        MemFree(lpstrFile);
    }
    else
        ArchSetLastError(ARCH_INVALID_PARAMETER);
    return r;
}
Exemple #4
0
int InternalEnumFiles(HZIP hZip)
{
    int r=-1;
    unz_global_info64 gi;
    ZIPDECOMPRESSION *p=(ZIPDECOMPRESSION*)hZip;
    int err=unzGetGlobalInfo64(p->hZip,&gi);
    if (err == UNZ_OK)
    {
        for (uLong i=0; i<gi.number_entry; i++)
        {
            char filename_inzip[256];
            unz_file_info64 file_info;
            err=unzGetCurrentFileInfo64(p->hZip,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
            if (err == UNZ_OK)
            {
                LPWSTR sourceFile=OemToUnicodeEx(filename_inzip,-1);

                if (p->bOnlyEnum)
                {
                    if (!p->bEnumAnsi)
                        r=(p->lpEnumProc(sourceFile)) ? 0 : -1;
                    else
                    {
                        char ansi_filename_inzip[256];
                        OemToAnsi(filename_inzip,ansi_filename_inzip);
                        r=(p->lpEnumProc((LPWSTR)ansi_filename_inzip)) ? 0 : -1;
                    }
                }
                else
                    r=ExtractCurrentFile(hZip,false);

                MemFree(sourceFile);
            }
            unzGoToNextFile(p->hZip);
        }
    }
    return r;
}
Exemple #5
0
static int UnzipFile(unzFile uf, void* buffer, size_t const bufferSize,
                     char const* outPath, bool const skipPaths,
                     bool const overwrite, char const* password,
                     std::string& errorMessage) {
  unz_global_info64 gi;
  uLong i;
  int res = TRI_ERROR_NO_ERROR;
  int err;

  err = unzGetGlobalInfo64(uf, &gi);
  if (err != UNZ_OK) {
    errorMessage = "Failed to get info: " + std::to_string(err);
    return TRI_ERROR_INTERNAL;
  }

  for (i = 0; i < gi.number_entry; i++) {
    res = ExtractCurrentFile(uf, buffer, bufferSize, outPath, skipPaths,
                             overwrite, password, errorMessage);

    if (res != TRI_ERROR_NO_ERROR) {
      break;
    }

    if ((i + 1) < gi.number_entry) {
      err = unzGoToNextFile(uf);
      if (err == UNZ_END_OF_LIST_OF_FILE) {
        break;
      } else if (err != UNZ_OK) {
        errorMessage = "Failed to jump to next file: " + std::to_string(err);
        res = TRI_ERROR_INTERNAL;
        break;
      }
    }
  }

  return res;
}
Exemple #6
0
EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
{
  Archive Arc(Cmd);
  if (!Arc.WOpen(ArcName))
    return EXTRACT_ARC_NEXT;

  if (!Arc.IsArchive(true))
  {
#ifndef GUI
    mprintf(St(MNotRAR),ArcName);
#endif
    if (CmpExt(ArcName,L"rar"))
      ErrHandler.SetErrorCode(RARX_WARNING);
    return EXTRACT_ARC_NEXT;
  }

  if (Arc.FailedHeaderDecryption) // Bad archive password.
    return EXTRACT_ARC_NEXT;

#ifndef SFX_MODULE
  if (Arc.Volume && !Arc.FirstVolume)
  {
    wchar FirstVolName[NM];
    VolNameToFirstName(ArcName,FirstVolName,ASIZE(FirstVolName),Arc.NewNumbering);

    // If several volume names from same volume set are specified
    // and current volume is not first in set and first volume is present
    // and specified too, let's skip the current volume.
    if (wcsicomp(ArcName,FirstVolName)!=0 && FileExist(FirstVolName) &&
        Cmd->ArcNames.Search(FirstVolName,false))
      return EXTRACT_ARC_NEXT;
  }
#endif

  int64 VolumeSetSize=0; // Total size of volumes after the current volume.

  if (Arc.Volume)
  {
    // Calculate the total size of all accessible volumes.
    // This size is necessary to display the correct total progress indicator.

    wchar NextName[NM];
    wcscpy(NextName,Arc.FileName);

    while (true)
    {
      // First volume is already added to DataIO.TotalArcSize 
      // in initial TotalArcSize calculation in DoExtract.
      // So we skip it and start from second volume.
      NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering);
      FindData FD;
      if (FindFile::FastFind(NextName,&FD))
        VolumeSetSize+=FD.Size;
      else
        break;
    }
    DataIO.TotalArcSize+=VolumeSetSize;
  }

  ExtractArchiveInit(Arc);

  if (*Cmd->Command=='T' || *Cmd->Command=='I')
    Cmd->Test=true;


  if (*Cmd->Command=='I')
  {
#ifndef GUI   
    Cmd->DisablePercentage=true;
#endif
  }
  else
    uiStartArchiveExtract(!Cmd->Test,ArcName);

  Arc.ViewComment();


  while (1)
  {
    size_t Size=Arc.ReadHeader();


    bool Repeat=false;
    if (!ExtractCurrentFile(Arc,Size,Repeat))
    {
      if (Repeat)
      {
        // If we started extraction from not first volume and need to
        // restart it from first, we must correct DataIO.TotalArcSize
        // for correct total progress display. We subtract the size
        // of current volume and all volumes after it and add the size
        // of new (first) volume.
        FindData OldArc,NewArc;
        if (FindFile::FastFind(Arc.FileName,&OldArc) &&
            FindFile::FastFind(ArcName,&NewArc))
          DataIO.TotalArcSize-=VolumeSetSize+OldArc.Size-NewArc.Size;
        return EXTRACT_ARC_REPEAT;
      }
      else
        break;
    }
  }


  return EXTRACT_ARC_NEXT;
}
Exemple #7
0
int vtUnzip::Extract(bool bFullPath, bool bOverwrite, const char *lpszDst,
					 bool progress_callback(int))
{
	int iCount = 0;
	int iTotal = GetGlobalCount();

	bool bOK = true;
	for (bool bContinue = GoToFirstFile(); bContinue; bContinue = GoToNextFile())
	{
		char szFileName[MAX_PATH];
		unz_file_info info;
		bOK = GetCurrentFileInfo(&info, szFileName, MAX_PATH);
		if (!bOK)
			break;

		vtString src_filename = szFileName;

		const char *short_fname = (const char *)src_filename;
		for (const char *p = short_fname;
			(*p) != '\0';
			p++)
		{
			if (((*p)=='/') || ((*p)=='\\'))
			{
				short_fname = p+1;
			}
		}
		vtString short_filename = short_fname;

		if ((*short_filename)=='\0')
		{
			if (bFullPath)
			{
				VTLOG("creating directory: %s\n", (const char *)src_filename);
				vtCreateDir(src_filename);
			}
		}
		else
		{
			bOK = OpenCurrentFile();
			if (bOK)
			{
				vtString write_filename;
				write_filename = vtString(lpszDst) + (bFullPath ? src_filename : short_filename);

				vtString strResult;

				VTLOG("Extracting %s ...", (const char *) write_filename);
				if (ExtractAccept(write_filename, bOverwrite))
				{
					FILE* file = vtFileOpen(write_filename, "wb");

					bool bWrite = (file != NULL);
					if (bWrite)
					{
						char buf[4096];
						bWrite = ExtractCurrentFile(file, buf, 4096);
						fclose(file);
					}
					if (bWrite)
					{
						vtUnzip::change_file_date(write_filename,info.dosDate, info.tmu_date);
						iCount++;
						if (progress_callback != NULL)
						{
							progress_callback(iCount * 99 / iTotal);
						}
					}
					else
					{
						m_error_count++;
						OnError(write_filename);
					}
					strResult = bWrite ? "ok" : "failed";
				}
				else
				{
					strResult = "skipped";
				}
				VTLOG(" %s\n", (const char *) strResult);
				CloseCurrentFile();
			}
		}
	}
	if (bOK)
		return iCount;
	else
		return -1;
}
bool DialogInstall::InstallPackage()
{
	if ((!m_MergeSkins && m_BackupSkins) || m_BackupPackage)
	{
		// Move skins into backup folder
		for (auto iter = m_PackageSkins.cbegin(); iter != m_PackageSkins.cend(); ++iter)
		{
			std::wstring from = g_Data.skinsPath + *iter;
			if (_waccess(from.c_str(), 0) == -1)
			{
				continue;
			}

			SHFILEOPSTRUCT fo =
			{
				nullptr,
				FO_DELETE,
				nullptr,
				nullptr,
				FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO
			};

			if (m_BackupPackage)
			{
				// Remove current skin
				from += L'\0';
				fo.pFrom = from.c_str();
				SHFileOperation(&fo);
			}
			else
			{
				std::wstring to = g_Data.skinsPath + L"@Backup\\";
				CreateDirectory(to.c_str(), nullptr);

				// Delete current backup
				to += *iter;
				to += L'\0';
				fo.pFrom = to.c_str();
				SHFileOperation(&fo);

				if (!CopyFiles(from, to, true))
				{
					m_ErrorMessage = L"Unable to move to:\n";
					m_ErrorMessage += to;
					return false;
				}
			}
		}
	}

	WCHAR buffer[MAX_PATH];

	// Helper to sets buffer with current file name
	auto getFileInfo = [&]()->bool
	{
		char cBuffer[MAX_PATH * 3];
		unz_file_info ufi;
		if (unzGetCurrentFileInfo(
				m_PackageUnzFile, &ufi, cBuffer, _countof(cBuffer), nullptr, 0, nullptr, 0) == UNZ_OK)
		{
			const uLong ZIP_UTF8_FLAG = 1 << 11;
			const DWORD codePage = (ufi.flag & ZIP_UTF8_FLAG) ? CP_UTF8 : CP_ACP;
			MultiByteToWideChar(codePage, 0, cBuffer, strlen(cBuffer) + 1, buffer, MAX_PATH);
			while (WCHAR* pos = wcschr(buffer, L'/')) *pos = L'\\';
			return true;
		}

		return false;
	};

	unzGoToFirstFile(m_PackageUnzFile);
	const WCHAR* root = m_PackageRoot.c_str();
	do
	{
		if (!getFileInfo())
		{
			m_ErrorMessage = L"Error retrieving file info.";
			return false;
		}

		if (wcsncmp(buffer, root, m_PackageRoot.length()) != 0)
		{
			// Ignore everything that isn't in the root directory
			continue;
		}

		WCHAR* component = buffer + m_PackageRoot.length();
		WCHAR* path = wcschr(component, L'\\');
		if (path)
		{
			*path = L'\0';
			++path;
		}
		else
		{
			continue;
		}

		bool error = false;
		std::wstring targetPath;

		WCHAR* pos = wcschr(path, L'\\');
		WCHAR* extension = PathFindExtension(pos ? pos : path);
		if (pos)
		{
			const std::wstring item(path, pos - path);

			if (_wcsicmp(component, L"Skins") == 0 &&
				m_PackageSkins.find(item) != m_PackageSkins.end())
			{
				targetPath = g_Data.skinsPath;
			}
			else if (_wcsicmp(component, L"Addons") == 0 &&
				m_PackageFormat == PackageFormat::Old &&
				m_PackageAddons.find(item) != m_PackageAddons.end())
			{
				targetPath = g_Data.settingsPath;
				targetPath += L"Addons\\";
			}
			else if (_wcsicmp(component, L"Plugins") == 0 &&
				_wcsnicmp(path, IsWin32Build() ? L"32bit" : L"64bit", pos - path) == 0 &&
				_wcsicmp(extension, L".dll") == 0 &&
				!wcschr(pos + 1, L'\\'))
			{
				const std::wstring plugin(pos + 1);
				if (m_PackagePlugins.find(plugin) != m_PackagePlugins.end())
				{
					path = pos + 1;
					targetPath = g_Data.settingsPath;
					targetPath += L"Plugins\\";
				}
			}

			if (!targetPath.empty())
			{
				targetPath += path;
				error = !ExtractCurrentFile(targetPath);
			}
			else if (_wcsicmp(component, m_PackageFormat == PackageFormat::New ? L"Layouts" : L"Themes") == 0 &&
				_wcsicmp(extension, m_PackageFormat == PackageFormat::New ? L".ini" : L".thm") == 0 &&
				m_PackageLayouts.find(item) != m_PackageLayouts.end())
			{
				if (m_PackageFormat == PackageFormat::Old)
				{
					wcscpy_s(extension, 5, L".ini");
				}

				targetPath = g_Data.settingsPath;
				targetPath += L"Layouts\\";
				targetPath += path;
				error = !ExtractCurrentFile(targetPath);
				if (!error)
				{
					CleanLayoutFile(targetPath.c_str());
				}
			}
		}
		else
		{
			if (_wcsicmp(component, L"Fonts") == 0 &&
				m_PackageFormat == PackageFormat::Old &&
				_wcsicmp(extension, L".ttf") == 0)
			{
				for (auto iter = m_PackageSkins.cbegin(); iter != m_PackageSkins.cend(); ++iter)
				{
					targetPath = g_Data.skinsPath;
					targetPath += *iter;
					targetPath += L"\\@Resources\\Fonts\\";
					targetPath += path;
					error = !ExtractCurrentFile(targetPath);
					if (error)
					{
						break;
					}
				}
			}
		}

		if (error)
		{
			m_ErrorMessage = L"Unable to create file:\n";
			m_ErrorMessage += targetPath;
			m_ErrorMessage += L"\n\nSkin Installer will now quit.";
			return false;
		}
	}
	while (unzGoToNextFile(m_PackageUnzFile) == UNZ_OK);

	if (!m_MergeSkins && m_BackupSkins)
	{
		KeepVariables();
	}

	return true;
}
bool DialogInstall::ReadPackage()
{
	const WCHAR* fileName = m_PackageFileName.c_str();
	const WCHAR* fileExtension = PathFindExtension(fileName);

	if (_wcsicmp(fileExtension, L".rmskin") == 0)
	{
		// Check if the footer is present (for new .rmskin format)
		PackageFooter footer = {0};

		FILE* file = _wfopen(fileName, L"rb");
		__int64 fileSize = 0;
		if (file)
		{
			fseek(file, -(long)sizeof(footer), SEEK_END);
			fileSize = _ftelli64(file);
			fread(&footer, sizeof(footer), 1, file);
			fclose(file);
		}

		if (strcmp(footer.key, "RMSKIN") == 0)
		{
			m_PackageFormat = PackageFormat::New;
			if (footer.size != fileSize)
			{
				return false;
			}

			if (footer.flags)
			{
				m_BackupPackage = !(footer.flags & PackageFlag::Backup);
			}
		}
	}
	else if (_wcsicmp(fileExtension, L".zip") != 0)
	{
		return false;
	}

	m_PackageUnzFile = unzOpen(ConvertToAscii(fileName).c_str());
	if (!m_PackageUnzFile)
	{
		return false;
	}

	WCHAR buffer[MAX_PATH];

	// Get temporary file to extract the options file and header bitmap
	GetTempPath(MAX_PATH, buffer);
	GetTempFileName(buffer, L"dat", 0, buffer);
	std::wstring tempFile = buffer;
	const WCHAR* tempFileSz = tempFile.c_str();

	// Helper to sets buffer with current file name
	auto getFileInfo = [&]()->bool
	{
		char cBuffer[MAX_PATH * 3];
		unz_file_info ufi;
		if (unzGetCurrentFileInfo(
				m_PackageUnzFile, &ufi, cBuffer, _countof(cBuffer), nullptr, 0, nullptr, 0) == UNZ_OK)
		{
			const uLong ZIP_UTF8_FLAG = 1 << 11;
			const DWORD codePage = (ufi.flag & ZIP_UTF8_FLAG) ? CP_UTF8 : CP_ACP;
			MultiByteToWideChar(codePage, 0, cBuffer, strlen(cBuffer) + 1, buffer, MAX_PATH);
			while (WCHAR* pos = wcschr(buffer, L'/')) *pos = L'\\';
			return true;
		}

		return false;
	};

	// Loop through the contents of the archive until the settings file is found
	WCHAR* path;
	bool optionsFound = false;
	do
	{
		if (!getFileInfo())
		{
			return false;
		}

		path = wcsrchr(buffer, L'\\');
		if (!path)
		{
			path = buffer;
		}
		else
		{
			if (m_PackageFormat == PackageFormat::New)
			{
				// New package files must be in root of archive
				continue;
			}

			++path;	// Skip slash
		}

		if (_wcsicmp(path, m_PackageFormat == PackageFormat::New ? L"RMSKIN.ini" : L"Rainstaller.cfg") == 0)
		{
			if (ExtractCurrentFile(tempFile))
			{
				optionsFound = ReadOptions(tempFileSz);
				DeleteFile(tempFileSz);
			}

			break;
		}
	}
	while (unzGoToNextFile(m_PackageUnzFile) == UNZ_OK);

	if (!optionsFound)
	{
		return false;
	}

	// Loop through the archive a second time and find included components
	unzGoToFirstFile(m_PackageUnzFile);

	m_PackageRoot.assign(buffer, path - buffer);
	const WCHAR* root = m_PackageRoot.c_str();
	do
	{
		if (!getFileInfo())
		{
			return false;
		}

		if (wcsncmp(buffer, root, m_PackageRoot.length()) != 0)
		{
			// Ignore everything that isn't in the root directory
			continue;
		}

		WCHAR* component = buffer + m_PackageRoot.length();
		path = wcschr(component, L'\\');
		if (path)
		{
			*path = L'\0';
			++path;
		}
		else
		{
			if (_wcsicmp(component, m_PackageFormat == PackageFormat::New ? L"RMSKIN.bmp" : L"Rainstaller.bmp") == 0)
			{
				if (!ExtractCurrentFile(tempFile))
				{
					return false;
				}

				m_HeaderBitmap = (HBITMAP)LoadImage(nullptr, tempFileSz, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
				DeleteFile(tempFileSz);
			}

			continue;
		}

		const WCHAR* pos = wcschr(path, L'\\');
		const WCHAR* extension = PathFindExtension(pos ? pos : path);
		if (pos)
		{
			// Component with subfolders
			const std::wstring item(path, pos - path);
			const WCHAR* itemSz = item.c_str();

			if (_wcsicmp(component, L"Skins") == 0 &&
				!IsIgnoredSkin(itemSz))
			{
				m_PackageSkins.insert(item);
			}
			else if (_wcsicmp(component, m_PackageFormat == PackageFormat::New ? L"Layouts" : L"Themes") == 0 &&
				_wcsicmp(extension, m_PackageFormat == PackageFormat::New ? L".ini" : L".thm") == 0 &&
				!IsIgnoredLayout(itemSz))
			{
				m_PackageLayouts.insert(item);
			}
			else if (_wcsicmp(component, L"Addons") == 0 &&
				m_PackageFormat == PackageFormat::Old &&
				!IsIgnoredAddon(itemSz))
			{
				m_PackageAddons.insert(item);
			}
			else if (_wcsicmp(component, L"Plugins") == 0 &&
				_wcsicmp(itemSz, IsWin32Build() ? L"32bit" : L"64bit") == 0 &&
				_wcsicmp(extension, L".dll") == 0 &&
				!wcschr(pos + 1, L'\\'))
			{
				const std::wstring plugin(pos + 1);
				if (!IsIgnoredPlugin(plugin.c_str()))
				{
					m_PackagePlugins.insert(plugin);
				}
			}
		}
		else
		{
			// Component with subfiles
			const std::wstring item = path;
			const WCHAR* itemSz = item.c_str();

			if (_wcsicmp(component, L"Fonts") == 0 &&
				m_PackageFormat == PackageFormat::Old &&
				_wcsicmp(extension, L".ttf") == 0)
			{
				m_PackageFonts.insert(item);
			}
		}
	}
	while (unzGoToNextFile(m_PackageUnzFile) == UNZ_OK);

	if (m_PackageSkins.empty())
	{
		// Fonts can be installed only with skins
		m_PackageFonts.clear();
	}

	return !(m_PackageSkins.empty() && m_PackageLayouts.empty() &&
		m_PackageAddons.empty() && m_PackageFonts.empty() && m_PackagePlugins.empty());
}
Exemple #10
0
EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
{
  Archive Arc(Cmd);
  if (!Arc.WOpen(ArcName,ArcNameW))
  {
    ErrHandler.SetErrorCode(OPEN_ERROR);
    return(EXTRACT_ARC_NEXT);
  }

  if (!Arc.IsArchive(true))
  {
#ifndef GUI
    mprintf(St(MNotRAR),ArcName);
#endif
    if (CmpExt(ArcName,"rar"))
      ErrHandler.SetErrorCode(WARNING);
    return(EXTRACT_ARC_NEXT);
  }

  // archive with corrupt encrypted header can be closed in IsArchive() call
  if (!Arc.IsOpened())
    return(EXTRACT_ARC_NEXT);

#ifndef SFX_MODULE
  if (Arc.Volume && Arc.NotFirstVolume)
  {
    char FirstVolName[NM];
    VolNameToFirstName(ArcName,FirstVolName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0);

    // If several volume names from same volume set are specified
    // and current volume is not first in set and first volume is present
    // and specified too, let's skip the current volume.
    if (stricomp(ArcName,FirstVolName)!=0 && FileExist(FirstVolName) &&
        Cmd->ArcNames->Search(FirstVolName,NULL,false))
      return(EXTRACT_ARC_NEXT);
  }
#endif

  int64 VolumeSetSize=0; // Total size of volumes after the current volume.

  if (Arc.Volume)
  {
    // Calculate the total size of all accessible volumes.
    // This size is necessary to display the correct total progress indicator.

    char NextName[NM];
    wchar NextNameW[NM];

    strcpy(NextName,Arc.FileName);
    strcpyw(NextNameW,Arc.FileNameW);

    while (true)
    {
      // First volume is already added to DataIO.TotalArcSize 
      // in initial TotalArcSize calculation in DoExtract.
      // So we skip it and start from second volume.
      NextVolumeName(NextName,NextNameW,ASIZE(NextName),(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat);
      struct FindData FD;
      if (FindFile::FastFind(NextName,NextNameW,&FD))
        VolumeSetSize+=FD.Size;
      else
        break;
    }
    DataIO.TotalArcSize+=VolumeSetSize;
  }

  ExtractArchiveInit(Cmd,Arc);

  if (*Cmd->Command=='T' || *Cmd->Command=='I')
    Cmd->Test=true;

#ifndef GUI
  if (*Cmd->Command=='I')
    Cmd->DisablePercentage=true;
  else
    if (Cmd->Test)
      mprintf(St(MExtrTest),ArcName);
    else
      mprintf(St(MExtracting),ArcName);
#endif

  Arc.ViewComment();

  // RAR can close a corrupt encrypted archive
  if (!Arc.IsOpened())
    return(EXTRACT_ARC_NEXT);


  while (1)
  {
    size_t Size=Arc.ReadHeader();
    bool Repeat=false;
    if (!ExtractCurrentFile(Cmd,Arc,Size,Repeat))
      if (Repeat)
      {
        // If we started extraction from not first volume and need to
        // restart it from first, we must correct DataIO.TotalArcSize
        // for correct total progress display. We subtract the size
        // of current volume and all volumes after it and add the size
        // of new (first) volume.
        struct FindData OldArc,NewArc;
        if (FindFile::FastFind(Arc.FileName,Arc.FileNameW,&OldArc) &&
            FindFile::FastFind(ArcName,ArcNameW,&NewArc))
          DataIO.TotalArcSize-=VolumeSetSize+OldArc.Size-NewArc.Size;
        return(EXTRACT_ARC_REPEAT);
      }
      else
        break;
  }

  return(EXTRACT_ARC_NEXT);
}
Exemple #11
0
EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
{
  Archive Arc(Cmd);
  if (!Arc.WOpen(ArcName,ArcNameW))
  {
    ErrHandler.SetErrorCode(OPEN_ERROR);
    return(EXTRACT_ARC_NEXT);
  }

  if (!Arc.IsArchive(true))
  {
#ifndef GUI
    mprintf(St(MNotRAR),ArcName);
#endif
    if (CmpExt(ArcName,"rar"))
      ErrHandler.SetErrorCode(WARNING);
    return(EXTRACT_ARC_NEXT);
  }

  if (!Arc.IsOpened())
    return(EXTRACT_ARC_NEXT);

#ifndef SFX_MODULE
  if (Arc.Volume && Arc.NotFirstVolume)
  {
    char FirstVolName[NM];

    VolNameToFirstName(ArcName,FirstVolName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING));
    if (stricomp(ArcName,FirstVolName)!=0 && FileExist(FirstVolName) &&
        Cmd->ArcNames->Search(FirstVolName,NULL,false))
      return(EXTRACT_ARC_NEXT);
  }
#endif
  ExtractArchiveInit(Cmd,Arc);

  if (*Cmd->Command=='T' || *Cmd->Command=='I')
    Cmd->Test=true;

#ifndef GUI
  if (*Cmd->Command=='I')
    Cmd->DisablePercentage=true;
  else
    if (Cmd->Test)
      mprintf(St(MExtrTest),ArcName);
    else
      mprintf(St(MExtracting),ArcName);
#endif

  Arc.ViewComment();

  while (1)
  {
    int Size=Arc.ReadHeader();
    bool Repeat=false;
    if (!ExtractCurrentFile(Cmd,Arc,Size,Repeat))
      if (Repeat)
      {
        return(EXTRACT_ARC_REPEAT);
      }
      else
        break;
  }
  return(EXTRACT_ARC_NEXT);
}