I want the generated gzip file to include the original file name in the metadata. How to do this using the Crypto ++ interface?
You cannot be out of the box. This is apparently a limitation of Crypto ++. (But see below.)
From RFC 1952 there is clearly a field for him:
(if FLG.FNAME set)
+=========================================+
|...original file name, zero-terminated...| (more
+=========================================+
But Crypto ++ does not allow you to install it (from gzip.c source code ):
void Gzip::WritePrestreamHeader()
{
m_totalLen = 0;
m_crc.Restart();
AttachedTransformation()->Put(MAGIC1);
AttachedTransformation()->Put(MAGIC2);
AttachedTransformation()->Put(DEFLATED);
AttachedTransformation()->Put(0);
AttachedTransformation()->PutWord32(0);
byte extra = (GetDeflateLevel() == 1) ? FAST : ((GetDeflateLevel() == 9) ? SLOW : 0);
AttachedTransformation()->Put(extra);
AttachedTransformation()->Put(GZIP_OS_CODE);
}
And Crypto ++ silently discards it if it is present during unpacking ( Gunzip- the GZIP decompressor) (from the source code of gzip.c ):
void Gunzip::ProcessPrestreamHeader()
{
...
if (flags & EXTRA_FIELDS)
{
word16 length;
if (m_inQueue.GetWord16(length, LITTLE_ENDIAN_ORDER) != 2) throw HeaderErr();
if (m_inQueue.Skip(length)!=length) throw HeaderErr();
}
if (flags & FILENAME)
do
if(!m_inQueue.Get(b)) throw HeaderErr();
while (b);
if (flags & COMMENTS)
do
if(!m_inQueue.Get(b)) throw HeaderErr();
while (b);
}
, , 15 , :)
, , , . Crypto ++ Gzip Gunzip. SVN diff Pastebin Diff Crypto ++ gzip . , , reset Gzip::WritePoststreamTail.
Gzip Gunzip:
word32 m_filetime;
std::string m_filename;
std::string m_comment;
-, m_filetime ( Gzip Gunzip). , Gzip ctors:
Gzip(const NameValuePairs ¶meters, BufferedTransformation *attachment=NULL)
: Deflator(parameters, attachment), m_filetime(0) {}
-, Gzip:
void SetFiletime(word32 filetime) { m_filetime = filetime; }
void SetFilename(const std::string& filename) { m_filename = filename; }
void SetComment(const std::string& comment) { m_comment = comment; }
-, Gunzip:
word32 GetFiletime() const { return m_filetime; }
const std::string& GetFilename() const { return m_filename; }
const std::string& GetComment() const { return m_comment; }
-, Gzip::WritePrestreamHeader cpp:
void Gzip::WritePrestreamHeader()
{
m_totalLen = 0;
m_crc.Restart();
int flags = 0;
if(!m_filename.empty())
flags |= FILENAME;
if(!m_comment.empty())
flags |= COMMENTS;
AttachedTransformation()->Put(MAGIC1);
AttachedTransformation()->Put(MAGIC2);
AttachedTransformation()->Put(DEFLATED);
AttachedTransformation()->Put((byte)flags);
AttachedTransformation()->PutWord32(m_filetime, LITTLE_ENDIAN_ORDER);
byte extra = (GetDeflateLevel() == 1) ? FAST : ((GetDeflateLevel() == 9) ? SLOW : 0);
AttachedTransformation()->Put(extra);
AttachedTransformation()->Put(GZIP_OS_CODE);
if(!m_filename.empty())
AttachedTransformation()->Put((const unsigned char*)m_filename.data(), m_filename.size() +1);
if(!m_comment.empty())
AttachedTransformation()->Put((const unsigned char*)m_comment.data(), m_comment.size() +1);
}
-, Gzip::WritePoststreamTail cpp:
void Gzip::WritePoststreamTail()
{
SecByteBlock crc(4);
m_crc.Final(crc);
AttachedTransformation()->Put(crc, 4);
AttachedTransformation()->PutWord32(m_totalLen, LITTLE_ENDIAN_ORDER);
m_filetime = 0;
m_filename.erase(0);
m_filename.reserve(16);
m_comment.erase(0);
m_comment.reserve(32);
}
-, Gunzip::ProcessPrestreamHeader cpp:
void Gunzip::ProcessPrestreamHeader()
{
m_length = 0;
m_crc.Restart();
m_filetime = 0;
m_filename.erase(0);
m_filename.reserve(16);
m_comment.erase(0);
m_comment.reserve(32);
byte buf[6];
byte b, flags;
if (m_inQueue.Get(buf, 2)!=2) throw HeaderErr();
if (buf[0] != MAGIC1 || buf[1] != MAGIC2) throw HeaderErr();
if (!m_inQueue.Get(b) || (b != DEFLATED)) throw HeaderErr();
if (!m_inQueue.Get(flags)) throw HeaderErr();
if (flags & (ENCRYPTED | CONTINUED)) throw HeaderErr();
if (m_inQueue.GetWord32(m_filetime, LITTLE_ENDIAN_ORDER) != 4) throw HeaderErr();
if (m_inQueue.Skip(2)!=2) throw HeaderErr();
if (flags & EXTRA_FIELDS)
{
word16 length;
if (m_inQueue.GetWord16(length, LITTLE_ENDIAN_ORDER) != 2) throw HeaderErr();
if (m_inQueue.Skip(length)!=length) throw HeaderErr();
}
if (flags & FILENAME)
{
do
{
if(!m_inQueue.Get(b)) throw HeaderErr();
if(b) m_filename.append( 1, (char)b );
}
while (b);
}
if (flags & COMMENTS)
{
do
{
if(!m_inQueue.Get(b)) throw HeaderErr();
if(b) m_comment.append( 1, (char)b );
}
while (b);
}
}
, :
try {
Gzip zipper(new FileSink("gzip-test.gz", true));
zipper.SetFilename("test-filename.txt");
zipper.SetComment("This is a test of filenames and comments");
string data = "abcdefghijklmnopqrstuvwxyz";
zipper.Put( (unsigned char*) data.c_str(), data.size());
zipper.MessageEnd();
}
catch(CryptoPP::Exception& ex)
{
cerr << ex.what() << endl;
}
gzip-test.gz. test-filename.txt, This is a test of filenames and comments.
:

, gzip -d, Mac OS X: , gz:

, , - , .
: Gzip ?.
: Simon on Super User, gunzip -N <gz-file> , , .
, , .
string s1, s2;
string data = "abcdefghijklmnopqrstuvwxyz";
Gzip zipper(new StringSink(s1));
zipper.SetFilename("test-filename.txt");
zipper.SetComment("This is a test of filenames and comments");
zipper.Put( (unsigned char*) data.c_str(), data.size());
zipper.MessageEnd();
Gunzip unzipper(new StringSink(s2));
unzipper.Put( (unsigned char*) s1.data(), s1.size());
unzipper.MessageEnd();
cout << "Filename: " << unzipper.GetFilename() << endl;
cout << "Comment: " << unzipper.GetComment() << endl;
cout << "Data: " << s2 << endl;
.
. , . , , . , .
, Crypto ++. Crypto ++ . NextMessage() . , , .
, . , , Gzip Gunzip , , , (DEFAULT_CHANNEL) (AAD_CHANNEL) .