# DFF -- An Open Source Digital Forensics Framework
# Copyright (C) 2009-2013 ArxSys
# This program is free software, distributed under the terms of
# the GNU General Public License Version 2. See the LICENSE file
# at the top of the source tree.
#  
# See http://www.digital-forensic.org for more information about this
# project. Please do not directly contact any of the maintainers of
# DFF for assistance; the project provides a web site, mailing lists
# and IRC channels for your use.
# 
# Author(s):
#  Solal Jacob <sja@digital-forensic.org>
# 

__dff_module_fileinfo_version__ = "1.0.0"

from dff.api.vfs import *
from dff.api.loader import *
from dff.api.module.module import *
from dff.api.module.script import *
from dff.api.types.libtypes import Variant, typeId, Argument

from dff.ui.console.utils import VariantTreePrinter

class FILEINFO(Script): 
  def __init__(self):
      Script.__init__(self, "fileinfo")
      self.vtreeprinter = VariantTreePrinter()

      
  def start(self, args):
    buff = ""
    node = args["file"].value()
    if args.has_key("max-items"):
      self.vtreeprinter.setMaxItemListToExpand(args["max-items"].value())
    else:
      self.vtreeprinter.setMaxItemListToExpand(-1)
    if args.has_key("max-depth"):
      self.vtreeprinter.setMaxDepth(args["max-depth"].value())
    else:
      self.vtreeprinter.setMaxDepth(-1)
    buff += self.fillBase(node)
    buff += self.fillAttributes(node)
    self.res["result"] = Variant(buff)


  def fillBase(self, node):
    buff = ""
    fsobj = node.fsobj()
    fsobjname = ""
    if fsobj != None:
      fsobjname = fsobj.name
    buff += "name :\t\t" + str(node.name()) + "\n"
    buff += "node type :\t\t" 
    if node.isFile():
      buff += "file"
      if node.hasChildren():
        buff += " " + "with module(s) applied on it"
    if node.isDir():
      buff += "folder"
      if not node.hasChildren():
        buff += " " + "empty"
    if node.isDeleted():
      buff += " " + "deleted"
    buff += "\n"

    buff += self.fillCompatModule(node)
    if node.hasChildren():
      buff += self.fillChildren(node)

    buff += "generated by:\t\t"
    buff += fsobjname + "\n"
    
    buff += "size:\t\t\t"
    buff += str(node.size())
    buff += "\n"
    return buff


  def fillCompatModule(self, node):
    buff = ""
    l = node.compatibleModules()
    if len(l) > 0:
      buff += "relevant module(s) :\t"
      for i in l:
        buff += str(i) + " " 
    buff += "\n"
    return buff


  def fillChildren(self, node): 
    buff = "children\t\t"
    children = node.children()
    filessize = 0
    filecount = 0
    dircount = 0
    for child in children:
      if child.size():
        filessize += child.size()
        filecount += 1
      elif child.isDir() or child.hasChildren():
        dircount += 1
    if filecount > 0:
      buff += "file(s)"
      buff += str(filecount) + " totalizing " + str(filessize) + " bytes\n"
    if dircount > 0:
      buff += "folder(s) "
      buff += str(dircount) + "\n"
    return buff


  def fillAttributes(self, node):
    buff = ""
    vmap = node.attributes()
    if len(vmap) > 0:
      buff = self.vtreeprinter.fillMap(1, vmap, "attributes:\n")
    return buff


class fileinfo(Module):
  """Display file attribute informations. (size, MAC time, ...)"""
  def __init__(self):
    Module.__init__(self, "fileinfo",  FILEINFO)
    self.conf.addArgument({"name": "file",
                           "input": Argument.Single|Argument.Required|typeId.Node,
                           "description": "File for which metadata will be shown"})
    self.conf.addArgument({"name": "max-items",
                           "input": Argument.Single|Argument.Optional|typeId.UInt64,
                           "description": "sets max items to expand in list (useful with large list)"})
    self.conf.addArgument({"name": "max-depth",
                           "input": Argument.Single|Argument.Optional|typeId.UInt64,
                           "description": "sets max depth on variant tree"})
    self.tags = "builtins"
