Exemplo n.º 1
0
// This internal function copies each file into a temporary zip that matches file specification, then does this for each subdirectory if requested
void ZipFile::UpdateFilesInZip(ZipFile* TempZipFile, String* FileSpec, String* CurrDirectory, int RootPathLength, UpdateOption UpdateWhen, Boolean AddNewFiles, Boolean RecurseSubdirectories, PathInclusion AddPathMethod, char* Password)
{
	IEnumerator* filesEnum = Directory::GetFiles(CurrDirectory, FileSpec)->GetEnumerator();
	String* fullFileName;
	String* adjustedFileName;
	CompressedFile* file;
	DateTime lastUpdate;
	bool updateFile;

	while (filesEnum->MoveNext())
	{
		fullFileName = filesEnum->Current->ToString();
		adjustedFileName = GetAdjustedFileName(fullFileName, RootPathLength, AddPathMethod);

		if (file = files->get_Item(adjustedFileName))
		{
			lastUpdate = File::GetLastWriteTime(fullFileName);

			switch (UpdateWhen)
			{
				case UpdateOption::Never:
					updateFile = false;
					break;
				case UpdateOption::Always:
					updateFile = true;
					break;
				case UpdateOption::ZipFileIsNewer:
					updateFile = (DateTime::Compare(file->get_FileDateTime(), lastUpdate) > 0);
					break;
				case UpdateOption::DiskFileIsNewer:
					updateFile = (DateTime::Compare(file->get_FileDateTime(), lastUpdate) < 0);
					break;
				default:
					updateFile = false;
					break;
			}

			if (updateFile)
			{
				// Need to update compressed file from disk, so we add the it the new temporary archive
				AddFileToZip(TempZipFile, this, fullFileName, adjustedFileName, Password, S"Update Zip File");
			}
			else
			{
				// Otherwise we just copy the compressed file from the original archive
				CopyFileInZip(file, this, TempZipFile, S"Update Zip File");
			}
		}
		else if (AddNewFiles)
		{
			// This was a new file so we just add it the new zip, if requested...
			AddFileToZip(TempZipFile, this, fullFileName, adjustedFileName, Password, S"Update Zip File");
		}
	}

	if (RecurseSubdirectories)
	{
		IEnumerator* dirsEnum = Directory::GetDirectories(CurrDirectory, "*")->GetEnumerator();

		while (dirsEnum->MoveNext())
			UpdateFilesInZip(TempZipFile, FileSpec, dirsEnum->Current->ToString(), RootPathLength, UpdateWhen, AddNewFiles, RecurseSubdirectories, AddPathMethod, Password);
	}
}
Exemplo n.º 2
0
// Extracts specified files from zip
void ZipFile::Extract(String* FileSpec, String* DestPath, UpdateOption OverwriteWhen, Boolean RecurseSubdirectories, PathInclusion CreatePathMethod)
{
	// Any file spec in destination path will be ignored
	DestPath = JustPath(DestPath);

	char* pszPassword = NULL;
	char* pszFileName = NULL;
	OpenFileForUnzip();

	// Just wrapping in a try/catch/finally to make sure unmanaged code allocations always get released
	try
	{
		Regex* filePattern = GetFilePatternRegularExpression(FileSpec, caseSensitive);
		IEnumerator* filesEnum = files->GetEnumerator();
		CompressedFile* file;
		String* sourceFileName;
		String* destFileName;
		bool writeFile;
 		int err;

		// Get ANSI password, if one was provided
		if (password)
			if (password->get_Length())
				pszPassword = StringToCharBuffer(password);

		// Loop through compressed file collection
		while (filesEnum->MoveNext())
		{
			file = static_cast<CompressedFile*>(filesEnum->Current);
			sourceFileName = file->get_FileName();

			if (filePattern->IsMatch(GetSearchFileName(FileSpec, sourceFileName, RecurseSubdirectories)))
			{
				pszFileName = StringToCharBuffer(sourceFileName);
				err = unzLocateFile(hUnzipFile, pszFileName, (caseSensitive ? 1 : 2));
				free(pszFileName);
				pszFileName = NULL;

				// We should find file in zip file if it was in our compressed file collection
				if (err != Z_OK) throw new CompressionException(String::Concat(S"Extract Zip File Error: Compressed file \"", sourceFileName, "\" cannot be found in zip file!"));

				// Open compressed file for unzipping
				if (pszPassword)
					err = unzOpenCurrentFilePassword(hUnzipFile, pszPassword);
				else
					err = unzOpenCurrentFile(hUnzipFile);

				if (err != Z_OK) throw new CompressionException(S"Extract Zip File", err);

				// Get full destination file name
				switch (CreatePathMethod)
				{
					case PathInclusion::FullPath:
						destFileName = sourceFileName;
						break;
					case PathInclusion::NoPath:
						destFileName = String::Concat(DestPath, Path::GetFileName(sourceFileName));
						break;
					case PathInclusion::RelativePath:
						destFileName = String::Concat(DestPath, sourceFileName);
						break;
				}

				// Make sure destination directory exists
				Directory::CreateDirectory(JustPath(destFileName));

				// See if destination file already exists
				if (File::Exists(destFileName))
				{
					DateTime lastUpdate = File::GetLastWriteTime(destFileName);

					switch (OverwriteWhen)
					{
						case UpdateOption::Never:
							writeFile = false;
							break;
						case UpdateOption::Always:
							writeFile = true;
							break;
						case UpdateOption::ZipFileIsNewer:
							writeFile = (DateTime::Compare(file->get_FileDateTime(), lastUpdate) > 0);
							break;
						case UpdateOption::DiskFileIsNewer:
							writeFile = (DateTime::Compare(file->get_FileDateTime(), lastUpdate) < 0);
							break;
						default:
							writeFile = false;
							break;
					}
				}
				else
					writeFile = true;

				if (writeFile)
				{
					System::Byte buffer[] = new System::Byte[BufferSize];
					System::Byte __pin * destBuff = &buffer[0];	// pin buffer so it can be safely passed into unmanaged code...
					FileStream* fileStream = File::Create(destFileName);
					int read;
					__int64 total = 0, len = -1;

					// Send initial progress event
					len = file->get_UncompressedSize();
					CurrentFile(destFileName, sourceFileName);
					FileProgress(0, len);					

					// Read initial buffer
					read = unzReadCurrentFile(hUnzipFile, destBuff, buffer->get_Length());
					if (read < 0) throw new CompressionException(S"Extract Zip File", read);

					while (read)
					{
						// Write data to file stream,
						fileStream->Write(buffer, 0, read);

						// Raise progress event
						total += read;
						FileProgress(total, len);

						// Read next buffer from source file stream
						read = unzReadCurrentFile(hUnzipFile, destBuff, buffer->get_Length());
						if (read < 0) throw new CompressionException(S"Extract Zip File", read);
					}

					fileStream->Close();
				}

				// Close compressed file
				unzCloseCurrentFile(hUnzipFile);
			}
		}
	}
	catch (CompressionException* ex)		
	{
		// We just rethrow any errors back to user
		throw ex;
	}
	catch (Exception* ex)
	{
		throw ex;
	}
	__finally
	{
		if (pszPassword)
			free(pszPassword);

		if (pszFileName)
			free(pszFileName);
	}
}