Пример #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;
}
Пример #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;
}
Пример #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);
}
Пример #4
0
HRESULT PkOpenPackageWithFilter(
    __in PPK_FILE_STREAM FileStream,
    __inout_opt PPK_ACTION_LIST ActionList,
    __in_opt PPK_PACKAGE_CALLBACK Callback,
    __in_opt PVOID Context,
    __out PPK_PACKAGE *Package
    )
{
    HRESULT result;
    PkFileStream *fileStream;
    IInArchive *inArchive;
    ULONG numberOfItems;
    ULONG i;

    fileStream = (PkFileStream *)FileStream;
    result = PkpCreateSevenZipObject(&SevenZipHandlerGuid, &IID_IInArchive_I, (void **)&inArchive);

    if (!SUCCEEDED(result))
        return result;

    result = inArchive->Open(&fileStream->InStream, NULL, NULL);

    if (!SUCCEEDED(result))
    {
        inArchive->Release();
        return result;
    }

    if (ActionList)
    {
        result = inArchive->GetNumberOfItems((UInt32 *)&numberOfItems);

        if (SUCCEEDED(result))
        {
            if (Callback)
            {
                for (i = 0; i < numberOfItems; i++)
                {
                    PK_PARAMETER_FILTER_ITEM filterItem;
                    PROPVARIANT pathValue;
                    PROPVARIANT attributesValue;
                    PROPVARIANT isDirValue;

                    PropVariantInit(&pathValue);
                    PropVariantInit(&attributesValue);
                    PropVariantInit(&isDirValue);

                    if (SUCCEEDED(inArchive->GetProperty(i, kpidPath, &pathValue)) &&
                        pathValue.vt == VT_BSTR &&
                        SUCCEEDED(inArchive->GetProperty(i, kpidAttrib, &attributesValue)) &&
                        SUCCEEDED(inArchive->GetProperty(i, kpidIsDir, &isDirValue)))
                    {
                        filterItem.Reject = FALSE;
                        filterItem.Path.Length = wcslen(pathValue.bstrVal) * sizeof(WCHAR);
                        filterItem.Path.Buffer = pathValue.bstrVal;
                        filterItem.FileAttributes = attributesValue.uintVal;
                        filterItem.NewContext = NULL;

                        if (isDirValue.boolVal)
                            filterItem.FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;

                        Callback(PkFilterItemMessage, NULL, &filterItem, Context);

                        if (!filterItem.Reject)
                        {
                            PkAppendUpdateToActionList(ActionList, i, filterItem.NewContext);
                        }

                        PropVariantClear(&pathValue);
                        PropVariantClear(&attributesValue);
                        PropVariantClear(&isDirValue);
                    }
                    else
                    {
                        result = E_FAIL;
                        PropVariantClear(&pathValue);
                        PropVariantClear(&attributesValue);
                        PropVariantClear(&isDirValue);
                        break;
                    }
                }
            }
            else
            {
                for (i = 0; i < numberOfItems; i++)
                {
                    PkAppendUpdateToActionList(ActionList, i, NULL);
                }
            }
        }
    }

    if (SUCCEEDED(result))
        *Package = (PPK_PACKAGE)inArchive;
    else
        inArchive->Release();

    return result;
}