ripnews/trunk/ripnews/encode/yenc.rb

298 lines
6.4 KiB
Ruby
Raw Normal View History

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