Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ronin compress command #184

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions lib/ronin/cli/commands/compress.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# frozen_string_literal: true
#
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
#
# 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 <https://www.gnu.org/licenses/>.
#

require 'ronin/cli/string_methods_command'
require 'ronin/support/compression'
require 'ronin/support/archive'

module Ronin
class CLI
module Commands
#
# Compress the files.
#
# ## Usage
#
# ronin compress [option] [FILE ...]
#
# ## Options
#
# -z, --zip zip archive the data
# -t, --tar tar archive the data
# -g, --gzip gzip compresses the data
#
# ## Arguments
#
# [FILE ...] Optional file(s) to compress
#
class Compress < StringMethodsCommand
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we only want to support processing files, then probably want to inherit from FileProcessorCommand, and define a process_input(io) method to compress the input File or from stdin.

If we do want to support accepting arbitrary Strings (ex: ronin compress --string "hello world"), then we should inherit from StringProcessorCommand.

StringMethodsCommand is more meant to be used by commands which simply map options to certain monkey-patch methods that are added to String (ex: ronin decode --base64 -> String#base64_decode).

usage '[option] [FILE ...]'

option :gzip, short: '-g',
desc: 'gzip compresses the data' do
@format = :gzip
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to support --gzip, we should also support a --zlib option. ronin-support also happens to have a Ronin::Support::Compression::Zlib module we can use.


option :tar, short: '-t',
desc: 'tar archive the data' do
@format = :tar
end

option :zip, short: '-z',
desc: 'zip archive the data' do
@format = :zip
end

description 'Compress the data'

man_page 'ronin-compress.1'

#
# The compression format.
#
# @return Symbol
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to explicitly list the possible values @return [:gzip, :tar, :zip].

#
attr_reader :format

def initialize(**kwargs)
postmodern marked this conversation as resolved.
Show resolved Hide resolved
super(**kwargs)

@format = :gzip
end

def process_file(file)
compression_class.send(@format, "#{file}.#{extension}") do |c|
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename @format to @method or @compression_method if we're going to send() it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So here's a question, if you gave this command the --zip option and multiple files, would the user expect each file to be compressed into it's own .zip file, or all files to be compressed into one zip file?

c.write File.read(file)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The files being compressed could be very very large. Probably more efficient to open the input file and read chunks of data from it using input.readpartial(4096) and write those to the output stream.

end
end

private

def compression_class
if @format == :gzip
Ronin::Support::Compression
else
Ronin::Support::Archive
end
end
postmodern marked this conversation as resolved.
Show resolved Hide resolved

def extension
return "gz" if @format == :gzip
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could probably set an @ext instance variable in the option blocks, along with @format. This way we follow the "Tell, don't ask" principle.


@format.to_s
end
end
end
end
end