# $Dwarf: uuencode.rb,v 1.6 2003/07/20 20:32:01 ward Exp $
# $Source$

#
# Copyright (c) 2002, 2003 Ward Wouts <ward@wouts.nl>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

require 'tempfile'

class UUEncode
class << self

Debuglevel = 0

def uudecode(data, outfile=nil)
	case data.class.to_s
		when "Array"
			print "Calling _uudecode_array\n" if Debuglevel>0
			mode, filename, body = _uudecode_array(data)
		when "File", "Tempfile"
			unless outfile
				print "uudecode: need outfile\n"
				exit
			end
			print "Calling _uudecode_file\n" if Debuglevel>0
			mode, filename, body = _uudecode_file(data, outfile)
		else
			print "Funny stuff in uudecode. Data of class \"#{data.class.to_s}\"\n"
	end
	return mode, filename, body
end

def _uudecode_file(file, outfile)
	mode = 0600
	filename = "unknown"
	c = 0
	lines = file.pos # horrible assumption FH is at end of file
	percent = 0
	mark = lines/100
	file.pos = 0

	while (! file.eof)
		line = file.gets
		print "line: #{line}" if Debuglevel > 0
		if  line =~ /^begin(.*)/
			m = $1
			print "beginning matched; rest: #{m}\n"  if Debuglevel > 0
			if m =~ /^(\s+(\d+))?(\s+(.*?\S))?\s*\Z/
				mode = $2
				filename = $4
				print "found beginning\n" if Debuglevel > 0
			else
				print "mode, file set to defaults: #{m}\n"
			end
			break
		end
	end

	if file.eof
		print "Not UUencoded!\n"
		return false
	end
	print "c: #{c} mark: #{mark} lines: #{lines}\n" if Debuglevel > 1

	while (! file.eof)
		if Debuglevel > 1
			c = file.pos
			if c > mark
				print "#{percent}%\n"
				print "c: #{c} mark: #{mark} lines: #{lines}\n" if Debuglevel > 1
				percent += 1
				mark = (lines/100)*(percent+1)
			end
		end
		line = file.gets
		print "line: #{line}" if Debuglevel > 1
		return mode, filename if line =~ /^end/
		next if line =~ /[a-z]/
		next if line == nil
		next unless ((((line[0] - 32) & 077) + 2) / 3).to_i == (line.length/4).to_i
		outfile.print line.unpack("u")
	end

	print "No \"end\" found!!!\n"
	#return mode, file, outfile
	return false
end

# gaat volgens mij niet verder als er meerdere uuencoded blocks zijn...
# zal dan meerdere keren aangeroepen moeten worden, grmbl...
# tis getting a mess as we speak...
# toch maar een keer aparte class van maken...
def _uudecode_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] =~ /^begin(.*)/
			m = $1
			print "beginning matched; rest: #{m}\n" if Debuglevel > 0
			if m =~ /^(\s+(\d+))?(\s+(.*?\S))?\s*\Z/
				mode = $2
				filename = $4
				print "found beginning\n" if Debuglevel > 0
			else
				print "mode, filename set to defaults: #{m}\n"
			end
			break
		end
		i += 1
	end

	unless (i < data.length)
		print "Not UUencoded!\n"
		return false
	end

	while (i < data.length)
		if Debuglevel > 1
			if c > mark
				print "#{percent}%\n"
				print "c: #{c} mark: #{mark} lines: #{lines} i: #{i}\n" if Debuglevel > 1
				percent += 1
				mark = (lines/100)*(percent+1)
			end
			c += 1
		end
		line = data[i]
		i += 1
		return mode, filename, decode if line =~ /^end/
		next if line =~ /[a-z]/
		next if line == nil
		next unless ((((line[0] - 32) & 077) + 2) / 3).to_i == (line.length/4).to_i
		unless line.unpack("u").eql?([""])
			decode.concat(line.unpack("u"))
		end
	end

	print "No \"end\" found!!!\n"
	return false
end

def is_uuencoded(data)
	if data.to_s =~ /begin\s+\d+?\s+.*?\S?\s*$/m
		return true
	else
		return false
	end
end

def get_filename(data)
	i = 0
	while i < data.length
		line = data[i]
		if line =~ /^begin(\s+(\d+))?(\s+(.*?\S))?\s*$/m
			return $4
		end
		i += 1
	end
	return false
end

end # class
end
