OSDN Git Service

na-get-lib,タスクセットの改修(NaGetTaskSet2)および、そのUnitTestを追加
[applistation/AppliStation.git] / na-get-lib / NaGet.Net / DownloadScanner.cs
index af3e39e..9b65a84 100644 (file)
@@ -1,4 +1,10 @@
-using System;\r
+/*\r
+ * This code is based on /mozilla/source/toolkit/components/downloads/src/nsDownloadScanner.cpp\r
+ * and sample code at https://bugzilla.mozilla.org/show_bug.cgi?id=103487,\r
+ * created by Rob Arnold.\r
+ */\r
+\r
+using System;\r
 using System.Reflection;\r
 using System.Collections.Generic;\r
 using System.Runtime.InteropServices;\r
 using System.Reflection;\r
 using System.Collections.Generic;\r
 using System.Runtime.InteropServices;\r
@@ -7,6 +13,18 @@ using NaGet.InteropServices;
 \r
 namespace NaGet.Net\r
 {\r
 \r
 namespace NaGet.Net\r
 {\r
+       public enum DownloadScannerResult : uint {\r
+               OK = 0, // S_OK\r
+               InfectedAndCleaned = 1, // S_FALSE\r
+               InfectedButNotCleaned = 0x80004005,     // E_FAIL\r
+               ErrorNotFound = 2,      // ERROR_NOT_FOUND\r
+               \r
+               ScannerNotFound = 0xFFFFFFFF,\r
+       }\r
+       \r
+       /// <summary>\r
+       /// ダウンロードしたファイルをスキャンする\r
+       /// </summary>\r
        public class DownloadScanner : IDisposable\r
        {\r
                #region COMInterop\r
        public class DownloadScanner : IDisposable\r
        {\r
                #region COMInterop\r
@@ -39,14 +57,15 @@ namespace NaGet.Net
                [Guid("56FFCC30-D398-11D0-B2AE-00A0C908FA49")]\r
                [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]\r
                private interface IOfficeAntiVirus {\r
                [Guid("56FFCC30-D398-11D0-B2AE-00A0C908FA49")]\r
                [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]\r
                private interface IOfficeAntiVirus {\r
-                       void Scan(ref MSOAVINFO pmsoavinfo);\r
+                       [PreserveSig()]\r
+                       uint Scan(ref MSOAVINFO pmsoavinfo);\r
                }\r
                #endregion\r
                \r
                /// <summary>\r
                /// ウイルススキャナーに渡すプログラム・ホスト名。\r
                /// </summary>\r
                }\r
                #endregion\r
                \r
                /// <summary>\r
                /// ウイルススキャナーに渡すプログラム・ホスト名。\r
                /// </summary>\r
-               public string HostName {\r
+               public static string HostName {\r
                        get {\r
                                // 実行アセンブリ名を返す\r
                                return Assembly.GetExecutingAssembly().GetName().FullName;\r
                        get {\r
                                // 実行アセンブリ名を返す\r
                                return Assembly.GetExecutingAssembly().GetName().FullName;\r
@@ -54,28 +73,39 @@ namespace NaGet.Net
                }\r
                \r
                private List<IOfficeAntiVirus> scanners;\r
                }\r
                \r
                private List<IOfficeAntiVirus> scanners;\r
-               \r
+\r
+               /// <summary>\r
+               /// コンストラクタ。内部でCOM呼び出し初期化(CoInitialize)されます。\r
+               /// </summary>\r
                public DownloadScanner()\r
                {\r
                public DownloadScanner()\r
                {\r
-                       ComDirectAccess.CoInitialize(IntPtr.Zero);\r
+                       int result = ComDirectAccess.CoInitialize(IntPtr.Zero);\r
+                       if (result == 0) {\r
+                               throw new System.ComponentModel.Win32Exception();\r
+                       }\r
                }\r
                \r
                }\r
                \r
+               /// <summary>\r
+               /// 内部でCOM開放(CoUninitialize)します。必ず呼び出す必要があります。\r
+               /// </summary>\r
                public void Dispose()\r
                {\r
                public void Dispose()\r
                {\r
-                       if ((scanners != null) && (scanners.Count > 0)) {\r
-                               foreach (IOfficeAntiVirus i in scanners) {\r
-                                       Marshal.ReleaseComObject(i);\r
-                               }\r
-                               scanners.Clear();\r
-                       }\r
-                       \r
+                       Release();\r
                        ComDirectAccess.CoUninitialize();\r
                        ComDirectAccess.CoUninitialize();\r
+                       GC.SuppressFinalize(this);\r
                }\r
                \r
                }\r
                \r
+               /// <summary>\r
+               /// ウイルススキャンがあるかないか\r
+               /// </summary>\r
+               /// <remarks>Init()呼出し後に使える</remarks>\r
                public bool HasScanner {\r
                        get { return scanners.Count > 0; }\r
                }\r
                \r
                public bool HasScanner {\r
                        get { return scanners.Count > 0; }\r
                }\r
                \r
+               /// <summary>\r
+               /// 初期化処理としてウイルススキャンを探す。\r
+               /// </summary>\r
                public void Init()\r
                {\r
                        scanners = new List<IOfficeAntiVirus>();\r
                public void Init()\r
                {\r
                        scanners = new List<IOfficeAntiVirus>();\r
@@ -91,12 +121,34 @@ namespace NaGet.Net
                        }\r
                }\r
                \r
                        }\r
                }\r
                \r
-               public bool Scan(string path, string origin)\r
+               /// <summary>\r
+               /// ウイルススキャンのオブジェクトを開放しInitの前の状態に戻す。\r
+               /// </summary>\r
+               public void Release()\r
                {\r
                {\r
-                       if (scanners.Count <= 0) {\r
-                               return false;\r
+                       if ((scanners != null) && (scanners.Count > 0)) {\r
+                               foreach (IOfficeAntiVirus i in scanners) {\r
+                                       Marshal.ReleaseComObject(i);\r
+                               }\r
+                               scanners.Clear();\r
                        }\r
                        }\r
-                       \r
+               }\r
+               \r
+               /// <summary>\r
+               /// ファイルをスキャンする。ウイルススキャンが複数個見つかっている\r
+               /// ならばそれらすべてでスキャンする。\r
+               /// ウイルススキャンの実装によるが、ウイルス発見時にはダイアログが開く。\r
+               /// ウイルスの処理はユーザに委ねられるので、それの制御は一切できない。\r
+               /// </summary>\r
+               /// <remarks>ウイルスが見つかったか否かは取得できない。</remarks>\r
+               /// <remarks>本メソッド呼び出し後にウイルスが退避されているかもしれないが、ファイルの存在確認でしかそれをチェックできない</remarks>\r
+               /// <param name="path">ファイルのパス</param>\r
+               /// <param name="origin">ファイルをダウンロードしたURL。nullであってはならない</param>\r
+               /// <exception cref="COMException">COMのエラー発生時。たとえば、AVGではウイルスと検出されたのにユーザが「無視」を指定したときにも投げられる。</exception>\r
+               /// <returns>ウイルススキャン結果。</returns>\r
+               /// <remarks>Init()呼出し後に使える</remarks>\r
+               public DownloadScannerResult Scan(string path, string origin)\r
+               {\r
                        MSOAVINFO info = new MSOAVINFO();\r
                        info.cbsize = Marshal.SizeOf(info);\r
                        info.uFlags = MSOAVINFOFLAG.fPath | MSOAVINFOFLAG.fHttpDownload;\r
                        MSOAVINFO info = new MSOAVINFO();\r
                        info.cbsize = Marshal.SizeOf(info);\r
                        info.uFlags = MSOAVINFOFLAG.fPath | MSOAVINFOFLAG.fHttpDownload;\r
@@ -105,10 +157,23 @@ namespace NaGet.Net
                        info.pwzHostName = HostName;\r
                        info.pwzOrigURL = origin;\r
                        \r
                        info.pwzHostName = HostName;\r
                        info.pwzOrigURL = origin;\r
                        \r
+                       DownloadScannerResult result = DownloadScannerResult.ScannerNotFound;\r
                        foreach (IOfficeAntiVirus i in scanners) {\r
                        foreach (IOfficeAntiVirus i in scanners) {\r
-                               i.Scan(ref info);\r
+                               if (System.IO.File.Exists(path)) {\r
+                                       result = (DownloadScannerResult) i.Scan(ref info);\r
+                                       if (result == DownloadScannerResult.OK && System.IO.File.Exists(path) == false) {\r
+                                               result = DownloadScannerResult.InfectedAndCleaned;\r
+                                       }\r
+                               } else {\r
+                                       result = DownloadScannerResult.ErrorNotFound;\r
+                               }\r
+                               \r
+                               if (result != DownloadScannerResult.OK) {\r
+                                       break;\r
+                               }\r
                        }\r
                        }\r
-                       return true;\r
+                       \r
+                       return result;\r
                }\r
        }\r
 }\r
                }\r
        }\r
 }\r