From 1b8496d583bf9d1644abd833f5a5c9eb4f3fcd60 Mon Sep 17 00:00:00 2001
From: Walter Purcaro <vuolter@users.noreply.github.com>
Date: Thu, 1 Oct 2015 04:49:54 +0200
Subject: [AntiVirus] Folder support

---
 module/plugins/hooks/AntiVirus.py | 72 ++++++++++++++++++++++++++-------------
 1 file changed, 48 insertions(+), 24 deletions(-)

(limited to 'module/plugins/hooks')

diff --git a/module/plugins/hooks/AntiVirus.py b/module/plugins/hooks/AntiVirus.py
index b58d0b61d..d7ec69031 100644
--- a/module/plugins/hooks/AntiVirus.py
+++ b/module/plugins/hooks/AntiVirus.py
@@ -10,23 +10,25 @@ except ImportError:
     pass
 
 from module.plugins.internal.Addon import Addon, Expose, threaded
+from module.plugins.internal.Plugin import exists
 from module.utils import fs_encode, save_join as fs_join
 
 
 class AntiVirus(Addon):
     __name__    = "AntiVirus"
     __type__    = "hook"
-    __version__ = "0.12"
+    __version__ = "0.13"
     __status__  = "testing"
 
     #@TODO: add trash option (use Send2Trash lib)
-    __config__ = [("action"    , "Antivirus default;Delete;Quarantine", "Manage infected files"                     , "Antivirus default"),
-                  ("quardir"   , "folder"                             , "Quarantine folder"                         , ""                 ),
-                  ("deltotrash", "bool"                               , "Move to trash (recycle bin) instead delete", True               ),
-                  ("scanfailed", "bool"                               , "Scan incompleted files (failed downloads)" , False              ),
-                  ("cmdfile"   , "file"                               , "Antivirus executable"                      , ""                 ),
-                  ("cmdargs"   , "str"                                , "Scan options"                              , ""                 ),
-                  ("ignore-err", "bool"                               , "Ignore scan errors"                        , False              )]
+    __config__ = [("action"    , "Antivirus default;Delete;Quarantine", "Manage infected files"       , "Antivirus default"),
+                  ("quardir"   , "folder"                             , "Quarantine folder"           , ""                 ),
+                  ("deltotrash", "bool"                               , "Move to trash instead delete", True               ),
+                  ("scanfailed", "bool"                               , "Scan failed downloads"       , False              ),
+                  ("avfile"    , "file"                               , "Antivirus executable"        , ""                 ),
+                  ("avargs"    , "str"                                , "Executable arguments"        , ""                 ),
+                  ("avtarget"  , "file;folder"                        , "Scan target"                 , "file"             ),
+                  ("ignore-err", "bool"                               , "Ignore scan errors"          , False              )]
 
     __description__ = """Scan downloaded files with antivirus program"""
     __license__     = "GPLv3"
@@ -36,12 +38,24 @@ class AntiVirus(Addon):
     @Expose
     @threaded
     def scan(self, pyfile, thread):
-        file     = fs_encode(pyfile.plugin.last_download)
-        filename = os.path.basename(pyfile.plugin.last_download)
-        cmdfile  = fs_encode(self.get_config('cmdfile'))
-        cmdargs  = fs_encode(self.get_config('cmdargs').strip())
+        avfile = fs_encode(self.get_config('avfile'))
+        avargs = fs_encode(self.get_config('avargs').strip())
 
-        if not os.path.isfile(file) or not os.path.isfile(cmdfile):
+        if not os.path.isfile(avfile):
+            self.fail(_("Antivirus executable not found"))
+
+        scanfolder = self.get_config('avtarget') is "folder"
+
+        if scanfolder:
+            download_folder = self.pyload.config.get("general", "download_folder")
+            package_folder  = pyfile.package().folder if self.pyload.config.get("general", "folder_per_package") else ""
+            target      = fs_join(download_folder, package_folder, pyfile.name)
+            target_repr = "Folder: " + package_folder or download_folder
+        else:
+            target      = fs_encode(pyfile.plugin.last_download)
+            target_repr = "File: " + os.path.basename(pyfile.plugin.last_download)
+
+        if not exists(target):
             return
 
         thread.addActive(pyfile)
@@ -49,24 +63,34 @@ class AntiVirus(Addon):
         pyfile.setProgress(0)
 
         try:
-            p = subprocess.Popen([cmdfile, cmdargs, file], bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            p = subprocess.Popen([avfile, avargs, target],
+                                 bufsize=-1,
+                                 stdout=subprocess.PIPE,
+                                 stderr=subprocess.PIPE)
 
             out, err = map(str.strip, p.communicate())
 
             if out:
-                self.log_info(filename, out)
+                self.log_info(target_repr, out)
 
             if err:
-                self.log_warning(filename, err)
+                self.log_warning(target_repr, err)
                 if not self.get_config('ignore-err'):
-                    self.log_debug("Delete/Quarantine task is aborted")
+                    self.log_debug("Delete/Quarantine task aborted due scan error")
                     return
 
             if p.returncode:
-                pyfile.error = _("Infected file")
                 action = self.get_config('action')
+
+                if scanfolder:
+                    if action is "Antivirus default":
+                        self.log_warning(_("Delete/Quarantine task skipped in folder scan mode")
+                    return
+
+                pyfile.error = _("Infected file")
+
                 try:
-                    if action == "Delete":
+                    if action is "Delete":
                         if not self.get_config('deltotrash'):
                             os.remove(file)
 
@@ -87,15 +111,15 @@ class AntiVirus(Addon):
                             else:
                                 self.log_debug("Successfully moved file to trash")
 
-                    elif action == "Quarantine":
+                    elif action is "Quarantine":
                         pyfile.setCustomStatus(_("file moving"))
                         shutil.move(file, self.get_config('quardir'))
 
                 except (IOError, shutil.Error), e:
-                    self.log_error(filename, action + " action failed!", e)
+                    self.log_error(target_repr, action + " action failed!", e)
 
-            elif not out and not err:
-                self.log_debug(filename, "No infected file found")
+            elif not err:
+                self.log_debug(target_repr, "No infected file found")
 
         finally:
             pyfile.setProgress(100)
@@ -108,5 +132,5 @@ class AntiVirus(Addon):
 
     def download_failed(self, pyfile):
         #: Check if pyfile is still "failed", maybe might has been restarted in meantime
-        if pyfile.status == 8 and self.get_config('scanfailed'):
+        if pyfile.status is 8 and self.get_config('scanfailed'):
             return self.scan(pyfile)
-- 
cgit v1.2.3