Gnash
0.8.10
|
00001 // stream.h - SWF stream reading class, for Gnash 00002 // 00003 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 00004 // Free Software Foundation, Inc 00005 // 00006 // This program is free software; you can redistribute it and/or modify 00007 // it under the terms of the GNU General Public License as published by 00008 // the Free Software Foundation; either version 3 of the License, or 00009 // (at your option) any later version. 00010 // 00011 // This program is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU General Public License 00017 // along with this program; if not, write to the Free Software 00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 00020 #ifndef GNASH_STREAM_H 00021 #define GNASH_STREAM_H 00022 00023 #include "SWF.h" 00024 #include "dsodefs.h" // still neded ? 00025 #include "GnashException.h" 00026 00027 #include <string> 00028 #include <sstream> 00029 #include <vector> // for composition 00030 #include <boost/cstdint.hpp> // for boost::?int??_t 00031 00032 // Define the following macro if you want to want Gnash parser 00033 // to assume the underlying SWF is well-formed. It would make 00034 // parsing faster, but might result in horrible behaviour with 00035 // malformed SWFs (like taking up all system memory, keeping 00036 // CPU busy for a long long time, or simply corrupting memory) 00037 // 00038 // This might be eventually set by a --disable-swf-checks or similar 00039 // configure switch... 00040 // 00041 //#define GNASH_TRUST_SWF_INPUT 00042 00043 namespace gnash { 00044 class IOChannel; 00045 } 00046 00047 namespace gnash { 00048 00050 // 00058 class DSOEXPORT SWFStream 00059 { 00060 public: 00061 SWFStream(IOChannel* input); 00062 ~SWFStream(); 00063 00068 // 00071 unsigned read_uint(unsigned short bitcount); 00072 00076 // 00079 bool read_bit(); 00080 00085 // 00088 int read_sint(unsigned short bitcount); 00089 00091 // 00094 float read_fixed(); 00095 00097 // 00100 float read_ufixed(); 00101 00103 // 00106 float read_short_ufixed(); 00107 00109 // 00112 float read_short_sfixed(); 00113 00115 // 00118 float read_short_float(); 00119 00121 // 00124 float read_long_float(); 00125 00127 // 00130 double read_d64(); 00131 00133 // 00141 void align() 00142 { 00143 m_unused_bits=0; 00144 // m_current_byte = 0; // this is not needed 00145 } 00146 00148 // 00151 unsigned read(char *buf, unsigned count); 00152 00154 // 00157 boost::uint8_t read_u8(); 00158 00160 // 00163 boost::int8_t read_s8(); 00164 00166 // 00169 boost::uint16_t read_u16(); 00170 00172 // 00175 boost::int16_t read_s16(); 00176 00178 // 00181 boost::uint32_t read_u32(); 00182 00185 // 00188 boost::int32_t read_s32(); 00189 00194 // 00197 boost::uint32_t read_V32() 00198 { 00199 ensureBytes(1); 00200 boost::uint32_t res = read_u8(); 00201 if (!(res & 0x00000080)) return res; 00202 00203 ensureBytes(1); 00204 res = (res & 0x0000007F) | read_u8() << 7; 00205 if (!(res & 0x00004000)) return res; 00206 00207 ensureBytes(1); 00208 res = (res & 0x00003FFF) | read_u8() << 14; 00209 if (!(res & 0x00200000)) return res; 00210 00211 ensureBytes(1); 00212 res = (res & 0x001FFFFF) | read_u8() << 21; 00213 if (!(res & 0x10000000)) return res; 00214 00215 ensureBytes(1); 00216 res = (res & 0x0FFFFFFF) | read_u8() << 28; 00217 return res; 00218 } 00219 00226 void skip_V32() 00227 { 00228 ensureBytes(1); 00229 if (!(read_u8() & 0x80)) return; 00230 ensureBytes(1); 00231 if (!(read_u8() & 0x80)) return; 00232 ensureBytes(1); 00233 if (!(read_u8() & 0x80)) return; 00234 ensureBytes(1); 00235 if (!(read_u8() & 0x80)) return; 00236 ensureBytes(1); 00237 static_cast<void> (read_u8()); 00238 } 00239 00242 // 00250 unsigned read_variable_count() 00251 { 00252 ensureBytes(1); 00253 unsigned count = read_u8(); 00254 if (count == 0xFF) 00255 { 00256 ensureBytes(2); 00257 count = read_u16(); 00258 } 00259 return count; 00260 }; 00261 00271 void read_string(std::string& to); 00272 00274 // 00284 void read_string_with_length(std::string& to); 00285 00287 // 00299 void read_string_with_length(unsigned len, std::string& to); 00300 00302 // 00310 unsigned long tell(); 00311 00313 // 00323 bool seek(unsigned long pos); 00324 00326 unsigned long get_tag_end_position(); 00327 00329 // 00332 SWF::TagType open_tag(); 00333 00335 void close_tag(); 00336 00338 // 00351 bool skip_bytes(unsigned num) 00352 { 00353 // there's probably a better way, but 00354 // it's the interface that counts atm 00355 size_t curpos = tell(); 00356 return seek(curpos+num); 00357 } 00358 00360 void skip_to_tag_end() 00361 { 00362 // seek will call align... 00363 seek(get_tag_end_position()); 00364 } 00365 00369 // 00376 void ensureBytes(unsigned long needed); 00377 00381 // 00388 void ensureBits(unsigned long needed) 00389 { 00390 #ifndef GNASH_TRUST_SWF_INPUT 00391 if ( _tagBoundsStack.empty() ) return; // not in a tag (should we check file length ?) 00392 unsigned long int bytesLeft = get_tag_end_position() - tell(); 00393 unsigned long int bitsLeft = (bytesLeft*8)+m_unused_bits; 00394 if ( bitsLeft < needed ) 00395 { 00396 std::stringstream ss; 00397 ss << "premature end of tag: need to read " << needed << " bytes, but only " << bitsLeft << " left in this tag"; 00398 throw ParserException(ss.str()); 00399 } 00400 #endif 00401 } 00402 00404 // 00419 void consumeInput(); 00420 00421 private: 00422 00423 IOChannel* m_input; 00424 boost::uint8_t m_current_byte; 00425 boost::uint8_t m_unused_bits; 00426 00427 typedef std::pair<unsigned long,unsigned long> TagBoundaries; 00428 // position of start and end of tag 00429 std::vector<TagBoundaries> _tagBoundsStack; 00430 }; 00431 00432 00433 } // namespace gnash 00434 00435 00436 #endif // GNASH_STREAM_H 00437 00438 00439 // Local Variables: 00440 // mode: C++ 00441 // c-basic-offset: 8 00442 // tab-width: 8 00443 // indent-tabs-mode: t 00444 // End: