开发者

Hide password with asterisk in lua

开发者 https://www.devze.com 2023-02-28 13:47 出处:网络
I there a way to ask passw开发者_JS百科ord in lua but hide with asterisks? I\'m asking about a console applicationFor Unix: use os.execute(\"stty -echo raw\") to turn off echoing and enter raw mode (

I there a way to ask passw开发者_JS百科ord in lua but hide with asterisks?

I'm asking about a console application


For Unix: use os.execute("stty -echo raw") to turn off echoing and enter raw mode (character-by-character input) and os.execute("stty echo cooked") to turn it on and exit raw mode when you are done. In raw mode, you can get each character of the input using io.stdin:read(1) and echo your asterisk as you go (use io.flush to ensure the character appears straight away). You will need to handle deletes and the end of line yourself.

For Windows, the situation is a bit trickier. Look at What would be the Windows batch equivalent for HTML's input type=“password”? for some approaches, the best of which seems to be a VB script.

Postscript

Thanks for lhf for pointing out that you need raw mode besides -echo on input and flush after each output asterisk to get the desired result: unless you have both, the asteriskes will not be echoed until the line is ended.


This code uses platform-specific features and works both on Linux and 32-bit Windows.
Compatible with Lua 5.1 and Lua 5.2

local console

local function enter_password(prompt_message, asterisk_char, max_length)
   -- returns password string
   -- "Enter" key finishes the password
   -- "Backspace" key undoes last entered character
   if not console then
      if (os.getenv'os' or ''):lower():find'windows' then
         ------------------ Windows ------------------
         local shift = 10
         -- Create executable file which returns (getch()+shift) as exit code
         local getch_filespec = 'getch.com'
         -- mov AH,8
         -- int 21h
         -- add AL,shift
         -- mov AH,4Ch
         -- int 21h
         local file = assert(io.open(getch_filespec, 'wb'))
         file:write(string.char(0xB4,8,0xCD,0x21,4,shift,0xB4,0x4C,0xCD,0x21))
         file:close()
         console = {
            wait_key = function()
               local code_Lua51, _, code_Lua52 = os.execute(getch_filespec)
               local code = (code_Lua52 or code_Lua51) - shift
               assert(code >= 0, getch_filespec..' execution failed')
               return string.char(code)
            end,
            on_start = function() end,
            on_finish = function() end,
            backspace_key = '\b'
         }
         -------------------------------------------
      else
         ------------------ Linux ------------------
         console = {
            wait_key = function()
               return io.read(1)
            end,
            on_start = function()
               os.execute'stty -echo raw'
            end,
            on_finish = function()
               os.execute'stty sane'
            end,
            backspace_key = '\127'
         }
         -------------------------------------------
      end
   end
   io.write(prompt_message or '')
   io.flush()
   local pwd = ''
   console.on_start()
   repeat
      local c = console.wait_key()
      if c == console.backspace_key then
         if #pwd > 0 then
            io.write'\b \b'
            pwd = pwd:sub(1, -2)
         end
      elseif c ~= '\r' and #pwd < (max_length or 32) then
         io.write(asterisk_char or '*')
         pwd = pwd..c
      end
      io.flush()
   until c == '\r'
   console.on_finish()
   io.write'\n'
   io.flush()
   return pwd
end

-- Usage example
local pwd = enter_password'Enter password: '
print('You entered: '..pwd:gsub('%c','?'))
print(pwd:byte(1,-1))


Bug in code, for at least linux implementation. Need to add 'and c ~= nil`: elseif c ~= '\r' and #pwd < (max_length or 32) and c ~= nil then

0

精彩评论

暂无评论...
验证码 换一张
取 消