├── ChangeLog.md ├── HashDB ├── Hash_DB.py ├── cloner.py ├── crypt.py ├── deleter.py ├── event_logger.py ├── finder.py ├── hashdb.py ├── inserter.py ├── reader.py └── writer.py ├── LICENSE ├── README.html ├── README.md └── img └── screenshot.JPG /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # ChangeLog 2 | 3 | ## v0.0.4 4 | * More information in the event-log compared to v0.0.3 5 | * Database Connection 6 | * Database Disconnection 7 | * Database state 8 | * Improving encryption algorithm with the addition of SHA512 with salting 9 | * Undo Database Operations 10 | * Database Fetching 11 | * Data Sorting 12 | * Database Inserting 13 | * Database Updating 14 | * Database Overwriting 15 | * Database Destruction 16 | * Database Querying 17 | * Checking if data exists in Database 18 | * Counting Database Elements 19 | * Other fixes 20 | 21 | ## v0.0.3 22 | * Changing of project name from Jndb to HashDB 23 | * Changing encryption algorithm from %256 to %512 24 | * Changing read() to load() 25 | * Seperate event-log for different databases 26 | * Advanced error handling and event logging compared to v0.0.2 27 | * Addition of HashDB Banner 28 | * Splitting of HashDB functions to different folders 29 | * Other fixes 30 | 31 | ## v0.0.2 32 | * More information in the event-log compared to v0.0.1 33 | * Handling error encountered when opening a DB that does not exist 34 | * Handling error encountered when cloning a DB that does not exist 35 | * Changing of create() to write() 36 | * Other fixes 37 | 38 | ## v0.0.1 39 | * Base Version 40 | * Database Creation and Encryption 41 | * Database Deletion 42 | * Database Reading and Decryption 43 | * Database Cloning 44 | * Data Location 45 | * Event Logging 46 | -------------------------------------------------------------------------------- /HashDB/Hash_DB.py: -------------------------------------------------------------------------------- 1 | from cloner import dump 2 | from crypt import encryptdb 3 | from writer import write 4 | from time import time 5 | from finder import find, coun, exist 6 | from event_logger import event_log 7 | from deleter import remf, remd, remdd 8 | from inserter import insA, ins, upd, tab 9 | from reader import load, close, dumps, literal_eval 10 | 11 | class connect: 12 | def __init__(self, dbname, password=None): 13 | _data, self.state, error = load(dbname, password) 14 | if str(type(_data)) != "": 15 | error = "A password is required to connect to DB {}".format(dbname) 16 | event_log(error) 17 | if error: 18 | raise Exception(error) 19 | self.__data = _data 20 | del _data 21 | self.__name = str(dbname) 22 | self.__dataCP = dumps(self.__data) 23 | 24 | def get(self, table=None, id=None, sort=0): 25 | if table: 26 | error = None 27 | if str(type(table)) != "": 28 | event_log("Expecting table to be of type str in function get", dbname) 29 | error = "Expecting table to be of type str in function get" 30 | if error: 31 | raise (error) 32 | try: 33 | if id: 34 | try: 35 | d = self.__data[table][id] 36 | event_log("Successfully retrieved table_id {} in table {} in DB {} contents".format(id, table, self.__name), self.__name) 37 | except: 38 | event_log("The table_id {} does not exist in table {} in DB {}".format(id, table, self.__name), self.__name) 39 | raise Exception("The table_id {} does not exist in table {} in DB {}".format(id, table, self.__name)) 40 | else: 41 | d = self.__data[table] 42 | event_log("Successfully retrieved table {} in DB {} contents".format(table, self.__name), self.__name) 43 | data = d 44 | del d 45 | except: 46 | event_log("The Table {} does not exist! in DB {}".format(table, self.__name), self.__name) 47 | raise Exception("The Table {} does not exist! in DB {}".format(table, self.__name)) 48 | else: 49 | event_log("Successfully retrieved DB {} contents".format(self.__name), self.__name) 50 | data = self.__data 51 | if int(sort) != 0: 52 | data2 = {} 53 | if int(sort) > 0: 54 | for i in sorted(data): 55 | data2[i] = data[i] 56 | elif int(sort) < 0: 57 | for i in sorted(data)[::-1]: 58 | data2[i] = data[i] 59 | data = data2 60 | del data2 61 | return data 62 | 63 | def tables(self): 64 | event_log("Successfully retrieved DB {} Tables".format(self.__name), self.__name) 65 | return list(self.__data.keys()) 66 | 67 | def table(self, table_): 68 | _data = dumps(self.__data) 69 | data, error = tab(self.__data, table_, self.__name) 70 | if error: 71 | raise Exception(error) 72 | self.__dataCP = _data 73 | self.__data = data 74 | 75 | def count(self, table=None, id=None): 76 | if (not table) and (not id): 77 | event_log("Successfully retrieved count of DB {}".format(self.__name), self.__name) 78 | return len(self.__data.keys()) 79 | elif (not table) and id: 80 | error = "Error! Can't get count of table_id without specifying table in function count" 81 | event_log(error, self.__name) 82 | raise Exception(error) 83 | value, error = coun(self.__name, self.__data, table, id) 84 | if error: 85 | 86 | raise Exception(error) 87 | return value 88 | 89 | def save(self, password=None, prettify=True): 90 | error = write(self.__name, self.__data, password, prettify) 91 | if error: 92 | raise Exception(error) 93 | 94 | def disconnect(self, s=True, password=None, prettify=True): 95 | if s: 96 | self.save(password, prettify) 97 | error = close(self.__name) 98 | if error: 99 | raise Exception(error) 100 | else: 101 | del self.__data, self.__dataCP, self.__name 102 | 103 | def clone(self, destination): 104 | error = dump(self.__name, destination) 105 | if error: 106 | raise Exception(error) 107 | 108 | def insert(self, table, data_, id=None): 109 | _data = dumps(self.__data) 110 | data, error = ins(self.__data, data_, table, self.__name, id) 111 | if error: 112 | raise Exception(error) 113 | self.__dataCP = _data 114 | self.__data = data 115 | 116 | def update(self, table, id, data_=None): 117 | _data = dumps(self.__data) 118 | data, error = upd(self.__data, data_, table, self.__name, id) 119 | if error: 120 | raise Exception(error) 121 | self.__dataCP = _data 122 | self.__data = data 123 | 124 | def exists(self, table=None, id_=None): 125 | res, error = exist(self.__name, self.__data, table, id_) 126 | if error: 127 | event_log("An Error occured when checking if data exists in DB {}".format(self.__name), self.__name) 128 | raise Exception(error) 129 | event_log("Successfully checked if data exists in DB {}".format(self.__name), self.__name) 130 | return res 131 | 132 | def overwrite(self, data_=None): 133 | _data = dumps(self.__data) 134 | data, error = insA(data_, self.__name) 135 | if error: 136 | raise Exception(error) 137 | self.__dataCP = _data 138 | self.__data = data 139 | 140 | def undo(self): 141 | self.__data = literal_eval(self.__dataCP.replace(": true,", ": True,").replace(": false,", ": False,")) 142 | event_log("Successfully Reversed Database Action", self.__name) 143 | 144 | def destroy(self): 145 | error = remf(self.__name) 146 | if error: 147 | raise Exception(error) 148 | self.__data, self.__dataCP = {}, "{}" 149 | 150 | def drop(self, table=None, id=None): 151 | _data = dumps(self.__data) 152 | if (not table) and (not id_): 153 | event_log("Successfully dropped DB {}".format(self.__name), self.__name) 154 | data_ = {} 155 | else: 156 | data_, error = remd(self.__data, self.__name, table, id) 157 | if error: 158 | raise Exception(error) 159 | self.__dataCP = _data 160 | self.__data = data_ 161 | 162 | def delete(self, query_=None, table=None): 163 | _data = dumps(self.__data) 164 | data_, error = remdd(self.__name, self.__data, table, query_) 165 | if error: 166 | raise Exception(error) 167 | self.__dataCP = _data 168 | self.__data = data_ 169 | 170 | def select(self, query_=None, table=None, limit=0): 171 | data_, error = find(self.__name, self.__data, table, query_, limit) 172 | if error: 173 | raise Exception(error) 174 | return data_ 175 | 176 | def create(dbname, data={}, password=None): 177 | if password: 178 | with open(dbname + ".hashdb", "w") as db: 179 | db.write(encryptdb(str(data), str(password), dbname)) 180 | else: 181 | with open(dbname + ".hashdb", "w") as db: 182 | db.write(dumps(data, indent=4)) 183 | event_log("Successfully created new DB {}".format(dbname), dbname) -------------------------------------------------------------------------------- /HashDB/cloner.py: -------------------------------------------------------------------------------- 1 | from os import path 2 | from reader import literal_eval, dumps 3 | from event_logger import event_log 4 | 5 | #cloner.py handles DB cloning; takes in 2 arguments (name of database to clone, new database name) 6 | 7 | def dump(source, destination): 8 | #Ensure the destination is a string or int or float 9 | if not str(type(destination)) in ["", "", ""]: 10 | event_log("Error! Expecting destination to be of type string or int or float in function clone", source) 11 | return {}, "Error! Expecting destination to be of type string or int or float" 12 | #Converts to a string incase it is a float or int 13 | destination = str(destination) 14 | if len(destination) == 0: 15 | event_log("Error! Destination cannot be empty in function clone", source) 16 | return "Destination cannot be empty in function clone" 17 | if source == destination: 18 | e = "Error! destination cant be the same as source in function clone!" 19 | event_log(e, source) 20 | return e 21 | try: 22 | #Basically read and write the database stored on the disk 23 | with open (source + ".hashdb", "r") as db0: 24 | content = db0.read() 25 | with open (destination + ".hashdb", "w") as db1: 26 | db1.write(dumps(content)) 27 | event_log("Successfully cloned DB {} to {}".format(source, destination), source) 28 | return None 29 | except Exception as e: 30 | event_log("There was an error cloning DB {} to {} - {}".format(source, destination, str(e)), source) 31 | return str(e) -------------------------------------------------------------------------------- /HashDB/crypt.py: -------------------------------------------------------------------------------- 1 | #ASCII ART! 2 | 3 | from event_logger import event_log 4 | from hashlib import sha512 5 | 6 | #Convert password to an integer 7 | def encpass(password, dbname): 8 | password = str(password) 9 | password = sha512((password + password + (password[0] * len(password))).encode()).hexdigest() 10 | try: 11 | tot = 0 12 | for p in range(len(password)): 13 | tot += ord(password[p]) * p 14 | tot += ord(password[0]) + ord(password[-1]) 15 | return (tot % 512) 16 | except Exception as e: 17 | event_log("There was an error parsing given password for DB {} - {}".format(dbname, str(e)), dbname) 18 | return str(e) 19 | 20 | #Encrypt database if password is given 21 | def encryptdb(dbcontent, password, dbname): 22 | try: 23 | values = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144][::-1] 24 | keys = list("<~,.?-}[@*|/") 25 | dbcontent = dbcontent[::-1] 26 | key = encpass(password, dbname) 27 | current_count, index = 0, 1 28 | new_word = "" 29 | for cur in dbcontent: 30 | value = ord(cur) + key + (index % len(password)) 31 | index += 1 32 | while(current_count < value): 33 | for i in range(len(keys)): 34 | if current_count + values[i] <= value: 35 | current_count += values[i] 36 | new_word += keys[i] 37 | new_word += ":" 38 | current_count = 0 39 | return new_word 40 | except Exception: 41 | return "{}" 42 | 43 | #Decrypt database if password is given 44 | def decryptdb(dbcontent, password, dbname): 45 | try: 46 | if dbcontent == "{}": return "{}" 47 | values = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144][::-1] 48 | keys = list("<~,.?-}[@*|/") 49 | key = encpass(password, dbname) 50 | new_word = "" 51 | index = 1 52 | for current_word in dbcontent.split(":")[:-1]: 53 | temp_word = 0 54 | for current in current_word: 55 | for i in range(len(keys)): 56 | if current == keys[i]: 57 | temp_word += values[i] 58 | val = temp_word - key - (index % len(password)) 59 | if val <= 0: 60 | val = 0 61 | new_word += chr(val) 62 | index += 1 63 | return new_word[::-1] 64 | except Exception: 65 | return "{}" -------------------------------------------------------------------------------- /HashDB/deleter.py: -------------------------------------------------------------------------------- 1 | from os import remove, path 2 | from event_logger import event_log 3 | 4 | #deletes a DB file given its name 5 | def remf(dbname): 6 | try: 7 | try: 8 | remove(dbname + ".hashdb") 9 | except Exception as e: 10 | event_log("There was an error destroying DB {} - {}".format(dbname, str(e)), dbname) 11 | return (str(e)) 12 | except Exception as e: 13 | event_log("There was an error destroying DB {} - {}".format(dbname, str(e)), dbname) 14 | return (str(e)) 15 | event_log("Successfully deleted DB {}".format(dbname), dbname) 16 | return None 17 | except Exception as e: 18 | event_log("There was an error destroying DB {} - {}".format(dbname, str(e)), dbname) 19 | return str(e) 20 | 21 | #deletes data from the database 22 | def remd(dbcontent, name_, table, id_): 23 | if id_ and (not (str(type(id_)) in ["", "", ""])): 24 | event_log("Error! Expecting id_ to be of type string or int or float in function drop", name_) 25 | return [], "Expecting id_ to be of type string or int or float in function drop" 26 | if not (str(type(table)) in ["", ""]): 27 | event_log("Error! Expecting table to be of type string or list in function drop", name_) 28 | return [], "Expecting table to be of type string or list in function drop" 29 | try: 30 | if str(type(table)) == "": 31 | if id_: 32 | del dbcontent[table][id_] 33 | event_log("Successfully dropped id_ {} in table {} in DB {}".format(id_, table, name_), name_) 34 | else: 35 | del dbcontent[table] 36 | event_log("Successfully dropped table {} in DB {}".format(table, name_), name_) 37 | else: 38 | for i in table: 39 | del dbcontent[i] 40 | return dbcontent, None 41 | except Exception as e: 42 | event_log("There was an error droping table {} in DB {} - {}".format(table, name_, str(e)), name_) 43 | return {}, str(e) 44 | 45 | def remdd(name_, dbcontent, table, query_): 46 | if (str(type(table)) != "" and str(type(table)) != "") and table: 47 | event_log("Error! Expecting table to be of type str or list in function delete", name_) 48 | return [], "Expecting table to be of type str or list in function delete" 49 | if str(type(table)) == "": 50 | table = [table] 51 | if str(type(query_)) != "" and query_: 52 | event_log("Error! Expecting query_ to be of type dict in function find", name_) 53 | return [], "Expecting query_ to be of type dict in function find" 54 | if (not query_) and (not table): 55 | del dbcontent 56 | return {}, None 57 | elif not query_: 58 | del dbcontent[table] 59 | return dbcontent, None 60 | try: 61 | if table: 62 | places_to_search = table 63 | else: 64 | places_to_search = list(dbcontent.keys()) 65 | selected = [] 66 | for places in places_to_search: 67 | for key in dbcontent[places]: 68 | present = False 69 | for query in query_: 70 | try: 71 | if "or" == query.lower() and (not present): 72 | for keyy in query_[query]: 73 | if dbcontent[places][key][keyy] == query_[query][keyy]: 74 | present = True 75 | except: 76 | pass 77 | try: 78 | if "or>" == query.lower() and (not present): 79 | for keyy in query_[query]: 80 | if dbcontent[places][key][keyy] > query_[query][keyy]: 81 | present = True 82 | except: 83 | pass 84 | try: 85 | if "or<" == query.lower() and (not present): 86 | for keyy in query_[query]: 87 | if dbcontent[places][key][keyy] < query_[query][keyy]: 88 | present = True 89 | except: 90 | pass 91 | if present: 92 | selected.append([places, key]) 93 | continue 94 | valid = True 95 | for query in query_: 96 | try: 97 | if "and" == query.lower(): 98 | for keyy in query_[query]: 99 | if dbcontent[places][key][keyy] != query_[query][keyy]: 100 | valid = False 101 | elif "not" == query.lower(): 102 | try: 103 | for keyy in query_[query]: 104 | if dbcontent[places][key][keyy] == query_[query][keyy]: 105 | valid = False 106 | except: 107 | pass 108 | elif "like" == query.lower(): 109 | for keyy in query_[query]: 110 | if not (str(query_[query][keyy]).lower() in str(dbcontent[places][key][keyy]).lower() and str(type(dbcontent[places][key][keyy])) == ""): 111 | valid = False 112 | elif ">" == query: 113 | for keyy in query_[query]: 114 | if str(type(query_[query][keyy])) in ["", ""]: 115 | if float(dbcontent[places][key][keyy]) < float(query_[query][keyy]): 116 | valid = False 117 | elif "<" == query: 118 | for keyy in query_[query]: 119 | if str(type(query_[query][keyy])) in ["", ""]: 120 | if float(dbcontent[places][key][keyy]) > float(query_[query][keyy]): 121 | valid = False 122 | else: 123 | if not query.lower() in "or or> or<".split(" "): 124 | event_log("Error! Invalid Delete Format", name_) 125 | return [], "Invalid Delete Format" 126 | elif query.lower() in "or or> or<".split(" "): 127 | pass 128 | else: 129 | valid = False 130 | except: 131 | valid = False 132 | pass 133 | if valid: 134 | selected.append([places, key]) 135 | for i in selected: 136 | try: 137 | del dbcontent[i[0]][i[1]] 138 | except: 139 | pass 140 | event_log("Successfully Deleted data from DB {}".format(name_), name_) 141 | return dbcontent, None 142 | except Exception as e: 143 | return {}, str(e) -------------------------------------------------------------------------------- /HashDB/event_logger.py: -------------------------------------------------------------------------------- 1 | #HashDB 2 | #Author - LordGhostX 3 | 4 | from time import strftime as strf 5 | 6 | #Event Logger 7 | #Logs every event that happens in HashDB 8 | def event_log(event, dbname=0): 9 | d, t = strf("%D"), strf("%T") 10 | if dbname == 0: 11 | with open("HashDB-event-log.txt", "a") as log: 12 | log.write("{} {} -> {}\n".format(d, t, event)) 13 | else: 14 | with open("{}-event-log.txt".format(dbname), "a") as log: 15 | log.write("{} {} -> {}\n".format(d, t, event)) -------------------------------------------------------------------------------- /HashDB/finder.py: -------------------------------------------------------------------------------- 1 | # HashDB 2 | # Author - LordGhostX 3 | 4 | from event_logger import event_log 5 | 6 | # Find all keys with specified values 7 | # Usage: find(, ) 8 | def find(name_, dbcontent, table, query_, limit): 9 | if str(type(table)) != "" and str(type(table)) != "" and table: 10 | event_log("Error! Expecting table to be of type str or type list in function select", name_) 11 | return [], "Expecting table to be of type str or type list in function select" 12 | if str(type(limit)) != "": 13 | event_log("Error! Expecting limit to be of type int in function select", name_) 14 | return [], "Expecting limit to be of type int in function select" 15 | if limit < 0: 16 | event_log("Error! Expecting limit to be a positive integer in function select", name_) 17 | return [], "Expecting limit to be be a positive integer in function select" 18 | if str(type(query_)) != "" and query_: 19 | event_log("Error! Expecting query_ to be of type dict in function select", name_) 20 | return [], "Expecting query_ to be of type dict in function select" 21 | if (not query_) and (not table): 22 | return list(dbcontent.items()), None 23 | elif not query_: 24 | return list(dbcontent[table].items()), None 25 | if str(type(table)) == "": 26 | table = [table] 27 | try: 28 | if table: 29 | places_to_search = table 30 | else: 31 | places_to_search = list(dbcontent.keys()) 32 | selected = [] 33 | for places in places_to_search: 34 | for key in dbcontent[places]: 35 | present = False 36 | for query in query_: 37 | try: 38 | if "or" == query.lower() and (not present): 39 | for keyy in query_[query]: 40 | if dbcontent[places][key][keyy] == query_[query][keyy]: 41 | present = True 42 | except: 43 | pass 44 | try: 45 | if "or>" == query.lower() and (not present): 46 | for keyy in query_[query]: 47 | if dbcontent[places][key][keyy] > query_[query][keyy]: 48 | present = True 49 | except: 50 | pass 51 | try: 52 | if "or<" == query.lower() and (not present): 53 | for keyy in query_[query]: 54 | if dbcontent[places][key][keyy] < query_[query][keyy]: 55 | present = True 56 | except: 57 | pass 58 | if present: 59 | selected.append({places: {key: dbcontent[places][key]}}) 60 | if len(selected) >= limit and limit > 0: 61 | return selected, None 62 | continue 63 | valid = True 64 | for query in query_: 65 | try: 66 | if "and" == query.lower(): 67 | for keyy in query_[query]: 68 | if dbcontent[places][key][keyy] != query_[query][keyy]: 69 | valid = False 70 | elif "not" == query.lower(): 71 | try: 72 | for keyy in query_[query]: 73 | if dbcontent[places][key][keyy] == query_[query][keyy]: 74 | valid = False 75 | except: 76 | pass 77 | elif "like" == query.lower(): 78 | for keyy in query_[query]: 79 | if not (str(query_[query][keyy]).lower() in str(dbcontent[places][key][keyy]).lower() and str(type(dbcontent[places][key][keyy])) == ""): 80 | valid = False 81 | elif ">" == query: 82 | for keyy in query_[query]: 83 | if str(type(query_[query][keyy])) in ["", ""]: 84 | if float(dbcontent[places][key][keyy]) < float(query_[query][keyy]): 85 | valid = False 86 | elif "<" == query: 87 | for keyy in query_[query]: 88 | if str(type(query_[query][keyy])) in ["", ""]: 89 | if float(dbcontent[places][key][keyy]) > float(query_[query][keyy]): 90 | valid = False 91 | else: 92 | if not query.lower() in "or or> or<".split(" "): 93 | event_log("Error! Invalid Select Format", name_) 94 | return [], "Invalid Select Format" 95 | elif query.lower() in "or or> or<".split(" "): 96 | pass 97 | else: 98 | valid = False 99 | except: 100 | valid = False 101 | pass 102 | if valid: 103 | selected.append({places: {key: dbcontent[places][key]}}) 104 | if len(selected) == limit and limit > 0: 105 | return selected, None 106 | event_log("Successfully Selected data from DB {}".format(name_), name_) 107 | return selected, None 108 | except Exception as e: 109 | event_log("Unable to Select data from DB".format(name_), name_) 110 | return [], str(e) 111 | 112 | 113 | def coun(name, data, table, index): 114 | try: 115 | if str(type(table)) != "": 116 | event_log("Error! Expecting table to be of type str in function count", name) 117 | return 0, "Expecting table to be of type str in function count" 118 | try: 119 | d = data[table] 120 | except: 121 | event_log("Error! table {} does not exist in DB {}".format(table, name), name) 122 | return 0, "Error! table {} does not exist in DB {}".format(table, name) 123 | if index: 124 | try: 125 | d = data[table][index] 126 | except: 127 | event_log("Error! table_id {} does not exist in table {} in DB {}".format(index, table, name), name) 128 | return 0, "Error! table_id {} does not exist in table {} in DB {}".format(index, table, name) 129 | event_log("Successfully retrieved count of table_id {} in table {} in DB {}".format(index, table, name), 130 | name) 131 | return len(data[table][index].keys()), None 132 | else: 133 | event_log("Successfully retrieved count of table {} in DB {}".format(table, name), name) 134 | return len(data[table].keys()), None 135 | except Exception as e: 136 | return 0, str(e) 137 | 138 | 139 | def exist(name, data_, table, id_): 140 | try: 141 | if table and id_: 142 | try: 143 | value = data_[table][id_] 144 | del value 145 | return True, None 146 | except: 147 | return False, None 148 | elif table and (not id_): 149 | try: 150 | value = data_[table] 151 | del value 152 | return True, None 153 | except: 154 | return False, None 155 | elif (not table) and id_: 156 | return None, "table cannot be absent when id is specified in function exists" 157 | except: 158 | return None, "An error occured when checking if data exists in DB {}".format(name) -------------------------------------------------------------------------------- /HashDB/hashdb.py: -------------------------------------------------------------------------------- 1 | from Hash_DB import connect, create 2 | 3 | def banner(): 4 | print("""# 5 | # ██╗ ██╗ █████╗ ███████╗██╗ ██╗ ██████╗ ██████╗ 6 | # ████████╗██╔══██╗██╔════╝██║ ██║ ██╔══██╗██╔══██╗ 7 | # ╚██╔═██╔╝███████║███████╗███████║█████╗██║ ██║██████╔╝ 8 | # ████████╗██╔══██║╚════██║██╔══██║╚════╝██║ ██║██╔══██╗ 9 | # ╚██╔═██╔╝██║ ██║███████║██║ ██║ ██████╔╝██████╔╝ 10 | # ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ 11 | #""") 12 | 13 | version = "HashDB v0.0.35" -------------------------------------------------------------------------------- /HashDB/inserter.py: -------------------------------------------------------------------------------- 1 | from event_logger import event_log 2 | 3 | def insA(data_, dbname): 4 | try: 5 | if not data_: 6 | event_log("Successfully overwritten data in DB {}".format(dbname), dbname) 7 | return {}, None 8 | if str(type(data_)) == "" or str(type(data_)) == "": 9 | if str(type(data_)) == "": 10 | data_ = {"data": data_} 11 | event_log("Successfully overwritten data in DB {}".format(dbname), dbname) 12 | return data_, None 13 | else: 14 | event_log("Expecting data_ to be of type dict or str in function overwrite", dbname) 15 | return {}, "Error! Expecting data_ to be of type dict or str" 16 | except Exception as e: 17 | event_log("There was an error overwriting data in DB {} - {}".format(dbname, str(e)), dbname) 18 | return {}, str(e) 19 | 20 | def ins(data, data_, table, dbname, id_): 21 | try: 22 | if str(type(data_)) != "": 23 | event_log("Expecting data_ to be of type dict in function insert", dbname) 24 | return {}, "Error! Expecting data_ to be of type dict" 25 | if str(type(table)) != "": 26 | event_log("Expecting table to be of type str in function insert", dbname) 27 | return {}, "Error! Expecting table to be of type str" 28 | if str(type(id_)) != "" and id_: 29 | event_log("Expecting id_ to be of type str in function insert", dbname) 30 | return {}, "Error! Expecting id_ to be of type str" 31 | if not id_: 32 | id_ = "id_{}".format(len(data[table])) 33 | try: 34 | data[table] 35 | except: 36 | event_log("table {} does not exist in DB {}".format(table, dbname), dbname) 37 | return {}, "table {} does not exist in DB {}".format(table, dbname) 38 | data[table][str(id_)] = data_ 39 | event_log("Successfully inserted data into DB {} in table {}".format(dbname, table), dbname) 40 | return data, None 41 | except Exception as e: 42 | event_log("There was an error inserting data into DB {} in table {} - {} does not exist".format(dbname, table, str(e)), dbname) 43 | return {}, str(e) + "does not exist" 44 | 45 | def upd(data, data_, table, dbname, id_): 46 | try: 47 | if str(type(data_)) != "": 48 | event_log("Expecting data_ to be of type dict in function update", dbname) 49 | return {}, "Error! Expecting data_ to be of type dict" 50 | if str(type(table)) != "": 51 | event_log("Expecting table to be of type str in function update", dbname) 52 | return {}, "Error! Expecting table to be of type str" 53 | if not str(type(id_)) in ["", ""]: 54 | event_log("Expecting id_ to be of type str or int in function update", dbname) 55 | return {}, "Error! Expecting id_ to be of type str or int" 56 | if not data_: 57 | data_ = {} 58 | try: 59 | if str(type(id_)) == "": 60 | bin_ = data[table][list(data[table].keys())[id_]] 61 | del bin_ 62 | data[table][list(data[table].keys())[id_]] = data_ 63 | else: 64 | bin_ = data[table][str(id_)] 65 | del bin_ 66 | data[table][str(id_)] = data_ 67 | except: 68 | event_log("There is no table_id with {} in table {} in DB {}".format(id_, table, dbname), dbname) 69 | return {}, "table_id {} does not exist in table {}".format(id_, table) 70 | event_log("Successfully updated data into DB {} in table {} with id {}".format(dbname, table, id_), dbname) 71 | return data, None 72 | except Exception as e: 73 | event_log("There was an error updating data in DB {} in table {} with id_ {} - {}".format(dbname, table, id_, str(e)), dbname) 74 | return {}, str(e) 75 | 76 | def tab(data_, table_, name_): 77 | try: 78 | if str(type(table_)) != "": 79 | event_log("Expecting table to be of type str in function table", dbname) 80 | return {}, "Error! Expecting table to be of type str" 81 | data_[table_] = {} 82 | event_log("Successfully created table {} in DB {}".format(table_, name_), name_) 83 | return data_, None 84 | except Exception as e: 85 | event_log("There was an error creating table {} in DB {} - {}".format(table_, name_, str(e)), name_) 86 | return {}, str(e) -------------------------------------------------------------------------------- /HashDB/reader.py: -------------------------------------------------------------------------------- 1 | from json import dumps 2 | from json import load as ll 3 | from ast import literal_eval 4 | from event_logger import event_log 5 | from crypt import decryptdb 6 | from os import path 7 | 8 | #Loading an existing HashDB Database 9 | #Usage: load(, ) 10 | def load(dbname, password=None): 11 | if not str(type(dbname)) in ["", "", ""]: 12 | event_log("Error! Expecting dbname to be of type string or int or float in function connect", 0) 13 | return {}, 0, "Error! Expecting dbname to be of type string or int or float" 14 | dbname = str(dbname) 15 | try: 16 | res = 0 17 | if not path.exists(dbname + ".hashdb"): 18 | with open(dbname + ".hashdb", "w") as db: 19 | db.write("{}") 20 | res = 1 21 | if password: 22 | with open(dbname + ".hashdb", "r") as db: 23 | try: 24 | dbcontent = decryptdb(db.read(), str(password), dbname) 25 | dbcontent = literal_eval(dbcontent.replace(": true,", ": True,").replace(": false,", ": False,")) 26 | event_log("Successfully connected to DB {}".format(dbname), dbname) 27 | except Exception as e: 28 | event_log("An incorrect password was used in connecting to DB {} or the DB is corrupted".format(dbname), dbname) 29 | return {}, 0, "An incorrect password was used in connecting to DB {} or the DB is corrupted".format(dbname) 30 | else: 31 | with open(dbname + ".hashdb") as db: 32 | try: 33 | dbcontent = ll(db) 34 | except Exception as e: 35 | event_log("A password is required to connect to DB {} - {}".format(dbname, str(e)), dbname) 36 | return {}, 0, "A password is required to connect to DB {}".format(dbname) 37 | db.close() 38 | 39 | event_log("Successfully connected to DB {}".format(dbname), dbname) 40 | return dbcontent, res, None 41 | except Exception as e: 42 | event_log("There was an error connecting to DB {} - {}".format(dbname, str(e)), dbname) 43 | return {}, 0, str(e) 44 | 45 | def close(dbname): 46 | try: 47 | event_log("Successfully disconnected from DB {}".format(dbname), dbname) 48 | return None 49 | except Exception as e: 50 | event_log("There was an error disconnecting from DB {}, Possibly due to Database Corruption - {}".format(dbname, str(e)), dbname) 51 | return str(e) -------------------------------------------------------------------------------- /HashDB/writer.py: -------------------------------------------------------------------------------- 1 | #HashDB 2 | #Author - LordGhostX 3 | 4 | from event_logger import event_log 5 | from crypt import encryptdb 6 | from json import dumps 7 | from time import time 8 | 9 | #Creating a new HashDB Database 10 | #Usage: write(, , , ) 11 | def write(dbname, dbcontent, password=None, prettify=True): 12 | try: 13 | with open(dbname + ".hashdb", "w") as db: 14 | if password: 15 | db.write(encryptdb(str(dbcontent), str(password), dbname)) 16 | event_log("Successfully saved DB {}".format(dbname), dbname) 17 | else: 18 | if prettify: 19 | db.write(dumps(dbcontent, indent=4)) 20 | else: 21 | db.write(dumps(dbcontent)) 22 | event_log("Successfully saved DB {}".format(dbname), dbname) 23 | return None 24 | except Exception as e: 25 | event_log("There was an error editing DB {} - {}".format(dbname, str(e)), dbname) 26 | return str(e) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 LordGhostX 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | # 3 | # ██╗ ██╗ █████╗ ███████╗██╗ ██╗ ██████╗ ██████╗ 4 | # ████████╗██╔══██╗██╔════╝██║ ██║ ██╔══██╗██╔══██╗ 5 | # ╚██╔═██╔╝███████║███████╗███████║█████╗██║ ██║██████╔╝ 6 | # ████████╗██╔══██║╚════██║██╔══██║╚════╝██║ ██║██╔══██╗ 7 | # ╚██╔═██╔╝██║ ██║███████║██║ ██║ ██████╔╝██████╔╝ 8 | # ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ 9 | # 10 | ``` 11 | # HashDB 12 | 13 | This library is an implementation for a NOSQL Database using JSON for storing of data. 14 | 15 | Best for small scale projects 16 | 17 | Check the ChangeLog for info on what has changed. 18 | 19 | ## Installation 20 | Windows / Linux / MAC 21 | 22 | On Windows, Linux and MAC, you can install this package easily by placing the py file in your project folder (not available via pip) 23 | 24 | ## Help 25 | Kindly view the README.html for more info or visit the Github page [here](https://lordghostx.github.io/HashDB/README.html), Thanks! 26 | 27 | ## TO-DO 28 | * Upgrade Encryption Format 29 | * Make available on pip 30 | * Upgrade querying runtime 31 | 32 | ## Version 33 | 0.0.4 34 | 35 | ## License 36 | [**MIT**](https://opensource.org/licenses/MIT) 37 | 38 | ## Author 39 | LordGhostX 40 | -------------------------------------------------------------------------------- /img/screenshot.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LordGhostX/HashDB/960aeb6558303ff37f3ac3fb2256172271ca0ae6/img/screenshot.JPG --------------------------------------------------------------------------------