Gnash  0.8.10
SWFStream.h
Go to the documentation of this file.
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: