-1

I'm working on a Windows 8 mock-up OS for Computercraft, and my log in system isn't working. I have been trying to figure it out for the past hour or so and it's really frustrating.

Here's the log in code:

    -- Log-in and User Definition Service

    --- Variables

    userExists = fs.exists("/Users/.config/userConfig.cfg")
    termx, termy = term.getSize()
    halfx = math.floor(termx*0.5)
    halfy = math.floor(termy*0.5)

    prompt = "Welcome"
    uprompt = "Username: "
    pprompt = "Password: "

    userConfig = fs.open("/Users/.config/userConfig.cfg", "r")
    edituserConfig = fs.open("/Users/.config/userConfig.cfg", "w")
    --- Functions

    function login(user)
      if user == "admin" then
        term.setCursorPos(1,1)
        term.setTextColor(256)
        print (user)

      elseif user == "guest" then
        print (user)

      else
        print ("nil")

      end
    end

    function userCheck()
      if userExists == true then
        term.clear()
        term.setBackgroundColor(8)
        term.setCursorPos(halfx-0.5*#prompt, halfy - 4)
        term.clear()

        print (prompt)

        term.setCursorPos((halfx-#uprompt), (halfy - 2))
        write (uprompt)
        term.setCursorPos((halfx-#uprompt), (halfy - 1))
        write (pprompt)
        term.setCursorPos((halfx), (halfy - 2))
        upin = read()
        term.setCursorPos((halfx), (halfy - 1))
        ppin = read("*")

        if upin == userConfig.readLine(21) and ppin == userConfig.readLine(24) then
          print ("ADMIN")

        elseif upin == userConfig.readLine(33) and ppin == userConfig.readLine(36) then
          login("guest")

        end

      elseif userExists == false then


      elseif userExists == nil then

      end 
    end

    --- Main

    userCheck()

userConfig.cfg:

    -- Format as follows:
    --
    --  (name):
    --    
    --    (prop):
    --    "(value)"
    --
    --    (prop):
    --    "(value)"
    --
    --    (prop):
    --    "(value)"
    --
    --
    --  (name):
    --    [etc.]

    Admin:

      user:
      "Admin"

      pass:
      "admin"

      auth:
      "1"


    Guest:

      user:
      "Admin"

      pass:
      nil

      auth:
      "0"


    Root:

      user:
      nil

      pass:
      nil

      auth:
      "2"
  • How is it not working? What's the expected result? What actually happens? – Colonel Thirty Two Oct 06 '14 at 02:55
  • @ColonelThirtyTwo It prints everything I want it to, but after I enter the credentials, it doesn't seem to check if they are correct. I'll edit the question to include screenshots and the "userConfig.cfg" file. – user3377520 Oct 06 '14 at 20:38
  • Sorry, my reputation isnt high enough for screenies, but if you have computercraft or an emulator you can test the code, just make sure that the files are in their correct directories, as defined in the code. – user3377520 Oct 06 '14 at 20:58

2 Answers2

1

readLine does not accept arguments and only reads the next line. Your best bet would be to use tables and textutils.serialize to write it all to a file and then when reading use textutils.unserialize to have it inside a table.

Admin:

  user:
  "Admin"

  pass:
  "admin"

  auth:
  "1"

Can be written inside a table such as

{
  Admin = {
            user = "Admin"

            pass = "admin"

            auth = "1"
          }

  Guest = {
            user = "Admin"

            pass = nil

            auth = "0"
          }
}

This would work much in the way that you want, and allows for more variability as well as expansion. Of course to read from it is a different story, and i would use a function to find and send either the auth code back, or nil if it didn't work.

Such as

local function findUsers(username,password)

    --This will read the file and put all it's data inside a table, and then close it.
    local file = fs.open("userConfig.cfg","r")
    local userRanks = textutils.unserialize(file.readAll())
    file.close()

    --To read all the data in a table, i'm going to do this.
    for a,v in pairs(userRanks) do
        if type(v) == "table" then
            if userRanks[a].user == username and userRanks[a].pass == password then
                return userRanks[a].auth
            end
        end
    end

    --[[If we look through the entire file table, and the username and password aren't the same 
        as on file, then we say we couldn't find it by returning nil]]--
    return nil
end

Now for your input area all you have to do is when they input the username and password just call this afterwards, also if allows you to have the auth code

local auth = findUsers(upin,ppin)

--If they inputted an actual username and password
if auth ~= nil then

    --If the auth code from the rank is "1"
    if auth == "1" then
       --Do whatever stuff you want
    elseif auth == "2" then
       --Do whatever other stuff for this auth code
    end
elseif auth == nil then
    print("Oh no you inputted an invalid username and/or password, please try again!"
end
Flamanis
  • 156
  • 5
  • Mostly since i can't comment on David's post, I'm not Oeed :P Yes your version would work David however he's using a format that would look alot like a table would make it work. – Flamanis Oct 12 '14 at 10:11
1

To expand on Dragon53535's answer:

Here's a quick routine I threw together that reads a file into a table:

local function fileToTable(path)
  -- first we make sure that the path can be opened
  assert(fs.exists(path), path..' does not exist!')
  assert(not fs.isDir(path), path..' is a directory!')

  local tSrc = {}
  local inFile = fs.open(path, 'r')

  -- we set line to a non-nil value
  local line = ''

  -- we continue the loop until line is nil
  while line do

    -- we read a line from the file
    line = inFile.readLine()

    -- now we save the value of line to our table
    -- line will be nil at EOF
    tSrc[#tSrc+1] = line
  end

  inFile.close()
  return tSrc
end

After running userConfig = fileToTable('/Users/.config/userConfig.cfg'), you'd replace something like userConfig.readLine(24) with userConfig[24].


Alternatively, you could check out CC's implementation of the io library. It's a standard Lua library (though in CC it's an fs wrapper), so code can be moved more easily out of CC. In particular, io.lines() would be helpful here.

The above code rewritten to use io.lines:

local function fileToTable(path)
  -- first we make sure that the path can be opened
  assert(fs.exists(path), path..' does not exist!')
  assert(not fs.isDir(path), path..' is a directory!')

  local tSrc = {}

  -- iterate over file
  -- io.lines is neat, since it opens and closes the file automatically
  for line in io.lines(path) do
    tSrc[#tSrc+1] = line
  end

  return tSrc
end

As you can see, this is much smaller (only 9 lines of code!) and more manageable. The reason it's not my preferred solution in CC is that io sits on top of fs, so it's probably better to remove the middleman.

Hope this helps.

skwerlman
  • 143
  • 1
  • 5