From 26e912c03a9aba191b2a8ef976189e7362409ca8 Mon Sep 17 00:00:00 2001 From: hasslesstech Date: Sat, 25 May 2024 19:18:26 +0300 Subject: [PATCH] initial commit --- .gitignore | 3 ++ server/cgi/db/object_pool.py | 10 +++++ server/cgi/db/question.py | 43 ++++++++++++++++++ server/cgi/db/response.py | 32 +++++++++++++ server/cgi/db/response_option.py | 43 ++++++++++++++++++ server/cgi/db/test.py | 27 +++++++++++ server/cgi/test_list.py | 12 +++++ server/cgi/view.py | 77 ++++++++++++++++++++++++++++++++ server/css/base_style.css | 8 ++++ server/html/base_layout.html | 14 ++++++ server/httputils.py | 31 +++++++++++++ server/index.py | 51 +++++++++++++++++++++ 12 files changed, 351 insertions(+) create mode 100644 .gitignore create mode 100644 server/cgi/db/object_pool.py create mode 100644 server/cgi/db/question.py create mode 100644 server/cgi/db/response.py create mode 100644 server/cgi/db/response_option.py create mode 100644 server/cgi/db/test.py create mode 100644 server/cgi/test_list.py create mode 100644 server/cgi/view.py create mode 100644 server/css/base_style.css create mode 100644 server/html/base_layout.html create mode 100644 server/httputils.py create mode 100644 server/index.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..969703c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +server/cgi/db-settings.json +server/venv/ +**/__pycache__/ diff --git a/server/cgi/db/object_pool.py b/server/cgi/db/object_pool.py new file mode 100644 index 0000000..96fd40e --- /dev/null +++ b/server/cgi/db/object_pool.py @@ -0,0 +1,10 @@ +class ObjectPool: + def __init__(self, selector, constructor): + self.selector = selector + self.constructor = constructor + self.pool = [] + + def load_from_db(self, cur): + cur.execute(f"SELECT * FROM {self.selector};") + self.pool = [self.constructor().init_from_data(i) for i in cur] + return self diff --git a/server/cgi/db/question.py b/server/cgi/db/question.py new file mode 100644 index 0000000..c603bba --- /dev/null +++ b/server/cgi/db/question.py @@ -0,0 +1,43 @@ +from object_pool import ObjectPool + +class Question: + def init(self, sID, title, max_time, test_id): + self.id = sID + self.title = title + self.max_time = max_time + self.test_id = test_id + + return self + + def init_from_data(self, data): + return self.init(*data) + + def get_id(self): + return self.id + + def get_title(self): + return self.title + + def get_max_time(self): + return self.max_time + + def get_test_id(self): + return self.test_id + +''' +class QuestionPool: + def __init__(self): + self.pool = [] + + def load_from_db(self, cur): + db.execute("SELECT * FROM response_option;") + self.pool = [ResponseOption().init_from_data(i) for i in cur] + return self +''' + +class QuestionPool: + def __init__(self): + self.object_pool = ObjectPool("question", Question) + + if db: + self.object_pool.load_from_db(db) diff --git a/server/cgi/db/response.py b/server/cgi/db/response.py new file mode 100644 index 0000000..b7f39f4 --- /dev/null +++ b/server/cgi/db/response.py @@ -0,0 +1,32 @@ +from object_pool import ObjectPool + +class Response: + def init(self, rID, optionID, pupilID, delay): + self.id = rID + self.optionID = optionID + self.pupilID = pupilID + self.delay = delay + + return self + + def init_from_data(self, data): + return self.init(*data) + + def get_id(self): + return self.id + + def get_option_id(self): + return self.optionID + + def get_pupil_id(self): + return self.pupilID + + def get_delay(self): + return delay + +class ResponsePool: + def __init__(self, db = None): + self.object_pool = ObjectPool("response", Response) + + if db: + self.object_pool.load_from_db(db) diff --git a/server/cgi/db/response_option.py b/server/cgi/db/response_option.py new file mode 100644 index 0000000..405f936 --- /dev/null +++ b/server/cgi/db/response_option.py @@ -0,0 +1,43 @@ +from object_pool import ObjectPool + +class ResponseOption: + def init(self, sID, label, questionID, correctness): + self.id = sID + self.label = label + self.questionID = questionID + self.correctness = correctness + + return self + + def init_from_data(self, data): + return self.init(*data) + + def get_id(self): + return self.id + + def get_label(self): + return self.label + + def get_question_id(self): + return self.questionID + + def get_correctness(self): + return correctness + +class ResponceOptionPool: + def __init__(self): + self.object_pool = ObjectPool("response_option", ResponseOption) + + if db: + self.object_pool.load_from_db(db) + +''' +class ResponceOptionPool: + def __init__(self): + self.pool = [] + + def load_from_db(self, cur): + db.execute("SELECT * FROM response_option;") + self.pool = [ResponseOption().init_from_data(i) for i in cur] + return self +''' diff --git a/server/cgi/db/test.py b/server/cgi/db/test.py new file mode 100644 index 0000000..ec899bf --- /dev/null +++ b/server/cgi/db/test.py @@ -0,0 +1,27 @@ +from db.object_pool import ObjectPool + +class Test: + def init(self, sID, name): + self.id = sID + self.name = name + + return self + + def init_from_data(self, data): + return self.init(*data) + + def get_id(self): + return self.id + + def get_name(self): + return self.name + + def render_short(self): + return f'
#{self.sID} {self.name}
' + +class TestPool: + def __init__(self, db): + self.object_pool = ObjectPool("test", Test) + + if db: + self.object_pool.load_from_db(db) diff --git a/server/cgi/test_list.py b/server/cgi/test_list.py new file mode 100644 index 0000000..91ab572 --- /dev/null +++ b/server/cgi/test_list.py @@ -0,0 +1,12 @@ +import mariadb as mdb + +from db.test import TestPool + +class TestList: + def __init__(self, cursor): + self.cursor = cursor + + def render(self): + tp = TestPool(self.cursor) + rendered_chunks = [i.render_short() for i in tp.object_pool.pool] + return "\n".join(rendered_chunks) diff --git a/server/cgi/view.py b/server/cgi/view.py new file mode 100644 index 0000000..ca30e8e --- /dev/null +++ b/server/cgi/view.py @@ -0,0 +1,77 @@ +import mariadb as mdb +import json +import os + +from test_list import TestList + +def readfile(path): + if os.path.exists(path): + return open(path).read() + +class View: + def __init__(self, query_args, connector_data = {}): + self.args = query_args + self.connector_data = connector_data + self.db_connection = None + + def get_db_connection(self): + if not self.db_connection: + args = {"host": "127.0.0.1", + "port": 3306, + "user": "root", + "password": "", + "database": "test_holder"} + + settings = json.loads(readfile("cgi/db-settings.json")) + args.update(settings) + + args.update(self.connector_data) + + self.db_connection = mdb.connect(**args) + + return self.db_connection + + def format_page(self, header, subheader, content): + base_layout = readfile("html/base_layout.html") + + base_layout = base_layout.replace("%HEADER%", header) + base_layout = base_layout.replace("%SUBHEADER%", subheader) + base_layout = base_layout.replace("%CONTENT%", content) + + return base_layout + + def render_page(self): + dbc = self.get_db_connection() + cur = dbc.cursor() + + if 'mode' in self.args: + mode = self.args['mode'] + else: + mode = "test-list" + + if mode == "test-list": + cur.execute("SELECT id FROM test;") + test_amount = len(list(cur)) + header = f'

Всього тестів: {test_amount}

' + + subheader = f'
Створити тест' + + content = TestList(cur).render() + + elif mode == "create-test": + header = f"

Створити новий тест" + subheader = "Введіть властивості нового тесту нижче" + + content = f'''
+
+ + +
''' + + else: + header = f"

No such view mode: {mode}

" + subheader = f'Повернутися на головну сторінку' + content = "" + + dbc.close() + return self.format_page(header, subheader, content) diff --git a/server/css/base_style.css b/server/css/base_style.css new file mode 100644 index 0000000..c74a4c7 --- /dev/null +++ b/server/css/base_style.css @@ -0,0 +1,8 @@ +* { + margin: 0; + padding: 0; +} + +html { + width: 100%; +} diff --git a/server/html/base_layout.html b/server/html/base_layout.html new file mode 100644 index 0000000..74a9266 --- /dev/null +++ b/server/html/base_layout.html @@ -0,0 +1,14 @@ + + + %TITLE% + + + +
+
%HEADER%
+
%SUBHEADER%
+
+
+ %CONTENT% +
+ diff --git a/server/httputils.py b/server/httputils.py new file mode 100644 index 0000000..dbbb6ae --- /dev/null +++ b/server/httputils.py @@ -0,0 +1,31 @@ +def decode_url(url): + i = 0 + end = len(url) + + decode_buffer = '' + char_buffer = bytearray() + + while i < end: + if url[i] == '%': + try: + char_buffer.append(int(f'0x{url[i+1:i+3]}', 16)) + decode_buffer += char_buffer.decode("UTF-8") + del char_buffer[:] + i += 3 + except: + i += 3 + else: + decode_buffer += url[i] + i += 1 + + return decode_buffer + +def parse_query(query): + query_items = [i for i in query.split("&") if i] + + query_dict = {} + for i in query_items: + k, v = i.split("=") + query_dict[decode_url(k)] = decode_url(v) + + return query_dict diff --git a/server/index.py b/server/index.py new file mode 100644 index 0000000..6c0e679 --- /dev/null +++ b/server/index.py @@ -0,0 +1,51 @@ +import sys +import os +print(f"PWD: {os.getcwd()}", file=sys.stderr) + +print(f"Environ: {os.environ}", file=sys.stderr) + +sys.path.insert(0, "/root/ipz-server-1/server/cgi/") + +from view import View +from httputils import parse_query +''' +def decode_url(url): + i = 0 + end = len(url) + + decode_buffer = '' + char_buffer = bytearray() + + while i < end: + if url[i] == '%': + try: + char_buffer.append(int(f'0x{url[i+1:i+3]}', 16)) + decode_buffer += char_buffer.decode("UTF-8") + del char_buffer[:] + i += 3 + except: + i += 3 + else: + decode_buffer += url[i] + i += 1 + + return decode_buffer + +query = [i for i in os.environ['QUERY_STRING'].split("&") if i] + +query_dict = {} +for i in query: + k, v = i.split("=") + query_dict[decode_url(k)] = decode_url(v) +''' + +query_dict = parse_query(os.environ['QUERY_STRING']) + +view = View(query_dict) +html_page = view.render_page() +page_length = len(html_page.encode("UTF-8")) + +print(f"Content-Type: text/html; charset=UTF-8\r\n" + \ + f"Content-Length: {page_length}\r\n" + \ + f"\r\n" + \ + f"{html_page}")