This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Grim Reaper's profile picture

[CC 1.33] Cannon OS Version 1.0!

Started by Grim Reaper, 22 June 2012 - 04:11 AM
Grim Reaper #1
Posted 22 June 2012 - 06:11 AM
Well after much procrastinating I actually got around to finishing up this project, not that anyone knew about it in the first place :P/>/>.

Updated to 1.85! Admin Support!

This program features:
- Full Account Manipulation
- (Almost!) Complete IRC Client and Server System
- OP System
- Complete E-Mail Client-Client System
- Contacts System
- Complete Filebrowser
- Working Update Feature (Possibly auto update in the next version!)
- Custom read function that allows for simple character limiting and preventing the entire line being cleared when reading
- Auto Updating
- Admin Support

!WARNING!
- The IRC option will not work unless you have the IRC server program running on the computer of your choice!

OPTIONAL FEATURES:
- Random 10,000 key generator
- Key server for basic anti-piracy

Cannon OS features a glamorous custom GUI and useful utilities while still allowing for full user manipulation of the Craft OS system underneath it. This is my most complete and lengthy project so it does contain some sloppy code that will be cleaned up in newer versions (if there are any). Despite the mess that is the source code, Cannon OS is completely functional to my knowledge and testing.

However, in the case that you may find a bug or an issue feel free to post or PM me the complaint/problem!

Screenshots:
Spoilerhttp://imgur.com/a/PI9Gv

IRC Commands: !kick <user>, !exit

Email Quick Notes:
- Under the recipient field during composing the mail, you can enter the name of a contact and the correct ID will be set for you!

Code:
SpoilerCannon OS:
Spoiler


oldpullEvent = os.pullEvent
os.pullEvent = os.pullEventRaw

-- Cannon OS by PaymentOption --
VERSION = 1.85
--------------------------------

rednet.open("top")
rednet.open("bottom")
rednet.open("back")
rednet.open("front")
rednet.open("right")
rednet.open("left")

--[[ Notes:
User information like passwords are located in the User/<computerID>/.info.
E-Mails are stored in the /Mail Directory.
E-Mail preferences are stored in /Mail/.prefs.

All printing functions like PrintMenu and PrintMainScreen do not clear the screen first; you must clear it before using them.
--]]


-- VARIABLES --

-- Update and Service Variables --
nServerID = 12 -- Update and key check server ID
----------------------------------

-- Screen Variables --
screenWidth, screenHeight = term.getSize()
selection = 1

sMenuState = "main"
----------------------

-- Account Variables --
sUserName = ""
sPassword = ""

bNewUser = true
bLogin = true

bAdmin = true -- Switch to false to disable the following features: CraftOS, Computer, Email, Account Manipulation
-----------------------

-- Authenticity Variables --
sLocalKey = ""
bIsAuthentic = false -- If the key entered by the user upon installation is correct, then this should be true
----------------------------

-- Mail --
if(fs.isDir("Mail")) then nMail = #(fs.list("Mail"))-1
else nMailCount = 0 end
----------
---------------

-- Software Validation --
function checkKey(sKey)
rednet.send(nServerID, "CHECKMYKEY")
rednet.send(nServerID, tostring(sKey))

sender, message = rednet.receive(1)

if sender == nServerID then
if message ~= "authentic" then bAuthentic = false; return false
else bAuthentic = true; return true end
end
end

function getKey()
if fs.exists(".key") then return end
if bIsAuthentic == true then return end -- To avoid embarassing double authentication!

clear()
printMainScreen()
sleep(2)

clear()
printBorder()

cPrint(3, "Welcome!")
cPrint(5, "You're about to install:")
cPrint(6, "Cannon OS V:"..VERSION.."!")
cPrint(7, " The installation wizard will walk you")
cPrint(8, " through product validation to installation.")
cPrint(10, "Before you continue, make sure that you have")
cPrint(11, " the product key given by your distributor.")

cPrint(15, "[ Continue ]")
while true do
event, key = os.pullEvent("key")

if key == 28 then break end
end

clear()
printBorder()

rPrint(17, "Cannon OS Version: "..VERSION.."*")
rPrint(16, "Software: LOCKED*")

cPrint(8, "Please enter your product key here:")
term.setCursorPos(15, 9); write("Key: ")
local sProductKey = newRead()

if checkKey(sProductKey) then
clear()
printBorder()

cPrint(9, "Congradulations,")
cPrint(10, "Your software has successfully been")
cPrint(11, "VALIDATED!")
sleep(3)

local file = fs.open(".key", "w")
file.writeLine(sProductKey)
file.close()
bIsAuthentic = true
else
clear()
printBorder()

cPrint(8, "I'm sorry, but the key")
cPrint(9, "entered doesn't seem to be valid.")
sleep(3)
os.shutdown()
end
end
-------------------------


-- Helper Functions --
function cPrint(height, string)
local xPos = screenWidth/2 - string.len(string)/2
term.setCursorPos(xPos, height); term.write(string)
end

function rPrint(height, string)
local xPos = screenWidth - string.len(string)
term.setCursorPos(xPos, height); term.write(string)
end

function clear() term.clear(); term.setCursorPos(1,1) end

function printBorder()
write(" "..string.rep("*", screenWidth-2).."n")
for i=1, screenHeight-2 do
write(" *"..string.rep(" ", screenWidth-4).."*n")
end
write(" "..string.rep("*", screenWidth-2))
end

function customWrite(height, string)
term.setCursorPos(3, height)
term.write(string)
end

function clearCenter()
cPrint(2, "* "..sUserName.." *")
cPrint(3, "*"..string.rep("*", string.len(sUserName)+2).."*")
rPrint(17, "Cannon OS Version: "..VERSION.. "*")

local line = 4
term.setCursorPos(34, 3); term.write("  ") -- Remove the very top part of the cannon logo
repeat
term.setCursorPos(1, line); term.clearLine()
line = line+1
until line == 12

line = 4
term.setCursorPos(1, 4)

repeat
write(" *"..string.rep(" ", screenWidth-4).."*n")
line = line+1
until line == 12
end

function printContainer()
term.setCursorPos(4, 5); term.write(string.rep("*", screenWidth-6))
local y = 6
for i=1, screenHeight - 13 do
term.setCursorPos(4, y); term.write("*"..string.rep(" ", screenWidth-8).."*")
y = y+1
end
term.setCursorPos(4, 11); term.write(string.rep("*", screenWidth-6))
end

-- Perfecting the pullEvent backspace attempt 1! --

function newRead( _charLimit, _ReplaceChar) -- The filter can either be a 1, 0, or nil. 1 is Numbers only, 0 is letters only, and nil is both 
local sMessage = ""
term.setCursorBlink(true)
local originalCursorX, originalCursorY = term.getCursorPos()

while true do
local cursorX, cursorY = term.getCursorPos()
local event, p1 = os.pullEvent()

if _charLimit ~= nil then
if string.len(sMessage) == _charLimit then term.setCursorBlink(false); return sMessage end
end

if event == "char" then sMessage = sMessage..p1
--[[elseif event == "key" then -- The escape key has keyID 1 so: 0 = keyID: 11, 1 = keyID: 2, 2 = keyID : 3 etc etc....
if p1 == 11 or p1 == 2 or p1 == 3 or p1 == 4 or p1 == 5 or p1 == 6 or p1 == 7 or p1 == 8 or p1 == 9 or p1 == 10 then
--        0       1          2          3          4          5          6          7          8           9
sMessage = sMessage..(p1-1)
end--]]
end

if event == "key" and p1 == 28 then term.setCursorBlink(false); return sMessage end-- Enter key; end the loop and let's see the string

if event == "key" and p1 == 14 then -- Backspace...
sMessage = string.sub(sMessage, 1, string.len(sMessage)-1) 
-- Set our message to the substring of the first charcter 
-- To the length of the message minus 1 to achieve one less letter.

term.setCursorPos(originalCursorX, cursorY)
term.write(sMessage.." ") -- Adding this empty space clears the removed character from the line, but may pose future issues
end

term.setCursorPos(originalCursorX, cursorY); term.write(string.rep(" ", string.len(sMessage)))
-- Clear the previous line just in case we get a new line
-- Now write the message on the new line
if _ReplaceChar ~= nil then
term.setCursorPos(originalCursorX, cursorY)
term.write(string.rep( _ReplaceChar, string.len(sMessage) ))
else
term.setCursorPos(originalCursorX, cursorY)
term.write(sMessage)
end
end
end
----------------------


-- System Functions --
function checkInstalltion()
if fs.exists("SYSTEM/.installed") then return true
else return false end
end

function runShell() shell.run("/rom/programs/shell") end

function getVersion() return VERSION end

function checkVersion()
local sCommand = "get"
if sCommand == "get" then
local sCode = "c17Hgq1A"
local sPath = ".tempVersion"

while true do
local response = http.get(
"http://pastebin.com/raw.php?i="..textutils.urlEncode( sCode )
)

if response then
local sResponse = response.readAll()
response.close()
if tonumber(sResponse) > VERSION then return true
else return false end
break
else return false end
end
end
end

function updateSelf()
local sCommand = "get"
if sCommand == "get" then
local sCode = "6a92bGGZ"
local sFile = "startup"
local sPath = shell.resolve( sFile )

while true do
local response = http.get(
"http://pastebin.com/raw.php?i="..textutils.urlEncode( sCode )
)

if response then
local sResponse = response.readAll()
response.close()

local file = fs.open( sPath, "w" )
file.write( sResponse )
file.close()
break
else return false end
end
end
end

function checkDirs()
if not fs.isDir("Mail") then shell.run("rom/programs/mkdir", "Mail"); nMailCount = (#(fs.list("/Mail"))) end
if not fs.isDir("User") then shell.run("rom/programs/mkdir", "User"); shell.run("rom/programs/mkdir", "User/"..tostring(os.getComputerID())) end
if not fs.isDir("User/"..tostring(os.getComputerID()).."/Projects") then shell.run("rom/programs/mkdir", "User/"..tostring(os.getComputerID()).."/Projects") end
if not fs.isDir("User/"..tostring(os.getComputerID()).."/Desktop") then shell.run("rom/programs/mkdir", "User/"..tostring(os.getComputerID()).."/Desktop") end
if not fs.isDir("User/"..tostring(os.getComputerID()).."/Desktop/Shortcuts") then shell.run("rom/programs/mkdir", "User/"..tostring(os.getComputerID()).."/Desktop/Shortcuts") end
if not fs.isDir("User/"..tostring(os.getComputerID()).."/Files") then shell.run("rom/programs/mkdir", "User/"..tostring(os.getComputerID()).."/Files") end

if not fs.isDir("Mail/Contacts") then shell.run("rom/programs/mkdir", "Mail/Contacts") end
if not fs.isDir("SYSTEM") then shell.run("rom/programs/mkdir", "SYSTEM") end
if not fs.exists("SYSTEM/Version") then
local file = fs.open("SYSTEM/Version", "w"); file.writeLine(tostring(VERSION))
file.close()
end
file = fs.open("SYSTEM/.installed", "w")
file.writeLine("TRUE")
file.close()
end


function checkUserInformation()
if fs.exists("User/"..os.getComputerID().."/.info") then
local file = fs.open("User/"..os.getComputerID().."/.info", "r")
sUserName = file.readLine()
sPassword = file.readLine()
file.close()
bNewUser = false
else
bNewUser = true
end
end

function getUserInformation()
if bNewUser == false then return nil -- This is to prevent accidental account resets
else
printNewUserScreen()
end
end

function handleLogin()
if fs.exists(".login") then
file = fs.open(".login", "r")
fileContents = file.readAll()
file.close()
fs.delete(".login")
bLogin = false

if fileContents == "false" then return end
end

if bNewUser == false then
printMainScreen(); sleep(2)
clear()

printBorder()
cPrint(4, "***************************")
cPrint(5, "* Identification required *")
cPrint(6, "***************************")

cPrint(8, "Username: ")
cPrint(9, "Password: ")
rPrint(17, "Cannon OS Version: "..VERSION.."*")
rPrint(16, "LOCKED*")

term.setCursorPos(screenWidth/2 - string.len("Username: ")/2 + string.len("Username: "), 8)
local tempUserName = newRead(14, nil)
term.setCursorPos(screenWidth/2 - string.len("Password: ")/2 + string.len("Password: "), 9)
local tempPassword = newRead(14, "*")

if tempUserName == sUserName and tempPassword == sPassword then
rPrint(16, "UNLOCKED*")
cPrint(11, "**********************")
cPrint(12, "* Successfull login! *")
cPrint(13, "**********************")
sleep(2)
return
else
cPrint(11, "************************")
cPrint(12, "* Unsuccessfull login! *")
cPrint(13, "************************")
sleep(2)
os.shutdown()
end
end
end

function printInstallation()
if checkInstalltion() then return end
printBorder()
cPrint(4, "*************************")
cPrint(5, "* Installation Progress *")
cPrint(6, "*************************")

local progressPosition = 6; -- X position to represent where the progress bars will be drawn
local nProgressPercent = 0;

cPrint(8, " * "..string.rep("*", screenWidth - 6))
cPrint(9, " * *"..string.rep(" ", screenWidth - 8).."*")
cPrint(10, " * "..string.rep("*", screenWidth - 6))

cPrint(12, "********")
cPrint(13, "* "..string.rep(" ", string.len("100%")).." *")
cPrint(14, "********")

for i=1, 80 do
if i%2 == 0 then
term.setCursorPos(progressPosition, 9); term.write("|")
progressPosition = progressPosition+1
sleep(0.2)
end
nProgressPercent = nProgressPercent+1
if nProgressPercent == 75 then nProgressPercent = 95 end
if nProgressPercent == 95 then sleep(1.1) end
term.setCursorPos(24, 13); term.write(nProgressPercent)
end
checkDirs()
end

-- Background Processes --
function checkMail(sender, message)
if string.find(message, "CANNONMAILMESSAGE") then
local file = fs.open("Mail/Unread"..nMailCount, "w")
message =  string.gsub(message, "CANNONMAILMESSAGE", "")
file.write(tostring(sender).."n"..tostring(message))
file.close()

nMailCount = nMailCount+1
end
end
--------------------------
----------------------


-- Menues and other screens --
function printNewUserScreen()
if bNewUser == false then return end
local bPasswordsMatch = false

printBorder()
printWelcome()
sleep(3)
clear()

printBorder()
cPrint(2, "* New User *")
cPrint(3, "************")

rPrint(17, "Cannon OS Version: "..VERSION.."*")

cPrint(6, "Username: ")
cPrint(7, "Password: ")
cPrint(8, " Confirm: ")
cPrint(12, "************************")
cPrint(13, "*Password not optional!*")
cPrint(14, "************************")

term.setCursorPos(screenWidth/2-string.len("Username: ")/2+string.len("Username: "), 6)
sUserName = newRead(14, nil)
if string.len(sUserName) > 14 then
cPrint(10, "Username is too long!"); sleep(1.3)
term.setCursorPos(1, 10); term.clearLine() -- Clear the line 10
term.write(" *"..string.rep(" ", screenWidth-4).."*")

term.setCursorPos(1, 6); term.clearLine() -- Clear the line 
term.write(" *"..string.rep(" ", screenWidth-4).."*")
cPrint(6, "Username: ")
term.setCursorPos(screenWidth/2-string.len("Username: ")/2+string.len("Username: "), 6)
sUserName = newRead(14, nil)
end
while bPasswordsMatch == false do
term.setCursorPos(screenWidth/2-string.len("Password: ")/2+string.len("Password: "), 7)
sPassword = newRead(14, "*")
if sPassword ~= nil and sPassword ~= "" then
term.setCursorPos(screenWidth/2-string.len(" Confirm: ")/2+string.len(" Confirm: "), 8)
local sConfirm = newRead(14, "*")
if sConfirm ~= sPassword then
cPrint(10, "Passwords do not match!"); sleep(1.3)
term.setCursorPos(1, 10); term.clearLine() -- Clear the line 10
term.write(" *"..string.rep(" ", screenWidth-4).."*")

term.setCursorPos(1, 7); term.clearLine() -- Clear the line 7
term.write(" *"..string.rep(" ", screenWidth-4).."*")
cPrint(7, "Password: ")

term.setCursorPos(1, 8); term.clearLine() -- Clear the line 8
term.write(" *"..string.rep(" ", screenWidth-4).."*")
cPrint(8, " Confirm: ")
else sPassword = sConfirm; bPasswordsMatch = true end
else sPassword = ""
end
end

local file = fs.open("User/"..os.getComputerID().."/.info", "w")
file.writeLine(tostring(sUserName))
if sPassword == "" then file.writeLine("N/A")
else  file.writeLine(tostring(sPassword))
end
file.close() 

cPrint(10, "Account '"..sUserName.. "' succesfully created!"); sleep(1.3)
end

function printWelcome()
customWrite(3, "__          __   _                           ")
customWrite(4, "         / /  | |                          ")
customWrite(5, "    /  / /___| | ___  ___  _ __ ___   ___ ")
customWrite(6, "   /  / // _  |/ __|/ _ | '_ ' _  / _ ")
customWrite(7, "     /  /|  __/ | (__| (_) | | | | | |  __/")
customWrite(8, "    /  /  ___|_|___|___/|_| |_| |_|___|")
customWrite(9, "          _    _               ")
customWrite(10, "         | |  | |              ")
customWrite(11, "         | |  | |___  ___ _ __ ")
customWrite(12, "         | |  | / __|/ _  '__|")
customWrite(13, "         | |__| __   __/ |   ")
customWrite(14, "          ____/|___/___|_|   ")

rPrint(17, "Cannon OS Version: "..VERSION.."*")
end

function printMainScreen()
printBorder()
customWrite(2, "                          ________")
customWrite(3, "                         | ______o|")
customWrite(4, "         _______________ ||__---_||")
customWrite(5, "        |  ___________  || ______ |")
customWrite(6, "        | |           | |||______||")
customWrite(7, "        | | Cannon OS | ||--------|")
customWrite(8, "        | |    By     | ||      O |")
customWrite(9, "        | |  Payment  | ||      | |")
customWrite(10, "        | '-----------' ||      | |")
customWrite(11, "        |_____________-_||      | |")
customWrite(12, "          __/_________  |::::::::|")
customWrite(13, "         ________________'-.__")
customWrite(14, "        /:::::::::':::':: .---.")
customWrite(15, "       /::======::: .:.::: _)   ")
customWrite(16, '       """"""""""""""""""""  -----')

term.setCursorPos(3, 17); term.write("By PaymentOption")
rPrint(17, "Version: "..VERSION.. "*")
end

function printLogo()
term.setCursorPos(34, 3); term.write("__")
customWrite(4, "                              /  ")
customWrite(5, "                        .-.  |    |")
customWrite(6, "                *    _.-'    __/")
customWrite(7, "                 .-'       ")
customWrite(8, "                /          _/")
customWrite(9, "               |      _  /")
customWrite(10, "               |     /_'")
customWrite(11, "                _____/")
end

function printLogout()
term.setCursorPos(34, 3); term.write("  ")

clearCenter()

cPrint(5, "********")
cPrint(6, "*Logout*")
cPrint(7, "********")
cPrint(8, "/   ")
cPrint(9, "***************")
cPrint(10, "*[ Yes ]  No  *")
cPrint(11, "***************")

while true do
event, key = os.pullEvent("key")

if key == 205 and selection < 2 then selection = 2
elseif key == 203 and selection > 1 then selection = 1

elseif key == 28 and selection == 1 then os.reboot()
elseif key == 28 and selection == 2 then sMenuState = "main"; selection = 6; break
end

if selection == 1 then cPrint(10, "*[ Yes ]  No  *")
else     cPrint(10, "*  Yes  [ No ]*") end
end
end

function printMainMenu()
printBorder()
cPrint(2, "* "..sUserName.." *")
cPrint(3, "*"..string.rep("*", string.len(sUserName)+2).."*")
rPrint(17, "Cannon OS Version: "..VERSION.. "*")

if sMenuState == "main" then printLogo(); rPrint(2, "Mail: "..nMailCount.."*") end

if selection == 1 then cPrint(13, "[ Computer ]     Craft OS     IRC          ")
  cPrint(15, "  E-Mail         Account      Update       ")
end

if selection == 2 then cPrint(13, "  Computer     [ Craft OS ]   IRC          ")
  cPrint(15, "  E-Mail         Account      Update       ")
end

if selection == 3 then cPrint(13, "  Computer       Craft OS   [ IRC ]        ")
  cPrint(15, "  E-Mail         Account      Update       ")
end

if selection == 4 then cPrint(13, "  Computer       Craft OS     IRC          ")
  cPrint(15, "[ E-Mail ]       Account      Update       ")
end

if selection == 5 then cPrint(13, "  Computer       Craft OS     IRC          ")
  cPrint(15, "  E-Mail       [ Account ]    Update       ")
end

if selection == 6 then cPrint(13, "  Computer       Craft OS     IRC          ")
  cPrint(15, "  E-Mail         Account    [ Update ]     ")
end
end
------------------------------












-- Mail related things --
function loadContacts()
local tContacts = fs.list("Mail/Contacts")
for i=1, #tContacts do -- Set the correct computer adress found
local file = fs.open("Mail/Contacts/"..tContacts[i], "r")
local fileContents = file.readAll()
file.close() 
tContacts[i] = { name = tContacts[i], id = fileContents }
end

return tContacts
end

function mailMenu()
recipientID = 0
sLine1 = "" -- The message will be split into two lines due to lack of multiline functionality of newread()
sLine2 = ""
sMessage = "" -- The two lines will be combined into the whole message in this variable

selection = 1
nMailCount = 0
screenWidth, screenHeight = term.getSize()

function cPrint(height, string)
local xPos = screenWidth/2 - string.len(string)/2
term.setCursorPos(xPos, height)
term.write(string)
end

function rPrint(height, string)
local xPos = screenWidth - string.len(string)
term.setCursorPos(xPos, height)
term.write(string)
end

clearCenter() -- Remove the cannon logo

local function sendMessage()
sMessage = ";alkdjien".."n"..sMessage
rednet.send(tonumber(recipientID), sMessage)
end

local function printMailMenu()
rPrint(2, "Mail: "..tostring((#(fs.list("Mail"))-1).."*"))

  cPrint(5, "***********")
if selection == 1 then cPrint(6, "*[ Write ]*")
else    cPrint(6, "*  Write  *") end

if selection == 2 then cPrint(7, "*[ eMail ]*")
else    cPrint(7, "*  eMail  *") end

if selection == 3 then cPrint(8, "*[ Cont. ]*")
else    cPrint(8, "*  Cont.  *") end

if selection == 4 then cPrint(9, "*[ Leave ]*")
else    cPrint(9, "*  Leave  *") end
  cPrint(10, "***********")
-- End these damn lines ^^
end

local function printRevise()
local nSelect = 1 -- Too much sharing of the 'select' variable

local function cDraw(width, height, string)
term.setCursorPos(width, height)
term.write(string)
end

local function printRevMenu()
cDraw(29, 5, "*****************")
if nSelect == 1 then cDraw(29, 6, "*[ Send ] Exit  *")
else                    cDraw(29, 6, "*  Send [ Exit ]*") end
cDraw(29, 7, "*****************")
end

while true do
printRevMenu()
event, key = os.pullEvent("key")
-- Freakin' lines man ^^

if key == 205 and nSelect == 1 then nSelect = nSelect+1
elseif key == 203 and nSelect == 2 then nSelect = nSelect-1

elseif key == 28 and nSelect == 1 then sendMessage(); clearCenter(); term.setCursorPos(4, 12); term.write(string.rep(" ", 42)); break
elseif key == 28 and nSelect == 2 then clearCenter(); break
end
end
end

local function composeMail()
clearCenter()

term.setCursorPos(4, 5); term.write("****************************")
term.setCursorPos(4, 6); term.write("*Recipient:                *") -- 15 is the x position for the retrieving of 'recipietID'
term.setCursorPos(4, 7); term.write("****************************")

term.setCursorPos(4, 9); term.write(string.rep("*", 42))
term.setCursorPos(4, 10); term.write("*"..string.rep(" ", 40).."*") -- 2 lines to write the body of the message; 38 spaces per line
term.setCursorPos(4, 11); term.write("*"..string.rep(" ", 40).."*")
term.setCursorPos(4, 12); term.write(string.rep("*", 42))

term.setCursorPos(15, 6) -- Get the recipient ID
recipientID = newRead(14) -- If they entered a contact name then find the id
local tContacts = loadContacts()

for i=1, #tContacts do
if tostring(recipientID) == tContacts[i].name then recipientID = tContacts[i].id end
end

term.setCursorPos(6, 10); sLine1 = newRead(38) -- Character only filter
term.setCursorPos(6, 11); sLine2 = newRead(38)

sMessage = sLine1.." "..sLine2

printRevise()
end

local function contacts()
local nSelect = 1
local scroll = 0;
local tContacts = fs.list("Mail/Contacts")

local function printContacts()
local y = 6
local tContacts = loadContacts()

for i = 1+scroll, #tContacts do
term.setCursorPos(5, y)
if nSelect == i then term.write("[ "..tContacts[i].name.." ]")
else  term.write("  "..tContacts[i].name.."  ") end

term.setCursorPos(43, y); term.write(tContacts[i].id)
y = y+1
if y == 11 then break end
end

term.setCursorPos(4, 3); term.write("********************")
term.setCursorPos(4, 4); term.write("* Ctrl:New Contact *")
end

while true do
clearCenter()
printContainer()
printContacts()

local event, key = os.pullEvent("key")
if key == 208 and nSelect < #(fs.list("Mail/Contacts")) then
if nSelect >= 4 and scroll < #tContacts then scroll = scroll+1; nSelect = nSelect+1
else nSelect = nSelect+1 end
elseif key == 200 and nSelect > 1 then
if nSelect >= 4 and scroll > 0 then scroll = scroll-1; nSelect = nSelect-1
else nSelect = nSelect-1 end
elseif key == 29 or key == 157 then
term.setCursorPos(5, 6); term.write(string.rep(" ", screenWidth-8))
term.setCursorPos(5, 6); term.write("Contact Name: ")
local sContact = newRead(14)

term.setCursorPos(5, 6); term.write(string.rep(" ", screenWidth-8))
term.setCursorPos(5, 6); term.write("Contact ID: ")
local nContactID = newRead(14)

local file = fs.open("Mail/Contacts/"..sContact, "w")
file.write(tostring(nContactID))
file.close()
elseif key == 14 then break

elseif key == 28 then
nSelected = 1
while true do
if nSelected == 1 then
term.setCursorPos(5, 6)
term.write("Delete? [ Yes ] No  ")
else
term.setCursorPos(5, 6)
term.write("Delete?   Yes [ No ]")
end

local event, key = os.pullEvent("key")

if key == 205 and nSelected == 1 then nSelected = nSelected+1
elseif key == 203 and nSelected == 2 then nSelected = nSelected-1

elseif key == 28 and nSelected == 1 then
local tContacts = loadContacts()

for i=1, #tContacts do
if nSelected == i then fs.delete("Mail/Contacts/"..tContacts[i].name) end
end
break
elseif key == 28 and nSelected == 2 then break
end
end
end
end
end

while true do
printMailMenu()

event, key = os.pullEvent("key")

if key == 200 and selection > 1 then selection = selection-1
elseif key == 208 and selection < 4 then selection = selection+1

elseif key == 28 and selection == 1 then composeMail(); sMenuState = "main"; break
elseif key == 28 and selection == 2 then readMail(); sMenuState = "main"; break
elseif key == 28 and selection == 3 then contacts(); selection = 1; term.setCursorPos(4, 3); term.write(string.rep(" ", 17)); clearCenter();
elseif key == 28 and selection == 4 then selection = 4; sMenuState = "main"; break
end
end
end

function newMessage(nSender, sContents)
rPrint(2, "Mail: "..nMailCount.."*")
sMenuState = "newMessage"
local nSelect = 1
local bReading = false -- This is to handle whether or not we should print the reception menu
clearCenter()

local function printMessageMenu()
cPrint(5, "*****************")
cPrint(6, "*  New Message  *")
cPrint(7, "*****************")
if nSelect == 1 then cPrint(8, "*[ Read ] Exit  *")
else  cPrint(8, "*  Read [ Exit ]*") end
cPrint(9, "*****************")
end

while true do
if not bReading then printMessageMenu() end
local event, key = os.pullEvent("key")

if key == 205 then nSelect = nSelect+1
elseif key == 203 then nSelect = nSelect-1

elseif key == 28 and nSelect == 1 then
nMailCount = nMailCount-1
bReading = true
clearCenter()
term.setCursorPos(4, 5); term.write("From: "..nSender)
term.setCursorPos(4, 6); term.write("******"..string.rep("*", string.len(nSender)))

term.setCursorPos(4, 7)
if string.len(sContents) > 42 then
local sContentsLine1 = string.sub(sContents, 1, 42) -- Split the message into two lines if it is greater than 38
local sContentsLine2 = string.sub(sContents, 43, string.len(sContents))

term.write(sContentsLine1)
term.setCursorPos(4, 9)
term.write(sContentsLine2)
else
term.write(sContents)
end
break -- Print the message then end
elseif key == 28 and nSelect == 2 then
clearCenter()
sMenuState = "main"
return
end
end

while true do
cPrint(9, "**********")
cPrint(10, "*[ Exit ]*")
cPrint(11, "**********")

local event, key = os.pullEvent("key")

if key == 28 then sMenuState = "main"; break end
end
end

function readMail()
local sFileOpen = ""
sMenuState = "archive"
clearCenter()

if #(fs.list("Mail"))-1 == 0 then
cPrint(6, "***************")
cPrint(7, "* No messages *")
cPrint(8, "***************")
sleep(1.3)
clearCenter()
cPrint(12, "                     ") -- Clear line 12
return
end

term.setCursorPos(4, 5); term.write(string.rep("*", screenWidth-6))
local y = 6
for i=1, screenHeight - 13 do
term.setCursorPos(4, y); term.write("*"..string.rep(" ", screenWidth-8).."*")
y = y+1
end
term.setCursorPos(4, 11); term.write(string.rep("*", screenWidth-6))

local tMessages = fs.list("Mail")
local nSelections = #tMessages -- How many selections for mail we have
local nSelected = 1

local function clearMessageRectangle()
local y = 6
for i=1, 5 do
term.setCursorPos(5, y); term.write(string.rep(" ", screenWidth - 8))
y = y+1
end
end

local function printMessages()
term.setCursorPos(5, 13); term.write(string.rep(" ", screenWidth - (string.len("*********************")+2)))
term.setCursorPos(screenWidth - (string.len("*********************")+2), 13)
term.write("*********************")
term.setCursorPos(screenWidth - (string.len("* Backspace to exit *")+2), 12)
term.write("* Backspace to exit *")

tMessages = fs.list("Mail")
for i=1, #tMessages do
if tMessages[i] == "Contacts" then table.remove(tMessages, i) end
end -- Remove the 'Contacts' directory from the list

term.setCursorPos(4, 5); term.write(string.rep("*", screenWidth-6))
local y = 6
for i=1, screenHeight - 13 do
term.setCursorPos(4, y); term.write("*"..string.rep(" ", screenWidth-8).."*")
y = y+1
end
term.setCursorPos(4, 11); term.write(string.rep("*", screenWidth-6))


local recX = 6
local recY = 6 -- Positions to hold the x and y coords of where we'll draw the mail
for i=1, #tMessages do
if recX > 41 or recX+string.len(tMessages[i]) > 41 then
recY = recY+2
recX = 6
end
if recY >= 10 then break end

if nSelected == i then recX = recX-1 end
term.setCursorPos(recX, recY)
if nSelected == i then term.write("["..tMessages[i].."]"); recX = recX+1 end
if nSelected ~= i then term.write(tMessages[i]) end

if nSelected == i then
recX = recX + string.len(tMessages[i]) + 2 -- The 2 is for the spaces between the options
else recX = recX + string.len(tMessages[i]) + 2 end
end
end

while true do
cPrint(12, "                     ") -- Clear the last line from the 'return' or 'delete' menu from reading a message
printMessages()

local event, key = os.pullEvent("key")

if key == 205 and nSelected < #tMessages then nSelected = nSelected+1
elseif key == 203 and nSelected > 1 then nSelected = nSelected-1

elseif key == 14 then clearCenter(); term.setCursorPos(5, 12); term.write(string.rep(" ", screenWidth - 7)); term.setCursorPos(5, 13); term.write(string.rep(" ", screenWidth - 7)); cPrint(13, "  Computer       Craft OS     File Browser "); return
elseif key == 28 then
clearCenter()
local sFileOpen = "Mail/"..tMessages[nSelected]
local file = fs.open("Mail/"..tMessages[nSelected], "r")
local nSender = file.readLine()
local sMessage = file.readAll(); -- We'll be using the File Contents as the message to read
file.close()

sMessage = string.gsub(sMessage, tostring(nSender), "") -- Get the message string without the sender
if string.len(sMessage) > 38 then
local sMessageLine1 = string.sub(sMessage, 1, 19)
local sMessageLine2 = string.sub(sMessage, 20, 38)
end

term.setCursorPos(4, 3); term.write("From: "..nSender)
term.setCursorPos(4, 4); term.write("******"..string.rep("*", string.len(tostring(nSender))))
term.setCursorPos(4, 5)
if sMessageLine1 ~= nil then
term.write(sMessageLine1)
term.setCursorPos(4, 6)
term.write(sMessageLine2)
else
term.write(sMessage)
end

nSelected = 1 -- Reset the selection for the 'back' or 'delete' option
term.setCursorPos(5, 12); term.write(string.rep(" ", screenWidth - 7)); term.setCursorPos(5, 13); term.write(string.rep(" ", screenWidth - 7))
while true do
  cPrint(10, "*********************")
if nSelected == 1 then cPrint(11, "*[ Return ] Delete  *")
else    cPrint(11, "*  Return [ Delete ]*") end
  cPrint(12, "*********************")
--

local event, key = os.pullEvent("key")

if key == 205 and nSelected == 1 then nSelected = 2
elseif key == 203 and nSelected == 2 then nSelected = 1

elseif key == 28 and nSelected == 1 then term.setCursorPos(4, 3); term.write(string.rep(" ", string.len("From: "..nSender))); term.setCursorPos(4, 4); term.write(string.rep(" ", string.len("From: "..nSender))) break
elseif key == 28 and nSelected == 2 then
fs.delete(sFileOpen)
sFileOpened = ""
nSelected = 1
term.setCursorPos(4, 3); term.write(string.rep(" ", string.len("From: "..nSender)))
term.setCursorPos(4, 4); term.write(string.rep(" ", string.len("From: "..nSender)))
break
end
end
end
end
end
-------------------------


-- Filbrowser --
function fileBrowser()
sMenuState = "browseing"
clearCenter()

local scroll = 0
local y = 0
local sObjectName = ""
local sObjectType = ""
local nObjectHeight = 0

local nSelect = 1
local tFiles = {}

local function printOptionMenu()
local previousSelection = nSelect
nSelect = 1

while true do
term.setCursorPos(6, 8); term.write(string.rep(" ", 40))
if nSelect == 1 and sObjectType == "File" then cPrint(8, "[Run] Edit  Delete  Exit ")
elseif nSelect == 2 and sObjectType == "File" then cPrint(8, " Run [Edit] Delete  Exit ")
elseif nSelect == 3 and sObjectType == "File" then cPrint(8, " Run  Edit [Delete] Exit ")
elseif nSelect == 4 and sObjectType == "File" then cPrint(8, " Run  Edit  Delete [Exit]")
end

local event, key = os.pullEvent("key")

if key == 205 and nSelect < 4 then nSelect = nSelect+1
elseif key == 203 and nSelect > 1 then nSelect = nSelect-1
elseif key == 14 or key == 28 and nSelect == 4 then nSelect = previousSelection; return false
elseif nSelect == 1 and key == 28 then clear(); shell.run(sObjectName); sMenuState = "main"; return true
elseif nSelect == 2 and key == 28 then clear(); shell.run("edit", sObjectName); sMenuState = "main"; return true
elseif nSelect == 3 and key == 28 then fs.delete(shell.dir().."/"..sObjectName); sMenuState = "main"; return true
end
end
end

local function printFileContainer()
term.setCursorPos(4, 5); term.write(string.rep("*", screenWidth-6))
local y = 6
for i=1, screenHeight - 13 do
term.setCursorPos(4, y); term.write("*"..string.rep(" ", screenWidth-8).."*")
y = y+1
end
term.setCursorPos(4, 11); term.write(string.rep("*", screenWidth-6))
end

local function printFiles()
local sDir = shell.dir()
clearCenter()
printFileContainer() -- This is the rectangle we'll be displaying the options in
y = 6
tFiles = fs.list( sDir )


for i=1+scroll, #tFiles do
if i == nSelect then nObjectHeight = y end
sObjectName = tostring(shell.dir()).."/"..tFiles[nSelect]
if fs.isDir(tostring(shell.dir()).."/"..tFiles[nSelect]) then sObjectType = "Dir"
else     sObjectType = "File"
end

term.setCursorPos(6, y)

if nSelect == i then term.write("["..tFiles[i].."]")
else  term.write(" "..tFiles[i].." ") end

if fs.isDir(tostring(shell.dir()).."/"..tFiles[i]) then term.setCursorPos(42, y); term.write("D ")
else term.setCursorPos(42, y); term.write("F ") end

y = y+1
if y == 11 then break end
end
end

while true do
printFiles()

local event, key = os.pullEvent("key")

if key == 200 and nSelect == 1 then nSelect = 1
elseif key == 208 and nSelect == #tFiles then nSelect = #tFiles

elseif key == 208 and nSelect < #tFiles then
if nSelect >= 5 and scroll < #tFiles then scroll = scroll+1; nSelect = nSelect+1
else nSelect = nSelect+1 end
elseif key == 200 and nSelect > 1 then
if nSelect >= 5 and scroll > 0 then scroll = scroll-1; nSelect = nSelect-1
else nSelect = nSelect-1 end

elseif key == 28 and sObjectType == "File" then
if printOptionMenu() then return end
elseif key == 28 and sObjectType == "Dir" then shell.setDir(sObjectName); scroll = 0; nSelect = 1
elseif key == 14 and shell.dir() ~= "" then shell.run("cd", ".."); scroll = 0; nSelect = 1
elseif key == 14 and shell.dir() == "/" or shell.dir() == "" then sMenuState = "main"; break
end
end
end
----------------


-- IRC Client --
function IRC_Client()
sMenuState = "irc"

-- VARS --
local sServerName = ""
local nServerID = 0
local bConnected = false

local sUserName = ""
local sText = ""

nConversationY = 3
----------

-- Helper local functions --
local function newReadIRC( _charLimit, _ReplaceChar) -- The filter can either be a 1, 0, or nil. 1 is Numbers only, 0 is letters only, and nil is both 
local sMessage = ""
term.setCursorBlink(true)
local originalCursorX, originalCursorY = term.getCursorPos()

while true do
local cursorX, cursorY = term.getCursorPos()
local event, p1, p2 = os.pullEvent()

if _charLimit ~= nil then
if string.len(sMessage) == _charLimit then term.setCursorBlink(false); return sMessage end
end

if event == "char" then sMessage = sMessage..p1
--[[elseif event == "key" then -- The escape key has keyID 1 so: 0 = keyID: 11, 1 = keyID: 2, 2 = keyID : 3 etc etc....
if p1 == 11 or p1 == 2 or p1 == 3 or p1 == 4 or p1 == 5 or p1 == 6 or p1 == 7 or p1 == 8 or p1 == 9 or p1 == 10 then
--        0       1          2          3          4          5          6          7          8           9
sMessage = sMessage..(p1-1)
end--]]
end

if event == "key" and p1 == 28 then
term.setCursorBlink(false)
term.setCursorPos(1, screenHeight)
term.write(string.rep(" ", screenWidth))
return sMessage
end-- Enter key; end the loop and let's see the string

if event == "key" and p1 == 14 then -- Backspace...
sMessage = string.sub(sMessage, 1, string.len(sMessage)-1) 
-- Set our message to the substring of the first charcter 
-- To the length of the message minus 1 to achieve one less letter.

term.setCursorPos(originalCursorX, cursorY)
term.write(sMessage.." ") -- Adding this empty space clears the removed character from the line, but may pose future issues
end

if event == "rednet_message" and p1 == nServerID then
if nConversationY == 10 then
for i=3, 14 do
term.setCursorPos(3, i); term.write(string.rep(" ", screenWidth-4))
end

term.setCursorPos(3, 2); term.write(sServerName..":")
term.setCursorPos(5, screenHeight-1)
nConversationY = 3
end

if p1 == nServerID and p2 == "dlskjfiejdlijfklsdj" then bConnected = false; return nil end
term.setCursorPos(3, nConversationY); term.write(p2)
nConversationY = nConversationY+1
term.setCursorPos(string.len(sMessage)+6, screenHeight)
end

term.setCursorPos(originalCursorX, cursorY); term.write(string.rep(" ", string.len(sMessage)))
-- Clear the previous line just in case we get a new line
-- Now write the message on the new line
if _ReplaceChar ~= nil then
term.setCursorPos(originalCursorX, cursorY)
term.write(string.rep( _ReplaceChar, string.len(sMessage) ))
else
term.setCursorPos(originalCursorX, cursorY)
term.write(sMessage)
end
end
end
----------------------

-- Input related local functions --
local function getInput()
cPrint(4, "IRC Version: Beta 1.0")
cPrint(5, "Server ID: ")
cPrint(6, " Username: ")

rPrint(17, "Common channels: 146, 174, 175, 176, 177*")

term.setCursorPos(screenWidth/2 - string.len("Server ID: ")/2 + string.len("Server ID: "), 5)
nServerID = tonumber(newRead(5))

term.setCursorPos(screenWidth/2 - string.len(" Username: ")/2 + string.len(" Username: "), 6)
sUserName = newRead(14)
end
-----------------------------

-- Networking related local functions --
local function connectToServer()
if bConnected == true then return nil end

if nServerID ~= nil then
rednet.send(tonumber(nServerID), "dlsk;fje3ijoidsjfl")

sender, message = rednet.receive(0.2)

if sender == nServerID and message == "a;sodifu39798d0f3" then
rednet.send(tonumber(nServerID), tostring(sUserName))

sender, message = rednet.receive(0.1)

if sender == nServerID and message == "ifjdslfije" then
bConnected = true

sender, message = rednet.receive(0.2)

if sender == nServerID then sServerName = message end
end
end
else os.shutdown() end
end

local function sendMessage( _sMessage )
rednet.send( tonumber(nServerID), _sMessage )
end
----------------------------------

printBorder()
getInput()
connectToServer()
clear()
printBorder()
term.setCursorPos(3, 2); term.write(sServerName..":")
term.setCursorPos(3, screenHeight-1); term.write("> ")

while bConnected do
if nConversationY == 10 then
for i=3, 14 do
term.setCursorPos(3, i); term.write(string.rep(" ", screenWidth-4))
end

term.setCursorPos(3, 2); term.write(sServerName..":")
term.setCursorPos(5, screenHeight-1)
nConversationY = 3
end

sText = newReadIRC(screenWidth-7) -- This will be our disconnection message: dslifj
if sText == "!exit" then clear(); sMenuState = "main"; break end
if sText == nil then term.setCursorBlink(false); sMenuState = "main"; break end

if sText ~= sUserName then sendMessage(sText)
else nConversationY = nConversationY-1 end
sText = ""
term.setCursorPos(3, screenHeight-1); term.write(string.rep(" ", screenWidth-4))
term.setCursorPos(3, screenHeight-1); term.write("> ")

term.setCursorPos(2, screenHeight); term.write(string.rep("*", screenWidth-2))
term.setCursorPos(5, screenHeight-1)
end
clear()
sMenuState = "main"
end
---------------------


-- Account --
function editAccount()
sMenuState = "account"
local nSelect = 1

clearCenter()
local function printInfoContainer()
term.setCursorPos(4, 5); term.write(string.rep("*", screenWidth-6))
local y = 6
for i=1, screenHeight - 13 do
term.setCursorPos(4, y); term.write("*"..string.rep(" ", screenWidth-8).."*")
y = y+1
end
term.setCursorPos(4, 11); term.write(string.rep("*", screenWidth-6))
end

printInfoContainer()
while true do
if nSelect == 3 then sMenuState = "main"; break end

term.setCursorPos(5, 7); term.write("Username: "..sUserName)
term.setCursorPos(5, 8); term.write("Password: "..string.rep("*", string.len(sPassword)))

if nSelect == 1 then term.setCursorPos((screenWidth-6)-(string.len("[ Change ]*")-4), 7); term.write("[ Change ]*")
else  term.setCursorPos((screenWidth-6)-(string.len("[ Change ]*")-4), 7); term.write("  Change  *") end

if nSelect == 2 then term.setCursorPos((screenWidth-6)-(string.len("[ Change ]*")-4), 8); term.write("[ Change ]*")
else  term.setCursorPos((screenWidth-6)-(string.len("[ Change ]*")-4), 8); term.write("  Change  *") end

local event, key = os.pullEvent("key")

if key == 208 and nSelect == 1 then nSelect = nSelect+1
elseif key == 200 and nSelect == 2 then nSelect = nSelect-1

elseif key == 28 and nSelect == 1 then
term.setCursorPos(5, 7); term.write(string.rep(" ", screenWidth-8))
term.setCursorPos(5, 7); term.write("New Username: ")
sUserName = newRead(14)
term.setCursorPos(5, 7); term.write(string.rep(" ", screenWidth-8))

local file = fs.open("User/"..os.getComputerID().."/.info", "w")
file.write(sUserName.."n"..sPassword)
file.close()
elseif key == 28 and nSelect == 2 then
term.setCursorPos(5, 8); term.write(string.rep(" ", screenWidth-8))
term.setCursorPos(5, 8); term.write("Old Password: ")
local sCheckPassword = newRead(14, "*")

if sCheckPassword == sPassword then
term.setCursorPos(5, 8); term.write(string.rep(" ", screenWidth-8))
term.setCursorPos(5, 8); term.write("New Password: ")
sPassword = newRead(14, "*")

local file = fs.open("User/"..os.getComputerID().."/.info", "w")
file.write(sUserName.."n"..sPassword)
file.close()
end
term.setCursorPos(5, 8); term.write(string.rep(" ", screenWidth-8))
elseif key == 14 then nSelect = 3
end
end
end
-------------

function printError()
sMenuState = "perms"; clearCenter()
cPrint(6, "*********************")
cPrint(7, "* Restricted Access *")
cPrint(8, "*********************")
sleep(2)
sMenuState = "main"
end



clear()
getKey() -- b8v2a6b8i1e2j8g91
clear()
printInstallation()
clear()
checkUserInformation()
getUserInformation()
handleLogin()

if bLogin then
if checkVersion() then
sMenuState = "updateScreen"
clear()
printBorder()
rPrint(17, "Cannon OS Version: "..VERSION.."*")
cPrint(6, "********************")
cPrint(7, "* Update Available *")
cPrint(8, "********************")

local select = 1
while true do
if select == 1 then cPrint(9, "*   [ Yes ] No     *")
else     cPrint(9, "*     Yes [ No ]   *")
end
cPrint(10, "********************")

local event, key = os.pullEvent("key")

if key == 205 and select == 1 then select = 2
elseif key == 203 and select == 2 then select = 1

elseif key == 28 and select == 1 then clear(); printBorder(); rPrint(17, "Cannon OS Version: "..VERSION.."*"); fs.delete("SYSTEM"); fs.delete("User"); term.setCursorPos(screenWidth/2-string.len("Updating...")/2, 9); textutils.slowPrint("Updating..."); updateSelf(); shell.run("startup")
elseif key == 28 and select == 2 then sMenuState = "main"; clearCenter(); break
end
end
end
end

-- Main OS Loop --
while true do
clear()
nMailCount = #(fs.list("Mail"))-1 -- -1 To eliminate the 'Contacts' directory from the list
printMainMenu()

event, key, p2 = os.pullEvent() -- Key will be p1, laziness has struck again

if event == "key" and key == 205 and selection < 6 and selection ~= 3 then selection = selection+1
elseif event == "key" and key == 203 and selection > 1 and selection ~= 4 then selection = selection-1
elseif event == "key" and key == 208 and selection < 6 and selection+3 <= 6 then selection = selection+3
elseif event == "key" and key == 200 and selection > 1 and selection-3 >= 1 then selection = selection-3

elseif event == "key" and key == 28 and selection == 6 then
clear(); printBorder(); rPrint(17, "Cannon OS Version: "..VERSION.."*"); term.setCursorPos(screenWidth/2-string.len("Updating...")/2, 9); textutils.slowPrint("Updating...")
if not updateSelf() then cPrint(9, "Update Failed"); sleep(1.3); shell.run("startup")
else fs.delete("SYSTEM"); fs.delete("User"); cPrint(9, "Update Successfull"); sleep(1.3); shell.run("startup")
end
elseif event == "key" and key == 28 and selection == 2 and bAdmin then clear(); shell.run("shell")-- If exit to Craft OS
elseif event == "key" and key == 28 and selection == 2 and not bAdmin then printError()

elseif event == "key" and key == 28 and selection == 4 and bAdmin then mailMenu()
elseif event == "key" and key == 28 and selection == 4 and not bAdmin then printError()

elseif event == "key" and key == 28 and selection == 1 and bAdmin then fileBrowser()
elseif event == "key" and key == 28 and selection == 1 and not bAdmin then printError()

elseif event == "key" and key == 28 and selection == 3 then clear(); IRC_Client()

elseif event == "key" and key == 28 and selection == 5 and bAdmin then editAccount()
elseif event == "key" and key == 28 and selection == 5 and not bAdmin then printError()

elseif event == "rednet_message" then
if string.find( p2, ";alkdjien") then
p2 = string.sub( p2, string.len(";alkdjien"), string.len( p2 ))
p2 = string.sub( p2, 3, string.len( p2 )) -- 3 to remove the n from the message
local file = fs.open("Mail/message"..#(fs.list("Mail"))+1, "w")
file.writeLine(key)
file.writeLine(p2)
file.close()

nMailCount = nMailCount+1
newMessage(key, p2) -- Key being the senderID and p2 being the message received
end
elseif event == "reboot" then selection = 1; sMenuState = "logout"; printLogout()
end
end
------------------

os.pullEvent = oldpullEvent

IRC Server:
Spoiler

-- IRC server by PaymentOption for Cannon OS --
VERSION = "Alpha 0.0.1"
-----------------------------------------------
rednet.open("top"); rednet.open("bottom")
rednet.open("front"); rednet.open("back")
rednet.open("right"); rednet.open("left")
-- VARS --
tUsers = {} -- Each user will have their computer ID and a set username
nOP = 0 -- This will be the user with Operator priveleges
sServerName = "testServer"
tConversation = {} -- This is where we will store each line of the conversation: {user, message}
----------
-- Connection related functions --
function connectUser( _nSender)
rednet.send( _nSender, "a;sodifu39798d0f3") -- This will be our request for their username: a;sodifu39798d0f3

sender, message = rednet.receive(0.2)

if sender == _nSender then
  tUsers[#tUsers+1] = {name = message, id = _nSender}
  rednet.send( _nSender, "ifjdslfije") -- This will be our connection confirmation message: ifjdslfije
  sleep(0.1); rednet.send( _nSender, tostring( sServerName ) ) -- Give the user the designated server name
  print("User: "..sender.." Connected")
else print("User: ".._nSender.." not Connected") end

if #tUsers == 1 then nOP = tUsers[1].id; tUsers[1].name = "@"..tUsers[1].name end
end
----------------------------------
-- Converstaion related functions --
function logMessage( _nSender, _sMessage)
if _sMessage == "dslifj" then
  for i=1, #tUsers do
   if tUsers[i].id == _nSender then table.remove( tUsers, i); print("User: ".._nSender.." Disconnected")
   return true end
  end
end

if _nSender == nOP then
  if string.find( _sMessage, "!kick" ) then
   local nKickUser = tonumber(string.sub( _sMessage, string.len("!kick "), string.len( _sMessage )))
   for i=1, #tUsers do -- This will be our kicked notificatio message: dlskjfiejdlijfklsdj
	if tUsers[i].id == nKickUser then table.remove( tUsers, i); rednet.send( nKickUser, "dlskjfiejdlijfklsdj") end
   end
  end
end

tConversation[#tConversation+1] = {user = tonumber(_nSender), message = tostring(_sMessage)}
local senderIndex = 0 -- We'll store the index number of the user who sent the message here for sending references

if #tUsers > 0 then
  for i=1, #tUsers do
   if tUsers[i].id == _nSender then senderIndex = i end
  end
end

if #tUsers > 0 then
  for i=1, #tUsers do
   for i = 1, #tUsers do
	if _sMessage == tUsers[i].name or _sMessage == "@"..tUsers[i].name then return false end
   end
   rednet.send(tUsers[i].id, tostring(tUsers[senderIndex].name).."> ".._sMessage)
  end
end
end
------------------------------------
term.clear(); term.setCursorPos(1,1)
while true do
sender, message = rednet.receive()

if message == "dlsk;fje3ijoidsjfl" then -- This will be our connection request message: dlsk;fje3ijoidsjfl
  connectUser( sender )
end

if sender == nOP and string.find( message, "!kick " ) then
  local sTemp = string.sub( message, string.len("!kick "), string.len(message))
  local sKickUser = string.sub(sTemp, 2, string.len(sTemp))
  for i=1, #tUsers do -- This will be our kicked notification message: dlskjfiejdlijfklsdj
   if tUsers[i].name == sKickUser then rednet.send(  tUsers[i].id, "dlskjfiejdlijfklsdj"); table.remove( tUsers, i) end
  end
elseif #tUsers > 0 then
  for i=1, #tUsers do
   if tUsers[i].id == sender then logMessage( sender, message ) end
  end
end
end

Key Generator:
Spoiler

local tCharacters = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
local sKey = ""
local nKeys = 10000
function keyGen()
local key = ""

for i=1, 9 do
  key = key..tCharacters[math.random(1,26)]..tostring(math.random(1,9))
end

return key
end
file = fs.open("keyList", "w")
repeat
sKey = keyGen()
file.writeLine(tostring(sKey))
sKey = ""

nKeys = nKeys-1
until nKeys == 0
file.close()

Key Validation Server:
Spoiler

--[[
function checkKey(sKey)
rednet.send(nServerID, tostring(sKey))

sender, message = rednet.receive(1)

if sender == nServerID then
  if message ~= "authentic" then bAuthentic = false; return false
  else bAuthentic = true; return true end
end
end
--]]
rednet.open("top")
rednet.open("bottom")
rednet.open("back")
rednet.open("front")
rednet.open("right")
rednet.open("left")
while true do
sender, message = rednet.receive()

if message == "CHECKMYKEY" then
  print("Checking KEY")
  confirmSender, message = rednet.receive(0.8)

  if confirmSender == sender then
   file = fs.open("keyList", "r")
   for i=1, 10000 do
	local fileContents = file.readLine()
  
	if fileContents == message then rednet.send(confirmSender, "authentic"); print("Key confirmed"); break end
   end
   file.close()
  else print("Lost connection...") end
end
end

LICENSE:
You are welcome to use this software as long as you give me credit for it. If you want to use it as base code or something along those lines then PM me for permission!

Feel free to comment and CONSTRUCTIVELY criticize.
kazagistar #2
Posted 22 June 2012 - 03:26 PM
Is this at all programmable? Does it have an API? It seems like all the apps are hardcoded in…
Grim Reaper #3
Posted 22 June 2012 - 05:34 PM
Yes they are all hardcoded in. However, if you want the code for each app I would be happy to release it.
Klausar #4
Posted 27 June 2012 - 12:48 PM
Can you release the email program only? Or can you add a version without the key installation?
Grim Reaper #5
Posted 18 August 2012 - 05:00 AM
I honestly didn't steal anything. Perhaps we all used similar methods of accomplishing the same thing.
adamrocks130 #6
Posted 18 February 2013 - 03:41 PM
Umm i don't know if i'm stupid or something, but i don't the "Product Validation Key"
tesla1889 #7
Posted 18 February 2013 - 05:59 PM
Umm i don't know if i'm stupid or something, but i don't the "Product Validation Key"
edit the code to bypass that
Grim Reaper #8
Posted 18 February 2013 - 06:14 PM
You guys still use this? It's almost over a year old. It's honestly horribly written :P/>
AnthonyD98™ #9
Posted 18 February 2013 - 07:05 PM
-_-/> Why did you guys bump an extremely old post? :P/>
theoriginalbit #10
Posted 18 February 2013 - 07:12 PM
-_-/> Why did you guys bump an extremely old post? :P/>
Well Grim Reaper is allowed to, he is the OP
AnthonyD98™ #11
Posted 18 February 2013 - 07:13 PM
-_-/> Why did you guys bump an extremely old post? :P/>
Well Grim Reaper is allowed to, he is the OP

No i'm not talking about Grim Reaper i'm talking about adamrocks130
Grim Reaper #12
Posted 18 February 2013 - 07:18 PM
-_-/> Why did you guys bump an extremely old post? :P/>
Well Grim Reaper is allowed to, he is the OP

No i'm not talking about Grim Reaper i'm talking about adamrocks130

He had an honest question so he asked it. Although it may have been better for him to send me a PM, I was glad to answer his question. It's also nice when this ol' thing gets some publicity :P/>.
AnthonyD98™ #13
Posted 18 February 2013 - 07:20 PM
-_-/> Why did you guys bump an extremely old post? :P/>
Well Grim Reaper is allowed to, he is the OP

No i'm not talking about Grim Reaper i'm talking about adamrocks130

He had an honest question so he asked it. Although it may have been better for him to send me a PM, I was glad to answer his question. It's also nice when this ol' thing gets some publicity :P/>.

Yeah I guess it is nice :)/>
Cranium #14
Posted 19 February 2013 - 02:43 AM
*sigh*
Why do I have to keep doing this? 1.33 CC is very out of date, and is no longer supported. I highly doubt that the OP is still supporting this OS anymore, event hough he did reply to you. Thread necromancy is something we want to avoid. Locked to prevent further spread.

If the OP wants it unlocked, go ahead and PM me.