#!/usr/bin/ruby begin require 'zlib' def ckcrc(str, crc) Zlib.crc32(str) == crc end rescue LoadError def ckcrc(str, crc) true end end class Ydec def initialize(fd = nil) @ybeginline = true @outfile = nil @outlen = nil @linelen = nil @ypartline = false @partoffset = nil @partsize = nil @partcrc = nil @curbuf = nil @specialchar = false mass_process fd if fd end def mass_process(io) l = nil io.each_line { |l| parse_line l } end # returns true if you should pass the next line def parse_line(l) l = l.chomp if @ybeginline parse_ybegin $1 if l =~ /^=ybegin\s+(.*?)\s*$/ !@ybeginline elsif @ypartline parse_ypart $1 if l =~ /^=ypart\s+(.*?)\s*$/ !@ypartline elsif @curbuf if l =~ /^=yend\s+(.*?)\s*$/ parse_yend $1 else ydecode l end !!@curbuf end end def parse_ybegin(l) raise "invalid ybegin #{l.inspect}" unless l =~ /(.*) name=(.*)/ l = $1 @outfile = $2 @ypartline = (l =~ /\bpart\b/) puts "ydec: decoding #{@outfile.inspect}#{' (part)' if @ypartline}" @outfile.gsub!(/[^a-zA-Z0-9_.+\-\[\]\(\)#'" ]/, '_') l.scan(/(\w+)=(\w+)/).each { |k, v| case k when 'line': @linelen = v.to_i when 'size': @outlen = v.to_i when 'part' else puts "unknown ybegin field #{k.inspect} = #{v.inspect}" end } @curbuf = '' @ybeginline = false true end def parse_ypart(l) l.scan(/(\w+)=(\w+)/).each { |k, v| case k when 'begin': @partoffset = v.to_i - 1 when 'end': @partsize = v.to_i - @partoffset else puts "unknown ypart field #{k.inspect} = #{v.inspect}" end } puts "ydec: decoding part: #@partsize o at #@partoffset" if $VERBOSE @curbuf = '' @ypartline = false true end def parse_yend(l) sz = nil crc = nil pcrc = nil l.scan(/(\w+)=(\w+)/).each { |k, v| case k when 'size': sz = v.to_i when 'crc32': crc = v[0..7].hex when 'pcrc32': pcrc = v[0..7].hex when 'part' else puts "unknown yend field #{k.inspect} = #{v.inspect}" end } puts "ydec: finished" if $VERBOSE if @partsize if pcrc and not ckcrc(@curbuf, pcrc) puts "bad part crc" end if sz if sz != @partsize puts "sz #{sz} != ypart sz #@partsize" end if sz != @curbuf.size puts "sz #{sz} != curbuf.sz #{@curbuf.size}" end end if @partsize and @curbuf.size != @partsize puts "ypart sz #@partsize != curbuf.sz #{@curbuf.size}" end File.open(@outfile, 'w') {} unless File.exist? @outfile File.open(@outfile, 'r+') { |fd| fd.seek @partoffset ; fd.write @curbuf } else if crc and not ckcrc(@curbuf, crc) puts "bad crc" end if sz if sz != @outlen puts "sz #{sz} != outlen #@outlen" end if sz != @curbuf.size puts "sz #{sz} != curbuf.sz #{@curbuf.size}" end end if @outlen != @curbuf.size puts "outlen #@outlen != curbuf.sz #{@curbuf.size}" end File.open(@outfile, 'w') { |fd| fd.write @curbuf } end @curbuf = nil @ybeginline = true end begin raise :pute require 'dl' LIB_YDEC = DL.dlopen('./libydec.so')['dec_yline', 'IsI'] def ydecode(l) len = LIB_YDEC.call(l, l.size) @curbuf << l[0..len] end rescue def ydecode(l) l.each_byte { |b| if @specialchar @specialchar = false @curbuf << ((b - 64 - 42) & 255) else case b when ?= @specialchar = true when ?\n, ?\r, ?\0 puts "special char #{b.chr.inspect} in stream..." else @curbuf << ((b - 42) & 255) end end } if @specialchar puts "line ends with specialchar.." @specialchar = false end end end end if $0 == __FILE__ Ydec.new(ARGF) end