@ -1,11 +1,11 @@
import csv
import curses
from curses import wrapper
from curses . textpad import Textbox
import sys
import os
import pyperclip as pc
import random
version = sys . argv [ 1 ]
## Initialization of bottomline dependencies
@ -22,33 +22,57 @@ fields = ["service", "user", "pswd"]
HOMEDIR = os . environ [ ' HOME ' ]
PASFILE = HOMEDIR + " /.pasfile.csv "
# Initializes Curses' screen
def main( stdscr ) :
# Opens password file
def reloadFiles( ) :
files . clear ( )
with open ( PASFILE , mode = ' r ' ) as pasfile :
# Creates reader object
csvreader = csv . DictReader ( pasfile )
for ids in csvreader :
files . append ( ids )
## Initializes color pairs
# Password pallete (Foreground = Background)
curses . init_pair ( 1 , curses . COLOR_BLACK , curses . COLOR_BLACK )
pwd_pallete = curses . color_pair ( 1 )
# Main window pallete
curses . init_pair ( 2 , curses . COLOR_WHITE , curses . COLOR_BLACK )
main_pallete = curses . color_pair ( 2 )
# Clears screen
stdscr . clear ( )
# Creates reader object
csvreader = csv . DictReader ( pasfile )
for ids in csvreader :
files . append ( ids )
# Initializes the curses screen
stdscr = curses . initscr ( )
curses . noecho ( )
curses . cbreak ( )
stdscr . keypad ( True )
stdscr . clear ( )
def steelbox ( ) :
reloadFiles ( )
# Initializes the main window
global mainwin
mainwin = curses . newwin ( TERM_LINES - 1 , TERM_COLS , 0 , 0 )
mainwin . keypad ( True )
mainwin . border ( )
# Initializes the bottom window
global statuswin
statuswin = curses . newwin ( 3 , TERM_COLS , TERM_LINES , 0 )
statuswin . keypad ( True )
statuswin . border ( )
cleanWins ( )
while True :
reloadFiles ( )
displayItems ( )
stdscr . move ( TERM_LINES , TERM_COLS )
command ( )
# Defines global variables
def globals ( ) :
## Global variables
# Determines terminal size
global TERM_LINES
TERM_LINES = curses . LINES - 1
if TERM_LINES < = 20 :
sys . exit ( " ERROR: Your terminal is too small! " )
clo se( " ERROR: Your terminal is too small! " )
global TERM_COLS
TERM_COLS = curses . COLS - 1
if TERM_COLS < = 80 :
sys . exit ( " ERROR: Your terminal is too small! " )
clo se( " ERROR: Your terminal is too small! " )
# Global (program-wide) variables for cursor position
global LINE
LINE = 0
@ -89,7 +113,6 @@ def main(stdscr):
# What row the cursor is in
global CUROW
CUROW = 0
global PSERV
PSERV = " "
global PUSER
@ -97,389 +120,317 @@ def main(stdscr):
global PPSWD
PPSWD = " "
# Initializes the main window
mainwin = curses . newwin ( TERM_LINES - 1 , TERM_COLS , 0 , 0 )
mainwin . keypad ( True )
mainwin . bkgd ( ' ' , main_pallete )
mainwin . border ( )
# Initializes the bottom window
statusWin = curses . newwin ( 3 , TERM_COLS , TERM_LINES , 0 )
statusWin . keypad ( True )
statusWin . border ( )
statusWin . bkgd ( ' ' , main_pallete )
statusWin . border ( )
while True :
# Creates a name list
displayList = [ ]
# This makes sure the cursor stays on the screen TODO: delete this
if ITEM_CURSOR < 0 : ITEM_CURSOR = 0
if ITEM_CURSOR > MAX_ITEMS or ITEM_CURSOR > len ( files ) - 1 : ITEM_CURSOR = 0
# Makes sure the windows are properly clean
mainwin . border ( )
statusWin . border ( )
mainwin . border ( )
mainwin . addstr ( 0 , 1 , " SteelBox V " + str ( version ) )
mainwin . refresh ( )
statusWin . border ( )
statusWin . refresh ( )
# Reset global necessities
LINE = 0
COLUMN = 0
currItem = 0
highOpt = ( )
# Defines what to display
startDisplay = ( CURR_PAGE - 1 ) * MAX_ITEMS
stopDisplay = CURR_PAGE * MAX_ITEMS
# Appends the names in the CSV to display on the main window
for ps_name in files :
displayList . append ( ps_name [ ' service ' ] [ : 15 ] )
for item in displayList [ startDisplay : stopDisplay ] :
# If the item is the one with the cursor, highlight it
if currItem == ITEM_CURSOR :
mode = curses . A_REVERSE
highOpt = mainwin . getyx ( )
else :
mode = curses . A_NORMAL
mainwin . addstr ( 1 + LINE , 1 + COLUMN , item , mode )
LINE + = 1
currItem + = 1
if LINE > = WINLIMIT :
LINE = 0
COLUMN + = 16
NROWS + = 1
mainwin . refresh ( )
STATUS_MESSAGE = " PrvPage(F1),NxtPage(F2),(d|el),(e)xamine,(n)ew,(c)opy,(m)odify,(r)andom,(q)uit "
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
## Command logic
# The GLOBAL_CURSOR points to the main files object, so that it gets the right file.
global c
c = mainwin . getch ( )
if c == ord ( ' q ' ) :
return ( 0 )
elif c == curses . KEY_DOWN :
if GLOBAL_CURSOR < len ( files ) - 1 :
ITEM_CURSOR + = 1
GLOBAL_CURSOR + = 1
elif c == curses . KEY_UP :
if GLOBAL_CURSOR > 0 :
ITEM_CURSOR - = 1
GLOBAL_CURSOR - = 1
elif c == curses . KEY_RIGHT :
# Gets user command
def command ( ) :
# The GLOBAL_CURSOR points to the main files object, so that it gets the right file.
global c
global CUROW
global ITEM_CURSOR
global GLOBAL_CURSOR
global CURR_PAGE
c = mainwin . getch ( )
if c == ord ( ' q ' ) :
close ( )
elif c == curses . KEY_DOWN :
if GLOBAL_CURSOR < len ( files ) - 1 :
ITEM_CURSOR + = 1
GLOBAL_CURSOR + = 1
elif c == curses . KEY_UP :
if GLOBAL_CURSOR > 0 :
ITEM_CURSOR - = 1
GLOBAL_CURSOR - = 1
elif c == curses . KEY_RIGHT :
if CUROW < NROWS and ( ITEM_CURSOR + MAX_LINES ) < len ( files ) - 1 :
ITEM_CURSOR + = MAX_LINES - 1
GLOBAL_CURSOR + = MAX_LINES - 1
CUROW + = 1
else :
ITEM_CURSOR = len ( files ) - 1
GLOBAL_CURSOR = len ( files ) - 1
if CUROW < NROWS :
ITEM_CURSOR + = MAX_LINES - 1
GLOBAL_CURSOR + = MAX_LINES - 1
CUROW + = 1
elif c == curses . KEY_LEFT :
if CUROW > 0 :
ITEM_CURSOR - = MAX_LINES - 1
GLOBAL_CURSOR - = MAX_LINES - 1
CUROW - = 1
elif c == curses . KEY_F1 or c == curses . KEY_PPAGE :
# The next two IF statements are here to avoid unintended GLOBAL_CURSOR changes
if CURR_PAGE > 1 :
CURR_PAGE - = 1
GLOBAL_CURSOR - = MAX_ITEMS
elif c == curses . KEY_F2 or c == curses . KEY_NPAGE :
if CURR_PAGE < MAX_PAGES :
CURR_PAGE + = 1
GLOBAL_CURSOR + = MAX_ITEMS
elif c == ord ( ' c ' ) or c == curses . KEY_F3 :
if len ( files ) > 0 :
pc . copy ( files [ GLOBAL_CURSOR ] [ ' pswd ' ] )
statusWin . border ( )
STATUS_MESSAGE = " Copied password for " + files [ GLOBAL_CURSOR ] [ ' service ' ]
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
mainwin . getch ( )
elif c == ord ( ' r ' ) :
ranWin = curses . newwin ( 3 , 49 , int ( TERM_LINES / 2 ) , int ( TERM_COLS / 2 ) )
ranWin . border ( )
ranWin . addstr ( 0 , 1 , " Random string " )
ranWin . addstr ( 1 , 1 , randString ( ) )
ranWin . refresh ( )
ranWin . getch ( )
elif c == ord ( ' d ' ) or c == curses . KEY_DC :
dlWin = curses . newwin ( 3 , 22 , int ( TERM_LINES / 2 ) , int ( TERM_COLS / 2 ) )
dlWin . border ( )
dlWin . refresh ( )
statusWin . border ( )
STATUS_MESSAGE = " Delete " + displayList [ GLOBAL_CURSOR ] + " ? "
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
dlWin . addstr ( 1 , 1 , " Are you sure? (y/N) " )
c = dlWin . getch ( )
if c == ord ( ' y ' ) :
files . pop ( GLOBAL_CURSOR )
with open ( PASFILE , mode = ' w ' ) as pasfile :
csvwriter = csv . DictWriter ( pasfile , fields )
csvwriter . writeheader ( )
csvwriter . writerows ( files )
files . clear ( )
with open ( PASFILE , mode = ' r ' ) as pasfile :
# Creates reader object
csvreader = csv . DictReader ( pasfile )
for ids in csvreader :
files . append ( ids )
# For some reason, KEY_UP is 10, instead of the 343 the debbuger flags... Welp ¯\_(ツ)_/¯
elif c == 10 or c == curses . KEY_ENTER or c == ord ( ' e ' ) :
# highOpt = Coordinates of the first option's character
LINE = highOpt [ 0 ]
COLUMN = highOpt [ 1 ]
# These if statements make it so files being shown will always do so inside the terminal screen
if COLUMN + 32 > TERM_COLS :
COLUMN - = int ( TERM_COLS / MAX_ROWS )
if LINE + 10 > TERM_LINES :
LINE - = 10
# Initializes the file viewer window
fileWin = curses . newwin ( 5 , 60 , LINE + 5 , COLUMN )
# Clears the window
fileWin . border ( )
fileWin . border ( )
passService = files [ GLOBAL_CURSOR ] [ ' service ' ] [ : 45 ]
passUser = files [ GLOBAL_CURSOR ] [ ' user ' ] [ : 45 ]
passPswd = files [ GLOBAL_CURSOR ] [ ' pswd ' ] [ : 45 ]
fileWin . addstr ( 0 , 1 , " View Password " )
fileWin . addstr ( 1 , 1 , " SRVC: " + passService )
fileWin . addstr ( 2 , 1 , " NAME: " + passUser )
fileWin . addstr ( 3 , 1 , " PSWD: " + passPswd )
statusWin . border ( )
STATUS_MESSAGE = " cmds:(d|DEL)ete,(m)odify, (c)opy "
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
fileWin . refresh ( )
# Gets command to act on the highlighted file
c = fileWin . getch ( )
if c == ord ( ' d ' ) or c == curses . KEY_DC :
dlWin = curses . newwin ( 3 , 22 , int ( TERM_LINES / 2 ) , int ( TERM_COLS / 2 ) )
dlWin . border ( )
dlWin . refresh ( )
statusWin . border ( )
STATUS_MESSAGE = " Delete " + displayList [ GLOBAL_CURSOR ] + " ? "
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
dlWin . addstr ( 1 , 1 , " Are you sure? (y/N) " )
c = dlWin . getch ( )
if c == ord ( ' y ' ) :
files . pop ( GLOBAL_CURSOR )
with open ( PASFILE , mode = ' w ' ) as pasfile :
csvwriter = csv . DictWriter ( pasfile , fields )
csvwriter . writeheader ( )
csvwriter . writerows ( files )
files . clear ( )
with open ( PASFILE , mode = ' r ' ) as pasfile :
# Creates reader object
csvreader = csv . DictReader ( pasfile )
for ids in csvreader :
files . append ( ids )
elif c == ord ( ' m ' ) :
# Extracts the file to be modified
modFile = files [ GLOBAL_CURSOR ]
# Removes it from the main file
files . pop ( GLOBAL_CURSOR )
# Creates the 'modify password' window
modWin = curses . newwin ( 5 , 60 , int ( TERM_LINES / 2 ) - 2 , int ( TERM_COLS / 2 ) - 18 )
# Gets the coordinates for the top left corner of said window
nwCord = modWin . getbegyx ( )
# Creates the fields in which the password will be edited
svWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 1 , nwCord [ 1 ] + 6 )
svWin . addstr ( 0 , 0 , modFile [ ' service ' ] )
svWin . move ( 0 , 0 )
svBox = Textbox ( svWin )
usWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 2 , nwCord [ 1 ] + 6 )
usWin . addstr ( 0 , 0 , modFile [ ' user ' ] )
usWin . move ( 0 , 0 )
usBox = Textbox ( usWin )
psWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 3 , nwCord [ 1 ] + 6 )
psWin . addstr ( 0 , 0 , modFile [ ' pswd ' ] )
psWin . move ( 0 , 0 )
psBox = Textbox ( psWin )
# Clears the 'modify password' window
modWin . border ( )
modWin . border ( )
modWin . addstr ( 0 , 1 , " Modify password " )
modWin . addstr ( 1 , 1 , " SRVC: " )
modWin . addstr ( 2 , 1 , " USER: " )
modWin . addstr ( 3 , 1 , " PSWD: " )
modWin . refresh ( )
svWin . refresh ( )
usWin . refresh ( )
psWin . refresh ( )
# Takes data
STATUS_MESSAGE = " Edit SERVICE field - CTRL+G to enter, leave empty to cancel, MAX 45 CHARS "
statusWin . border ( )
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
svBox . edit ( )
passService = svBox . gather ( )
STATUS_MESSAGE = " Edit USER field - CTRL+G to enter, leave empty to cancel, MAX 45 CHARS "
statusWin . border ( )
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
usBox . edit ( )
passUser = usBox . gather ( )
STATUS_MESSAGE = " Edit PASSWORD field - CTRL+G to enter, leave empty for random string "
statusWin . border ( )
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
psBox . edit ( )
passPswd = psBox . gather ( )
modFile = { ' service ' : passService , ' user ' : passUser , ' pswd ' : passPswd }
files . insert ( GLOBAL_CURSOR , modFile )
with open ( PASFILE , mode = ' w ' ) as pasfile :
# Creates writer object and writes to the csv file
csvwriter = csv . DictWriter ( pasfile , fields )
csvwriter . writeheader ( )
csvwriter . writerows ( files )
files . clear ( )
with open ( PASFILE , mode = ' r ' ) as pasfile :
# Creates reader object
csvreader = csv . DictReader ( pasfile )
for ids in csvreader :
files . append ( ids )
elif c == ord ( ' c ' ) or c == curses . KEY_F3 :
pc . copy ( files [ GLOBAL_CURSOR ] [ ' pswd ' ] )
statusWin . border ( )
STATUS_MESSAGE = " Copied password for " + files [ GLOBAL_CURSOR ] [ ' service ' ]
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
mainwin . getch ( )
elif c == ord ( ' n ' ) :
# Initializes the 'new password' window
npWin = curses . newwin ( 5 , 60 , int ( TERM_LINES / 2 ) - 2 , int ( TERM_COLS / 2 ) - 18 )
nwCord = npWin . getbegyx ( )
# Initializes the windows in which the textboxes will reside for input
svWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 1 , nwCord [ 1 ] + 6 )
svBox = Textbox ( svWin )
usWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 2 , nwCord [ 1 ] + 6 )
usBox = Textbox ( usWin )
psWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 3 , nwCord [ 1 ] + 6 )
psBox = Textbox ( psWin )
# Clears the 'new password' window
npWin . border ( )
npWin . border ( )
npWin . addstr ( 0 , 1 , " New password " )
npWin . addstr ( 1 , 1 , " SRVC: " )
npWin . addstr ( 2 , 1 , " USER: " )
npWin . addstr ( 3 , 1 , " PSWD: " )
STATUS_MESSAGE = " CTRL+G to enter, MAX 45 CHARS "
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
npWin . refresh ( )
# Takes data
svBox . edit ( )
passService = svBox . gather ( )
usBox . edit ( )
passUser = usBox . gather ( )
psBox . edit ( )
passPswd = psBox . gather ( )
if passService != ' ' and passUser != ' ' :
if passPswd == ' ' :
passPswd = randString ( )
# wtf = write to file
wtf = { ' service ' : passService , ' user ' : passUser , ' pswd ' : passPswd }
files . append ( wtf )
with open ( PASFILE , mode = ' w ' ) as pasfile :
csvwriter = csv . DictWriter ( pasfile , fields )
csvwriter . writeheader ( )
csvwriter . writerows ( files )
elif c == ord ( ' m ' ) :
# Extracts the file to be modified
modFile = files [ GLOBAL_CURSOR ]
# Removes it from the main file
files . pop ( GLOBAL_CURSOR )
# Creates the 'modify password' window
modWin = curses . newwin ( 5 , 60 , int ( TERM_LINES / 2 ) - 2 , int ( TERM_COLS / 2 ) - 18 )
# Gets the coordinates for the top left corner of said window
nwCord = modWin . getbegyx ( )
# Creates the fields in which the password will be edited
svWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 1 , nwCord [ 1 ] + 6 )
svWin . addstr ( 0 , 0 , modFile [ ' service ' ] )
svWin . move ( 0 , 0 )
svBox = Textbox ( svWin )
usWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 2 , nwCord [ 1 ] + 6 )
usWin . addstr ( 0 , 0 , modFile [ ' user ' ] )
usWin . move ( 0 , 0 )
usBox = Textbox ( usWin )
psWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 3 , nwCord [ 1 ] + 6 )
psWin . addstr ( 0 , 0 , modFile [ ' pswd ' ] )
psWin . move ( 0 , 0 )
psBox = Textbox ( psWin )
# Clears the 'modify password' window
modWin . border ( )
modWin . border ( )
modWin . addstr ( 0 , 1 , " Modify password " )
modWin . addstr ( 1 , 1 , " SRVC: " )
modWin . addstr ( 2 , 1 , " USER: " )
modWin . addstr ( 3 , 1 , " PSWD: " )
STATUS_MESSAGE = " CTRL+G to enter, MAX 45 CHARS "
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
modWin . refresh ( )
svWin . refresh ( )
usWin . refresh ( )
psWin . refresh ( )
# Takes data
STATUS_MESSAGE = " Edit SERVICE field "
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
svBox . edit ( )
passService = svBox . gather ( )
STATUS_MESSAGE = " Edit USER field "
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
usBox . edit ( )
passUser = usBox . gather ( )
STATUS_MESSAGE = " Edit PASSWORD field "
statusWin . addstr ( 0 , 0 , STATUS_MESSAGE )
statusWin . refresh ( )
psBox . edit ( )
passPswd = psBox . gather ( )
modFile = { ' service ' : passService , ' user ' : passUser , ' pswd ' : passPswd }
files . insert ( GLOBAL_CURSOR , modFile )
with open ( PASFILE , mode = ' w ' ) as pasfile :
# Creates writer object and writes to the csv file
csvwriter = csv . DictWriter ( pasfile , fields )
csvwriter . writeheader ( )
csvwriter . writerows ( files )
files . clear ( )
with open ( PASFILE , mode = ' r ' ) as pasfile :
# Creates reader object
csvreader = csv . DictReader ( pasfile )
for ids in csvreader :
files . append ( ids )
else :
CUROW = NROWS
elif c == curses . KEY_LEFT :
if CUROW > 0 :
ITEM_CURSOR - = MAX_LINES - 1
GLOBAL_CURSOR - = MAX_LINES - 1
CUROW - = 1
elif c == curses . KEY_F1 or c == curses . KEY_PPAGE :
# The next two IF statements are here to avoid unintended GLOBAL_CURSOR changes
if CURR_PAGE > 1 :
CURR_PAGE - = 1
GLOBAL_CURSOR - = MAX_ITEMS
elif c == curses . KEY_F2 or c == curses . KEY_NPAGE :
if CURR_PAGE < MAX_PAGES :
CURR_PAGE + = 1
GLOBAL_CURSOR + = MAX_ITEMS
elif c == 10 or c == curses . KEY_ENTER or c == ord ( ' e ' ) :
examine ( )
elif c == ord ( ' c ' ) or c == curses . KEY_F3 :
copy ( )
elif c == ord ( ' n ' ) or c == curses . KEY_F4 :
newFile ( )
elif c == ord ( ' m ' ) or c == curses . KEY_F5 :
modFile ( )
elif c == ord ( ' d ' ) or c == curses . KEY_DC :
delFile ( )
elif c == ord ( ' r ' ) :
rwin ( )
elif c == ord ( ' h ' ) :
sbhelp ( )
def newFile ( ) :
# Initializes the 'new password' window
npWin = curses . newwin ( 5 , 60 , int ( TERM_LINES / 2 ) - 2 , int ( TERM_COLS / 2 ) - 18 )
nwCord = npWin . getbegyx ( )
# Initializes the windows in which the textboxes will reside for input
svWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 1 , nwCord [ 1 ] + 6 )
svBox = Textbox ( svWin )
usWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 2 , nwCord [ 1 ] + 6 )
usBox = Textbox ( usWin )
psWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 3 , nwCord [ 1 ] + 6 )
psBox = Textbox ( psWin )
# Clears the 'new password' window
npWin . border ( )
npWin . border ( )
npWin . addstr ( 0 , 1 , " New password " )
npWin . addstr ( 1 , 1 , " SRVC: " )
npWin . addstr ( 2 , 1 , " USER: " )
npWin . addstr ( 3 , 1 , " PSWD: " )
STATUS_MESSAGE = " CTRL+G to enter, MAX 45 CHARS "
displayStatus ( STATUS_MESSAGE )
npWin . refresh ( )
# Takes data
svBox . edit ( )
passService = svBox . gather ( )
usBox . edit ( )
passUser = usBox . gather ( )
psBox . edit ( )
passPswd = psBox . gather ( )
if passService != ' ' and passUser != ' ' :
if passPswd == ' ' :
passPswd = randString ( )
# wtf = write to file
wtf = { ' service ' : passService , ' user ' : passUser , ' pswd ' : passPswd }
files . append ( wtf )
with open ( PASFILE , mode = ' w ' ) as pasfile :
csvwriter = csv . DictWriter ( pasfile , fields )
csvwriter . writeheader ( )
csvwriter . writerows ( files )
reloadFiles ( )
def examine ( ) :
# highOpt = Coordinates of the first option's character
LINE = highOpt [ 0 ]
COLUMN = highOpt [ 1 ]
# These if statements make it so files being shown will always do so inside the terminal screen
if COLUMN + 32 > TERM_COLS :
COLUMN - = int ( TERM_COLS / MAX_ROWS )
if LINE + 10 > TERM_LINES :
LINE - = 10
# Initializes the file viewer window
fileWin = curses . newwin ( 5 , 60 , LINE + 5 , COLUMN )
# Clears the window
fileWin . border ( )
fileWin . border
passService = files [ GLOBAL_CURSOR ] [ ' service ' ] [ : 45 ]
passUser = files [ GLOBAL_CURSOR ] [ ' user ' ] [ : 45 ]
passPswd = files [ GLOBAL_CURSOR ] [ ' pswd ' ] [ : 45 ]
fileWin . addstr ( 0 , 1 , " View Password " )
fileWin . addstr ( 1 , 1 , " SRVC: " + passService )
fileWin . addstr ( 2 , 1 , " NAME: " + passUser )
fileWin . addstr ( 3 , 1 , " PSWD: " + passPswd )
STATUS_MESSAGE = " cmds:(d|DEL)ete,(m)odify, (c)opy "
displayStatus ( STATUS_MESSAGE )
# Gets command to act on the highlighted file
c = fileWin . getch ( )
if c == ord ( ' d ' ) or c == curses . KEY_DC :
delFile ( )
elif c == ord ( ' m ' ) :
modFile ( )
elif c == ord ( ' c ' ) or c == curses . KEY_F3 :
copy ( )
def modFile ( ) :
# Extracts the file to be modified
modFile = files [ GLOBAL_CURSOR ]
# Removes it from the main file
files . pop ( GLOBAL_CURSOR )
# Creates the 'modify password' window
modWin = curses . newwin ( 5 , 60 , int ( TERM_LINES / 2 ) - 2 , int ( TERM_COLS / 2 ) - 18 )
# Gets the coordinates for the top left corner of said window
nwCord = modWin . getbegyx ( )
# Creates the fields in which the password will be edited
svWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 1 , nwCord [ 1 ] + 6 )
svWin . addstr ( 0 , 0 , modFile [ ' service ' ] )
svWin . move ( 0 , 0 )
svBox = Textbox ( svWin )
usWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 2 , nwCord [ 1 ] + 6 )
usWin . addstr ( 0 , 0 , modFile [ ' user ' ] )
usWin . move ( 0 , 0 )
usBox = Textbox ( usWin )
psWin = curses . newwin ( 1 , 45 , nwCord [ 0 ] + 3 , nwCord [ 1 ] + 6 )
psWin . addstr ( 0 , 0 , modFile [ ' pswd ' ] )
psWin . move ( 0 , 0 )
psBox = Textbox ( psWin )
# Clears the 'modify password' window
modWin . border ( )
modWin . border
modWin . addstr ( 0 , 1 , " Modify password " )
modWin . addstr ( 1 , 1 , " SRVC: " )
modWin . addstr ( 2 , 1 , " USER: " )
modWin . addstr ( 3 , 1 , " PSWD: " )
modWin . refresh ( )
svWin . refresh ( )
usWin . refresh ( )
psWin . refresh ( )
# Takes data
STATUS_MESSAGE = " Edit SERVICE field - CTRL+G to enter, leave empty to cancel, MAX 45 CHARS "
displayStatus ( STATUS_MESSAGE )
svBox . edit ( )
passService = svBox . gather ( )
STATUS_MESSAGE = " Edit USER field - CTRL+G to enter, leave empty to cancel, MAX 45 CHARS "
displayStatus ( STATUS_MESSAGE )
usBox . edit ( )
passUser = usBox . gather ( )
STATUS_MESSAGE = " Edit PASSWORD field - CTRL+G to enter, leave empty for random string "
displayStatus ( STATUS_MESSAGE )
psBox . edit ( )
passPswd = psBox . gather ( )
if passPswd == ' ' :
passPswd = randString ( )
modFile = { ' service ' : passService , ' user ' : passUser , ' pswd ' : passPswd }
files . insert ( GLOBAL_CURSOR , modFile )
with open ( PASFILE , mode = ' w ' ) as pasfile :
# Creates writer object and writes to the csv file
csvwriter = csv . DictWriter ( pasfile , fields )
csvwriter . writeheader ( )
csvwriter . writerows ( files )
reloadFiles ( )
def delFile ( ) :
dlWin = curses . newwin ( 3 , 22 , int ( TERM_LINES / 2 ) , int ( TERM_COLS / 2 ) )
dlWin . border ( )
dlWin . refresh ( )
STATUS_MESSAGE = " Delete " + displayList [ GLOBAL_CURSOR ] + " ? "
displayStatus ( STATUS_MESSAGE )
dlWin . addstr ( 1 , 1 , " Are you sure? (y/N) " )
c = dlWin . getch ( )
if c == ord ( ' y ' ) :
files . pop ( GLOBAL_CURSOR )
with open ( PASFILE , mode = ' w ' ) as pasfile :
csvwriter = csv . DictWriter ( pasfile , fields )
csvwriter . writeheader ( )
csvwriter . writerows ( files )
reloadFiles ( )
# Opens a new window with a random string of length 45
def rwin ( ) :
ranWin = curses . newwin ( 3 , 49 , int ( TERM_LINES / 2 ) , int ( TERM_COLS / 2 ) )
ranWin . border ( )
ranWin . addstr ( 0 , 1 , " Random string " )
ranWin . addstr ( 1 , 1 , randString ( ) )
ranWin . refresh ( )
ranWin . getch ( )
# Copies password to clipboard
def copy ( ) :
if len ( files ) > 0 :
pc . copy ( files [ GLOBAL_CURSOR ] [ ' pswd ' ] )
STATUS_MESSAGE = " Copied password for " + files [ GLOBAL_CURSOR ] [ ' service ' ]
displayStatus ( STATUS_MESSAGE )
mainwin . getch ( )
# Cleans the windows
def cleanWins ( ) :
mainwin . clear ( )
statuswin . clear ( )
mainwin . border ( )
statuswin . border ( )
mainwin . addstr ( 0 , 1 , " SteelBox V " + str ( version ) )
mainwin . refresh ( )
statuswin . refresh ( )
# Displays the items on the screen properly
def displayItems ( ) :
cleanWins ( )
global NROWS
global ITEM_CURSOR
# Creates a name list
global displayList
displayList = [ ]
# Appends the names in the CSV to display on the main window
for ps_name in files :
displayList . append ( ps_name [ ' service ' ] [ : 15 ] )
# Reset global necessities
LINE = 0
COLUMN = 0
currItem = 0
NROWS = 0
global highOpt
highOpt = ( )
# Defines what to display
startDisplay = ( CURR_PAGE - 1 ) * MAX_ITEMS
stopDisplay = CURR_PAGE * MAX_ITEMS
for item in displayList [ startDisplay : stopDisplay ] :
# If the item is the one with the cursor, highlight it
if currItem == ITEM_CURSOR :
mode = curses . A_REVERSE
highOpt = mainwin . getyx ( )
else :
mode = curses . A_NORMAL
mainwin . addstr ( 1 + LINE , 1 + COLUMN , item , mode )
LINE + = 1
currItem + = 1
if LINE > = WINLIMIT :
LINE = 0
COLUMN + = 16
NROWS + = 1
STATUS_MESSAGE = " PrvPage(F1),NxtPage(F2),(d|el),(e)xamine,(n)ew,(c)opy,(m)odify,(r)andom,(q)uit "
displayStatus ( STATUS_MESSAGE )
mainwin . refresh ( )
# Displays on the status window
def displayStatus ( msg ) :
statuswin . border ( )
statuswin . addstr ( 0 , 0 , msg )
statuswin . refresh ( )
def sbhelp ( ) :
helpwin = curses . newwin ( TERM_LINES - 1 , TERM_COLS - 1 , 0 , 0 )
helpwin . border ( )
helpwin . addstr ( 1 , 1 , " Steelbox V. " + version )
line = 2
with open ( " sbhelp " , mode = ' r ' ) as sbhfile :
sbh = sbhfile . readlines ( )
for lines in sbh :
helpwin . addstr ( line , 1 , lines )
line + = 1
line + = 1
helpwin . addstr ( line , 1 , " PRESS ANY KEY TO CONTINUE " , curses . A_REVERSE )
helpwin . getch ( )
# Returns a random string of length 45
def randString ( ) :
result = ' '
for _ in range ( 45 ) :
@ -489,4 +440,16 @@ def randString():
result + = chr ( ascNum )
return ( result )
wrapper ( main )
# Finishes the application
def close ( error = ' ' ) :
curses . nocbreak ( )
stdscr . keypad ( False )
curses . echo ( )
curses . endwin ( )
sys . exit ( error )
globals ( )
steelbox ( )
close ( )