1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2003-2007 Jonathan Turkanis
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
5 
6 // See http://www.boost.org/libs/iostreams for documentation.
7 
8 // To configure Boost to work with libbz2, see the
9 // installation instructions here:
10 // http://boost.org/libs/iostreams/doc/index.html?path=7
11 
12 // Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
13 // knows that we are building the library (possibly exporting code), rather
14 // than using it (possibly importing code).
15 #define BOOST_IOSTREAMS_SOURCE
16 
17 #include <boost/iostreams/detail/config/dyn_link.hpp>
18 #include <boost/iostreams/filter/gzip.hpp>
19 #include <boost/throw_exception.hpp>
20 
21 namespace boost { namespace iostreams {
22 
23 //------------------Implementation of gzip_header-----------------------------//
24 
25 namespace detail {
26 
process(char c)27 void gzip_header::process(char c)
28 {
29     uint8_t value = static_cast<uint8_t>(c);
30     switch (state_) {
31     case s_id1:
32         if (value != gzip::magic::id1)
33             boost::throw_exception(gzip_error(gzip::bad_header));
34         state_ = s_id2;
35         break;
36     case s_id2:
37         if (value != gzip::magic::id2)
38             boost::throw_exception(gzip_error(gzip::bad_header));
39         state_ = s_cm;
40         break;
41     case s_cm:
42         if (value != gzip::method::deflate)
43             boost::throw_exception(gzip_error(gzip::bad_method));
44         state_ = s_flg;
45         break;
46     case s_flg:
47         flags_ = value;
48         state_ = s_mtime;
49         break;
50     case s_mtime:
51         mtime_ += value << (offset_ * 8);
52         if (offset_ == 3) {
53             state_ = s_xfl;
54             offset_ = 0;
55         } else {
56             ++offset_;
57         }
58         break;
59     case s_xfl:
60         state_ = s_os;
61         break;
62     case s_os:
63         os_ = value;
64         if (flags_ & gzip::flags::extra) {
65             state_ = s_xlen;
66         } else if (flags_ & gzip::flags::name) {
67             state_ = s_name;
68         } else if (flags_ & gzip::flags::comment) {
69             state_ = s_comment;
70         } else if (flags_ & gzip::flags::header_crc) {
71             state_ = s_hcrc;
72         } else {
73             state_ = s_done;
74         }
75         break;
76     case s_xlen:
77         xlen_ += value << (offset_ * 8);
78         if (offset_ == 1) {
79             state_ = s_extra;
80             offset_ = 0;
81         } else {
82             ++offset_;
83         }
84         break;
85     case s_extra:
86         if (--xlen_ == 0) {
87             if (flags_ & gzip::flags::name) {
88                 state_ = s_name;
89             } else if (flags_ & gzip::flags::comment) {
90                 state_ = s_comment;
91             } else if (flags_ & gzip::flags::header_crc) {
92                 state_ = s_hcrc;
93             } else {
94                 state_ = s_done;
95             }
96         }
97         break;
98     case s_name:
99         if (c != 0) {
100             file_name_ += c;
101         } else if (flags_ & gzip::flags::comment) {
102             state_ = s_comment;
103         } else if (flags_ & gzip::flags::header_crc) {
104             state_ = s_hcrc;
105         } else {
106             state_ = s_done;
107         }
108         break;
109     case s_comment:
110         if (c != 0) {
111             comment_ += c;
112         } else if (flags_ & gzip::flags::header_crc) {
113             state_ = s_hcrc;
114         } else {
115             state_ = s_done;
116         }
117         break;
118     case s_hcrc:
119         if (offset_ == 1) {
120             state_ = s_done;
121             offset_ = 0;
122         } else {
123             ++offset_;
124         }
125         break;
126     default:
127         BOOST_ASSERT(0);
128     }
129 }
130 
reset()131 void gzip_header::reset()
132 {
133     file_name_.clear();
134     comment_.clear();
135     os_ = flags_ = offset_ = xlen_ = 0;
136     mtime_ = 0;
137     state_ = s_id1;
138 }
139 
140 //------------------Implementation of gzip_footer-----------------------------//
141 
process(char c)142 void gzip_footer::process(char c)
143 {
144     uint8_t value = static_cast<uint8_t>(c);
145     if (state_ == s_crc) {
146         crc_ += value << (offset_ * 8);
147         if (offset_ == 3) {
148             state_ = s_isize;
149             offset_ = 0;
150         } else {
151             ++offset_;
152         }
153     } else if (state_ == s_isize) {
154         isize_ += value << (offset_ * 8);
155         if (offset_ == 3) {
156             state_ = s_done;
157             offset_ = 0;
158         } else {
159             ++offset_;
160         }
161     } else {
162         BOOST_ASSERT(0);
163     }
164 }
165 
reset()166 void gzip_footer::reset()
167 {
168     crc_ = isize_ = offset_ = 0;
169     state_ = s_crc;
170 }
171 
172 } // End namespace boost::iostreams::detail.
173 
174 } } // End namespaces iostreams, boost.
175