15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/filter/gzip_header.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <algorithm> 84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/zlib/zlib.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint8 GZipHeader::magic[] = { 0x1f, 0x8b }; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GZipHeader::GZipHeader() { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Reset(); 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GZipHeader::~GZipHeader() { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GZipHeader::Reset() { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = IN_HEADER_ID1; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags_ = 0; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extra_length_ = 0; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GZipHeader::Status GZipHeader::ReadMore(const char* inbuf, int inbuf_len, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char** header_end) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(inbuf_len, 0); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* pos = reinterpret_cast<const uint8*>(inbuf); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* const end = pos + inbuf_len; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ( pos < end ) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch ( state_ ) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_HEADER_ID1: 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( *pos != magic[0] ) return INVALID_HEADER; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_HEADER_ID2: 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( *pos != magic[1] ) return INVALID_HEADER; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_HEADER_CM: 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( *pos != Z_DEFLATED ) return INVALID_HEADER; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_HEADER_FLG: 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags_ = (*pos) & (FLAG_FHCRC | FLAG_FEXTRA | 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAG_FNAME | FLAG_FCOMMENT); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_HEADER_MTIME_BYTE_0: 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_HEADER_MTIME_BYTE_1: 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_HEADER_MTIME_BYTE_2: 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_HEADER_MTIME_BYTE_3: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_HEADER_XFL: 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_HEADER_OS: 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_XLEN_BYTE_0: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( !(flags_ & FLAG_FEXTRA) ) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = IN_FNAME; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have a two-byte little-endian length, followed by a 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // field of that length. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extra_length_ = *pos; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_XLEN_BYTE_1: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extra_length_ += *pos << 8; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We intentionally fall through, because if we have a 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // zero-length FEXTRA, we want to check to notice that we're 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // done reading the FEXTRA before we exit this loop... 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_FEXTRA: { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Grab the rest of the bytes in the extra field, or as many 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of them as are actually present so far. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int num_extra_bytes = static_cast<const int>(std::min( 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ptrdiff_t>(extra_length_), 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (end - pos))); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos += num_extra_bytes; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extra_length_ -= num_extra_bytes; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( extra_length_ == 0 ) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = IN_FNAME; // advance when we've seen extra_length_ bytes 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags_ &= ~FLAG_FEXTRA; // we're done with the FEXTRA stuff 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_FNAME: 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( !(flags_ & FLAG_FNAME) ) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = IN_FCOMMENT; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if we can find the end of the \0-terminated FNAME field. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos = reinterpret_cast<const uint8*>(memchr(pos, '\0', (end - pos))); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( pos != NULL ) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; // advance past the '\0' 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags_ &= ~FLAG_FNAME; // we're done with the FNAME stuff 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = IN_FCOMMENT; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos = end; // everything we have so far is part of the FNAME 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_FCOMMENT: 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( !(flags_ & FLAG_FCOMMENT) ) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = IN_FHCRC_BYTE_0; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if we can find the end of the \0-terminated FCOMMENT field. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos = reinterpret_cast<const uint8*>(memchr(pos, '\0', (end - pos))); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( pos != NULL ) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; // advance past the '\0' 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags_ &= ~FLAG_FCOMMENT; // we're done with the FCOMMENT stuff 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = IN_FHCRC_BYTE_0; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos = end; // everything we have so far is part of the FNAME 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_FHCRC_BYTE_0: 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( !(flags_ & FLAG_FHCRC) ) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = IN_DONE; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_FHCRC_BYTE_1: 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos++; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags_ &= ~FLAG_FHCRC; // we're done with the FHCRC stuff 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_++; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IN_DONE: 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *header_end = reinterpret_cast<const char*>(pos); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return COMPLETE_HEADER; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( (state_ > IN_HEADER_OS) && (flags_ == 0) ) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *header_end = reinterpret_cast<const char*>(pos); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return COMPLETE_HEADER; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return INCOMPLETE_HEADER; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 182