[Windows Mobile Development and Hacking General] ChaosR:
I wanted to share a small script I wrote for those who know how to use it. It converts non-binary pim-backup message files to html files.

Usage: ruby <file> <message_file>

#-sms2html----------------------------------------------------------------#
# ChaosR (<chaosr@gmail.com>) wrote this file. As long as #
# you do not touch this note and keep this note here you can do whatever #
# you want with this stuff. Also, the author(s) are not responsible for #
# whatever happens using this. #
#-------------------------------------------------------------------------#

require 'jcode' if RUBY_VERSION[0..2] == "1.8"

class SMSConverter
attr_accessor :messages, :raw, :by_folder, :by_name, :by_number

SPEC = [
:msg_id,
:sender_name,
:sender_address,
:sender_address_type,
:prefix,
:subject,
:body,
:body_type,
:folder,
:account,
:msg_class,
:content_length,
:msg_size,
:msg_flags,
:msg_status,
:modify_time,
:delivery_time,
:recipient_nbr,
:recipients,
:attachment_nbr,
:attachments
]

RECIP_SPEC = [
:id,
:name,
:phone,
:var1,
:var2,
:type
]

FOLDERS = {
"\\%MDF1" => "INBOX",
"\\%MDF2" => "OUTBOX",
"\\%MDF3" => "SENT",
"\\%MDF4" => "TRASH",
"\\%MDF5" => "DRAFTS"
}

def initialize(file)
f = File.open(file)
@raw = f.read
f.close

raw2array
clean_messages
sort_messages
end

def raw2array
messages = []
state = { :arg => 0, :escaped => false, :in_string => false }
sms = {}

@raw.each_char do |byte|
arg = SPEC[state[:arg]]
sms[arg] = "" unless sms[arg]

if byte == "\0" or byte == "\r"
next

elsif state[:escaped]
sms[arg] << byte
state[:escaped] = false

elsif state[:in_string]
if byte == "\""
state[:in_string] = false
elsif byte == "\\"
state[:escaped] = true
else
sms[arg] << byte
end

elsif byte == "\\"
state[:escaped] = true

elsif byte == "\""
state[:in_string] = true

elsif byte == ";"
state[:arg] += 1

elsif byte == "\n"
raise "Faulty conversion or corrupt file" if state[:escaped] or state[:in_string] or state[:arg] != 20
messages << sms
sms = {}
state[:arg] = 0

else
sms[arg] << byte

end
end
@messages = messages
end

def clean_messages
@messages.map! do |sms|
sms[:modify_time] = Time.local( *sms[:modify_time].split(",") )
unless sms[:delivery_time] == ""
sms[:delivery_time] = Time.local( *sms[:delivery_time].split(",") )
else
sms[:delivery_time] = sms[:modify_time]
end
sms[:recipient_nbr] = sms[:recipient_nbr].to_i
sms[:body_type] = sms[:body_type].to_i
sms[:msg_flags] = sms[:msg_flags].to_i
sms[:msg_status] = sms[:msg_status].to_i
sms[:attachment_nbr] = sms[:attachment_nbr].to_i
sms[:content_length] = sms[:content_length].to_i
sms[:msg_size] = sms[:msg_size].to_i
sms[:folder] = FOLDERS[sms[:folder]]

if sms[:recipient_nbr] > 0
recipients = {}
sms[:recipients].split(";").each_with_index { |var, index| recipients[RECIP_SPEC[index]] = var }
recipients[:id] = recipients[:id].to_i
recipients[:var1] = recipients[:var1].to_i
recipients[:var2] = recipients[:var2].to_i
sms[:recipients] = recipients
end

sms
end
end

def sort_messages
@messages = @messages.sort { |a, b| a[:delivery_time] <=> b[:delivery_time] }

@by_folder = {}
@messages.each do |sms|
@by_folder[sms[:folder]] = [] unless @by_folder[sms[:folder]]
@by_folder[sms[:folder]] << sms
end

@by_name = {}
@messages.each do |sms|
if sms[:recipient_nbr] > 0
if sms[:recipients][:name] != ""
name = sms[:recipients][:name]
else
name = sms[:recipients][:phone]
end
else
if sms[:sender_name] != ""
name = sms[:sender_name]
else
name = get_number_from_address(sms[:sender_address])
end
end

@by_name[name] = [] unless @by_name[name]
@by_name[name] << sms
end

@by_number = {}
@messages.each do |sms|
if sms[:recipient_nbr] > 0
name = sms[:recipients][:phone]
else
name = get_number_from_address(sms[:sender_address])
end

@by_number[name] = [] unless @by_number[name]
@by_number[name] << sms
end
end

def get_number_from_address(address)
if address =~ /^(\+?\d+)$/
return address
elsif address =~ /\<(\+?\d+)\>/
return $1
else
return false
end
end
end

if $0 == __FILE__
require 'fileutils'

dir = "./messages"
my_name = "yourname"

sms = SMSConverter.new(ARGV[0])

FileUtils.mkdir_p(dir)
sms.by_name.each { |name, messages|
filename = File.join(dir, "#{name}.html")
f = File.open(filename, "w")
f << "<html><body>"
messages.each { |sms|
sent = sms[:recipient_nbr] > 0
message = sms[:subject]

f << "<b>--- #{sent ? my_name : name} (#{sms[:delivery_time].strftime("%H:%M:%S, %a %d-%b-%Y")}) ---</b><br/>"
f << "<pre>#{message.strip}</pre><br/><br/>"
}
f << "</body></html>"
f.close
}
end