2003-04-18 22:53:25 +00:00
|
|
|
#################################
|
|
|
|
|
#
|
2003-04-22 19:11:15 +00:00
|
|
|
# $Dwarf: yenc.rb,v 1.6 2003/04/21 19:45:38 ward Exp $
|
2003-04-18 22:53:25 +00:00
|
|
|
# $Source$
|
|
|
|
|
#
|
|
|
|
|
# article.rb
|
|
|
|
|
#
|
|
|
|
|
# (C) 2002, Ward Wouts
|
|
|
|
|
#
|
|
|
|
|
#################################
|
|
|
|
|
|
|
|
|
|
require 'tempfile'
|
|
|
|
|
|
2003-04-20 18:31:17 +00:00
|
|
|
class YEnc
|
|
|
|
|
class << self
|
2003-04-18 22:53:25 +00:00
|
|
|
|
|
|
|
|
Debuglevel = 0
|
|
|
|
|
|
|
|
|
|
def ydecode(data, outfile=nil)
|
2003-04-20 18:31:17 +00:00
|
|
|
@ymap = {}
|
|
|
|
|
(-106..255).each do |b|
|
|
|
|
|
@ymap[b]=((b-42)%256)
|
2003-04-18 22:53:25 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
case data.type.to_s
|
|
|
|
|
when "Array"
|
|
|
|
|
print "Calling _ydecode_array\n" if Debuglevel>0
|
|
|
|
|
mode, filename, body = _ydecode_array(data)
|
|
|
|
|
when "File", "Tempfile"
|
|
|
|
|
unless outfile
|
|
|
|
|
print "ydecode: need outfile\n"
|
|
|
|
|
exit
|
|
|
|
|
end
|
|
|
|
|
print "Calling _ydecode_file\n" if Debuglevel>0
|
|
|
|
|
mode, filename, body = _ydecode_file(data, outfile)
|
|
|
|
|
else
|
|
|
|
|
print "Funny stuff in ydecode. Data of type \"#{data.type.to_s}\"\n"
|
|
|
|
|
end
|
|
|
|
|
return mode, filename, body
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def _ydecode_line(line)
|
|
|
|
|
i = 0
|
|
|
|
|
ll = line.length
|
|
|
|
|
ostr = ''
|
|
|
|
|
while i < ll
|
|
|
|
|
if line[i] == 0x3d
|
|
|
|
|
i += 1
|
|
|
|
|
line[i] -= 64
|
|
|
|
|
end
|
|
|
|
|
ostr << @ymap[line[i]]
|
|
|
|
|
i += 1
|
|
|
|
|
end
|
2003-04-20 18:31:17 +00:00
|
|
|
return ostr
|
2003-04-18 22:53:25 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def _ydecode_file(file, outfile)
|
2003-04-20 18:31:17 +00:00
|
|
|
mode = 0600 # mode is a bit stupid with yencoding... it don't get it
|
2003-04-18 22:53:25 +00:00
|
|
|
filename = "unknown"
|
|
|
|
|
lines = file.pos
|
|
|
|
|
file.pos = 0
|
|
|
|
|
bytes = 0
|
|
|
|
|
total = 0
|
2003-04-20 21:31:12 +00:00
|
|
|
oldpartbegin = 0
|
2003-04-18 22:53:25 +00:00
|
|
|
oldpartend = 0
|
|
|
|
|
search_begin = false
|
2003-04-20 21:31:12 +00:00
|
|
|
skip = false
|
2003-04-18 22:53:25 +00:00
|
|
|
|
|
|
|
|
while (! file.eof)
|
|
|
|
|
line = file.gets
|
|
|
|
|
print "line: #{line}" if Debuglevel > 0
|
|
|
|
|
if line =~ /^\=ybegin\s+(.*line\=.*)/
|
|
|
|
|
m = $1
|
|
|
|
|
print "ybegin match; rest: #{m}\n" if Debuglevel > 0
|
2003-04-20 18:31:17 +00:00
|
|
|
if m =~ /^\s*(part\=(\d+)\s+)?(total\=(\d+)\s+)?(line\=(\d+))(\s*size\=(\d+))(\s*name=(.*?\S))\s*$/
|
2003-04-18 22:53:25 +00:00
|
|
|
part = $2.to_i
|
|
|
|
|
total = $4.to_i
|
|
|
|
|
linesize = $6.to_i
|
|
|
|
|
totalsize = $8.to_i
|
|
|
|
|
filename = $10
|
2003-04-20 18:31:17 +00:00
|
|
|
if Debuglevel > 0
|
|
|
|
|
print "found beginning"
|
|
|
|
|
if part != nil
|
|
|
|
|
print " of part #{part}"
|
|
|
|
|
end
|
|
|
|
|
if total != nil
|
|
|
|
|
print " of #{total}"
|
|
|
|
|
end
|
|
|
|
|
print ", linesize = #{linesize}, size = #{totalsize}, filename = #{filename}\n"
|
2003-04-18 22:53:25 +00:00
|
|
|
end
|
|
|
|
|
break
|
|
|
|
|
else
|
|
|
|
|
print "not a valid yenc begin line\n"
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if file.eof
|
|
|
|
|
print "Not yencoded!\n"
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
while (! file.eof)
|
|
|
|
|
print "at #{file.pos} need to go to #{lines}\n" if Debuglevel > 1
|
|
|
|
|
line = file.gets
|
|
|
|
|
line.chop!
|
|
|
|
|
|
|
|
|
|
if line =~ /^=yend\s+(.*)\Z/
|
|
|
|
|
m = $1
|
|
|
|
|
m =~ /(\s*size=(\d+)\s+)(\s*part=(\d+))?(\s+crc32=(\S+))?/
|
|
|
|
|
size = $2.to_i
|
|
|
|
|
part = $4.to_i
|
|
|
|
|
crc = $6
|
|
|
|
|
if size != bytes
|
|
|
|
|
print "part size mismatch, is #{bytes}, should be #{size}\n"
|
|
|
|
|
end
|
|
|
|
|
if part == nil
|
|
|
|
|
return mode, filename
|
|
|
|
|
end
|
|
|
|
|
total += bytes
|
|
|
|
|
if total >= totalsize
|
|
|
|
|
if total != totalsize
|
|
|
|
|
print "total size mismatch, is #{total}, should be #{totalsize}\n"
|
|
|
|
|
end
|
|
|
|
|
return mode, filename
|
|
|
|
|
end
|
|
|
|
|
search_begin = true
|
|
|
|
|
bytes = 0
|
|
|
|
|
next
|
|
|
|
|
end
|
|
|
|
|
if search_begin && line =~ /^\=ybegin\s+(.*)\Z/
|
|
|
|
|
m = $1
|
|
|
|
|
search_begin = false
|
2003-04-20 18:31:17 +00:00
|
|
|
if m =~ /^\s*(part\=(\d+)\s+)?(total\=(\d+)\s+)?(line\=(\d+))(\s*size\=(\d+))(\s*name=(.*?\S))\s*$/
|
2003-04-18 22:53:25 +00:00
|
|
|
part = $2.to_i
|
|
|
|
|
total = $4.to_i
|
|
|
|
|
linesize = $6.to_i
|
|
|
|
|
totalsize = $8.to_i
|
|
|
|
|
filename = $10
|
|
|
|
|
print "found beginning of part #{part}, linesize = #{linesize}, size = #{totalsize}, filename = #{filename}\n" if Debuglevel > 0
|
|
|
|
|
end
|
|
|
|
|
next
|
|
|
|
|
end
|
|
|
|
|
if search_begin == true
|
|
|
|
|
next
|
|
|
|
|
end
|
|
|
|
|
if line =~ /^=ypart\s+(\s*begin=(\d+))(\s+end=(\d+))/
|
2003-04-20 21:31:12 +00:00
|
|
|
skip = false
|
2003-04-18 22:53:25 +00:00
|
|
|
b = $2
|
|
|
|
|
e = $4
|
|
|
|
|
print " next part begin #{b}, end #{e}\n"
|
2003-04-20 21:31:12 +00:00
|
|
|
if b.to_i == oldpartbegin && e.to_i == oldpartend
|
|
|
|
|
print "Skipping duplicate part\n"
|
|
|
|
|
skip = true
|
|
|
|
|
next
|
|
|
|
|
end
|
2003-04-18 22:53:25 +00:00
|
|
|
if b.to_i == oldpartend + 1
|
|
|
|
|
oldpartend = e.to_i
|
2003-04-20 21:31:12 +00:00
|
|
|
oldpartbegin = b.to_i
|
2003-04-18 22:53:25 +00:00
|
|
|
else
|
|
|
|
|
raise PermError, "Parts not continuous! last end #{oldpartend}, begin #{b}"
|
|
|
|
|
end
|
|
|
|
|
next
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# This seems to be a common 'error' - maybe I misunderstand the spec or
|
|
|
|
|
# something
|
|
|
|
|
# if line.length != linesize
|
|
|
|
|
# print "linesize mismatch, was #{line.length}, should be #{linesize}...\n"
|
|
|
|
|
# end
|
|
|
|
|
|
2003-04-20 21:31:12 +00:00
|
|
|
if !skip
|
|
|
|
|
print "line: #{line}" if Debuglevel > 0
|
|
|
|
|
ostr = _ydecode_line(line)
|
|
|
|
|
outfile << ostr
|
|
|
|
|
bytes += ostr.length
|
|
|
|
|
end
|
2003-04-18 22:53:25 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
print "No \"=yend\" found!!!\n"
|
|
|
|
|
return mode, filename, outfile
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# toch maar een keer aparte class van maken... geld ook voor dit geneuzel
|
|
|
|
|
def _ydecode_array(data)
|
|
|
|
|
decode = ""
|
|
|
|
|
mode = 0600
|
|
|
|
|
filename = "unknown"
|
2003-04-21 19:45:38 +00:00
|
|
|
oldpartend = 0
|
|
|
|
|
oldpartbegin = 0
|
2003-04-18 22:53:25 +00:00
|
|
|
c = 0
|
|
|
|
|
lines = data.length
|
|
|
|
|
bytes = 0
|
|
|
|
|
percent = 0
|
|
|
|
|
mark = lines/100
|
|
|
|
|
|
|
|
|
|
i = 0
|
|
|
|
|
while (i < data.length)
|
|
|
|
|
if data[i] =~ /^\=ybegin\s+(.*line\=.*)/
|
|
|
|
|
m = $1
|
|
|
|
|
print "ybegin match; rest: #{m}\n" if Debuglevel > 0
|
2003-04-20 18:31:17 +00:00
|
|
|
if m =~ /^\s*(part\=(\d+)\s+)?(total\=(\d+)\s+)?(line\=(\d+))(\s*size\=(\d+))(\s*name=(.*?\S))\s*$/
|
2003-04-18 22:53:25 +00:00
|
|
|
part = $2.to_i
|
|
|
|
|
total = $4.to_i
|
|
|
|
|
linesize = $6.to_i
|
|
|
|
|
size = $8.to_i
|
|
|
|
|
filename = $10
|
|
|
|
|
print "found beginning, linesize = #{linesize}, size = #{size}, filename = #{filename}\n" if Debuglevel > 0
|
|
|
|
|
i += 1
|
|
|
|
|
break
|
|
|
|
|
else
|
|
|
|
|
print "not a valid yenc begin line\n"
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
i += 1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
unless (i < data.length)
|
|
|
|
|
print "Not yencoded!\n"
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
while (i < data.length)
|
|
|
|
|
line = data[i]
|
2003-04-22 19:11:15 +00:00
|
|
|
line.chomp!("\r\n")
|
2003-04-20 18:31:17 +00:00
|
|
|
print "at #{i} need to go to #{data.length}\n" if Debuglevel > 1
|
|
|
|
|
print "line: #{line}" if Debuglevel > 0
|
2003-04-18 22:53:25 +00:00
|
|
|
i += 1
|
|
|
|
|
if line =~ /^\=yend(\s+size=(\d+))(\s+crc32=(\S+))?/
|
|
|
|
|
size = $2.to_i
|
|
|
|
|
crc = $4
|
|
|
|
|
if size != decode.length
|
|
|
|
|
print "size mismatch, was #{decode.length}, should be #{size}\n"
|
|
|
|
|
end
|
|
|
|
|
dec = [ decode ]
|
|
|
|
|
return mode, filename, dec
|
|
|
|
|
end
|
2003-04-20 21:31:12 +00:00
|
|
|
if line =~ /^=ypart\s+(\s*begin=(\d+))(\s+end=(\d+))/
|
|
|
|
|
skip = false
|
|
|
|
|
b = $2
|
|
|
|
|
e = $4
|
|
|
|
|
print " next part begin #{b}, end #{e}\n"
|
|
|
|
|
if b.to_i == oldpartbegin && e.to_i == oldpartend
|
|
|
|
|
print "Skipping duplicate part\n"
|
|
|
|
|
skip = true
|
|
|
|
|
next
|
|
|
|
|
end
|
|
|
|
|
if b.to_i == oldpartend + 1
|
|
|
|
|
oldpartend = e.to_i
|
|
|
|
|
oldpartbegin = b.to_i
|
|
|
|
|
else
|
|
|
|
|
raise PermError, "Parts not continuous! last end #{oldpartend}, begin #{b}"
|
|
|
|
|
end
|
2003-04-18 22:53:25 +00:00
|
|
|
next
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# This seems to be a common 'error' - maybe I misunderstand the spec or
|
|
|
|
|
# something
|
|
|
|
|
# if line.length != linesize
|
|
|
|
|
# print "#{i}: linesize mismatch, was #{line.length}, should be #{linesize}...\n"
|
|
|
|
|
# end
|
|
|
|
|
|
2003-04-20 21:31:12 +00:00
|
|
|
if !skip
|
|
|
|
|
print "line: #{line}" if Debuglevel > 0
|
|
|
|
|
ostr = _ydecode_line(line)
|
|
|
|
|
decode << ostr
|
|
|
|
|
bytes += ostr.length
|
|
|
|
|
end
|
2003-04-18 22:53:25 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
print "${i}: no \"=yend\" found!!!\n"
|
|
|
|
|
dec = [ decode ]
|
|
|
|
|
return mode, filename, dec
|
|
|
|
|
end
|
|
|
|
|
|
2003-04-20 18:31:17 +00:00
|
|
|
def is_yencoded(data)
|
|
|
|
|
if data.to_s =~ /=ybegin/m
|
|
|
|
|
return true
|
2003-04-18 22:53:25 +00:00
|
|
|
else
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2003-04-20 18:31:17 +00:00
|
|
|
def get_filename(data)
|
2003-04-20 20:15:34 +00:00
|
|
|
i = 0
|
|
|
|
|
while i < data.length
|
|
|
|
|
line = data[i]
|
|
|
|
|
if line =~ /=ybegin\s*(part\=(\d+)\s+)?(total\=(\d+)\s+)?(line\=(\d+))(\s*size\=(\d+))(\s*name=(.*?\S))\s*$/m
|
|
|
|
|
return $10
|
|
|
|
|
end
|
|
|
|
|
i += 1
|
2003-04-18 22:53:25 +00:00
|
|
|
end
|
2003-04-20 20:15:34 +00:00
|
|
|
return false
|
2003-04-18 22:53:25 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end # class
|
2003-04-20 18:31:17 +00:00
|
|
|
end
|