import os
-from http.server import BaseHTTPRequestHandler
+from http.server import BaseHTTPRequestHandler
+from http.cookies import SimpleCookie
+import json
class PlomException(Exception):
return
# collect modification times of numbered .bak files
+ # print('DEBUG BACKUP')
bak_prefix = f'{self.db_file}.bak.'
- backup_dates = []
- i = 0
- bak_as = f'{bak_prefix}{i}'
- while os.path.exists(bak_as):
- mod_time = os.path.getmtime(bak_as)
- backup_dates += [str(datetime.fromtimestamp(mod_time))]
- i += 1
- bak_as = f'{bak_prefix}{i}'
+ # backup_dates = []
+ mtimes_to_paths = {}
+ for path in [path for path in os.listdir(os.path.dirname(bak_prefix))
+ if path.startswith(os.path.basename(bak_prefix))]:
+ path = os.path.dirname(bak_prefix) + f'/{path}'
+ mod_time = os.path.getmtime(path)
+ # print(f'DEBUG pre-exists: {path} {mod_time}')
+ mtimes_to_paths[str(datetime.fromtimestamp(mod_time))] = path
+
+ # for mtime in sorted(mtimes_to_paths.keys()):
+ # print(f'DEBUG mtimes_to_paths: {mtime}:{mtimes_to_paths[mtime]}')
# collect what numbered .bak files to save: the older, the fewer; for each
# timedelta, keep the newest file that's older
ages_to_keep = [timedelta(minutes=4**i) for i in range(0, 8)]
- now = datetime.now()
- to_save = []
+ # print(f'DEBUG ages_to_keep: {ages_to_keep}')
+ now = datetime.now()
+ to_save = {}
for age in ages_to_keep:
- limit = now - age
- for i, date in enumerate(reversed(backup_dates)):
- if datetime.strptime(date, '%Y-%m-%d %H:%M:%S.%f') < limit:
- unreversed_i = len(backup_dates) - i - 1
- if unreversed_i not in to_save:
- to_save += [unreversed_i]
+ limit = now - age
+ for mtime in reversed(sorted(mtimes_to_paths.keys())):
+ # print(f'DEBUG checking if {mtime} < {limit} ({now} - {age})')
+ if len(mtime) < 20:
+ mtime_test = mtime + '.000000'
+ else:
+ mtime_test = mtime
+ if datetime.strptime(mtime_test, '%Y-%m-%d %H:%M:%S.%f') < limit:
+ # print('DEBUG it is, adding!')
+ to_save[mtime] = mtimes_to_paths[mtime]
break
- # remove redundant backup files
- j = 0
- for i in to_save:
- if i != j:
- source = f'{bak_prefix}{i}'
- target = f'{bak_prefix}{j}'
+ for path in [path for path in mtimes_to_paths.values()
+ if path not in to_save.values()]:
+ # print(f'DEBUG removing {path} cause not in to_save')
+ os.remove(path)
+
+ i = 0
+ for mtime in sorted(to_save.keys()):
+ source = to_save[mtime]
+ target = f'{bak_prefix}{i}'
+ # print(f'DEBUG to_save {source} -> {target}')
+ if source != target:
shutil.move(source, target)
- j += 1
- for i in range(j, len(backup_dates)):
- try:
- os.remove(f'{bak_prefix}{i}')
- except FileNotFoundError:
- pass
+ i += 1
- # put copy of current state at end of bak list
- shutil.copy(self.db_file, f'{bak_prefix}{j}')
+ # put copy of current state at end of bak list
+ # print(f'DEBUG saving current state to {bak_prefix}{i}')
+ shutil.copy(self.db_file, f'{bak_prefix}{i}')
def write_text_to_db(self, text, mode='w'):
self.lock()
self.unlock()
-class PlomHandler(BaseHTTPRequestHandler):
+class PlomHandler(BaseHTTPRequestHandler):
homepage = '/'
html_head = '<!DOCTYPE html>\n<html>\n<meta charset="UTF-8">'
html_foot = '</body>\n</html>'
-
+
def fail_400(self, e):
self.send_HTML(f'ERROR: {e}', 400)
self.send_code_and_headers(code, [('Content-type', 'text/html')])
self.wfile.write(bytes(f'{self.html_head}\n{html}\n{self.html_foot}', 'utf-8'))
+ def ensure_cookies_to_set(self):
+ if not hasattr(self, 'cookies_to_set'):
+ self.cookies_to_set = []
+
+ def set_cookie(self, cookie_name, cookie_path, cookie_db):
+ self.ensure_cookies_to_set()
+ cookie = SimpleCookie()
+ cookie[cookie_name] = json.dumps(cookie_db)
+ cookie[cookie_name]['path'] = cookie_path
+ self.cookies_to_set += [cookie]
+
+ def unset_cookie(self, cookie_name, cookie_path):
+ self.ensure_cookies_to_set()
+ cookie = SimpleCookie()
+ cookie[cookie_name] = ''
+ cookie[cookie_name]['path'] = cookie_path
+ cookie[cookie_name]['expires'] = 'Thu, 01 Jan 1970 00:00:00 GMT'
+ self.cookies_to_set += [cookie]
+
+ def get_cookie_db(self, cookie_name):
+ cookie_db = {}
+ if 'Cookie' in self.headers:
+ cookie = SimpleCookie(self.headers['Cookie'])
+ if cookie_name in cookie:
+ cookie_db = json.loads(cookie[cookie_name].value)
+ return cookie_db
+
def send_code_and_headers(self, code, headers=[]):
+ self.ensure_cookies_to_set()
self.send_response(code)
+ for cookie in self.cookies_to_set:
+ for morsel in cookie.values():
+ self.send_header('Set-Cookie', morsel.OutputString())
for fieldname, content in headers:
self.send_header(fieldname, content)
self.end_headers()
def try_do(self, do_method):
try:
- do_method()
+ do_method()
except PlomException as e:
self.fail_400(e)