diff --git a/bin/xtminfo b/bin/xtminfo index 09f6364..230ed2c 100755 --- a/bin/xtminfo +++ b/bin/xtminfo @@ -1,84 +1,82 @@ -#!/usr/bin/ruby +#!/usr/bin/env ruby require 'optparse' +require 'xtmfile/header' -require 'rubygems' -require 'bindata' +module XtmFile + class XtmInfo + class XtmInfoArgumentError < ArgumentError ; end -require 'xtmfile/xtmheader' + attr_reader :opts -class XtmInfo - class XtmInfoArgumentError < ArgumentError ; end - - attr_reader :opts - - - def initialize args - @args = [] - @input_xtm = nil - parse_command_line args - end - - def parse_command_line args - @args = args.clone - @opts = OptionParser.new do |opts| - opts.banner = "Usage: #{File.basename $0} [options]\n" - - opts.separator "" - opts.separator "Mandatory options" - - opts.on("-i", "--input FILE", "Input XTM file") do |r| - @input_xtm = r - end - - opts.separator "" - opts.separator "General options:" - - opts.on("-h", "--help", "Show this help") do |h| - @help = h - end - opts.on("-v", "--verbose", "Show warnings too") do |v| - @verbose = v - end - opts.separator "" + def initialize args + @args = [] + @input_xtm = nil + parse_command_line args end - end - def validate! - @opts.parse! + def parse_command_line args + @args = args.clone + @opts = OptionParser.new do |opts| + opts.banner = "Usage: #{File.basename $0} [options]\n" - raise XtmInfoArgumentError, "No input XTM file specified!" if @input_xtm.nil? - end + opts.separator "" + opts.separator "Mandatory options" + opts.on("-i", "--input FILE", "Input XTM file") do |r| + @input_xtm = r + end - def run - validate! + opts.separator "" + opts.separator "General options:" - File.open( @input_xtm, "rb" ) do |io| - header = XtmHeader::read io - puts header + opts.on("-h", "--help", "Show this help") do |h| + @help = h + end + opts.on("-v", "--verbose", "Show warnings too") do |v| + @verbose = v + end + opts.separator "" + end end - end - def self.main args - xj = nil - begin - xj = XtmInfo.new args - xj.run - exit 0 - rescue XtmInfoArgumentError => e - STDERR.puts "%s" % xj.opts - STDERR.puts "error: %s" % e.message + def validate! + @opts.parse! - exit 1 - rescue SystemExit => e - raise e - rescue Exception => e - STDERR.puts "error: %s" % e.message - exit 1 + raise XtmInfoArgumentError, "No input XTM file specified!" if @input_xtm.nil? + end + + + def run + validate! + + File.open( @input_xtm, "rb" ) do |io| + header = Header::read io + puts header.to_summary_string + end + end + + def self.main args + xj = nil + begin + xj = XtmInfo.new args + xj.run + exit 0 + rescue XtmInfoArgumentError => e + STDERR.puts "%s" % xj.opts + STDERR.puts "error: %s" % e.message + + exit 1 + rescue SystemExit => e + raise e + rescue Exception => e + STDERR.puts "error: %s" % e.message + STDERR.puts e.backtrace + exit 1 + end end end end -XtmInfo.main ARGV +XtmFile::XtmInfo.main ARGV diff --git a/xtmfile/header.rb b/xtmfile/header.rb new file mode 100644 index 0000000..8835f46 --- /dev/null +++ b/xtmfile/header.rb @@ -0,0 +1,70 @@ + +require 'rubygems' +gem 'bindata', '~> 1.2.1' +require 'bindata' + +# +# Offset | Information | Size (bytes) +# -------------------------------------------- +# 0 | Software name length | 1 +# 1 | Software name | 20 +# 21 | Version length | 1 +# 22 | Version | 4 +# 26 | Not used | 10 +# 36 | Date | 4 +# 40 | Filename length | 1 +# 41 | Filename | 50 +# 91 | MD5 Enable | 1 +# 92 | File parts count | 4 +# 96 | Original file size | 8 +# +class Header < BinData::Record + endian :little + + uint8 :progname_len, :value => lambda { progname_str.length } + string :progname_str, :length => 20 + + uint8 :version_len, :value => lambda { version_str.length } + string :version_str, :length => 4 + + string :unused, :length => 10 + + uint32le :date + + uint8 :filename_len + string :filename_str, :read_length => :filename_len + # fake padding + string :filename_str_pad, :read_length => lambda { 50 - filename_len } + + uint8 :md5 + + uint32 :filecount + uint64 :filesize + + def to_full_string + r = [] + r << "[%03d] Progname len : %s" % [self.progname_len.offset, self.progname_len] + r << "[%03d] Progname str : %s" % [self.progname_str.offset, self.progname_str] + r << "[%03d] Version len : %s" % [self.version_len.offset, self.version_len] + r << "[%03d] Version str : %s" % [self.version_str.offset, self.version_str] + r << "[%03d] Unused : %s" % [self.unused.offset, self.unused] + r << "[%03d] Date : %s" % [self.date.offset, self.date] + r << "[%03d] Filename len : %s" % [self.filename_len.offset, self.filename_len] + r << "[%03d] Filename str : %s" % [self.filename_str.offset, self.filename_str] + r << "[%03d] md5 : %s" % [self.md5.offset, self.md5] + r << "[%03d] Filecount : %d" % [self.filecount.offset, self.filecount] + r << "[%03d] Filesize : %s" % [self.filesize.offset, self.filesize] + return r.join("\n") + end + + def to_summary_string + r = [] + r << " Software : %s (%s)" % [self.progname_str,self.version_str] + r << " Date : %s" % self.date + r << "Filename str : %s" % self.filename_str + r << " md5 : %s" % ( self.md5 ? 'enabled' : 'disabled' ) + r << " Filecount : %d" % self.filecount + r << " Filesize : %s" % self.filesize + return r.join("\n") + end +end diff --git a/xtmfile/xtmheader.rb b/xtmfile/xtmheader.rb deleted file mode 100644 index 0f00b2a..0000000 --- a/xtmfile/xtmheader.rb +++ /dev/null @@ -1,52 +0,0 @@ - -class XtmHeader < BinData::Record - # Offset Information Taille (octets) - # 0 Longueur du nom du programme 1 - # 1 *Nom du programme 20 - # 21 Longueur de la version 1 - # 22 Version 4 - # 26 Not used 10 - # 36 Date 4 - # 40 Longueur du nom du fichier original 1 - # 41 Nom du fichier original 50 - # 91 **Hash MD5 1 - # 92 Nombre de fichiers 4 - # 96 Taille du fichier original 8 - - endian :little - - uint8 :progname_len, :value => lambda { progname_str.length } - string :progname_str, :length => 20 - - uint8 :version_len, :value => lambda { version_str.length } - string :version_str, :length => 4 - - string :unused, :length => 10 - - uint32le :date - - uint8 :filename_len - string :filename_str, :read_length => :filename_len - string :filename_str_pad, :read_length => lambda { 50 - filename_len } - - uint8 :md5 - - uint32 :filecount - uint64 :filesize - - def to_s - r = [] - r << ( "Progname len : %s [%s]" % [self.progname_len, self.progname_len.offset] ) - r << ( "Progname str : %s [%s]" % [self.progname_str, self.progname_str.offset] ) - r << ( " Version len : %s [%s]" % [self.version_len, self.version_len.offset] ) - r << ( " Version str : %s [%s]" % [self.version_str, self.version_str.offset] ) - r << ( " Unused : %s [%s]" % [self.unused, self.unused.offset] ) - r << ( " Date : %s [%s]" % [self.date, self.date.offset] ) - r << ( "Filename len : %s [%s]" % [self.filename_len, self.filename_len.offset] ) - r << ( "Filename str : %s [%s]" % [self.filename_str, self.filename_str.offset] ) - r << ( " md5 : %s [%s]" % [self.md5, self.md5.offset] ) - r << ( " Filecount : %d [%s]" % [self.filecount, self.filecount.offset] ) - r << ( " Filesize : %s [%s]" % [self.filesize, self.filesize.offset] ) - return r.join("\n") - end -end