see TODO.md
This commit is contained in:
@@ -668,3 +668,8 @@ fabric.properties
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
|
||||
|
||||
## ENVIRONMENT
|
||||
|
||||
.env
|
||||
@@ -11,17 +11,19 @@
|
||||
## To implement:
|
||||
|
||||
things not yet implemented in the program
|
||||
NOTE: That things which are in italic text are already implemented!
|
||||
|
||||
### url filtering:
|
||||
- [ ] block external URL in strict mode (eg a link with href to some porn site or something)
|
||||
- [ ] allow relative paths:
|
||||
- eg "/path/to/my/awesome/post.html"
|
||||
- [ ] apply to any of these:
|
||||
- a
|
||||
- img
|
||||
- link href
|
||||
- [ ] add custom attribute filter function
|
||||
|
||||
- *[x] block external URL in strict mode (eg a link with href to some porn site or something)*
|
||||
- *[x] allow relative paths:*
|
||||
*- eg "/path/to/my/awesome/post.html"*
|
||||
- *[x] apply to any of these:*
|
||||
- *a*
|
||||
- *img*
|
||||
- *link href*
|
||||
- *[x] add custom attribute filter function*
|
||||
- [] load dotenv (chore for profiles.py) ; do this someday when implementing JSON configs. Or dotenv stuff : PRIO:HIGH
|
||||
---
|
||||
|
||||
### Expland strict mode:
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# src/log/Logger.py
|
||||
# AGPL-3.0 - saningi-html
|
||||
# usage:
|
||||
# insantiate using logger = Logger()
|
||||
# import using import .log.Logger
|
||||
#
|
||||
#
|
||||
|
||||
import time
|
||||
import sys
|
||||
import colorama
|
||||
|
||||
colorama.init(autoreset=True)
|
||||
|
||||
class Logger:
|
||||
@staticmethod
|
||||
def _now() -> str:
|
||||
return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||
|
||||
@staticmethod
|
||||
def log_error(message: str) -> None:
|
||||
print(f"{colorama.Fore.RED}[ ERROR@{Logger._now()} ]: {message}", file=sys.stderr)
|
||||
|
||||
@staticmethod
|
||||
def log_info(message: str) -> None:
|
||||
print(f"{colorama.Fore.CYAN}[ INFO@{Logger._now()} ]: {message}", file=sys.stderr)
|
||||
|
||||
@staticmethod
|
||||
def log_debug(message: str) -> None:
|
||||
print(f"[ DEBUG@{Logger._now()} ]: {message}", file=sys.stderr)
|
||||
|
||||
@staticmethod
|
||||
def log_warning(message: str) -> None:
|
||||
print(f"{colorama.Fore.YELLOW}[ WARNING@{Logger._now()} ]: {message}", file=sys.stderr)
|
||||
+8
-25
@@ -1,30 +1,13 @@
|
||||
#
|
||||
# src/profiles.py
|
||||
# AGPL-3 - saningi-html
|
||||
#
|
||||
# entrypoint
|
||||
#
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import bleach
|
||||
from profiles import STRICT, LOOSE
|
||||
|
||||
PROFILES = {
|
||||
"strict": STRICT,
|
||||
"loose": LOOSE,
|
||||
}
|
||||
|
||||
def sanitize(html : str, mode : str) -> str:
|
||||
# this should be used with caution! it is for trusted
|
||||
# individuals only
|
||||
if mode == "passthrough":
|
||||
return html
|
||||
|
||||
config = PROFILES.get(mode)
|
||||
if not config:
|
||||
raise ValueError(f"Unknown mode! : {mode}")
|
||||
|
||||
return bleach.clean(
|
||||
html,
|
||||
tags=config["tags"],
|
||||
attributes=config["attributes"],
|
||||
protocols=config["protocols"],
|
||||
strip=config["strip"],
|
||||
)
|
||||
from sanitizer import sanitize
|
||||
|
||||
def entry():
|
||||
parser = argparse.ArgumentParser(description="saningi-html sanitizer")
|
||||
|
||||
+49
-1
@@ -4,6 +4,49 @@
|
||||
#
|
||||
# presets for sanitization of HTML
|
||||
#
|
||||
import re
|
||||
from dotenv import dotenv_values
|
||||
from urllib.parse import urlparse
|
||||
|
||||
def is_safe_url(url : str, allowed_domain=None, allow_relative : bool = True) -> bool:
|
||||
"""
|
||||
Determine wether or not a URL is safe or not.
|
||||
Safe URL's are only local so /this/url
|
||||
Unsafe URL's are external ones like https://pornhub.com
|
||||
"""
|
||||
if not url:
|
||||
return False
|
||||
|
||||
if allow_relative:
|
||||
if url.startswith(("#", "/", "./", "../")):
|
||||
return True
|
||||
|
||||
if url.startswith("//"):
|
||||
if not allowed_domain:
|
||||
return False
|
||||
|
||||
parsed = urlparse("http:" + url)
|
||||
domain = parsed.netloc or parsed.path.split("/")[0]
|
||||
return domain in allowed_domain
|
||||
|
||||
parsed = urlparse(url)
|
||||
if parsed.scheme in ("http", "https"):
|
||||
if not allowed_domain:
|
||||
return False
|
||||
return parsed.netloc in allowed_domain
|
||||
|
||||
return False
|
||||
|
||||
def create_url_filter(allowed_attrs, allowed_domains=None, allow_relative=True):
|
||||
def filter_func(tag, name, value):
|
||||
if name not in allowed_attrs:
|
||||
return None
|
||||
if name in ('href', 'src'):
|
||||
if is_safe_url(value, allowed_domains, allow_relative):
|
||||
return value
|
||||
return None
|
||||
return value
|
||||
return filter_func
|
||||
|
||||
STRICT = {
|
||||
"tags" : [
|
||||
@@ -12,7 +55,12 @@ STRICT = {
|
||||
"br", "hr",
|
||||
"h1", "h2", "h3", "h4", "h5", "h6"
|
||||
],
|
||||
"attributes": {},
|
||||
"attributes": {
|
||||
# TODO: add loading dotenv variables
|
||||
"a": create_url_filter(["href"], allowed_domains=[], allow_relative=True),
|
||||
"img" : create_url_filter(["src", "alt"], allowed_domains=[], allow_relative=True),
|
||||
"link" : create_url_filter(["href"], allowed_domains=[], allow_relative=True),
|
||||
},
|
||||
"protocols": [],
|
||||
"strip": True,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import bleach
|
||||
from profiles import STRICT, LOOSE
|
||||
from log.Logger import *
|
||||
logger = Logger()
|
||||
|
||||
PROFILES = {
|
||||
"strict": STRICT,
|
||||
"loose": LOOSE,
|
||||
}
|
||||
|
||||
def sanitize(html : str, mode : str) -> str:
|
||||
# this should be used with caution! it is for trusted
|
||||
# individuals only
|
||||
if mode == "passthrough":
|
||||
return html
|
||||
|
||||
config = PROFILES.get(mode)
|
||||
if not config:
|
||||
raise ValueError(f"Unknown mode! : {mode}")
|
||||
|
||||
logger.log_debug(
|
||||
"called sanitizer! using this as args: \n" +
|
||||
str(html) +
|
||||
str(config["tags"]) + "\n" +
|
||||
str(config["protocols"]) + "\n" +
|
||||
str(config["strip"])
|
||||
)
|
||||
|
||||
return bleach.clean(
|
||||
html,
|
||||
tags=config["tags"],
|
||||
attributes=config["attributes"],
|
||||
protocols=config["protocols"],
|
||||
strip=config["strip"],
|
||||
)
|
||||
Reference in New Issue
Block a user