end
local function space_pad(s, n)
- return string.sub(s,1,n) .. string.rep(" ", math.max(0,n-string.len(s)))
+ return string.rep(" ", math.max(0,n-string.len(s))) .. string.sub(s,1,n)
end
local fs = {}
posix.mkdir(dirname)
end
-function fs.rmdir(dirname)
- posix.rmdir(dirname)
+function fs.rmdir(dirname, force)
+ if force then
+ for i,fname in ipairs(posix.glob(dirname .. "/*")) do
+ posix.unlink(fname)
+ end
+ end
+ assert(posix.rmdir(dirname))
end
function fs.copy(filename, destfilename)
return posix.mkdtemp("/tmp/obbs-XXXXXX")
end
+--- Message parsing ---
+
+local msgs = {}
+function Message(msg)
+ msgs[msg.number] = msg
+end
+
--- QWK formatting ---
local qwk = {}
function qwk.write_message (target_dir, obbs)
local mf = assert(io.open(target_dir .. "/MESSAGES.DAT", "w"))
+ local pkt_msg_num = 0
+
mf:write(space_pad("Produced by Qmail...Copyright (c) 1987 by Sparkware." ..
" All Rights Reserved", 128))
for cnum,cname in ipairs(obbs.conferences) do
- for mnum,msg_fname in ipairs(fs.dir(obbs.path .. "/conferences/" .. cname)) do
- msg = io.open(obbs.path .. "/conferences/" .. cname .. "/" .. msg_fname, "r"):read("*all")
-
- qwk.write_message_header_block(mf, obbs, cnum, mnum, msg)
+ msgs = {}
+ dofile(obbs.path .. "/conferences/" .. cname .. ".msgs")
+ for i,msg in ipairs(msgs) do
+ pkt_msg_num = pkt_msg_num + 1
+ qwk.write_message_header_block(mf, obbs, cnum, pkt_msg_num, msg)
qwk.write_message_blocks(mf, obbs, msg)
end
end
mf:close()
end
-function qwk.write_message_header_block(mf, obbs, conf_num, msg)
+function qwk.write_message_header_block(mf, obbs, conf_num, pkt_msg_num, msg)
+ mf:write(" ") -- Message status flag
+ mf:write(space_pad(tostring(msg.number), 7))
+ mf:write(msg.date) -- mm-dd-yy
+ mf:write(msg.time) -- hh:mm
+ mf:write(space_pad(string.upper(msg.to), 25))
+ mf:write(space_pad(string.upper(msg.from), 25))
+ mf:write(space_pad(msg.subject, 25))
+ mf:write(string.rep(" ", 12)) -- Password (blank)
+
+ if msg.reply_to then
+ mf:write(space_pad(tostring(msg.reply_to), 8))
+ else
+ mf:write(string.rep(" ", 8))
+ end
+
+ nblocks = math.ceil(string.len(msg.text)/128) + 1
+ mf:write(space_pad(tostring(nblocks), 6)) -- number of blocks including header
-
+ mf:write("\xe1") -- flag indicating message is "active" (not "to be killed")
+ mf:write(string.pack("I2",conf_num))
+ mf:write(string.pack("I2",pkt_msg_num))
+ mf:write(" ") -- No network tag-line present
end
function qwk.write_message_blocks(mf, obbs, msg)
+ mf:write(string.gsub(msg.text, "\n", "\xe3"))
+
+ local padding = (128 - (string.len(msg.text) % 128)) % 128
+ mf:write(string.rep("\0",padding))
end
--- Commands ---
fs.mkdir(obbs.path .. "conferences")
for i,v in ipairs(obbs.conferences) do
- fs.mkdir(obbs.path .. "conferences/" .. v)
+ fs.touch(obbs.path .. "conferences/" .. v .. ".msgs")
end
fs.mkdir(obbs.path .. "incoming")
"/outgoing/" .. obbs.bbsid ..
".qwk " .. target_dir)
- fs.rmdir(target_dir)
+ fs.rmdir(target_dir, true)
end
-- Main