/// <summary>
        /// 
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="sourceFile"></param>
        /// <param name="inputStream"></param>
        /// <returns></returns>
        public static TagHandler.AbstractTagHandler Create(Tag tag, SwfFile sourceFile, Stream inputStream)
        {
            TagHandler.AbstractTagHandler product = null;

            //
            // Make parsing non-linear by explicitly placing the inputStream at the
            // OffsetData of the Tag.
            //
            inputStream.Seek((long)tag.OffsetData, SeekOrigin.Begin);
            long before = inputStream.Position;

            //
            // Produce TagHandler
            //
            bool enabled = false;

            try
            {
                enabled = SwfFile.Configuration.TagHandlers(tag.TagTypeName);
            }
            catch(Exception e)
            {
                Log.Error("TagHandlerFactory", "The tag" + tag.TagTypeName + "could not be found in the Dictionary");
                throw e;
            }

            if (!enabled)
            {
                product = new TagHandler.GenericTag(sourceFile.Version);
                Log.Info(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, "TagHandler for Tag type " + tag.TagTypeName + " disabled in configuration, using generic");
            }

            if (null == product)
            {

                switch (tag.TagType)
                {
                    // Actions section
                    //
                    case TagTypes.DoAction:
                        product = new TagHandler.DoAction(sourceFile.Version);
                        break;

                    case TagTypes.DoInitAction:
                        product = new TagHandler.DoInitAction(sourceFile.Version);
                        break;

                    case TagTypes.FileAttributes:
                        product = new TagHandler.FileAttributes(sourceFile.Version);
                        break;

                    case TagTypes.PlaceObject:
                        product = new TagHandler.PlaceObject(sourceFile.Version);
                        break;

                    case TagTypes.PlaceObject2:
                        product = new TagHandler.PlaceObject2(sourceFile.Version);
                        break;

                    case TagTypes.PlaceObject3:
                        product = new TagHandler.PlaceObject3(sourceFile.Version);
                        break;

                    // Shapes section
                    //
                    case TagTypes.DefineShape:
                        product = new TagHandler.DefineShape(sourceFile.Version);
                        break;

                    case TagTypes.DefineShape2:
                        product = new TagHandler.DefineShape(sourceFile.Version);
                        break;

                    case TagTypes.DefineShape3:
                        product = new TagHandler.DefineShape(sourceFile.Version);
                        break;

                    case TagTypes.DefineShape4:
                        product = new TagHandler.DefineShape4(sourceFile.Version);
                        break;

                    // Bitmap section
                    //
                    case TagTypes.DefineBits:
                        product = new TagHandler.DefineBits(sourceFile.Version);
                        break;

                    case TagTypes.JPEGTables:
                        product = new TagHandler.JPEGTables(sourceFile.Version);
                        break;

                    case TagTypes.DefineBitsJPEG2:
                        product = new TagHandler.DefineBitsJPEG2(sourceFile.Version);
                        break;

                    case TagTypes.DefineBitsJPEG3:
                        product = new TagHandler.DefineBitsJPEG3(sourceFile.Version);
                        break;

                    case TagTypes.DefineBitsLossless:
                        product = new TagHandler.DefineBitsLossless(sourceFile.Version);
                        break;

                    case TagTypes.DefineBitsLossless2:
                        product = new TagHandler.DefineBitsLossless2(sourceFile.Version);
                        break;

                    // Shape Morphing Section
                    //
                    case TagTypes.DefineMorphShape:
                        product = new TagHandler.DefineMorphShape(sourceFile.Version);
                        break;
                    case TagTypes.DefineMorphShape2:
                        product = new TagHandler.DefineMorphShape2(sourceFile.Version);
                        break;

                    // Fonts and Text section
                    //
                    case TagTypes.DefineFont:
                        product = new TagHandler.DefineFont(sourceFile.Version);
                        break;

                    case TagTypes.DefineFont2:
                        product = new TagHandler.DefineFont2(sourceFile.Version);
                        break;

                    case TagTypes.DefineFont3:
                        product = new TagHandler.DefineFont3(sourceFile.Version);
                        break;

                    case TagTypes.DefineFont4:
                        product = new TagHandler.DefineFont4(sourceFile.Version);
                        break;

                    case TagTypes.DefineFontInfo:
                        product = new TagHandler.DefineFontInfo(sourceFile.Version);
                        break;

                    case TagTypes.DefineFontInfo2:
                        product = new TagHandler.DefineFontInfo(sourceFile.Version);
                        break;

                    case TagTypes.DefineFontAlignZones:
                        product = new TagHandler.DefineFontAlignZones(sourceFile.Version);
                        break;

                    case TagTypes.DefineFontName:
                        product = new TagHandler.DefineFontName(sourceFile.Version);
                        break;

                    case TagTypes.DefineText:
                        product = new TagHandler.DefineText(sourceFile.Version);
                        break;

                    case TagTypes.DefineText2:
                        product = new TagHandler.DefineText(sourceFile.Version);
                        break;

                    case TagTypes.DefineEditText:
                        product = new TagHandler.DefineEditText(sourceFile.Version);
                        break;

                    case TagTypes.CSMTextSettings:
                        product = new TagHandler.CsmTextSettings(sourceFile.Version);
                        break;

                    // Sounds Section
                    //
                    case TagTypes.DefineSound:
                        product = new TagHandler.DefineSound(sourceFile.Version);
                        break;

                    case TagTypes.StartSound:
                        product = new TagHandler.StartSound(sourceFile.Version);
                        break;

                    case TagTypes.StartSound2:
                        product = new TagHandler.StartSound2(sourceFile.Version);
                        break;

                    case TagTypes.SoundStreamHead:
                        product = new TagHandler.SoundStreamHead(sourceFile.Version);
                        break;

                    case TagTypes.SoundStreamHead2:
                        product = new TagHandler.SoundStreamHead2(sourceFile.Version);
                        break;

                    case TagTypes.SoundStreamBlock:
                        product = new TagHandler.SoundStreamBlock(sourceFile.Version);
                        break;

                    // Control Section
                    //
                    case TagTypes.DefineSceneAndFrameLabelData:
                        product = new TagHandler.DefineSceneAndFrameLabelData(sourceFile.Version);
                        break;

                    case TagTypes.DefineScalingGrid:
                        product = new TagHandler.DefineScalingGrid(sourceFile.Version);
                        break;

                    case TagTypes.SetTabIndex:
                        product = new TagHandler.SetTabIndex(sourceFile.Version);
                        break;

                    case TagTypes.SetBackgroundColor:
                        product = new TagHandler.SetBackgroundColor(sourceFile.Version);
                        break;

                    case TagTypes.Protect:
                        product = new TagHandler.Protect(sourceFile.Version);
                        break;

                    case TagTypes.Metadata:
                        product = new TagHandler.Metadata(sourceFile.Version);
                        break;

                    case TagTypes.ImportAssets:
                        product = new TagHandler.ImportAssets(sourceFile.Version);
                        break;

                    case TagTypes.ImportAssets2:
                        product = new TagHandler.ImportAssets2(sourceFile.Version);
                        break;

                    case TagTypes.FrameLabel:
                        product = new TagHandler.FrameLabel(sourceFile.Version);
                        break;

                    case TagTypes.ExportAssets:
                        product = new TagHandler.ExportAssets(sourceFile.Version);
                        break;

                    case TagTypes.EnableDebugger:
                        product = new TagHandler.EnableDebugger(sourceFile.Version);
                        break;

                    case TagTypes.EnableDebugger2:
                        product = new TagHandler.EnableDebugger2(sourceFile.Version);
                        break;

                    // Buttons Section
                    //
                    case TagTypes.DefineButton:
                        product = new TagHandler.DefineButton(sourceFile.Version);
                        break;

                    case TagTypes.DefineButton2:
                        product = new TagHandler.DefineButton2(sourceFile.Version);
                        break;

                    // Sprites and Movie Clips section
                    //
                    case TagTypes.DefineSprite:
                        product = new TagHandler.DefineSprite(sourceFile.Version);
                        break;

                    // Video section
                    //

                    // Binary Data section
                    //

                    // Blitzabeleiter internals

                    case TagTypes.ProductID:
                        product = new TagHandler.ProductID(sourceFile.Version);
                        break;

                    case TagTypes.DebugID:
                        product = new TagHandler.DebugID(sourceFile.Version);
                        break;

                    case TagTypes.DefineBinaryData:
                        product = new TagHandler.DefineBinaryData(sourceFile.Version);
                        break;

                    // ABC / AVM2 Code
                    case TagTypes.DoABC:
                        product = new TagHandler.DoABC(sourceFile.Version);
                        break;

                    //case TagTypes.ScriptLimits:
                    //    product = new TagHandler.ScriptLimits(sourceFile.Version);
                    //    break;

                    default:
                        product = new TagHandler.GenericTag(sourceFile.Version);
                        break;
                }
            }

            // Exceptions during this operation propagate all
            // the way up to SwfFile
            product.Read(tag, sourceFile, inputStream);

            // Note: we don't have to check that the stream did only consume as much
            // data as the Tag declared, since the Tag.ReadContent() method reads only
            // the declared amount of data from the Tag and produces a MemoryStream with
            // that. Tag.ReadContent() is used by AbstractTagHandler.Read().

            return product;
        }
Beispiel #2
0
        /// <summary>
        /// Parses a Swf file tag by tag
        /// </summary>
        /// <param name="input">The Swf file as stream</param>
        /// <returns>The next tag</returns>
        public Stream Read(Stream input)
        {
            CwsSource = new CwsFile();
            FwsSource = new FwsFile();
            List<Tag> tags = new List<Tag>();

            Stream next = CwsSource.Read(input);

            if (this.CwsSource.Compressed)
            {
                // Fire compressed event
                if (null != SwfFileCompressed)
                    SwfFileCompressed(this, new CompressedEventArgs(true));
            }

            next = FwsSource.Read(next);

            HeaderDeclaredLength = FwsSource.Length;

            #region Reading tags

            Tag t;
            int tagNumber = 1;
            uint tagsLenghts = (uint)next.Position;

            do
            {
                t = new Tag();

                try
                {
                    next = t.Read(next);
                    Log.Debug(this, "Reading Tag #" + tagNumber + "(" + t.TagTypeName +")" + " Offset : 0x" + t.Offset.ToString("X08") + " Total-Length : 0x" + t.LengthTotal.ToString("X08"));
                    // Fire TagReadCompleted, ReadProgressChanged, if protected SwfFileProtected  events
                    if (null != TagReadCompleted)
                        TagReadCompleted(this, new TagHandlerReadCompleteEventArgs(t.TagType));
                    if (null != this.ReadProgressChanged)
                        ReadProgressChanged(this, new SwfReadProgressChangedEventArgs(next.Length, next.Position));
                    if (null != SwfFileProtected && t.TagType == TagTypes.Protect)
                        SwfFileProtected(this, new ProtectionEventArgs(""));

                    // Knowing if the offset end is longer than header declared length is enough to verfiy
                    if (t.OffsetEnd > this.FwsSource.Length)
                    {
                        if ((SwfFile.Configuration.HandleHeadSizeIssue == HandleHeadSizeIssueBy.Fix) && t.OffsetEnd <= (ulong)input.Length)
                        {
                            this.FwsSource.Length = (uint)t.OffsetEnd;
                            Log.Warn(this, "Tag #" + tagNumber + " ends outside (0x" + t.OffsetEnd.ToString("X08") + ") the declared Swf content range 0x" + this.FwsSource.Length.ToString("X08") + " Fixing.");
                        }
                        if ((SwfFile.Configuration.HandleHeadSizeIssue == HandleHeadSizeIssueBy.Ignore) && t.OffsetEnd <= (ulong)input.Length)
                        {
                            Log.Warn(this, "Tag #" + tagNumber + " ends outside (0x" + t.OffsetEnd.ToString("X08") + ") the declared Swf content range 0x" + this.FwsSource.Length.ToString("X08") + " Ignoring.");
                        }
                        else
                        {
                            SwfFormatException e = new SwfFormatException("Tag #" + tagNumber + " ends outside (0x" + t.OffsetEnd.ToString("X08") + ") the declared Swf content range 0x" + this.FwsSource.Length.ToString("X08"));
                            Log.Error(this, e);
                            throw e;
                        }

                    }

                    tagsLenghts += t.LengthTotal;
                    tagNumber++;
                    tags.Add(t);
                }
                catch (IOException ioe)
                {
                    //This is the point where we find no end tag which basically means that a tag declared more memory than the stream actaully has
                    Log.Error(this, ioe);
                    SwfFormatException e = new SwfFormatException("Tag list is incomplete, does not end with an END tag or a tag length exceeds the file size.");
                    Log.Error(this, e);

                    throw e;
                }
            }
            while (t.TagType != TagTypes.End);

            #endregion

            #region Length checking

            // Performing length checks now
            //
            // 1. Do the length of all tags match the stream length
            if (tagsLenghts != next.Length)
            {

                    SwfFormatException e = new SwfFormatException("The length of tags (" + tagsLenghts.ToString() + ") does not match the stream size(" + next.Length.ToString() + ").");
                    Log.Error(this, e);
                    throw e;
            }

            // 2. Does the tags lengths do match the header declared length
            if (tagsLenghts != this.CwsSource.Length)
            {
                if (SwfFile.Configuration.HandleHeadSizeIssue == HandleHeadSizeIssueBy.Fix)
                {
                    this.CwsSource.Length = tagsLenghts;
                    Log.Warn(this, "The length of tags (" + tagsLenghts.ToString() + ") does not match the header declared length(" + this.CwsSource.Length.ToString() + "). Stream size will be fixed.");
                }
                else if (SwfFile.Configuration.HandleHeadSizeIssue == HandleHeadSizeIssueBy.RaiseError)
                {
                    SwfFormatException e = new SwfFormatException("The length of tags (" + tagsLenghts.ToString() + ") does not match the header declared length(" + this.CwsSource.Length.ToString() + ").");
                    Log.Error(this, e);
                    throw e;
                }
                else
                {
                    Log.Warn(this, "The length of tags (" + tagsLenghts.ToString() + ") does not match the header declared length(" + this.CwsSource.Length.ToString() + "). Stream size will be fixed.");
                }

            }

            // 3. If stream and header length match has already been checked in FWSFile class

            // 4. Has the stream been consumed completely
            if (next.Position != next.Length)
            {
                if (SwfFile.Configuration.HandleStreamOversize == HandleStreamOversizeBy.Resize)
                {
                    this.FixIncorrectStreamSize(next, next.Position);
                    Log.Warn(this, "Trailing garbage after END tag detected. Position 0x" + input.Position.ToString("X08") + ", Length " + input.Length.ToString() + ". Dumping Trailing Garbage.");
                }
                else if (SwfFile.Configuration.HandleStreamOversize == HandleStreamOversizeBy.Ignore)
                {
                    Log.Warn(this, "Trailing garbage after END tag detected. Position 0x" + input.Position.ToString("X08") + ", Length " + input.Length.ToString());
                }
                else
                {
                    SwfFormatException e = new SwfFormatException("Trailing garbage after END tag detected. Position 0x" + input.Position.ToString("X08") + ", Length " + input.Length.ToString());
                    Log.Error(this, e);
                }

            }

            #endregion

            #region Producing tag handlers

            TagHandlers = new List<Recurity.Swf.TagHandler.AbstractTagHandler>();
            for (int i = 0; i < tags.Count; i++)
            {
                //
                // Only accept tag types that are documented by Adobe
                //
                if (!tags[i].IsTagTypeKnown)
                {
                    string msg = "Tag type " + ((UInt16)tags[i].TagType).ToString("d") + " not known/documented";

                    if (SwfFile.Configuration.AllowUnknownTagTypes)
                    {
                        Log.Warn(this, msg);
                    }
                    else
                    {
                        SwfFormatException e = new SwfFormatException(msg);
                        Log.Error(this, e);
                        throw e;
                    }
                }

                //
                // The factory automatically fires .Read() on the produced class. Therefore,
                // we catch Exceptions here (Stream too short) and convert them to SwfFormatExceptions
                //
                try
                {
                    TagHandlers.Add(TagHandlerFactory.Create(tags[i], this, next));

                    // Fire TagProduced event
                    if (null != TagProduced)//If a handler is attached
                        TagProduced(this, new TagHandlerProducedEventArgs(tags[i].TagType, (Int64)tags.Count, (Int64)i));
                }
                catch (Exception e)
                {
                    SwfFormatException swfE = new SwfFormatException("Tag handler #" + i + " (" + tags[i].TagTypeName + ") failed parsing: " + e.Message);
                    throw swfE;
                }

                if (tags[i].TagType.Equals(TagTypes.ST_GLYPHNAMES) || tags[i].TagType.Equals(TagTypes.ST_REFLEX))
                {
                    //this.CWSSource._GeneratorSoftware = "SwfTools";
                }

                //
                // Verify the required Version of each Tag against the header declared
                // Version.
                // It may be considered to make failing this test fatal.
                //
                if (TagHandlers[i].MinimumVersionRequired > this.Version)
                {
                    Log.Warn(this, "Tag " + (tags[i].IsTagTypeKnown ? tags[i].TagTypeName : tags[i].TagType.ToString()) +
                        " requires Swf version " + TagHandlers[i].MinimumVersionRequired.ToString() +
                        ", header declares " + this.Version.ToString());
                }
            }
            #endregion

            return next;
        }