From 1db82593d1faf4e0ba6e0875c55a4e520ad3d0e6 Mon Sep 17 00:00:00 2001 From: Ward Wouts Date: Mon, 6 May 2002 21:18:45 +0000 Subject: [PATCH] yEnc support added by Stijn Hoop. Thanks! --- trunk/ripnews/news/article.rb | 242 ++++++++++++++++++++++++++++++++++ trunk/ripnews/ripnews.rb | 41 ++++-- 2 files changed, 271 insertions(+), 12 deletions(-) diff --git a/trunk/ripnews/news/article.rb b/trunk/ripnews/news/article.rb index c871fe1..1be6c19 100644 --- a/trunk/ripnews/news/article.rb +++ b/trunk/ripnews/news/article.rb @@ -508,6 +508,248 @@ def is_uuencoded(data) end end +####################################################################### + +def ydecode(data, outfile=nil) + case data.type.to_s + when "Array" + print "Calling _ydecode_array\n" if Debuglevel>0 + mode, file, 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, file, body = _ydecode_file(data, outfile) + else + print "Funny stuff in ydecode. Data of type \"#{data.type.to_s}\"\n" + end + return mode, file, body +end + +def _ydecode_file(file, outfile) + mode = 0600 + filename = "unknown" + lines = file.pos + file.pos = 0 + bytes = 0 + total = 0 + + 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 + if m =~ /^\s*(part\=(\d+)\s+)?(line\=(\d+))(\s*size\=(\d+))(\s*name=(.*))\Z/ + part = $2.to_i + linesize = $4.to_i + totalsize = $6.to_i + filename = $8 + print "found beginning" + if part + print " of part #{part}" + end + print ", linesize = #{linesize}, size = #{size}, filename = #{filename}\n" + break + else + print "not a valid yenc begin line\n" + end + end + end + + print "not yencoded!\n" if file.eof + + print " ydecoding...\n" + + while (! file.eof) + print "at #{file.pos} need to go to #{lines}\n" if Debuglevel > 1 + line = file.gets + line = line[0 ... line.length - 1] + + 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 + 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 = 1 + bytes = 0 + next + end + if search_begin && line =~ /^\=ybegin\s+(.*)\Z/ + m = $1 + search_begin = 0 + if m =~ /^\s*(part\=(\d+)\s+)?(line\=(\d+))(\s*size\=(\d+))(\s*name=(.*))\Z/ + part = $2.to_i + linesize = $4.to_i + totalsize = $6.to_i + filename = $8 + print "found beginning of part #{part}, linesize = #{linesize}, size = #{size}, filename = #{filename}\n" if Debuglevel > 0 + end + next + end + if search_begin == 1 + next + end + if line =~ /^=ypart\s+(\s*begin=(\d+))(\s+end=(\d+))/ + b = $2 + e = $4 + print "next part begin #{b}, end #{e}\n" + 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 + special = 0 + line.each_byte { |b| + if special == 0 + if b == 0x3d + special = 1 + next + end + else + special = 0 + b = (b - 64) % 256 + end + outfile.putc((b - 42) % 256) + bytes += 1 + } + end + + print "No \"=yend\" found!!!\n" + return mode, file, outfile +end + +# toch maar een keer aparte class van maken... geld ook voor dit geneuzel +def _ydecode_array(data) + decode = "" + mode = 0600 + filename = "unknown" + c = 0 + lines = data.length + 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 + if m =~ /^(\s*(part\=(\d+)\s+)?line\=(\d+))(\s*size\=(\d+))(\s*name=(.*))\Z/ + linesize = $4.to_i + size = $6.to_i + filename = $8 + 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" + end + + print "ydecoding...\n" + + while (i < data.length) + print "at #{i} need to go to #{data.length}\r" if Debuglevel > 1 + line = data[i] + 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 + if line =~ /^\=ypart.*\Z/ + # ignore for now + 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 + + special = 0 + str = "" + line.each_byte { |b| + if special == 0 + if b == 0x3d + special = 1 + next + end + else + special = 0 + b = (b - 64) % 256 + end + str += ((b - 42) % 256).chr + } + decode += str + end + + print "${i}: no \"=yend\" found!!!\n" + dec = [ decode ] + return mode, filename, dec +end + +def ydecode_group(subj, tempdir=nil) + group_subjects unless @grouped + + body = get_group_body_first(subj) + if body.to_s =~ /=ybegin/ + print "yencoded!\n" if Debuglevel > 0 + #if (file and outfile) + if (tempdir != nil) + file = Tempfile.new("#{tempdir}/riptmp") + body.collect{|i| file.print "#{i}\n"} + get_group_body_rest(subj, file) + mode, filename, result = ydecode(file, outfile) + else + body += get_group_body_rest(subj) + mode, filename, result = ydecode(body) + end + return mode, filename, result + else + print "Not yencoded!\n" if Debuglevel > 0 + return false + end +end + +def is_yencoded(data) + if data.to_s =~ /=ybegin/ + return true + else + return false + end +end + ############################################################### def subject_sort diff --git a/trunk/ripnews/ripnews.rb b/trunk/ripnews/ripnews.rb index 081c9f0..6b2d2c0 100755 --- a/trunk/ripnews/ripnews.rb +++ b/trunk/ripnews/ripnews.rb @@ -190,11 +190,14 @@ def get_single(subj) body = @articles.get_group_body(subj) if @articles.is_uuencoded(body) mode, filename, body = @articles.uudecode(body) - else - print "Not UUencoded!\n" - return false + return mode, filename, body end - return mode, filename, body + if @articles.is_yencoded(body) + mode, filename, body = @articles.ydecode(body) + return mode, filename, body + end + print "unknown encoding (not UU, not yEnc), skipping...\n" + return false end def get_multi(subj, group) @@ -203,10 +206,14 @@ def get_multi(subj, group) body = @articles.get_group_body(subj) if @articles.is_uuencoded(body) mode, filename, body = @articles.uudecode(body) - else - print "Multipart article not UUencoded!\n" - return false + return mode, filename, body end + if @articles.is_yencoded(body) + mode, filename, body = @articles.ydecode(body) + return mode, filename, body + end + print "unknown encoding (not UU, not yEnc), skipping...\n" + return false else body = @articles.get_group_body_first(subj) next if body == false @@ -219,12 +226,22 @@ def get_multi(subj, group) body = fileout.path file.close fileout.close - else - print "Multipart article not UUencoded!\n" - return false + return mode, filename, body end + if @articles.is_yencoded(body) + file = Tempfile.new("riptmp", @config[group]["TEMPDIR"]) + body.collect{|x| file.print "#{x}\n"} + next unless @articles.get_group_body_rest(subj, file) + fileout = Tempfile.new("riptmp", @config[group]["TEMPDIR"]) + mode, filename, body = @articles.ydecode(file, fileout) + body = fileout.path + file.close + fileout.close + return mode, filename, body + end + print "unknown encoding (not UU, not yEnc), skipping...\n" + return false end - return mode, filename, body end def output_data(subject, mode, filename="", body="") @@ -253,7 +270,7 @@ end ############################################################################################# -defaults = {'-c' => '.ripnewsrc'} +defaults = {'-c' => "#{ENV['HOME']}/.ripnewsrc"} defaults = parse_options(defaults) parse_config(defaults) check_config