コード例 #1
0
        public AppMetaData(string sourcePath, List <string> rulePaths)
        {
            //Initial value for ApplicationName may be replaced if rule pattern match found later
            if (Directory.Exists(sourcePath))
            {
                try
                {
                    ApplicationName = sourcePath.Substring(sourcePath.LastIndexOf(Path.DirectorySeparatorChar)).Replace(Path.DirectorySeparatorChar, ' ').Trim();
                }
                catch (Exception)
                {
                    ApplicationName = Path.GetFileNameWithoutExtension(sourcePath);
                }
            }
            else
            {
                ApplicationName = Path.GetFileNameWithoutExtension(sourcePath);
            }

            //initialize standard set groups using dynamic lists variables that may have more than one value; some are filled
            //using tag tests and others by different means like file type examination
            KeyedPropertyLists = new Dictionary <string, HashSet <string> >
            {
                ["strGrpRulePaths"]          = rulePaths.ToHashSet(),
                ["strGrpPackageTypes"]       = new HashSet <string>(),
                ["strGrpAppTypes"]           = new HashSet <string>(),
                ["strGrpFileTypes"]          = new HashSet <string>(),
                ["strGrpUniqueTags"]         = new HashSet <string>(),
                ["strGrpOutputs"]            = new HashSet <string>(),
                ["strGrpTargets"]            = new HashSet <string>(),
                ["strGrpOSTargets"]          = new HashSet <string>(),
                ["strGrpFileExtensions"]     = new HashSet <string>(),
                ["strGrpFileNames"]          = new HashSet <string>(),
                ["strGrpCPUTargets"]         = new HashSet <string>(),
                ["strGrpCloudTargets"]       = new HashSet <string>(),
                ["strGrpUniqueDependencies"] = new HashSet <string>()
            };

            //predefined standard tags to track; only some are propertygrouplist are tag based
            _propertyTagSearchPatterns = new Dictionary <string, string>();
            _propertyTagSearchPatterns.Add("strGrpOSTargets", ".OS.Targets");
            _propertyTagSearchPatterns.Add("strGrpCloudTargets", ".Cloud");
            _propertyTagSearchPatterns.Add("strGrpOutputs", ".Outputs");
            _propertyTagSearchPatterns.Add("strGrpCPUTargets", ".CPU");

            //read default/user preferences on what tags to count
            if (File.Exists(Utils.GetPath(Utils.AppPath.tagCounterPref)))
            {
                TagCounters = JsonConvert.DeserializeObject <List <TagCounter> >(File.ReadAllText(Utils.GetPath(Utils.AppPath.tagCounterPref)));
            }
            else
            {
                TagCounters = new List <TagCounter>();
            }

            HashSet <string> dupCountersCheck = new HashSet <string>();

            foreach (TagCounter counter in TagCounters)
            {
                if (!dupCountersCheck.Add(counter.Tag))
                {
                    WriteOnce.SafeLog("Duplidate counter specified in preferences", NLog.LogLevel.Error);
                }
            }

            Languages = new Dictionary <string, int>();
        }
コード例 #2
0
        /// <summary>
        /// Main WORKHORSE for analyzing file; called from file based or decompression functions
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="fileText"></param>
        void ProcessInMemory(string filePath, string fileText)
        {
            #region quickvalidation
            if (fileText.Length > MAX_FILESIZE)
            {
                WriteOnce.SafeLog("File too large: " + filePath, LogLevel.Trace);
                WriteOnce.SafeLog(ErrMsg.FormatString(ErrMsg.ID.ANALYZE_FILESIZE_SKIPPED, filePath), LogLevel.Error);
                _appProfile.MetaData.FilesSkipped++;
                return;
            }

            if (!_arg_allowSampleFiles && _fileExclusionList.Any(v => filePath.Contains(v)))
            {
                WriteOnce.SafeLog("Part of excluded list: " + filePath, LogLevel.Trace);
                WriteOnce.SafeLog(ErrMsg.FormatString(ErrMsg.ID.ANALYZE_FILESIZE_SKIPPED, filePath), LogLevel.Error);
                _appProfile.MetaData.FilesSkipped++;
                return;
            }

            //determine if file is a compressed item to unpackage for processing
            string language = Language.FromFileName(filePath);

            // Skip files written in unknown language
            if (string.IsNullOrEmpty(language))
            {
                WriteOnce.SafeLog("Language not found for file: " + filePath, LogLevel.Trace);
                language = Path.GetFileName(filePath);
                _appProfile.MetaData.FilesSkipped++;
                return;
            }
            else
            {
                WriteOnce.SafeLog("Preparing to process file: " + filePath, LogLevel.Trace);
            }

            #endregion

            #region minorRollupTrackingAndProgress

            _appProfile.MetaData.FilesAnalyzed++;
            _appProfile.MetaData.AddLanguage(language);
            _appProfile.MetaData.FileExtensions.Add(Path.GetExtension(filePath).Replace('.', ' ').TrimStart());
            LastUpdated = File.GetLastWriteTime(filePath);

            int totalFilesReviewed = _appProfile.MetaData.FilesAnalyzed + _appProfile.MetaData.FilesSkipped;
            int percentCompleted   = (int)((float)totalFilesReviewed / (float)_appProfile.MetaData.TotalFiles * 100);
            WriteOnce.General("\r" + ErrMsg.FormatString(ErrMsg.ID.ANALYZE_FILES_PROCESSED_PCNT, percentCompleted), false);

            #endregion

            //process file against rules
            Issue[] matches = _rulesProcessor.Analyze(fileText, language);

            //if any matches found for this file...
            if (matches.Count() > 0)
            {
                _appProfile.MetaData.FilesAffected++;
                _appProfile.MetaData.TotalMatchesCount += matches.Count();

                HashSet <string> uniqueTagsControl = new HashSet <string>();

                // Iterate through each match issue
                foreach (Issue match in matches)
                {
                    WriteOnce.SafeLog(string.Format("Processing pattern matches for ruleId {0}, ruleName {1} file {2}", match.Rule.Id, match.Rule.Name, filePath), LogLevel.Trace);

                    //maintain a list of unique tags; multi-purpose but primarily for filtering -u option
                    bool dupTagFound = false;
                    foreach (string t in match.Rule.Tags)
                    {
                        dupTagFound = !uniqueTagsControl.Add(t);
                    }

                    //save all unique dependendencies even if Dependency tag pattern is not-unique
                    var    tagPatternRegex = new Regex("Dependency.SourceInclude", RegexOptions.IgnoreCase);
                    String textMatch;
                    if (match.Rule.Tags.Any(v => tagPatternRegex.IsMatch(v)))
                    {
                        textMatch = ExtractDependency(fileText, match.Boundary.Index, match.PatternMatch, language);
                    }
                    else
                    {
                        textMatch = ExtractTextSample(fileText, match.Boundary.Index, match.Boundary.Length);
                    }

                    //wrap rule issue result to add metadata
                    MatchRecord record = new MatchRecord()
                    {
                        Filename   = filePath,
                        Language   = language,
                        Filesize   = fileText.Length,
                        TextSample = textMatch,
                        Excerpt    = ExtractExcerpt(fileText, match.StartLocation.Line),
                        Issue      = match
                    };

                    //preserve issue level characteristics as rolled up meta data of interest
                    bool valid = _appProfile.MetaData.AddStandardProperties(record);

                    //bail after extracting any dependency unique items IF user requested
                    if (_arg_outputUniqueTagsOnly && dupTagFound)
                    {
                        continue;
                    }
                    else if (valid)
                    {
                        _appProfile.MatchList.Add(record);
                    }
                }
            }
            else
            {
                WriteOnce.SafeLog("No pattern matches detected for file: " + filePath, LogLevel.Trace);
            }
        }
コード例 #3
0
        void UnZipAndProcess(string filename)
        {
            if (!File.Exists(filename))
            {
                throw new OpException(ErrMsg.FormatString(ErrMsg.ID.CMD_INVALID_FILE_OR_DIR, filename));
            }

            // Ignore images and other junk like that
            var  fileExtension = new FileInfo(filename).Extension;
            var  mimeType      = MimeTypeMap.GetMimeType(fileExtension);
            bool mimeMatch     = false;

            if (!IgnoreMimeRegex.IsMatch(mimeType))
            {
                var isValidExtension = COMPRESSED_EXTENSIONS.Any(fileExtension.Contains);
                if (isValidExtension || fileExtension == "ts")
                {
                    mimeMatch = true;
                }
                else if (mimeType.Contains("zip", StringComparison.CurrentCultureIgnoreCase) || // Should have been caught in file extensions above, but still OK.
                         mimeType.Contains("tar", StringComparison.CurrentCultureIgnoreCase) ||
                         mimeType.Contains("compressed", StringComparison.CurrentCultureIgnoreCase))
                {
                    mimeMatch = true;
                }

                if (mimeMatch)
                {
                    // Now process the file
                    switch (fileExtension)
                    {
                    case ".tgz":
                        ProcessTarGzFile(filename);
                        break;

                    case ".gz":
                        if (filename.Contains(".tar.gz"))
                        {
                            ProcessTarGzFile(filename);
                        }
                        else
                        {
                            WriteOnce.SafeLog("no support for .gz unless .tar.gz: " + fileExtension, LogLevel.Warn);
                            _appProfile.MetaData.PackageTypes.Add("compressed-unsupported");
                        }
                        break;

                    case ".jar":
                    case ".zip":
                        ProcessZipFile(filename);
                        break;

                    case ".gem":
                    case ".tar":
                    case ".nupkg":
                        WriteOnce.SafeLog($"Processing of {fileExtension} not implemented yet.", LogLevel.Warn);
                        break;

                    default:
                        WriteOnce.SafeLog("no support for compressed type: " + fileExtension, LogLevel.Warn);
                        break;
                    }

                    _appProfile.MetaData.PackageTypes.Add("compressed");
                }
                else
                {
                    _appProfile.MetaData.PackageTypes.Add("compressed-unsupported");
                }
            }
        }
コード例 #4
0
        /// <summary>
        /// Add default and/or custom rules paths
        /// Iterate paths and add to ruleset
        /// </summary>
        void ConfigRules()
        {
            WriteOnce.SafeLog("AnalyzeCommand::ConfigRules", LogLevel.Trace);

            RuleSet       rulesSet  = new RuleSet(Program.Logger);
            List <string> rulePaths = new List <string>();

            if (!_arg_ignoreDefaultRules)
            {
                rulePaths.Add(Utils.GetPath(Utils.AppPath.defaultRules));
            }

            if (!string.IsNullOrEmpty(_arg_customRulesPath))
            {
                rulePaths.Add(_arg_customRulesPath);
            }

            foreach (string rulePath in rulePaths)
            {
                if (Directory.Exists(rulePath))
                {
                    rulesSet.AddDirectory(rulePath);
                }
                else if (File.Exists(rulePath))
                {
                    rulesSet.AddFile(rulePath);
                }
                else
                {
                    throw new OpException(ErrMsg.FormatString(ErrMsg.ID.CMD_INVALID_RULE_PATH, rulePath));
                }
            }

            //error check based on ruleset not path enumeration
            if (rulesSet.Count() == 0)
            {
                throw new OpException(ErrMsg.GetString(ErrMsg.ID.CMD_NORULES_SPECIFIED));
            }

            //instantiate a RuleProcessor with the added rules and exception for dependency
            _rulesProcessor = new RuleProcessor(rulesSet, _arg_confidence, _arg_outputUniqueTagsOnly, _arg_simpleTagsOnly, Program.Logger);

            if (_arg_outputUniqueTagsOnly)
            {
                List <TagException> tagExceptions;
                if (File.Exists(Utils.GetPath(Utils.AppPath.tagCounterPref)))
                {
                    tagExceptions = JsonConvert.DeserializeObject <List <TagException> >(File.ReadAllText(Utils.GetPath(Utils.AppPath.tagCounterPref)));
                    string[] exceptions = new string[tagExceptions.Count];
                    for (int i = 0; i < tagExceptions.Count; i++)
                    {
                        exceptions[i] = tagExceptions[i].Tag;
                    }
                    _rulesProcessor.UniqueTagExceptions = exceptions;
                }
            }

            _appProfile      = new AppProfile(_arg_sourcePath, rulePaths, false, _arg_simpleTagsOnly, _arg_outputUniqueTagsOnly);
            _appProfile.Args = "analyze -f " + _arg_fileFormat + " -u " + _arg_outputUniqueTagsOnly.ToString().ToLower() + " -v " +
                               WriteOnce.Verbosity.ToString() + " -x " + _arg_confidence + " -i " + _arg_ignoreDefaultRules.ToString().ToLower();
        }
コード例 #5
0
        /// <summary>
        /// Main WORKHORSE for analyzing file; called from file based or decompression functions
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="fileText"></param>
        void ProcessInMemory(string filePath, string fileText, LanguageInfo languageInfo)
        {
            #region minorRollupTrackingAndProgress

            WriteOnce.SafeLog("Preparing to process file: " + filePath, LogLevel.Trace);

            _appProfile.MetaData.FilesAnalyzed++;

            int totalFilesReviewed = _appProfile.MetaData.FilesAnalyzed + _appProfile.MetaData.FilesSkipped;
            int percentCompleted   = (int)((float)totalFilesReviewed / (float)_appProfile.MetaData.TotalFiles * 100);
            //earlier issue now resolved so app handles mixed zipped/zipped and unzipped/zipped directories but catch all for non-critical UI
            if (percentCompleted > 100)
            {
                percentCompleted = 100;
            }

            WriteOnce.General("\r" + ErrMsg.FormatString(ErrMsg.ID.ANALYZE_FILES_PROCESSED_PCNT, percentCompleted), false);

            #endregion

            //process file against rules
            Issue[] matches = _rulesProcessor.Analyze(fileText, languageInfo);

            //if any matches found for this file...
            if (matches.Count() > 0)
            {
                _appProfile.MetaData.FilesAffected++;
                _appProfile.MetaData.TotalMatchesCount += matches.Count();

                // Iterate through each match issue
                foreach (Issue match in matches)
                {
                    WriteOnce.SafeLog(string.Format("Processing pattern matches for ruleId {0}, ruleName {1} file {2}", match.Rule.Id, match.Rule.Name, filePath), LogLevel.Trace);

                    //maintain a list of unique tags; multi-purpose but primarily for filtering -d option
                    bool dupTagFound = false;
                    foreach (string t in match.Rule.Tags)
                    {
                        dupTagFound = !_uniqueTagsControl.Add(t);
                    }

                    //save all unique dependencies even if Dependency tag pattern is not-unique
                    var    tagPatternRegex = new Regex("Dependency.SourceInclude", RegexOptions.IgnoreCase);
                    String textMatch;
                    if (match.Rule.Tags.Any(v => tagPatternRegex.IsMatch(v)))
                    {
                        textMatch = ExtractDependency(fileText, match.Boundary.Index, match.PatternMatch, languageInfo.Name);
                    }
                    else
                    {
                        textMatch = ExtractTextSample(fileText, match.Boundary.Index, match.Boundary.Length);
                    }

                    //wrap rule issue result to add metadata
                    MatchRecord record = new MatchRecord()
                    {
                        Filename   = filePath,
                        Language   = languageInfo,
                        Filesize   = fileText.Length,
                        TextSample = textMatch,
                        Excerpt    = ExtractExcerpt(fileText, match.StartLocation.Line),
                        Issue      = match
                    };

                    //preserve issue level characteristics as rolled up meta data of interest
                    bool addAsFeatureMatch = _appProfile.MetaData.AddStandardProperties(ref record);

                    //bail after extracting any dependency unique items IF user requested
                    if (_arg_outputUniqueTagsOnly && dupTagFound)
                    {
                        continue;
                    }
                    else if (addAsFeatureMatch)
                    {
                        _appProfile.MatchList.Add(record);
                    }
                }
            }
            else
            {
                WriteOnce.SafeLog("No pattern matches detected for file: " + filePath, LogLevel.Trace);
            }
        }
コード例 #6
0
        /// <summary>
        /// Main WORKHORSE for analyzing file; called from file based or decompression functions
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="fileText"></param>
        void ProcessInMemory(string filePath, string fileText)
        {
            #region quickvalidation
            if (fileText.Length > MAX_FILESIZE)
            {
                WriteOnce.SafeLog(ErrMsg.FormatString(ErrMsg.ID.ANALYZE_FILESIZE_SKIPPED, filePath), LogLevel.Warn);
                _appProfile.MetaData.FilesSkipped++;
                return;
            }

            //exclude sample, test or similar files by default or as specified in exclusion list
            if (!_arg_allowSampleFiles && _fileExclusionList.Any(v => filePath.ToLower().Contains(v)))
            {
                WriteOnce.SafeLog("Part of excluded list: " + filePath, LogLevel.Trace);
                WriteOnce.SafeLog(ErrMsg.FormatString(ErrMsg.ID.ANALYZE_FILESIZE_SKIPPED, filePath), LogLevel.Trace);
                _appProfile.MetaData.FilesSkipped++;
                return;
            }

            //check for supported language
            LanguageInfo languageInfo = new LanguageInfo();
            // Skip files written in unknown language
            if (!Language.FromFileName(filePath, ref languageInfo))
            {
                WriteOnce.SafeLog("Language not found for file: " + filePath, LogLevel.Trace);
                _appProfile.MetaData.FilesSkipped++;
                return;
            }
            else
            {
                WriteOnce.SafeLog("Preparing to process file: " + filePath, LogLevel.Trace);
            }

            #endregion

            #region minorRollupTrackingAndProgress

            _appProfile.MetaData.FilesAnalyzed++;
            _appProfile.MetaData.AddLanguage(languageInfo.Name);
            _appProfile.MetaData.FileExtensions.Add(Path.GetExtension(filePath).Replace('.', ' ').TrimStart());
            LastUpdated = File.GetLastWriteTime(filePath);

            int totalFilesReviewed = _appProfile.MetaData.FilesAnalyzed + _appProfile.MetaData.FilesSkipped;
            int percentCompleted   = (int)((float)totalFilesReviewed / (float)_appProfile.MetaData.TotalFiles * 100);
            //reported: if a zip contains more zip files in it the total count may be off -complex.  ~workaround: freeze UI
            if (percentCompleted > 100)
            {
                percentCompleted = 100;
            }

            WriteOnce.General("\r" + ErrMsg.FormatString(ErrMsg.ID.ANALYZE_FILES_PROCESSED_PCNT, percentCompleted), false);

            #endregion

            //process file against rules
            Issue[] matches = _rulesProcessor.Analyze(fileText, languageInfo.Name);

            //if any matches found for this file...
            if (matches.Count() > 0)
            {
                _appProfile.MetaData.FilesAffected++;
                _appProfile.MetaData.TotalMatchesCount += matches.Count();

                // Iterate through each match issue
                foreach (Issue match in matches)
                {
                    WriteOnce.SafeLog(string.Format("Processing pattern matches for ruleId {0}, ruleName {1} file {2}", match.Rule.Id, match.Rule.Name, filePath), LogLevel.Trace);

                    //do not accept features from build type files (only metadata) to avoid false positives that are not part of the executable program
                    if (languageInfo.Type == LanguageInfo.LangFileType.Build && match.Rule.Tags.Any(v => !v.Contains("Metadata")))
                    {
                        continue;
                    }

                    //maintain a list of unique tags; multi-purpose but primarily for filtering -d option
                    bool dupTagFound = false;
                    foreach (string t in match.Rule.Tags)
                    {
                        dupTagFound = !_uniqueTagsControl.Add(t);
                    }

                    //save all unique dependendencies even if Dependency tag pattern is not-unique
                    var    tagPatternRegex = new Regex("Dependency.SourceInclude", RegexOptions.IgnoreCase);
                    String textMatch;
                    if (match.Rule.Tags.Any(v => tagPatternRegex.IsMatch(v)))
                    {
                        textMatch = ExtractDependency(fileText, match.Boundary.Index, match.PatternMatch, languageInfo.Name);
                    }
                    else
                    {
                        textMatch = ExtractTextSample(fileText, match.Boundary.Index, match.Boundary.Length);
                    }

                    //wrap rule issue result to add metadata
                    MatchRecord record = new MatchRecord()
                    {
                        Filename   = filePath,
                        Language   = languageInfo,
                        Filesize   = fileText.Length,
                        TextSample = textMatch,
                        Excerpt    = ExtractExcerpt(fileText, match.StartLocation.Line),
                        Issue      = match
                    };

                    //preserve issue level characteristics as rolled up meta data of interest
                    bool addAsFeatureMatch = _appProfile.MetaData.AddStandardProperties(record);

                    //bail after extracting any dependency unique items IF user requested
                    if (_arg_outputUniqueTagsOnly && dupTagFound)
                    {
                        continue;
                    }
                    else if (addAsFeatureMatch)
                    {
                        _appProfile.MatchList.Add(record);
                    }
                }
            }
            else
            {
                WriteOnce.SafeLog("No pattern matches detected for file: " + filePath, LogLevel.Trace);
            }
        }
コード例 #7
0
        public int Run()
        {
            bool issues = false;

            WriteOnce.Operation(ErrMsg.FormatString(ErrMsg.ID.CMD_RUNNING, "Verify Rules"));

            //load [each] rules file separately to report out where a failure is happening
            RuleSet rules = new RuleSet(WriteOnce.Log);
            IEnumerable <string> fileListing = new List <string>();

            foreach (string rulePath in _rulePaths)
            {
                if (Directory.Exists(rulePath))
                {
                    fileListing = Directory.EnumerateFiles(rulePath, "*.json", SearchOption.AllDirectories);
                }
                else if (File.Exists(rulePath) && Path.GetExtension(rulePath) == ".json")
                {
                    fileListing = new List <string>()
                    {
                        new string(rulePath)
                    }
                }
                ;
                else
                {
                    throw new OpException(ErrMsg.FormatString(ErrMsg.ID.CMD_INVALID_RULE_PATH, rulePath));
                }

                //test loading each file
                foreach (string filename in fileListing)
                {
                    try
                    {
                        rules.AddFile(filename);
                        WriteOnce.Info(string.Format("Rule file added {0}", filename), true, WriteOnce.ConsoleVerbosity.High);
                    }
                    catch (Exception e)
                    {
                        WriteOnce.Error(string.Format("Rule file add failed {0}", filename));
                        WriteOnce.SafeLog(e.Message + "\n" + e.StackTrace, NLog.LogLevel.Error);
                        issues = true;
                    }
                }
            }

            //option to write validating data
            if (_arg_consoleVerbosityLevel == WriteOnce.ConsoleVerbosity.High)
            {
                WritePartialRuleDetails(rules);
            }

            //final status report
            if (issues)
            {
                WriteOnce.Any(ErrMsg.GetString(ErrMsg.ID.VERIFY_RULES_RESULTS_FAIL), true, ConsoleColor.Red, WriteOnce.ConsoleVerbosity.Low);
            }
            else
            {
                WriteOnce.Any(ErrMsg.GetString(ErrMsg.ID.VERIFY_RULES_RESULTS_SUCCESS), true, ConsoleColor.Green, WriteOnce.ConsoleVerbosity.Low);
            }

            WriteOnce.Operation(ErrMsg.FormatString(ErrMsg.ID.CMD_COMPLETED, "Verify Rules"));
            WriteOnce.FlushAll();
            if (!String.IsNullOrEmpty(_arg_outputFile))
            {
                WriteOnce.Any(ErrMsg.FormatString(ErrMsg.ID.ANALYZE_OUTPUT_FILE, _arg_outputFile), true, ConsoleColor.Gray, WriteOnce.ConsoleVerbosity.Low);
            }

            return(issues ? (int)ExitCode.NotVerified : (int)ExitCode.Verified);
        }
コード例 #8
0
        /// <summary>
        /// Main entry point to start analysis; handles setting up rules, directory enumeration
        /// file type detection and handoff
        /// Pre: All Configure Methods have been called already and we are ready to SCAN
        /// </summary>
        /// <returns></returns>
        public int Run()
        {
            WriteOnce.SafeLog("AnalyzeCommand::Run", LogLevel.Trace);

            DateTime start = DateTime.Now;

            WriteOnce.Operation(ErrMsg.FormatString(ErrMsg.ID.CMD_RUNNING, "Analyze"));

            _appProfile.MetaData.TotalFiles = _srcfileList.Count();//updated for zipped files later

            // Iterate through all files and process against rules
            foreach (string filename in _srcfileList)
            {
                //exclude sample, test or similar files by default or as specified in exclusion list
                if (!_arg_allowSampleFiles && _fileExclusionList.Any(v => filename.ToLower().Contains(v)))
                {
                    WriteOnce.SafeLog("Part of excluded list: " + filename, LogLevel.Trace);
                    WriteOnce.SafeLog(ErrMsg.FormatString(ErrMsg.ID.ANALYZE_FILESIZE_SKIPPED, filename), LogLevel.Trace);
                    _appProfile.MetaData.FilesSkipped++;
                    continue;
                }

                ArchiveFileType archiveFileType = MiniMagic.DetectFileType(filename);
                if (archiveFileType == ArchiveFileType.UNKNOWN)
                {
                    ProcessAsFile(filename);
                }
                else
                {
                    UnZipAndProcess(filename, archiveFileType);
                }
            }

            WriteOnce.General("\r" + ErrMsg.FormatString(ErrMsg.ID.ANALYZE_FILES_PROCESSED_PCNT, 100));
            WriteOnce.Operation(ErrMsg.GetString(ErrMsg.ID.CMD_PREPARING_REPORT));

            //Prepare report results
            _appProfile.MetaData.LastUpdated = LastUpdated.ToString();
            _appProfile.DateScanned          = DateScanned.ToString();
            _appProfile.PrepareReport();
            TimeSpan timeSpan = start - DateTime.Now;

            WriteOnce.SafeLog(String.Format("Processing time: seconds:{0}", timeSpan.TotalSeconds * -1), LogLevel.Trace);
            FlushAll();

            //wrapup result status
            if (_appProfile.MetaData.TotalFiles == _appProfile.MetaData.FilesSkipped)
            {
                WriteOnce.Error(ErrMsg.GetString(ErrMsg.ID.ANALYZE_NOSUPPORTED_FILETYPES));
            }
            else if (_appProfile.MatchList.Count == 0)
            {
                WriteOnce.Error(ErrMsg.GetString(ErrMsg.ID.ANALYZE_NOPATTERNS));
            }
            else
            {
                WriteOnce.Operation(ErrMsg.FormatString(ErrMsg.ID.CMD_COMPLETED, "Analyze"));
            }

            return(_appProfile.MatchList.Count() == 0 ? (int)ExitCode.NoMatches :
                   (int)ExitCode.MatchesFound);
        }