From 8bece6d545494963b2cd7afe13d83a792a9cb7f2 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 30 Dec 2024 10:11:04 +0000 Subject: [PATCH 1/8] prompt for weblog password --- CHANGELOG.md | 4 ++++ jinjafx_server.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eaa254a..fce4742 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## CHANGELOG +### [25.1.1] - In Development +- Prompt for weblog password if it isn't provided + ### [25.1.0] - Dec 29, 2024 - Added support for nested templates within `template.j2` using Jinja2 include syntax - Added support for encrypted DataTemplates using Vaulty (ChaCha20-Poly1305 encryption) @@ -365,6 +368,7 @@ - Initial release +[25.1.1]: https://github.com/cmason3/jinjafx_server/compare/25.1.0...25.1.1 [25.1.0]: https://github.com/cmason3/jinjafx_server/compare/24.12.1...25.1.0 [24.12.1]: https://github.com/cmason3/jinjafx_server/compare/24.12.0...24.12.1 [24.12.0]: https://github.com/cmason3/jinjafx_server/compare/24.10.1...24.12.0 diff --git a/jinjafx_server.py b/jinjafx_server.py index 35cb5e3..2fe0f88 100755 --- a/jinjafx_server.py +++ b/jinjafx_server.py @@ -28,7 +28,7 @@ import re, argparse, hashlib, traceback, glob, hmac, uuid, struct, binascii, gzip, requests, ctypes, subprocess import cmarkgfm, emoji -__version__ = '25.1.0' +__version__ = '25.1.1' llock = threading.RLock() rlock = threading.RLock() From 96099dd4a9f25ac7d55a8a5a0ef24891e7623229 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Tue, 31 Dec 2024 09:53:48 +0000 Subject: [PATCH 2/8] prompt for weblog password --- jinjafx_server.py | 111 +++++++++++++++++++++++++++----------------- www/jinjafx_logs.js | 24 ++++++++++ www/logs.html | 22 ++++++++- 3 files changed, 113 insertions(+), 44 deletions(-) diff --git a/jinjafx_server.py b/jinjafx_server.py index 2fe0f88..6e06623 100755 --- a/jinjafx_server.py +++ b/jinjafx_server.py @@ -19,9 +19,9 @@ if sys.version_info < (3, 9): sys.exit('Requires Python >= 3.9') -from http.cookies import SimpleCookie +#from http.cookies import SimpleCookie from http.server import HTTPServer, BaseHTTPRequestHandler -from urllib.parse import urlparse, parse_qs +#from urllib.parse import urlparse, parse_qs from jinja2 import __version__ as jinja2_version import jinjafx, os, io, socket, signal, threading, yaml, json, base64, time, datetime, resource @@ -217,55 +217,80 @@ def do_GET(self, head=False, cache=True, versioned=False): r = [ 'text/plain', 200, 'OK\r\n'.encode('utf-8'), sys._getframe().f_lineno ] elif fpath == '/logs' and jfx_weblog_key is not None: - qs = parse_qs(urlparse(self.path).query, keep_blank_values=True) - key = None + fpath = '/logs.html' - if 'key' in qs: - for kv in qs['key']: - self.path = self.path.replace('key=' + kv, 'key=*') + elif fpath == '/get_logs' and jfx_weblog_key is not None: + if hasattr(self, 'headers') and 'X-WebLog-Password' in self.headers: + if self.headers['X-WebLog-Password'] == jfx_weblog_key: + with llock: + logs = '\r\n'.join(logring) + + logs = logs.replace('&', '&').replace('<', '<').replace('>', '>') + logs = logs.replace('\033[1;31m', '') + logs = logs.replace('\033[1;32m', '') + logs = logs.replace('\033[1;33m', '') + logs = logs.replace('\033[0m', '') + r = [ 'text/plain', 200, logs.encode('utf-8'), sys._getframe().f_lineno ] - key = qs['key'][-1] + else: + if not self.ratelimit(remote_addr, 3, False): + r = [ 'text/plain', 401, '401 Unauthorized\r\n'.encode('utf-8'), sys._getframe().f_lineno ] + else: + r = [ 'text/plain', 429, '429 Too Many Requests\r\n'.encode('utf-8'), sys._getframe().f_lineno ] - elif hasattr(self, 'headers'): - cookies = SimpleCookie(self.headers.get('Cookie')) - if 'jfx_weblog_key' in cookies: - key = cookies['jfx_weblog_key'].value + else: + r = [ 'text/plain', 401, '401 Unauthorized\r\n'.encode('utf-8'), sys._getframe().f_lineno ] - if key == jfx_weblog_key: - if 'key' in qs: - cheaders['Set-Cookie'] = 'jfx_weblog_key=' + key + '; path=/logs' - if 'raw' in qs: - cheaders['Location'] = '/logs?raw' - else: - cheaders['Location'] = '/logs' - r = [ 'text/plain', 302, '302 Found\r\n'.encode('utf-8'), sys._getframe().f_lineno ] - else: - if not self.ratelimit(remote_addr, 3, True): - if 'raw' in qs: - with llock: - logs = '\r\n'.join(logring) - - logs = logs.replace('&', '&').replace('<', '<').replace('>', '>') - logs = logs.replace('\033[1;31m', '') - logs = logs.replace('\033[1;32m', '') - logs = logs.replace('\033[1;33m', '') - logs = logs.replace('\033[0m', '') - r = [ 'text/plain', 200, logs.encode('utf-8'), sys._getframe().f_lineno ] +# qs = parse_qs(urlparse(self.path).query, keep_blank_values=True) +# key = None - else: - with open(base + '/www/logs.html', 'rb') as f: - r = [ 'text/html', 200, f.read(), sys._getframe().f_lineno ] +# if 'key' in qs: +# for kv in qs['key']: +# self.path = self.path.replace('key=' + kv, 'key=*') - else: - r = [ 'text/plain', 429, '429 Too Many Requests\r\n'.encode('utf-8'), sys._getframe().f_lineno ] +# key = qs['key'][-1] - else: - cheaders['Set-Cookie'] = 'jfx_weblog_key=; path=/logs; max-age=0' - if not self.ratelimit(remote_addr, 3, False): - r = [ 'text/plain', 401, '401 Unauthorized\r\n'.encode('utf-8'), sys._getframe().f_lineno ] - else: - r = [ 'text/plain', 429, '429 Too Many Requests\r\n'.encode('utf-8'), sys._getframe().f_lineno ] +# elif hasattr(self, 'headers'): +# cookies = SimpleCookie(self.headers.get('Cookie')) +# if 'jfx_weblog_key' in cookies: +# key = cookies['jfx_weblog_key'].value + +# if key == jfx_weblog_key: +# if 'key' in qs: +# cheaders['Set-Cookie'] = 'jfx_weblog_key=' + key + '; path=/logs' +# if 'raw' in qs: +# cheaders['Location'] = '/logs?raw' +# else: +# cheaders['Location'] = '/logs' +# r = [ 'text/plain', 302, '302 Found\r\n'.encode('utf-8'), sys._getframe().f_lineno ] + +# else: +# if not self.ratelimit(remote_addr, 3, True): +# if 'raw' in qs: +# with llock: +# logs = '\r\n'.join(logring) + +# logs = logs.replace('&', '&').replace('<', '<').replace('>', '>') +# logs = logs.replace('\033[1;31m', '') +# logs = logs.replace('\033[1;32m', '') +# logs = logs.replace('\033[1;33m', '') +# logs = logs.replace('\033[0m', '') +# r = [ 'text/plain', 200, logs.encode('utf-8'), sys._getframe().f_lineno ] + +# else: +# with open(base + '/www/logs.html', 'rb') as f: +# r = [ 'text/html', 200, f.read(), sys._getframe().f_lineno ] + +# else: +# r = [ 'text/plain', 429, '429 Too Many Requests\r\n'.encode('utf-8'), sys._getframe().f_lineno ] + +# else: +# cheaders['Set-Cookie'] = 'jfx_weblog_key=; path=/logs; max-age=0' +# if not self.ratelimit(remote_addr, 3, False): +# r = [ 'text/plain', 401, '401 Unauthorized\r\n'.encode('utf-8'), sys._getframe().f_lineno ] +# else: +# r = [ 'text/plain', 429, '429 Too Many Requests\r\n'.encode('utf-8'), sys._getframe().f_lineno ] else: if fpath == '/': diff --git a/www/jinjafx_logs.js b/www/jinjafx_logs.js index 1b027df..5fe548e 100644 --- a/www/jinjafx_logs.js +++ b/www/jinjafx_logs.js @@ -16,7 +16,13 @@ scroll(); setTimeout(update, interval * 1000); } + else if (this.status == 401) { + new bootstrap.Modal(document.getElementById('password_input'), { + keyboard: false + }).show(); + } else { + alert("eek"); document.getElementById('container').innerHTML = 'HTTP ERROR ' + this.status; } }; @@ -35,6 +41,24 @@ xHR.send(); } + document.getElementById('password_input').addEventListener('shown.bs.modal', function (e) { + document.getElementById("in_password").focus(); + }); + + document.getElementById('password_input').addEventListener('hidden.bs.modal', function (e) { + document.getElementById("in_password").value = ''; + }); + + document.getElementById('in_password').onkeyup = function(e) { + if (e.which == 13) { + document.getElementById('ml-password-ok').click(); + } + }; + + document.getElementById('ml-password-ok').onclick = function() { + window.location.search = '?' + document.getElementById("in_password").value; + }; + window.onresize = scroll; window.onload = function() { update(); diff --git a/www/logs.html b/www/logs.html index 6f6d729..c23eee0 100644 --- a/www/logs.html +++ b/www/logs.html @@ -8,9 +8,29 @@ - + +

+    
   
 

From 63c3a2df1786b9f757ecb5585122aadab22f3861 Mon Sep 17 00:00:00 2001
From: Chris Mason 
Date: Tue, 31 Dec 2024 16:46:18 +0000
Subject: [PATCH 3/8] prompt for weblog password

---
 jinjafx_server.py    |  7 +++---
 www/jinjafx_logs.css |  2 +-
 www/jinjafx_logs.js  | 51 +++++++++++++++++++++++++++-----------------
 www/logs.html        |  6 +++---
 4 files changed, 39 insertions(+), 27 deletions(-)

diff --git a/jinjafx_server.py b/jinjafx_server.py
index 6e06623..a730326 100755
--- a/jinjafx_server.py
+++ b/jinjafx_server.py
@@ -91,12 +91,12 @@ def log_message(self, format, *args):
         else:
           ansi = '31'
 
-        if (args[1] != '204' and args[1] != '404' and args[1] != '501' and not path.startswith('/output.html') and not '/dt/' in path and (not path.startswith('/logs') or (args[1] != '200' and args[1] != '304'))) or self.critical or verbose:
+        if (args[1] != '204' and args[1] != '404' and args[1] != '501' and not path.startswith('/output.html') and not '/dt/' in path and (path != '/get_logs' or (args[1] != '200' and args[1] != '304'))) or self.critical or verbose:
           src = str(self.client_address[0])
           proto_ver = ''
           ctype = ''
 
-          if path.startswith('/logs') and args[1] == '302':
+          if path == '/get_logs' and args[1] == '302':
             ansi = '32'
 
           if hasattr(self, 'headers'):
@@ -217,7 +217,8 @@ def do_GET(self, head=False, cache=True, versioned=False):
         r = [ 'text/plain', 200, 'OK\r\n'.encode('utf-8'), sys._getframe().f_lineno ]
 
       elif fpath == '/logs' and jfx_weblog_key is not None:
-        fpath = '/logs.html'
+        with open(base + '/www/logs.html', 'rb') as f:
+          r = [ 'text/html', 200, f.read(), sys._getframe().f_lineno ]
 
       elif fpath == '/get_logs' and jfx_weblog_key is not None:
         if hasattr(self, 'headers') and 'X-WebLog-Password' in self.headers:
diff --git a/www/jinjafx_logs.css b/www/jinjafx_logs.css
index 53d5024..6cd0a1c 100644
--- a/www/jinjafx_logs.css
+++ b/www/jinjafx_logs.css
@@ -1,8 +1,8 @@
 body {
-  color: white;
   background: #000040;
 }
 pre {
+  color: white;
   height: 100%;
   font-variant-ligatures: none;
   white-space: pre-wrap;
diff --git a/www/jinjafx_logs.js b/www/jinjafx_logs.js
index 5fe548e..ad890bb 100644
--- a/www/jinjafx_logs.js
+++ b/www/jinjafx_logs.js
@@ -1,5 +1,6 @@
 (function() {
   let interval = 60;
+  let key = '';
 
   function scroll() {
     let e = document.getElementById('container');
@@ -8,10 +9,11 @@
 
   function update() {
     var xHR = new XMLHttpRequest();
-    xHR.open("GET", '/logs?raw', true);
+    xHR.open("GET", '/get_logs', true);
 
     xHR.onload = function() {
       if (this.status == 200) {
+        sessionStorage.setItem('jfx_weblog_key', key);
         document.getElementById('container').innerHTML = xHR.responseText;
         scroll();
         setTimeout(update, interval * 1000);
@@ -22,7 +24,6 @@
         }).show();
       }
       else {
-        alert("eek");
         document.getElementById('container').innerHTML = 'HTTP ERROR ' + this.status;
       }
     };
@@ -38,29 +39,39 @@
     };
 
     xHR.timeout = 3000;
+    xHR.setRequestHeader("X-WebLog-Password", key);
     xHR.send();
   }
 
-  document.getElementById('password_input').addEventListener('shown.bs.modal', function (e) {
-    document.getElementById("in_password").focus();
-  });
+  window.onresize = scroll;
+  window.onload = function() {
+    document.getElementById('password_input').addEventListener('shown.bs.modal', function (e) {
+      document.getElementById("in_password").focus();
+    });
+  
+    document.getElementById('password_input').addEventListener('hidden.bs.modal', function (e) {
+      document.getElementById("in_password").value = '';
+    });
+  
+    document.getElementById('ml-password-ok').addEventListener('click', function (e) {
+      key = document.getElementById("in_password").value;
+      update();
+    });
 
-  document.getElementById('password_input').addEventListener('hidden.bs.modal', function (e) {
-    document.getElementById("in_password").value = '';
-  });
+    document.getElementById('in_password').addEventListener('keyup', function(e) {
+      if (e.which == 13) {
+        document.getElementById('ml-password-ok').click();
+      }
+    });
 
-  document.getElementById('in_password').onkeyup = function(e) {
-    if (e.which == 13) {
-      document.getElementById('ml-password-ok').click();
+    if (sessionStorage.getItem('jfx_weblog_key')) {
+      key = sessionStorage.getItem('jfx_weblog_key');
+      update();
+    }
+    else {
+      new bootstrap.Modal(document.getElementById('password_input'), {
+        keyboard: false
+      }).show();
     }
-  };
-
-  document.getElementById('ml-password-ok').onclick = function() {
-    window.location.search = '?' + document.getElementById("in_password").value;
-  };  
-
-  window.onresize = scroll;
-  window.onload = function() {
-    update();
   };
 })();
diff --git a/www/logs.html b/www/logs.html
index c23eee0..e274f16 100644
--- a/www/logs.html
+++ b/www/logs.html
@@ -7,9 +7,9 @@
     
     
     
-    
+    
     
-    
+    
   
   
     

@@ -17,7 +17,7 @@