小型内容检测库
介绍一个根据文件内容(和扩展名)检测内容的库。
引言
在我最近发表的关于Zeta Uploader应用程序的文章(简而言之,一个上传文件并通过电子邮件发送上传文件链接的网站)中,关于需要管理上传的文件以避免侵犯版权的讨论出现了(感谢Phil.Benson)。
本文介绍了一个我昨晚和今天早上编写的库(所以它非常“新鲜”),它是在正确的方向上迈出的第一步。
该库的功能
因为我想避免(至少现在)强制Zeta Uploader的用户注册和登录才能使用该服务,所以我决定尝试一种不同的方法
文件上传后,会检查该文件是否被认为是“禁止的”,即不能使用 Zeta Uploader 上传。 目前,我已将电影(AVI、MOV 等)和音乐(MP3、WAV 等)等文件列为禁止上传的文件。
该库的工作方式
检测算法使用以下机制来测试文件是被禁止还是允许
-
文件扩展名
查看文件扩展名。 如果它与禁止列表中的给定扩展名匹配,则该文件被认为是“禁止的”。
-
文件内容
查看文件的前几个字节中已知的二进制模式(“魔术字节”),以匹配禁止模式列表。
-
存档提取
如果检测到该文件是存档文件,则会临时提取该文件,并且还会扫描提取的文件(如果它们也包含存档,则会递归地扫描)。
下一节简要讨论这些不同的机制。
文件扩展名检查
这将直接检查文件名的扩展名。 由于这很容易作弊,因此文件扩展名检查仅作为第一次快速检查。 如果匹配,则会为给定的文件完成整个检测。
如果不是,则会进行内容分析,如下所述。
内容分析
该库的主要工作是对文件内容应用简单的“模式匹配”。 通过可扩展的ISignatureChecker
接口,以后可以添加更复杂的测试。 我已经包含了一个简单的 MP3 检查,它不仅仅是模式匹配(类Mp3SignatureChecker
)。
ISignatureChecker
interface
定义如下
/// <summary>
/// Interface to implement when checking a buffer
/// for a certain signature.
/// </summary>
internal interface ISignatureChecker
{
/// <summary>
/// Check whether a given buffer matches the signature.
///
/// <param name="buffer">The buffer.</param>
/// <returns></returns>
bool MatchesSignature(
byte[] buffer );
/// <summary>
/// Gets the first number of bytes to read.
/// </summary>
/// <value>The first number of bytes to read.</value>
int FirstNumberOfBytesToRead
{
get;
}
/// <summary>
/// Gets the minimum length of the required buffer.
/// </summary>
/// <value>The minimum length of the required buffer.</value>
int MinimumRequiredBufferLength
{
get;
}
}
通过此interface
,检查引擎与离散接口进行通信。 有关详细信息和示例,请参见源文件。
存档提取
由于大多数文件都是压缩存档,因此提取这些文件也很重要。
同样,我已经构建了一个基于IArchiveExtractor
interface
的可扩展的迷你框架,以便将来添加更多存档提取器。
interface
定义如下
/// <summary>
/// Interface for archive extractors.
///
internal interface IArchiveExtractor
{
/// <summary>
/// Extracts the specified file path.
/// </summary>
/// <param name="filePath">The file path.</param>
/// <param name="folderPathToExtractInto">The folder path
/// to extract into.</param>
void Extract(
FileInfo filePath,
DirectoryInfo folderPathToExtractInto );
}
目前,我使用SharpZipLib来为ZIP,gzip和bzip2提供提取器。
测试应用程序
下载中没有测试应用程序。 相反,以下代码段是我自己的测试控制台应用程序的完整Main
函数。
/// <summary>
/// The main function.
/// </summary>
private static void Main()
{
// Instantiate the engine.
ContentDetectorEngine engine = new ContentDetectorEngine();
// --
// Testing discrete files.
// Collect some files to test.
FileInfo[] filePaths = new FileInfo[]
{
new FileInfo( @"c:\AnotherFolder\112431940.mp3" ),
new FileInfo( @"c:\AnotherFolder\247293565.txt" ),
new FileInfo( @"c:\AnotherFolder\008284502.zip" ),
new FileInfo( @"c:\AnotherFolder\190243241.mdb" ),
new FileInfo( @"c:\AnotherFolder\182944456.zip" ),
};
// Iterate over the files.
foreach ( FileInfo filePath in filePaths )
{
bool contains =
engine.ContainsFileProhibitedContent( filePath );
Console.WriteLine(
@"Contains '{0}': {1}.",
filePath.Name,
contains );
}
// --
// Testing a complete folder.
// Find all files in the given folder.
FileInfo[] prohibitedPaths =
engine.ContainsFolderProhibitedContent(
new DirectoryInfo(
@"C:\SomeFolder" ) );
Console.WriteLine( @"Folder contains {0} prohibited files.",
prohibitedPaths.Length );
foreach ( FileInfo prohibitedPath in prohibitedPaths )
{
Console.WriteLine(
@"\tProhibited file: '{0}'.", prohibitedPath );
}
}
只需将其复制到您自己的控制台应用程序中即可。
结论
在本文中,我向您展示了一个基于文件内容检测文件类型的库。 虽然这只是该库的第一个版本,并且可能某些方法有些幼稚,但我确信该代码很有用,并且将来可以扩展为更可用。
如果您有反馈,问题或评论,只需在下面的评论部分中发布即可。 我期待您的消息!
参考文献
- HeaderSig.txt - 几种文件类型的签名
- 魔术数字(编程) - 维基百科文章
历史
- 2007-05-01: 初始版本的库