Warning, file /include/xrootd/private/XrdZip/XrdZipCDFH.hh was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #ifndef SRC_XRDZIP_XRDZIPCDFH_HH_
0026 #define SRC_XRDZIP_XRDZIPCDFH_HH_
0027
0028 #include "XrdZip/XrdZipLFH.hh"
0029 #include "XrdZip/XrdZipUtils.hh"
0030 #include "XrdZip/XrdZipDataDescriptor.hh"
0031
0032 #include <string>
0033 #include <algorithm>
0034 #include <iterator>
0035 #include <unordered_map>
0036 #include <memory>
0037 #include <tuple>
0038
0039 #include <sys/types.h>
0040
0041 namespace XrdZip
0042 {
0043
0044
0045
0046 struct CDFH;
0047
0048
0049
0050
0051 typedef std::vector<std::unique_ptr<CDFH>> cdvec_t;
0052
0053
0054
0055
0056 typedef std::unordered_map<std::string, size_t> cdmap_t;
0057
0058
0059
0060
0061 typedef std::unordered_map<std::string, std::unique_ptr<CDFH>> cdrecs_t;
0062
0063
0064
0065
0066 struct CDFH
0067 {
0068
0069
0070
0071
0072
0073
0074
0075 inline static std::tuple<cdvec_t, cdmap_t> Parse( const char *buffer, uint32_t bufferSize, uint16_t nbCdRecords )
0076 {
0077 uint32_t offset = 0;
0078 cdvec_t cdvec;
0079 cdmap_t cdmap;
0080 cdvec.reserve( nbCdRecords );
0081
0082 for( size_t i = 0; i < nbCdRecords; ++i )
0083 {
0084 if( bufferSize < cdfhBaseSize ) break;
0085
0086 uint32_t signature = to<uint32_t>( buffer + offset );
0087 if( signature != cdfhSign ) throw bad_data();
0088
0089 std::unique_ptr<CDFH> cdfh( new CDFH( buffer + offset, bufferSize ) );
0090 offset += cdfh->cdfhSize;
0091 bufferSize -= cdfh->cdfhSize;
0092 cdmap[cdfh->filename] = i;
0093 cdvec.push_back( std::move( cdfh ) );
0094 }
0095
0096 return std::make_tuple( std::move( cdvec ), std::move( cdmap ) );
0097 }
0098
0099
0100
0101
0102
0103
0104
0105 inline static std::tuple<cdvec_t, cdmap_t> Parse( const char *&buffer, uint32_t bufferSize )
0106 {
0107 cdvec_t cdvec;
0108 cdmap_t cdmap;
0109 size_t i = 0;
0110 while( bufferSize > 0 )
0111 {
0112 if( bufferSize < sizeof( uint32_t ) ) throw bad_data();
0113
0114 uint32_t signature = to<uint32_t>( buffer );
0115 if( signature != cdfhSign )
0116 return std::make_tuple( std::move( cdvec ), std::move( cdmap ) );
0117
0118 std::unique_ptr<CDFH> cdfh( new CDFH( buffer ) );
0119 if( bufferSize < cdfh->cdfhSize ) throw bad_data();
0120 buffer += cdfh->cdfhSize;
0121 bufferSize -= cdfh->cdfhSize;
0122 cdmap[cdfh->filename] = i++;
0123 cdvec.push_back( std::move( cdfh ) );
0124 }
0125
0126 return std::make_tuple( std::move( cdvec ), std::move( cdmap ) );
0127 }
0128
0129
0130
0131
0132 inline static size_t CalcSize( const cdvec_t &cdvec, uint32_t orgcdsz, uint32_t orgcdcnt )
0133 {
0134 size_t size = 0;
0135 auto itr = cdvec.begin() + orgcdcnt;
0136 for( ; itr != cdvec.end() ; ++itr )
0137 {
0138 CDFH *cdfh = itr->get();
0139 size += cdfh->cdfhSize;
0140 }
0141 return size + orgcdsz;
0142 }
0143
0144 inline static void Serialize( uint32_t orgcdcnt,
0145 const buffer_t &orgcdbuf,
0146 const cdvec_t &cdvec,
0147 buffer_t &buffer )
0148 {
0149 std::copy( orgcdbuf.begin(), orgcdbuf.end(), std::back_inserter( buffer ) );
0150 auto itr = cdvec.begin() + orgcdcnt;
0151 for( ; itr != cdvec.end() ; ++itr )
0152 {
0153 CDFH *cdfh = itr->get();
0154 cdfh->Serialize( buffer );
0155 }
0156 }
0157
0158
0159
0160
0161 CDFH( LFH *lfh, mode_t mode, uint64_t lfhOffset ):
0162 zipVersion( ( 3 << 8 ) | 63 ),
0163 generalBitFlag( lfh->generalBitFlag ),
0164 compressionMethod( lfh->compressionMethod ),
0165 timestmp( lfh->timestmp ),
0166 ZCRC32( lfh->ZCRC32 ),
0167 compressedSize( lfh->compressedSize ),
0168 uncompressedSize( lfh->uncompressedSize ),
0169 filenameLength( lfh->filenameLength ),
0170 commentLength( 0 ),
0171 nbDisk( 0 ),
0172 internAttr( 0 ),
0173 externAttr( mode << 16 ),
0174 filename( lfh->filename ),
0175 extra( new Extra( lfh->extra.get(), lfhOffset ) )
0176 {
0177 if ( lfhOffset >= ovrflw<uint32_t>::value )
0178 offset = ovrflw<uint32_t>::value;
0179 else
0180 offset = lfhOffset;
0181
0182 extraLength = extra->totalSize;
0183
0184 if ( extraLength == 0 )
0185 minZipVersion = 10;
0186 else
0187 minZipVersion = 45;
0188
0189 cdfhSize = cdfhBaseSize + filenameLength + extraLength + commentLength;
0190 }
0191
0192
0193
0194
0195 CDFH( const char *buffer, const uint32_t maxSize = 0 )
0196 {
0197 zipVersion = to<uint16_t>(buffer + 4);
0198 minZipVersion = to<uint16_t>(buffer + 6);
0199 generalBitFlag = to<uint16_t>(buffer + 8);
0200 compressionMethod = to<uint16_t>(buffer + 10);
0201 timestmp.time = to<uint16_t>(buffer + 12);
0202 timestmp.date = to<uint16_t>(buffer + 14);
0203 ZCRC32 = to<uint32_t>(buffer + 16);
0204 compressedSize = to<uint32_t>(buffer + 20);
0205 uncompressedSize = to<uint32_t>(buffer + 24);
0206 filenameLength = to<uint16_t>(buffer + 28);
0207 extraLength = to<uint16_t>(buffer + 30);
0208 commentLength = to<uint16_t>(buffer + 32);
0209 nbDisk = to<uint16_t>(buffer + 34);
0210 internAttr = to<uint16_t>(buffer + 36);
0211 externAttr = to<uint32_t>(buffer + 38);
0212 offset = to<uint32_t>(buffer + 42);
0213 if(maxSize > 0 && (uint32_t)(cdfhBaseSize+filenameLength + extraLength + commentLength) > maxSize){
0214 throw bad_data();
0215 }
0216 filename.assign( buffer + 46, filenameLength );
0217
0218
0219 ParseExtra( buffer + 46 + filenameLength, extraLength );
0220
0221 cdfhSize = cdfhBaseSize + filenameLength + extraLength + commentLength;
0222 }
0223
0224
0225
0226
0227 inline static uint64_t GetOffset( const CDFH &cdfh )
0228 {
0229 if( cdfh.offset != ovrflw<uint32_t>::value )
0230 return cdfh.offset;
0231 return cdfh.extra->offset;
0232 }
0233
0234
0235
0236
0237 void ParseExtra( const char *buffer, uint16_t length)
0238 {
0239 uint8_t ovrflws = Extra::NONE;
0240 uint16_t exsize = 0;
0241
0242
0243 if( compressedSize == ovrflw<uint32_t>::value)
0244 {
0245 ovrflws |= Extra::CPMSIZE;
0246 exsize += sizeof( uint64_t );
0247 }
0248
0249
0250 if( uncompressedSize == ovrflw<uint32_t>::value )
0251 {
0252 ovrflws |= Extra::UCMPSIZE;
0253 exsize += sizeof( uint64_t );
0254 }
0255
0256
0257 if( offset == ovrflw<uint32_t>::value )
0258 {
0259 ovrflws |= Extra::OFFSET;
0260 exsize += sizeof( uint64_t );
0261 }
0262
0263
0264 if( nbDisk == ovrflw<uint16_t>::value )
0265 {
0266 ovrflws |= Extra::NBDISK;
0267 exsize += sizeof( uint32_t );
0268 }
0269
0270
0271
0272 if( exsize == 0 ) return;
0273
0274
0275 buffer = Extra::Find( buffer, length );
0276 if( buffer )
0277 {
0278 extra.reset( new Extra() );
0279 extra->FromBuffer( buffer, exsize, ovrflws );
0280 }
0281 }
0282
0283
0284
0285
0286 void Serialize( buffer_t &buffer )
0287 {
0288 copy_bytes( cdfhSign, buffer );
0289 copy_bytes( zipVersion, buffer );
0290 copy_bytes( minZipVersion, buffer );
0291 copy_bytes( generalBitFlag, buffer );
0292 copy_bytes( compressionMethod, buffer );
0293 copy_bytes( timestmp.time, buffer );
0294 copy_bytes( timestmp.date, buffer );
0295 copy_bytes( ZCRC32, buffer );
0296 copy_bytes( compressedSize, buffer );
0297 copy_bytes( uncompressedSize, buffer );
0298 copy_bytes( filenameLength, buffer );
0299 copy_bytes( extraLength, buffer );
0300 copy_bytes( commentLength, buffer );
0301 copy_bytes( nbDisk, buffer );
0302 copy_bytes( internAttr, buffer );
0303 copy_bytes( externAttr, buffer );
0304 copy_bytes( offset, buffer );
0305 std::copy( filename.begin(), filename.end(), std::back_inserter( buffer ) );
0306 if( extra )
0307 extra->Serialize( buffer );
0308
0309 if ( commentLength > 0 )
0310 std::copy( comment.begin(), comment.end(), std::back_inserter( buffer ) );
0311 }
0312
0313
0314
0315
0316 inline bool IsZIP64() const
0317 {
0318 return extra.get();
0319 }
0320
0321
0322
0323
0324 bool HasDataDescriptor()
0325 {
0326 return generalBitFlag & DataDescriptor::flag;
0327 }
0328
0329 uint16_t zipVersion;
0330 uint16_t minZipVersion;
0331 uint16_t generalBitFlag;
0332 uint16_t compressionMethod;
0333 dos_timestmp timestmp;
0334 uint32_t ZCRC32;
0335 uint32_t compressedSize;
0336 uint32_t uncompressedSize;
0337 uint16_t filenameLength;
0338 uint16_t extraLength;
0339 uint16_t commentLength;
0340 uint16_t nbDisk;
0341 uint16_t internAttr;
0342 uint32_t externAttr;
0343 uint32_t offset;
0344 std::string filename;
0345 std::unique_ptr<Extra> extra;
0346 std::string comment;
0347 uint16_t cdfhSize;
0348
0349
0350
0351
0352 static const uint32_t cdfhSign = 0x02014b50;
0353 static const uint16_t cdfhBaseSize = 46;
0354 };
0355 }
0356
0357 #endif