This adds simple MIME support to the Rex library

git-svn-id: file:///home/svn/framework3/trunk@4607 4d416f70-5f16-0410-b530-b9f4589650da
unstable
HD Moore 2007-04-02 03:58:11 +00:00
parent b16fc9fd53
commit 964c5b8081
4 changed files with 216 additions and 0 deletions

9
lib/rex/mime.rb Normal file
View File

@ -0,0 +1,9 @@
module Rex
module MIME
require 'rex/mime/header'
require 'rex/mime/part'
require 'rex/mime/message'
end
end

75
lib/rex/mime/header.rb Normal file
View File

@ -0,0 +1,75 @@
module Rex
module MIME
class Header
require 'rex/text'
attr_accessor :headers
def initialize(data='')
self.headers = []
parse(data)
end
def parse(data)
prev = nil
data.gsub("\r", '').split("\n").each do |line|
# Handle header folding
if (line =~ /^\s+/)
# Ignore if there is no previous header
next if not prev
next if not self.headers[prev]
self.headers[prev][1] << line.strip
next
end
var,val = line.split(':')
self.headers << [ var.strip, val.strip ]
prev = self.headers.length - 1
end
end
def to_s
self.headers.map{ |pair| "#{pair[0]}: #{pair[1]}\r\n" }.join
end
def find(idx)
if (idx.class == ::Fixnum)
return self.headers[idx]
else
self.headers.each do |pair|
if (pair[0] == idx.to_s)
return pair
end
end
end
nil
end
def set(var, val)
hdr = self.find(var) || self.add(var, '')
hdr[1] = val
end
def add(var, val)
self.headers << [var, val]
self.headers[-1]
end
def remove(idx)
if (idx.class == ::Fixnum)
self.headers.delete_at(idx)
else
self.headers.each_index do |i|
pair = self.headers[i]
if (pair[0] == idx.to_s)
self.headers.delete_at(i)
end
end
end
end
end
end
end

112
lib/rex/mime/message.rb Normal file
View File

@ -0,0 +1,112 @@
module Rex
module MIME
class Message
require 'rex/mime/header'
require 'rex/mime/part'
require 'rex/text'
attr_accessor :header, :parts, :bound, :content
def initialize
self.header = Rex::MIME::Header.new
self.parts = []
self.bound = "_Part_#{rand(1024)}_#{rand(0xffffffff)}_#{rand(0xffffffff)}"
self.content = ''
end
def to
(self.header.find('To') || [nil, nil])[1]
end
def to=(val)
self.header.set("To", val)
end
def from=(val)
self.header.set("From", val)
end
def from
(self.header.find('From') || [nil, nil])[1]
end
def subject=(val)
self.header.set("Subject", val)
end
def subject
(self.header.find('Subject') || [nil, nil])[1]
end
def mime_defaults
self.header.set("MIME-Version", "1.0")
self.header.set("Content-Type", "multipart/mixed; boundary=\"#{self.bound}\"")
self.header.set("Subject", '') # placeholder
self.header.set("Date", Time.now.strftime("%a,%e %b %Y %H:%M:%S %z"))
self.header.set("Message-ID",
"<"+
Rex::Text.rand_text_alphanumeric(rand(20)+40)+
"@"+
Rex::Text.rand_text_alpha(rand(20)+3)+
">"
)
self.header.set("From", '') # placeholder
self.header.set("To", '') # placeholder
end
def add_part(data='', content_type='text/plain', transfer_encoding="8bit", content_disposition=nil)
part = Rex::MIME::Part.new
part.header.set("Content-Type", content_type)
if (transfer_encoding)
part.header.set("Content-Transfer-Encoding", transfer_encoding)
end
if (content_disposition)
part.header.set("Content-Disposition", content_disposition)
end
part.content = data
self.parts << part
part
end
def add_part_attachment(data, name)
self.add_part(
Rex::Text.encode_base64(data, "\r\n"),
"application/octet-stream; name=\"#{name}\"",
"base64",
"attachment; filename=\"#{name}\""
)
end
def add_part_inline_attachment(data, name)
self.add_part(
Rex::Text.encode_base64(data, "\r\n"),
"application/octet-stream; name=\"#{name}\"",
"base64",
"inline; filename=\"#{name}\""
)
end
def to_s
msg = self.header.to_s + "\r\n"
msg << self.content + "\r\n"
self.parts.each do |part|
msg << "--" + self.bound + "\r\n"
msg << part.to_s
end
msg << "--" + self.bound + "--"
msg
end
end
end
end

20
lib/rex/mime/part.rb Normal file
View File

@ -0,0 +1,20 @@
module Rex
module MIME
class Part
require 'rex/mime/header'
attr_accessor :header, :content
def initialize
self.header = Rex::MIME::Header.new
self.content = ''
end
def to_s
self.header.to_s + "\r\n" + self.content + "\r\n"
end
end
end
end