5
\$\begingroup\$

I'm new to programming. I wrote this following code in Python. It's a simple script that locks and unlocks a folder (basic functionality of a folder-lock) with a password.

I hope someone could suggest me to improve the code and make it shorter. Currently, it can lock single folder; however, I wanna make it multi-threading so that it can work on more than one directory. Any suggestion or advice in this regard will be highly appreciated.

r""" FolderLockV1.py: A simple python script to lock a folder with a password """
import os
import sys
import stat
import shutil
import ctypes
import hashlib
__author__ = 'AJ'
__version__ = '1.0.0'
TEMP_LOCATION = os.path.join(os.path.expanduser('~'), 'Desktop', 'TEMP_FOLDER') # dir path where target will be hidden
PASS_FILE = os.path.join(os.path.expanduser('~'), 'Desktop/TEMP_FOLDER', 'password.txt') # password file
FILE_PATH_CURRENT_FOLDER_TEXT_FILE = os.path.join(os.path.expanduser('~'), 'Desktop/TEMP_FOLDER', 'current_folder.txt')
def hash_data(data):
 """ A function that returns hashed data, here sha512 hashing has been implemented """
 encrypt_data = data.encode('utf-8')
 hashed = hashlib.sha512(encrypt_data).hexdigest()
 return hashed
def current_fold_path_fetcher():
 """ Returns folder_path input from the user """
 while True:
 x = input('Path to the folder you wish to lock\n>>> ')
 if os.path.exists(x):
 return x
 print('Not a valid folder path')
def store_retrieve_info(file_path, **kwargs):
 """ A modified function for writing and reading texts to/from text files """
 if len(kwargs) < 1:
 print('Need to provide kwarg(s)')
 if 'text' in kwargs:
 with open(file_path, 'w') as f:
 f.write(kwargs['text'])
 if 'read' in kwargs:
 if kwargs['read'] is True:
 with open(file_path, 'r') as f:
 x = f.read()
 return x
def folder_lock():
 """ One of the core functions, it basically locks(rather moves) the folder to a secret path """
 fold_path = current_fold_path_fetcher()
 global FILE_PATH_CURRENT_FOLDER_TEXT_FILE
 store_retrieve_info(FILE_PATH_CURRENT_FOLDER_TEXT_FILE, text=fold_path) # writes current dir path to txt file
 pass_word = input('password\n>>> ')
 pass_word_hashed = hash_data(pass_word) # inputted password is being hashed
 global PASS_FILE
 store_retrieve_info(PASS_FILE, text=pass_word_hashed) # writes hashed password in a text file
 global TEMP_LOCATION
 shutil.move(fold_path, TEMP_LOCATION) # moves current dir to the temp dir to make it visualize as locked
 print('Folder Locked')
def folder_unlock():
 """ The other core function that unlocks the target dir """
 global PASS_FILE
 global TEMP_LOCATION
 global FILE_PATH_CURRENT_FOLDER_TEXT_FILE
 current_folder_path_from_file = str(store_retrieve_info(FILE_PATH_CURRENT_FOLDER_TEXT_FILE, read=True)) # reads
 # current folder path from stored txt file
 current_folder_in_temp = TEMP_LOCATION + '\\' + current_folder_path_from_file.rsplit('\\', 1)[-1] # recreates the
 # old dir path where the hidden dir was initially located
 in_pass = input('Password\n>>> ')
 in_pass_hashed = hash_data(in_pass) # inputted password by the user is being hashed for verification
 read_password = str(store_retrieve_info(PASS_FILE, read=True)) # loads the saved password in the memory
 if in_pass_hashed == read_password: # matches inputted password with stored one
 shutil.move(current_folder_in_temp, current_folder_path_from_file) # moves target dir to it's original path
 print('fokder unlocked')
 remove_file() # removes the temp folder and it's contents
 else:
 print('incorrect pass')
def initial_checkups():
 """ An initial checkup function that makes sure that a temp dir exists """
 global TEMP_LOCATION
 if os.path.exists(TEMP_LOCATION):
 pass
 else:
 os.makedirs(TEMP_LOCATION)
 ctypes.windll.kernel32.SetFileAttributesW(TEMP_LOCATION, 0x02) # changes file-mode to hidden, 0x01 value to
 # make it visible
def remove_file():
 """ A supporting function that removes temp dir and it's contents """
 # There are three options to make it happen, only option 2 has been chosen
 # global PASS_FILE
 # global FILE_PATH_CURRENT_FOLDER_TEXT_FILE
 global TEMP_LOCATION
 # option 1: remove each file then changing file-mode of the folder, then remove dir
 # os.remove(PASS_FILE)
 # os.remove(FILE_PATH_CURRENT_FOLDER_TEXT_FILE)
 # os.chmod(TEMP_LOCATION, stat.S_IWRITE)
 # os.rmdir(TEMP_LOCATION)
 # option 2: change file-mode and then remove dir
 os.chmod(TEMP_LOCATION, stat.S_IWRITE) # changes file attribute to writable i.e., make it not readonly dir
 shutil.rmtree(TEMP_LOCATION) # removes temp dir
 # option 3: remove dir and it's contents without changing any file-mode, more direct approach
 # os.system('rmdir /S /Q "{}"'.format(TEMP_LOCATION))
def get_choice():
 """ A function that return user choices """
 while True:
 choice_input = input('Press "L" to lock folder\nPress "U" to unlock folder\n'
 'Press "Q" to quit application').lower()
 if choice_input in {'l', 'u', 'q'}:
 return choice_input
 print('Wrong option selected')
def main():
 print('Welcome to FolderLocker V0.1 by AJ\n')
 initial_checkups() # creates temp dir
 choice_made = get_choice()
 if choice_made == 'l':
 folder_lock()
 if choice_made == 'u':
 try:
 folder_unlock()
 except FileNotFoundError:
 print('You NEED TO LOCK a folder before you try unlocking it!!!')
 os.system('pause') # allows user to read console message
 else:
 sys.exit(0)
if __name__ == '__main__':
 main()
Mast
13.8k12 gold badges56 silver badges127 bronze badges
asked Oct 6, 2017 at 16:27
\$\endgroup\$
1
  • \$\begingroup\$ I have upgraded your beautiful program locker with the possibility to add more than one folder and I will add more option, if possible i would you like to collaborate with you for this project, what do you think about it? Please contact me. \$\endgroup\$ Commented Apr 26, 2019 at 18:07

1 Answer 1

2
\$\begingroup\$

Currently, it can lock single folder; however, I wanna make it multi-threading so that it can work on more than one directory.

The most straight forward approach would be removing your dependence on global. The (over)use of global is frowned upon either way. Not just in Python either, proper scoping makes your code more robust. It decreases the risk of side effects, especially when the size of the code starts growing.

You'll also need to move TEMP_LOCATION, PASS_FILE and FILE_PATH_CURRENT_FOLDER_TEXT_FILE into something that keeps track of the single folder they're associated with. After all, they will likely vary between targets. Could make a class and instantiate it once per folder. The start and end of your program would then look somewhat like this:

class FolderLocker:
 def __init__(self):
 self.temp_location = os.path.join(os.path.expanduser('~'), 'Desktop', 'TEMP_FOLDER')
 self.pass_file = os.path.join(self.temp_location, 'password.txt')
 self.current_folder_file = os.path.join(self.temp_location, 'current_folder.txt')
...
 def run(self):
 """Runs the main menu of the folder locker application"""
 print('Welcome to FolderLocker V0.1\n')
 self.initial_checkups()
 choice = self.get_choice()
 if choice == 'l':
 self.lock_folder()
 elif choice == 'u':
 self.unlock_folder()
 else:
 sys.exit(0)
if __name__ == '__main__':
 folder_locker = FolderLocker()
 folder_locker.run()

Next step would be using arguments to set your various folders to lock etc., but reorganization of the code is required before you make that step.

answered Mar 10 at 16:28
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.