mirror of
https://github.com/benbusby/whoogle-search
synced 2024-11-14 18:12:45 +00:00
cb5557cc2e
For pip installed instances of Whoogle, there seems to be an issue where files other than sessions are being stored in the same directory as the sessions. From a brief investigation, this does not seem to be caused by Whoogle, since Flask-Session objects are the only files stored in that directory. It could be an issue with the library that is being used for sessions, however. Regardless, the app shouldn't crash when trying to validate and remove invalid sessions, so a file size limit of 4KB was imposed during validation. Any file found in the session directory that exceeds this size limit will be ignored. Fixes #777 Fixes #793
170 lines
6.2 KiB
Python
170 lines
6.2 KiB
Python
from app.filter import clean_query
|
|
from app.request import send_tor_signal
|
|
from app.utils.session import generate_user_key
|
|
from app.utils.bangs import gen_bangs_json
|
|
from app.utils.misc import gen_file_hash, read_config_bool
|
|
from datetime import datetime, timedelta
|
|
from flask import Flask
|
|
from flask_session import Session
|
|
import json
|
|
import logging.config
|
|
import os
|
|
from stem import Signal
|
|
import threading
|
|
from dotenv import load_dotenv
|
|
|
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
|
|
|
app = Flask(__name__, static_folder=os.path.dirname(
|
|
os.path.abspath(__file__)) + '/static')
|
|
|
|
app.wsgi_app = ProxyFix(app.wsgi_app)
|
|
|
|
# Load .env file if enabled
|
|
if os.getenv('WHOOGLE_DOTENV', ''):
|
|
dotenv_path = '../whoogle.env'
|
|
load_dotenv(os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
|
dotenv_path))
|
|
|
|
# Session values
|
|
# NOTE: SESSION_COOKIE_SAMESITE must be set to 'lax' to allow the user's
|
|
# previous session to persist when accessing the instance from an external
|
|
# link. Setting this value to 'strict' causes Whoogle to revalidate a new
|
|
# session, and fail, resulting in cookies being disabled.
|
|
#
|
|
# This could be re-evaluated if Whoogle ever switches to client side
|
|
# configuration instead.
|
|
app.default_key = generate_user_key()
|
|
app.config['SECRET_KEY'] = os.urandom(32)
|
|
app.config['SESSION_TYPE'] = 'filesystem'
|
|
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
|
|
|
|
if os.getenv('HTTPS_ONLY'):
|
|
app.config['SESSION_COOKIE_NAME'] = '__Secure-session'
|
|
app.config['SESSION_COOKIE_SECURE'] = True
|
|
|
|
app.config['VERSION_NUMBER'] = '0.7.4'
|
|
app.config['APP_ROOT'] = os.getenv(
|
|
'APP_ROOT',
|
|
os.path.dirname(os.path.abspath(__file__)))
|
|
app.config['STATIC_FOLDER'] = os.getenv(
|
|
'STATIC_FOLDER',
|
|
os.path.join(app.config['APP_ROOT'], 'static'))
|
|
app.config['BUILD_FOLDER'] = os.path.join(
|
|
app.config['STATIC_FOLDER'], 'build')
|
|
app.config['CACHE_BUSTING_MAP'] = {}
|
|
app.config['LANGUAGES'] = json.load(open(
|
|
os.path.join(app.config['STATIC_FOLDER'], 'settings/languages.json'),
|
|
encoding='utf-8'))
|
|
app.config['COUNTRIES'] = json.load(open(
|
|
os.path.join(app.config['STATIC_FOLDER'], 'settings/countries.json'),
|
|
encoding='utf-8'))
|
|
app.config['TRANSLATIONS'] = json.load(open(
|
|
os.path.join(app.config['STATIC_FOLDER'], 'settings/translations.json'),
|
|
encoding='utf-8'))
|
|
app.config['THEMES'] = json.load(open(
|
|
os.path.join(app.config['STATIC_FOLDER'], 'settings/themes.json'),
|
|
encoding='utf-8'))
|
|
app.config['HEADER_TABS'] = json.load(open(
|
|
os.path.join(app.config['STATIC_FOLDER'], 'settings/header_tabs.json'),
|
|
encoding='utf-8'))
|
|
app.config['CONFIG_PATH'] = os.getenv(
|
|
'CONFIG_VOLUME',
|
|
os.path.join(app.config['STATIC_FOLDER'], 'config'))
|
|
app.config['DEFAULT_CONFIG'] = os.path.join(
|
|
app.config['CONFIG_PATH'],
|
|
'config.json')
|
|
app.config['CONFIG_DISABLE'] = read_config_bool('WHOOGLE_CONFIG_DISABLE')
|
|
app.config['SESSION_FILE_DIR'] = os.path.join(
|
|
app.config['CONFIG_PATH'],
|
|
'session')
|
|
app.config['MAX_SESSION_SIZE'] = 4000 # Sessions won't exceed 4KB
|
|
app.config['BANG_PATH'] = os.getenv(
|
|
'CONFIG_VOLUME',
|
|
os.path.join(app.config['STATIC_FOLDER'], 'bangs'))
|
|
app.config['BANG_FILE'] = os.path.join(
|
|
app.config['BANG_PATH'],
|
|
'bangs.json')
|
|
|
|
# Config fields that are used to check for updates
|
|
app.config['RELEASES_URL'] = 'https://github.com/' \
|
|
'benbusby/whoogle-search/releases'
|
|
app.config['LAST_UPDATE_CHECK'] = datetime.now() - timedelta(hours=24)
|
|
app.config['HAS_UPDATE'] = ''
|
|
|
|
# The alternative to Google Translate is treated a bit differently than other
|
|
# social media site alternatives, in that it is used for any translation
|
|
# related searches.
|
|
translate_url = os.getenv('WHOOGLE_ALT_TL', 'https://farside.link/lingva')
|
|
if not translate_url.startswith('http'):
|
|
translate_url = 'https://' + translate_url
|
|
app.config['TRANSLATE_URL'] = translate_url
|
|
|
|
app.config['CSP'] = 'default-src \'none\';' \
|
|
'frame-src ' + translate_url + ';' \
|
|
'manifest-src \'self\';' \
|
|
'img-src \'self\' data:;' \
|
|
'style-src \'self\' \'unsafe-inline\';' \
|
|
'script-src \'self\';' \
|
|
'media-src \'self\';' \
|
|
'connect-src \'self\';'
|
|
|
|
if not os.path.exists(app.config['CONFIG_PATH']):
|
|
os.makedirs(app.config['CONFIG_PATH'])
|
|
|
|
if not os.path.exists(app.config['SESSION_FILE_DIR']):
|
|
os.makedirs(app.config['SESSION_FILE_DIR'])
|
|
|
|
# Generate DDG bang filter, and create path if it doesn't exist yet
|
|
if not os.path.exists(app.config['BANG_PATH']):
|
|
os.makedirs(app.config['BANG_PATH'])
|
|
if not os.path.exists(app.config['BANG_FILE']):
|
|
json.dump({}, open(app.config['BANG_FILE'], 'w'))
|
|
bangs_thread = threading.Thread(
|
|
target=gen_bangs_json,
|
|
args=(app.config['BANG_FILE'],))
|
|
bangs_thread.start()
|
|
|
|
# Build new mapping of static files for cache busting
|
|
if not os.path.exists(app.config['BUILD_FOLDER']):
|
|
os.makedirs(app.config['BUILD_FOLDER'])
|
|
|
|
cache_busting_dirs = ['css', 'js']
|
|
for cb_dir in cache_busting_dirs:
|
|
full_cb_dir = os.path.join(app.config['STATIC_FOLDER'], cb_dir)
|
|
for cb_file in os.listdir(full_cb_dir):
|
|
# Create hash from current file state
|
|
full_cb_path = os.path.join(full_cb_dir, cb_file)
|
|
cb_file_link = gen_file_hash(full_cb_dir, cb_file)
|
|
build_path = os.path.join(app.config['BUILD_FOLDER'], cb_file_link)
|
|
|
|
try:
|
|
os.symlink(full_cb_path, build_path)
|
|
except FileExistsError:
|
|
# Symlink hasn't changed, ignore
|
|
pass
|
|
|
|
# Create mapping for relative path urls
|
|
map_path = build_path.replace(app.config['APP_ROOT'], '')
|
|
if map_path.startswith('/'):
|
|
map_path = map_path[1:]
|
|
app.config['CACHE_BUSTING_MAP'][cb_file] = map_path
|
|
|
|
# Templating functions
|
|
app.jinja_env.globals.update(clean_query=clean_query)
|
|
app.jinja_env.globals.update(
|
|
cb_url=lambda f: app.config['CACHE_BUSTING_MAP'][f])
|
|
|
|
Session(app)
|
|
|
|
# Attempt to acquire tor identity, to determine if Tor config is available
|
|
send_tor_signal(Signal.HEARTBEAT)
|
|
|
|
from app import routes # noqa
|
|
|
|
# Disable logging from imported modules
|
|
logging.config.dictConfig({
|
|
'version': 1,
|
|
'disable_existing_loggers': True,
|
|
})
|