Example #1
0
int ArchiveFile::ExtractItem(int index, const char* outFilename) const
{
	assert(!s_formatInfos.empty());
	//assert(index >= 0 && index < m_numItems);
	if(!(index >= 0 && index < m_numItems)) return 0;

	ArchiveItem& item = m_items[index];
	int rv = item.size;

#ifndef ANDROID
	DWORD outAttributes = GetFileAttributes(outFilename);
	if(outAttributes & FILE_ATTRIBUTE_READONLY)
		SetFileAttributes(outFilename, outAttributes & ~FILE_ATTRIBUTE_READONLY); // temporarily remove read-only attribute so we can decompress to there
#endif

	if(m_typeIndex < 0)
	{
#ifndef ANDROID //I don't *think* we care about this
		// uncompressed
		if(!CopyFile(m_filename, outFilename, false))
#endif
			rv = 0;
	}
	else
	{
		IInArchive* object = NULL;
		HRESULT hr = E_FAIL;
		if(SUCCEEDED(CreateObject(&s_formatInfos[m_typeIndex].guid, &IID_IInArchive, (void**)&object)))
		{
			InFileStream* ifs = new InFileStream(m_filename);
			if(SUCCEEDED(object->Open(ifs,0,0)))
			{
				gameInfo.resize(rv);
				OutStream* os = new OutStream(index, outFilename);
				const UInt32 indices [1] = {index};
				hr = object->Extract(indices, 1, 0, os);
				object->Close();
			}
			object->Release();
		}
		if(FAILED(hr))
			rv = 0;
	}

#ifndef ANDROID
	if(outAttributes & FILE_ATTRIBUTE_READONLY)
		SetFileAttributes(outFilename, outAttributes); // restore read-only attribute
#endif

	return rv;
}
Example #2
0
int ArchiveFile::ExtractItem(int index, unsigned char* outBuffer, int bufSize) const
{
	assert(!s_formatInfos.empty());
	//assert(index >= 0 && index < m_numItems);
	if(!(index >= 0 && index < m_numItems)) return 0;

	ArchiveItem& item = m_items[index];

	if(bufSize < item.size)
		return 0;

	if(m_typeIndex < 0)
	{
		// uncompressed
		FILE* file = fopen(m_filename, "rb");
		fread(outBuffer, 1, item.size, file);
		fclose(file);
	}
	else
	{
		IInArchive* object = NULL;
		HRESULT hr = E_FAIL;
		if(SUCCEEDED(CreateObject(&s_formatInfos[m_typeIndex].guid, &IID_IInArchive, (void**)&object)))
		{
			InFileStream* ifs = new InFileStream(m_filename);
			if(SUCCEEDED(object->Open(ifs,0,0)))
			{
				OutStream* os = new OutStream(index, outBuffer, item.size);
				const UInt32 indices [1] = {index};
				hr = object->Extract(indices, 1, 0, os);
				object->Close();
			}
			object->Release();
		}
		if(FAILED(hr))
			return 0;
	}

	return item.size;
}
Example #3
0
ArchiveFile::ArchiveFile(const char* filename)
{
	assert(!s_formatInfos.empty());

	m_typeIndex = -1;
	m_numItems = 0;
	m_items = NULL;
	m_filename = NULL;

	FILE* file = fopen(filename, "rb");
	if(!file)
		return;

	m_filename = new char[strlen(filename)+1];
	strcpy(m_filename, filename);

	// detect archive type using format signature in file
	for(size_t i = 0; i < s_formatInfos.size() && m_typeIndex < 0; i++)
	{
		fseek(file, 0, SEEK_SET);
		
		std::string& formatSig = s_formatInfos[i].signature;
		int len = formatSig.size();

		if(len == 0)
			continue; // because some formats have no signature

		char* fileSig = (char*)_alloca(len);
		fread(fileSig, 1, len, file);

		if(!memcmp(formatSig.c_str(), fileSig, len))
			m_typeIndex = i;
	}

	// if no signature match has been found, detect archive type using filename.
	// this is only for signature-less formats
	const char* fileExt = strrchr(filename, '.');
	if(fileExt++)
	{
		for(size_t i = 0; i < s_formatInfos.size() && m_typeIndex < 0; i++)
		{
			if(s_formatInfos[i].signature.empty())
			{
				std::vector<std::string>& formatExts = s_formatInfos[i].extensions;
				for(size_t j = 0; j < formatExts.size(); j++)
				{
					if(!_stricmp(formatExts[j].c_str(), fileExt))
					{
						m_typeIndex = i;
						break;
					}
				}
			}
		}
	}

	if(m_typeIndex < 0)
	{
		// uncompressed

		m_numItems = 1;
		m_items = new ArchiveItem[m_numItems];

		fseek(file, 0, SEEK_END);
		m_items[0].size = ftell(file);

		m_items[0].name = new char[strlen(filename)+1];
		strcpy(m_items[0].name, filename);
	}
	else
	{
		IInArchive* object = NULL;
		if(SUCCEEDED(CreateObject(&s_formatInfos[m_typeIndex].guid, &IID_IInArchive, (void**)&object)))
		{
			InFileStream* ifs = new InFileStream(filename);
			if(SUCCEEDED(object->Open(ifs,0,0)))
			{
				UInt32 numItems = 0;
				object->GetNumberOfItems(&numItems);
				m_numItems = numItems;
				m_items = new ArchiveItem[m_numItems];

				for(int i = 0; i < m_numItems; i++)
				{
					PROPVARIANT var = {VT_EMPTY};
					ArchiveItem& item = m_items[i];

					object->GetProperty(i, kpidSize, &var);
					item.size = var.uhVal.LowPart;

					object->GetProperty(i, kpidPath, &var);
					std::string& path = wstrToStr(var.bstrVal);
					item.name = new char[path.size()+1];
					strcpy(item.name, path.c_str());

					//object->GetProperty(i, kpidMethod, &var);
					//std::string& method = wstrToStr(var.bstrVal);
					//item.method = new char[method.size()+1];
					//strcpy(item.method, method.c_str());

					object->GetProperty(i, kpidEncrypted, &var);
#ifdef _NO_CRYPTO
					if(var.boolVal)
						item.size = 0; // don't support decompressing it, pretend size zero
#else
					#error password support NYI... see client7z.cpp
					item.encrypted = !!var.boolVal;
#endif

					VariantClear((VARIANTARG*)&var);
				}

				object->Close();
			}

			object->Release();
		}
	}

	fclose(file);
}