#
# Copyright (c) 2006-2011 Hal Brodigan (postmodern.mod3 at gmail.com)
#
# This file is part of Ronin.
#
# Ronin is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ronin is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ronin. If not, see .
#
require 'ronin/target'
require 'ronin/model'
require 'ronin/extensions/file'
require 'dm-timestamps'
require 'dm-tags'
require 'fileutils'
module Ronin
class RemoteFile
include Model
# Primary key of the remote file
property :id, Serial
# Remote path of the file
property :remote_path, String, :required => true,
:index => true
# The target the file was recovered from
belongs_to :target
# The address the file was recovered from
has 1, :address, :through => :target
# Tracks when the remote file was first recovered
timestamps :created_at
# Tags
has_tags_on :tags
# Validates the uniqueness of the remote_path and the target.
validates_uniqueness_of :remote_path, :scope => [:target]
#
# Searches for all remote files with the basename.
#
# @param [String] basename
# The basename of the file.
#
# @return [Array]
# The matching remote files.
#
# @since 1.0.0
#
def self.named(basename)
all(:remote_path => basename) |
all(:remote_path.like => "%/#{basename}")
end
#
# Searches for all remote files with the file name extension.
#
# @param [String, Symbol] ext
# The file name extension.
#
# @return [Array]
# The matching remote files.
#
# @since 1.0.0
#
def self.extension(ext)
all(:remote_path => "%.#{ext}")
end
#
# The local path for the remote file.
#
# @return [String, nil]
# The local path within the `~/.ronin/campaigns` directory.
#
# @since 1.0.0
#
def local_path
if self.target
escaped_path = File.escape_path(self.remote_path)
return File.join(self.target.directory,escaped_path)
end
end
#
# Determines whether the remote file has been downloaded yet.
#
# @return [Boolean]
# Specifies whether the remote file was downloaded.
#
# @since 1.0.0
#
def downloaded?
!(File.file?(local_path))
end
#
# Opens the downloaded remote file for reading.
#
# @yield [file]
# The opened file will be passed to the given block.
#
# @yieldparam [File] file
# The opened file.
#
# @return [File, nil]
# If no block is given, the opened file will be returned.
#
# @since 1.0.0
#
def open(&block)
File.open(local_path,'rb',&block)
end
#
# Opens a local file for saving the contents of the remote file.
#
# @yield [file]
# The opened file will be passed to the given block.
#
# @yieldparam [File] file
# The opened file.
#
# @return [File, nil]
# If no block is given, the opened file will be returned.
#
def download!(&block)
path = local_path
directory = File.dirname(path)
FileUtils.mkdir_p(directory) unless File.directory?(directory)
return File.open(path,'wb',&block)
end
end
end