Beispiel #1
0
        /// <summary>
        /// Tries to automatically detect the format of the given file, and creates an instance of it
        /// </summary>
        /// <typeparam name="T">Base type of file (i.e. image, archive)</typeparam>
        /// <param name="fileStream">File stream with data to use</param>
        /// <param name="endianness">Endianness of the file data</param>
        /// <returns>Instance of file; null if no instance was created</returns>
        public static T FromFile <T>(FileStream fileStream, Endian endianness) where T : FileFormat
        {
            // TODO: rework identification system?

            List <IdentificationMatch> matchedTypes = new List <IdentificationMatch>();

            EndianBinaryReader reader = new EndianBinaryReader(fileStream, endianness);

            {
                foreach (var assembly in AssemblyHelpers.GetNonSystemAssemblies())
                {
                    foreach (var type in assembly.GetExportedTypes().Where(x => x == typeof(T) || x.InheritsFrom(typeof(T))))
                    {
                        IdentificationMatch magicMatch = null, patternMatch = null;

                        var  customAttribs          = type.GetCustomAttributes(false);
                        bool requireMagicAndPattern = customAttribs.Any(x => x is MagicNumberAttribute) && customAttribs.Any(x => x is FilenamePatternAttribute);
                        var  magicNumberAttrib      = customAttribs.FirstOrDefault(x => x is MagicNumberAttribute);

                        var verifyMethod = type.GetMethod("VerifyMagicNumber", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
                        if (verifyMethod == null)
                        {
                            throw new NullReferenceException("Reflection error on method fetch for file verification");
                        }
                        VerifyResult verifyResult = ((VerifyResult)verifyMethod.Invoke(null, new object[] { reader, type }));

                        if (verifyResult == VerifyResult.VerifyOkay)
                        {
                            uint weight = int.MaxValue;
                            if (magicNumberAttrib != null)
                            {
                                weight += (uint)(magicNumberAttrib as MagicNumberAttribute).MagicNumber.Length;
                            }
                            magicMatch = new IdentificationMatch(type, weight);
                        }
                        else if (verifyResult == VerifyResult.WrongMagicNumber)
                        {
                            continue;
                        }

                        foreach (var fnPatternAttrib in type.GetCustomAttributes(typeof(FilenamePatternAttribute), false))
                        {
                            string pattern = (fnPatternAttrib as FilenamePatternAttribute).Pattern;
                            Regex  regEx   = new Regex(pattern, RegexOptions.IgnoreCase);
                            if (regEx.IsMatch(fileStream.Name))
                            {
                                patternMatch = new IdentificationMatch(type, (uint)pattern.Length);
                            }
                        }

                        if (requireMagicAndPattern)
                        {
                            if (magicMatch != null && patternMatch != null)
                            {
                                matchedTypes.Add(magicMatch);
                                matchedTypes.Add(patternMatch);
                            }
                        }
                        else
                        {
                            if (magicMatch != null)
                            {
                                matchedTypes.Add(magicMatch);
                            }
                            if (patternMatch != null)
                            {
                                matchedTypes.Add(patternMatch);
                            }
                        }
                    }

                    if (matchedTypes.Count > 0)
                    {
                        T fileInstance = (T)Activator.CreateInstance(matchedTypes.OrderByDescending(x => x.Weight).FirstOrDefault().Type);
                        fileInstance.Open(reader);
                        return(fileInstance);
                    }
                }
            }

            return(default(T));
        }
Beispiel #2
0
 protected abstract void OnOpen(EndianBinaryReader reader);