Merge remote-tracking branch 'upstream/main' into fix/invalid-token-401
This commit is contained in:
commit
9ed2c592ea
|
@ -410,7 +410,7 @@ Browser settings:
|
|||
2. Go to `Default Results` and click the `Setup fallback results` button. Click `+` and add Whoogle, then drag it to the top.
|
||||
- Chrome/Chromium-based Browsers
|
||||
- Automatic
|
||||
- Visit the home page of your Whoogle Search instance -- this may automatically add the search engine to your list of search engines. If not, you can add it manually.
|
||||
- Visit the home page of your Whoogle Search instance -- this will automatically add the search engine if the [requirements](https://www.chromium.org/tab-to-search/) are met (GET request, no OnSubmit script, no path). If not, you can add it manually.
|
||||
- Manual
|
||||
- Under search engines > manage search engines > add, manually enter your Whoogle instance details with a `<whoogle url>/search?q=%s` formatted search URL.
|
||||
|
||||
|
|
|
@ -2,11 +2,12 @@ from app.models.config import Config
|
|||
from app.models.endpoint import Endpoint
|
||||
from app.models.g_classes import GClasses
|
||||
from app.request import VALID_PARAMS, MAPS_URL
|
||||
from app.utils.misc import read_config_bool
|
||||
from app.utils.misc import get_abs_url, read_config_bool
|
||||
from app.utils.results import *
|
||||
from bs4 import BeautifulSoup
|
||||
from bs4.element import ResultSet, Tag
|
||||
from cryptography.fernet import Fernet
|
||||
import cssutils
|
||||
from flask import render_template
|
||||
import re
|
||||
import urllib.parse as urlparse
|
||||
|
@ -53,17 +54,50 @@ def clean_query(query: str) -> str:
|
|||
return query[:query.find('-site:')] if '-site:' in query else query
|
||||
|
||||
|
||||
def clean_css(css: str, page_url: str) -> str:
|
||||
"""Removes all remote URLs from a CSS string.
|
||||
|
||||
Args:
|
||||
css: The CSS string
|
||||
|
||||
Returns:
|
||||
str: The filtered CSS, with URLs proxied through Whoogle
|
||||
"""
|
||||
sheet = cssutils.parseString(css)
|
||||
urls = cssutils.getUrls(sheet)
|
||||
|
||||
for url in urls:
|
||||
abs_url = get_abs_url(url, page_url)
|
||||
if abs_url.startswith('data:'):
|
||||
continue
|
||||
css = css.replace(
|
||||
url,
|
||||
f'/element?type=image/png&url={abs_url}'
|
||||
)
|
||||
|
||||
return css
|
||||
|
||||
|
||||
class Filter:
|
||||
# Limit used for determining if a result is a "regular" result or a list
|
||||
# type result (such as "people also asked", "related searches", etc)
|
||||
RESULT_CHILD_LIMIT = 7
|
||||
|
||||
def __init__(self, user_key: str, config: Config, mobile=False) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
user_key: str,
|
||||
config: Config,
|
||||
root_url='',
|
||||
page_url='',
|
||||
mobile=False) -> None:
|
||||
self.config = config
|
||||
self.mobile = mobile
|
||||
self.user_key = user_key
|
||||
self.root_url = root_url
|
||||
self.page_url = page_url
|
||||
self.main_divs = ResultSet('')
|
||||
self._elements = 0
|
||||
self._av = set()
|
||||
|
||||
def __getitem__(self, name):
|
||||
return getattr(self, name)
|
||||
|
@ -89,6 +123,7 @@ class Filter:
|
|||
self.remove_block_titles()
|
||||
self.remove_block_url()
|
||||
self.collapse_sections()
|
||||
self.update_css(soup)
|
||||
self.update_styling(soup)
|
||||
self.remove_block_tabs(soup)
|
||||
|
||||
|
@ -264,7 +299,7 @@ class Filter:
|
|||
# enabled
|
||||
parent.decompose()
|
||||
|
||||
def update_element_src(self, element: Tag, mime: str) -> None:
|
||||
def update_element_src(self, element: Tag, mime: str, attr='src') -> None:
|
||||
"""Encrypts the original src of an element and rewrites the element src
|
||||
to use the "/element?src=" pass-through.
|
||||
|
||||
|
@ -272,10 +307,12 @@ class Filter:
|
|||
None (The soup element is modified directly)
|
||||
|
||||
"""
|
||||
src = element['src']
|
||||
src = element[attr].split(' ')[0]
|
||||
|
||||
if src.startswith('//'):
|
||||
src = 'https:' + src
|
||||
elif src.startswith('data:'):
|
||||
return
|
||||
|
||||
if src.startswith(LOGO_URL):
|
||||
# Re-brand with Whoogle logo
|
||||
|
@ -287,9 +324,29 @@ class Filter:
|
|||
element['src'] = BLANK_B64
|
||||
return
|
||||
|
||||
element['src'] = f'{Endpoint.element}?url=' + self.encrypt_path(
|
||||
src,
|
||||
is_element=True) + '&type=' + urlparse.quote(mime)
|
||||
element[attr] = f'{self.root_url}/{Endpoint.element}?url=' + (
|
||||
self.encrypt_path(
|
||||
src,
|
||||
is_element=True
|
||||
) + '&type=' + urlparse.quote(mime)
|
||||
)
|
||||
|
||||
def update_css(self, soup) -> None:
|
||||
"""Updates URLs used in inline styles to be proxied by Whoogle
|
||||
using the /element endpoint.
|
||||
|
||||
Returns:
|
||||
None (The soup element is modified directly)
|
||||
|
||||
"""
|
||||
# Filter all <style> tags
|
||||
for style in soup.find_all('style'):
|
||||
style.string = clean_css(style.string, self.page_url)
|
||||
|
||||
# TODO: Convert remote stylesheets to style tags and proxy all
|
||||
# remote requests
|
||||
# for link in soup.find_all('link', attrs={'rel': 'stylesheet'}):
|
||||
# print(link)
|
||||
|
||||
def update_styling(self, soup) -> None:
|
||||
# Remove unnecessary button(s)
|
||||
|
@ -384,9 +441,12 @@ class Filter:
|
|||
# Strip unneeded arguments
|
||||
link['href'] = filter_link_args(q)
|
||||
|
||||
# Add no-js option
|
||||
if self.config.nojs:
|
||||
append_nojs(link)
|
||||
# Add alternate viewing options for results,
|
||||
# if the result doesn't already have an AV link
|
||||
netloc = urlparse.urlparse(link['href']).netloc
|
||||
if self.config.anon_view and netloc not in self._av:
|
||||
self._av.add(netloc)
|
||||
append_anon_view(link, self.config)
|
||||
|
||||
if self.config.new_tab:
|
||||
link['target'] = '_blank'
|
||||
|
|
|
@ -28,6 +28,7 @@ class Config:
|
|||
self.new_tab = read_config_bool('WHOOGLE_CONFIG_NEW_TAB')
|
||||
self.view_image = read_config_bool('WHOOGLE_CONFIG_VIEW_IMAGE')
|
||||
self.get_only = read_config_bool('WHOOGLE_CONFIG_GET_ONLY')
|
||||
self.anon_view = read_config_bool('WHOOGLE_CONFIG_ANON_VIEW')
|
||||
self.accept_language = False
|
||||
|
||||
self.safe_keys = [
|
||||
|
@ -39,7 +40,9 @@ class Config:
|
|||
'new_tab',
|
||||
'view_image',
|
||||
'block',
|
||||
'safe'
|
||||
'safe',
|
||||
'nojs',
|
||||
'anon_view'
|
||||
]
|
||||
|
||||
# Skip setting custom config if there isn't one
|
||||
|
|
|
@ -16,6 +16,7 @@ from app.models.config import Config
|
|||
from app.models.endpoint import Endpoint
|
||||
from app.request import Request, TorError
|
||||
from app.utils.bangs import resolve_bang
|
||||
from app.filter import Filter
|
||||
from app.utils.misc import read_config_bool, get_client_ip, get_request_url, \
|
||||
check_for_update
|
||||
from app.utils.results import add_ip_card, bold_search_terms,\
|
||||
|
@ -252,7 +253,7 @@ def opensearch():
|
|||
'opensearch.xml',
|
||||
main_url=opensearch_url,
|
||||
request_type='' if get_only else 'method="post"'
|
||||
), 200, {'Content-Disposition': 'attachment; filename="opensearch.xml"'}
|
||||
), 200, {'Content-Type': 'application/xml'}
|
||||
|
||||
|
||||
@app.route(f'/{Endpoint.search_html}', methods=['GET'])
|
||||
|
@ -458,15 +459,16 @@ def imgres():
|
|||
@session_required
|
||||
@auth_required
|
||||
def element():
|
||||
cipher_suite = Fernet(g.session_key)
|
||||
url = request.args.get('url')
|
||||
src_url = ""
|
||||
try:
|
||||
src_url = cipher_suite.decrypt(url.encode()).decode()
|
||||
except (InvalidSignature, InvalidToken) as e:
|
||||
return render_template(
|
||||
'error.html',
|
||||
error_message=str(e)), 401
|
||||
element_url = src_url = request.args.get('url')
|
||||
if element_url.startswith('gAAAAA'):
|
||||
try:
|
||||
cipher_suite = Fernet(g.session_key)
|
||||
src_url = cipher_suite.decrypt(element_url.encode()).decode()
|
||||
print(src_url)
|
||||
except (InvalidSignature, InvalidToken) as e:
|
||||
return render_template(
|
||||
'error.html',
|
||||
error_message=str(e)), 401
|
||||
|
||||
src_type = request.args.get('type')
|
||||
|
||||
|
@ -486,18 +488,62 @@ def element():
|
|||
|
||||
|
||||
@app.route(f'/{Endpoint.window}')
|
||||
@session_required
|
||||
@auth_required
|
||||
def window():
|
||||
get_body = g.user_request.send(base_url=request.args.get('location')).text
|
||||
get_body = get_body.replace('src="/',
|
||||
'src="' + request.args.get('location') + '"')
|
||||
get_body = get_body.replace('href="/',
|
||||
'href="' + request.args.get('location') + '"')
|
||||
target_url = request.args.get('location')
|
||||
if target_url.startswith('gAAAAA'):
|
||||
cipher_suite = Fernet(g.session_key)
|
||||
target_url = cipher_suite.decrypt(target_url.encode()).decode()
|
||||
|
||||
content_filter = Filter(
|
||||
g.session_key,
|
||||
root_url=request.url_root,
|
||||
config=g.user_config)
|
||||
target = urlparse.urlparse(target_url)
|
||||
host_url = f'{target.scheme}://{target.netloc}'
|
||||
|
||||
get_body = g.user_request.send(base_url=target_url).text
|
||||
|
||||
results = bsoup(get_body, 'html.parser')
|
||||
src_attrs = ['src', 'href', 'srcset', 'data-srcset', 'data-src']
|
||||
|
||||
for script in results('script'):
|
||||
script.decompose()
|
||||
# Parse HTML response and replace relative links w/ absolute
|
||||
for element in results.find_all():
|
||||
for attr in src_attrs:
|
||||
if not element.has_attr(attr) or not element[attr].startswith('/'):
|
||||
continue
|
||||
|
||||
element[attr] = host_url + element[attr]
|
||||
|
||||
# Replace or remove javascript sources
|
||||
for script in results.find_all('script', {'src': True}):
|
||||
if 'nojs' in request.args:
|
||||
script.decompose()
|
||||
else:
|
||||
content_filter.update_element_src(script, 'application/javascript')
|
||||
|
||||
# Replace all possible image attributes
|
||||
img_sources = ['src', 'data-src', 'data-srcset', 'srcset']
|
||||
for img in results.find_all('img'):
|
||||
_ = [
|
||||
content_filter.update_element_src(img, 'image/png', attr=_)
|
||||
for _ in img_sources if img.has_attr(_)
|
||||
]
|
||||
|
||||
# Replace all stylesheet sources
|
||||
for link in results.find_all('link', {'href': True}):
|
||||
content_filter.update_element_src(link, 'text/css', attr='href')
|
||||
|
||||
# Use anonymous view for all links on page
|
||||
for a in results.find_all('a', {'href': True}):
|
||||
a['href'] = '/window?location=' + a['href'] + (
|
||||
'&nojs=1' if 'nojs' in request.args else '')
|
||||
|
||||
# Remove all iframes -- these are commonly used inside of <noscript> tags
|
||||
# to enforce loading Google Analytics
|
||||
for iframe in results.find_all('iframe'):
|
||||
iframe.decompose()
|
||||
|
||||
return render_template(
|
||||
'display.html',
|
||||
|
|
|
@ -22,6 +22,11 @@ li {
|
|||
color: var(--whoogle-dark-text) !important;
|
||||
}
|
||||
|
||||
.anon-view {
|
||||
color: var(--whoogle-dark-text) !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
textarea {
|
||||
background: var(--whoogle-dark-page-bg) !important;
|
||||
color: var(--whoogle-dark-text) !important;
|
||||
|
|
|
@ -22,6 +22,11 @@ li {
|
|||
color: var(--whoogle-text) !important;
|
||||
}
|
||||
|
||||
.anon-view {
|
||||
color: var(--whoogle-text) !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
textarea {
|
||||
background: var(--whoogle-page-bg) !important;
|
||||
color: var(--whoogle-text) !important;
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
"config-block-url": "Block by URL",
|
||||
"config-block-url-help": "Use regex",
|
||||
"config-theme": "Theme",
|
||||
"config-nojs": "Show NoJS Links",
|
||||
"config-nojs": "Remove Javascript in Anonymous View",
|
||||
"config-anon-view": "Show Anonymous View Links",
|
||||
"config-dark": "Dark Mode",
|
||||
"config-safe": "Safe Search",
|
||||
"config-alts": "Replace Social Media Links",
|
||||
|
@ -41,7 +42,8 @@
|
|||
"maps": "Maps",
|
||||
"videos": "Videos",
|
||||
"news": "News",
|
||||
"books": "Books"
|
||||
"books": "Books",
|
||||
"anon-view": "Anonymous View"
|
||||
},
|
||||
"lang_nl": {
|
||||
"search": "Zoeken",
|
||||
|
@ -58,7 +60,8 @@
|
|||
"config-block-url": "Blokkeren op URL",
|
||||
"config-block-url-help": "Gebruik regex",
|
||||
"config-theme": "Thema",
|
||||
"config-nojs": "Laat NoJS links zien",
|
||||
"config-nojs": "Javascript verwijderen in anonieme weergave",
|
||||
"config-anon-view": "Toon anonieme links bekijken",
|
||||
"config-dark": "Donkere Modus",
|
||||
"config-safe": "Veilig zoeken",
|
||||
"config-alts": "Social Media Links Vervangen",
|
||||
|
@ -85,7 +88,8 @@
|
|||
"maps": "Maps",
|
||||
"videos": "Videos",
|
||||
"news": "Nieuws",
|
||||
"books": "Boeken"
|
||||
"books": "Boeken",
|
||||
"anon-view": "Anonieme Weergave"
|
||||
},
|
||||
"lang_de": {
|
||||
"search": "Suchen",
|
||||
|
@ -102,7 +106,8 @@
|
|||
"config-block-url": "Nach URL blockieren",
|
||||
"config-block-url-help": "Regex verwenden",
|
||||
"config-theme": "Thema",
|
||||
"config-nojs": "NoJS-Links anzeigen",
|
||||
"config-nojs": "Entfernen Sie Javascript in der anonymen Ansicht",
|
||||
"config-anon-view": "Anonyme Ansichtslinks anzeigen",
|
||||
"config-dark": "Dark Mode",
|
||||
"config-safe": "Sicheres Suchen",
|
||||
"config-alts": "Social-Media-Links ersetzen",
|
||||
|
@ -129,7 +134,8 @@
|
|||
"maps": "Maps",
|
||||
"videos": "Videos",
|
||||
"news": "Nieuws",
|
||||
"books": "Bücher"
|
||||
"books": "Bücher",
|
||||
"anon-view": "Anonyme Ansicht"
|
||||
},
|
||||
"lang_es": {
|
||||
"search": "Buscar",
|
||||
|
@ -146,7 +152,8 @@
|
|||
"config-block-url": "Bloquear por URL",
|
||||
"config-block-url-help": "Usar expresiones regulares",
|
||||
"config-theme": "Tema",
|
||||
"config-nojs": "Mostrar Enlaces NoJS",
|
||||
"config-nojs": "Eliminar Javascript en vista anónima",
|
||||
"config-anon-view": "Mostrar enlaces de vista anónima",
|
||||
"config-dark": "Modo Oscuro",
|
||||
"config-safe": "Búsqueda Segura",
|
||||
"config-alts": "Reemplazar Enlaces de Redes Sociales",
|
||||
|
@ -173,7 +180,8 @@
|
|||
"maps": "Maps",
|
||||
"videos": "Vídeos",
|
||||
"news": "Noticias",
|
||||
"books": "Libros"
|
||||
"books": "Libros",
|
||||
"anon-view": "Vista Anónima"
|
||||
},
|
||||
"lang_it": {
|
||||
"search": "Cerca",
|
||||
|
@ -190,7 +198,8 @@
|
|||
"config-block-url": "Blocca per url",
|
||||
"config-block-url-help": "Usa regex",
|
||||
"config-theme": "Tema",
|
||||
"config-nojs": "Mostra link NoJS",
|
||||
"config-nojs": "Rimuovere Javascript in visualizzazione anonima",
|
||||
"config-anon-view": "Mostra collegamenti di visualizzazione anonimi",
|
||||
"config-dark": "Modalità Notte",
|
||||
"config-safe": "Ricerca Sicura",
|
||||
"config-alts": "Sostituisci link dei social",
|
||||
|
@ -217,7 +226,8 @@
|
|||
"maps": "Maps",
|
||||
"videos": "Video",
|
||||
"news": "Notizie",
|
||||
"books": "Libri"
|
||||
"books": "Libri",
|
||||
"anon-view": "Vista Anonima"
|
||||
},
|
||||
"lang_pt": {
|
||||
"search": "Pesquisar",
|
||||
|
@ -234,7 +244,8 @@
|
|||
"config-block-url": "Bloquear por url",
|
||||
"config-block-url-help": "Use regex",
|
||||
"config-theme": "Tema",
|
||||
"config-nojs": "Mostrar Links NoJS",
|
||||
"config-nojs": "Remover Javascript na visualização anônima",
|
||||
"config-anon-view": "Mostrar links de visualização anônimos",
|
||||
"config-dark": "Modo Escuro",
|
||||
"config-safe": "Pesquisa Segura",
|
||||
"config-alts": "Substituir Links de Redes Sociais",
|
||||
|
@ -261,31 +272,33 @@
|
|||
"maps": "Maps",
|
||||
"videos": "Vídeos",
|
||||
"news": "Notícias",
|
||||
"books": "Livros"
|
||||
"books": "Livros",
|
||||
"anon-view": "Visualização Anônima"
|
||||
},
|
||||
"lang_ru": {
|
||||
"search": "Поиск",
|
||||
"config": "Настройка",
|
||||
"config-country": "Установить страну",
|
||||
"config-country": "Указать страну",
|
||||
"config-lang": "Язык интерфейса",
|
||||
"config-lang-search": "Язык поиска",
|
||||
"config-near": "Около",
|
||||
"config-near-help": "Название города",
|
||||
"config-block": "Блокировать",
|
||||
"config-block-help": "Список сайтов, разделенный запятыми",
|
||||
"config-block-help": "Список сайтов через запятую",
|
||||
"config-block-title": "Блокировать по названию",
|
||||
"config-block-title-help": "Используйте regex",
|
||||
"config-block-url": "Блокировать по URL-адресу",
|
||||
"config-block-url-help": "Используйте regex",
|
||||
"config-theme": "Оформление",
|
||||
"config-nojs": "Показывать ссылки NoJS",
|
||||
"config-dark": "Темный режим",
|
||||
"config-theme": "Тема",
|
||||
"config-nojs": "Удалить Javascript в анонимном просмотре",
|
||||
"config-anon-view": "Показать ссылки для анонимного просмотра",
|
||||
"config-dark": "Тёмный режим",
|
||||
"config-safe": "Безопасный поиск",
|
||||
"config-alts": "Заменить ссылки на социальные сети",
|
||||
"config-alts-help": "Замена ссылкок Twitter, YouTube, Instagram и т.д. на альтернативы, уважающие конфиденциальность.",
|
||||
"config-new-tab": "Открывать ссылки в новой вкладке",
|
||||
"config-images": "Поиск полноразмерных изображений",
|
||||
"config-images-help": "(Экспериментально) Добавляет опцию 'Просмотр изображения' к поиску изображений в ПК-режиме. Это приведет к тому, что миниатюры изображений будут иметь более низкое разрешение.",
|
||||
"config-images-help": "(Эксперимент) Добавляет опцию 'Просмотр изображения' к поиску изображений в ПК-режиме. Это приведет к тому, что миниатюры изображений будут иметь более низкое разрешение.",
|
||||
"config-tor": "Использовать Tor",
|
||||
"config-get-only": "Только GET-запросы",
|
||||
"config-url": "Корневой URL-адрес",
|
||||
|
@ -293,19 +306,20 @@
|
|||
"load": "Загрузить",
|
||||
"apply": "Применить",
|
||||
"save-as": "Сохранить как...",
|
||||
"github-link": "Посмотреть в GitHub",
|
||||
"github-link": "Посмотреть на GitHub",
|
||||
"translate": "перевести",
|
||||
"light": "светлое",
|
||||
"dark": "темное",
|
||||
"system": "системное",
|
||||
"ratelimit": "Число экземпляров ограничено",
|
||||
"continue-search": "Продолжайте поиск с Farside",
|
||||
"light": "светлая",
|
||||
"dark": "тёмная",
|
||||
"system": "системная",
|
||||
"ratelimit": "Инстанс был ограничен по операциям",
|
||||
"continue-search": "Продолжить поиск с Farside",
|
||||
"all": "Все",
|
||||
"images": "Картинки",
|
||||
"maps": "Карты",
|
||||
"videos": "Видео",
|
||||
"news": "Новости",
|
||||
"books": "Книги"
|
||||
"books": "Книги",
|
||||
"anon-view": "Анонимный просмотр"
|
||||
},
|
||||
"lang_zh-CN": {
|
||||
"search": "搜索",
|
||||
|
@ -322,7 +336,8 @@
|
|||
"config-block-url": "按网站链接屏蔽",
|
||||
"config-block-url-help": "使用正则表达式",
|
||||
"config-theme": "主题",
|
||||
"config-nojs": "显示 NoJS 链接",
|
||||
"config-nojs": "在匿名视图中删除 Javascript",
|
||||
"config-anon-view": "显示匿名查看链接",
|
||||
"config-dark": "深色模式",
|
||||
"config-safe": "安全搜索",
|
||||
"config-alts": "替换社交媒体链接",
|
||||
|
@ -349,7 +364,8 @@
|
|||
"maps": "地圖",
|
||||
"videos": "影片",
|
||||
"news": "新聞",
|
||||
"books": "書籍"
|
||||
"books": "書籍",
|
||||
"anon-view": "匿名视图"
|
||||
},
|
||||
"lang_si": {
|
||||
"search": "සොයන්න",
|
||||
|
@ -366,7 +382,8 @@
|
|||
"config-block-url": "ඒ.ස.නි. මඟින් අවහිර කරන්න",
|
||||
"config-block-url-help": "රෙජෙක්ස් භාවිතා කරන්න",
|
||||
"config-theme": "තේමාව",
|
||||
"config-nojs": "නෝජේඑස් සබැඳි පෙන්වන්න",
|
||||
"config-nojs": "Anonymous View හි Javascript ඉවත් කරන්න",
|
||||
"config-anon-view": "නිර්නාමික බලන්න සබැඳි පෙන්වන්න",
|
||||
"config-dark": "අඳුරු ආකාරය",
|
||||
"config-safe": "ආරක්ෂිත සෙවුම",
|
||||
"config-alts": "සමාජ මාධ්ය සබැඳි ප්රතිස්ථාපනය කරන්න",
|
||||
|
@ -393,7 +410,8 @@
|
|||
"maps": "සිතියම්",
|
||||
"videos": "වීඩියෝ",
|
||||
"news": "අනුරූප",
|
||||
"books": "පොත්"
|
||||
"books": "පොත්",
|
||||
"anon-view": "නිර්නාමික දසුන"
|
||||
},
|
||||
"lang_fr": {
|
||||
"search": "Chercher",
|
||||
|
@ -410,7 +428,8 @@
|
|||
"config-block-url": "Bloquer par URL",
|
||||
"config-block-url-help": "Utiliser l'expression régulière",
|
||||
"config-theme": "Theme",
|
||||
"config-nojs": "Montrer les liens NoJS",
|
||||
"config-nojs": "Supprimer Javascript dans la vue anonyme",
|
||||
"config-anon-view": "Afficher les liens de vue anonymes",
|
||||
"config-dark": "Mode Sombre",
|
||||
"config-safe": "Recherche sécurisée",
|
||||
"config-alts": "Remplacer les liens des réseaux sociaux",
|
||||
|
@ -437,7 +456,8 @@
|
|||
"maps": "Maps",
|
||||
"videos": "Vidéos",
|
||||
"news": "Actualités",
|
||||
"books": "Livres"
|
||||
"books": "Livres",
|
||||
"anon-view": "Vue anonyme"
|
||||
},
|
||||
"lang_fa": {
|
||||
"search": "جستجو",
|
||||
|
@ -454,7 +474,8 @@
|
|||
"config-block-url": "بلوک بر اساس URL",
|
||||
"config-block-url-help": "از عبارت منظم استفاده کنید",
|
||||
"config-theme": "پوسته",
|
||||
"config-nojs": "نمایش پیوندهای بدون جاوا اسکیریپت",
|
||||
"config-nojs": "جاوا اسکریپت را در نمای ناشناس حذف کنید",
|
||||
"config-anon-view": "نمایش پیوندهای مشاهده ناشناس",
|
||||
"config-dark": "حالت تاریک",
|
||||
"config-safe": "جستجوی امن",
|
||||
"config-alts": "جایگزینی پیوندهای شبکههای اجتماعی",
|
||||
|
@ -481,7 +502,8 @@
|
|||
"maps": "نقشهها",
|
||||
"videos": "ویدئوها",
|
||||
"news": "اخبار",
|
||||
"books": "کتابها"
|
||||
"books": "کتابها",
|
||||
"anon-view": "نمای ناشناس"
|
||||
},
|
||||
"lang_cs": {
|
||||
"search": "Hledat",
|
||||
|
@ -498,7 +520,8 @@
|
|||
"config-block-url": "Blokovat podle adresy URL",
|
||||
"config-block-url-help": "Použijte regulární výraz",
|
||||
"config-theme": "Motiv",
|
||||
"config-nojs": "Zobrazit NoJS odkazy",
|
||||
"config-nojs": "Odeberte Javascript v anonymním zobrazení",
|
||||
"config-anon-view": "Zobrazit odkazy anonymního zobrazení",
|
||||
"config-dark": "Tmavý motiv",
|
||||
"config-safe": "Bezpečné vyhledávání",
|
||||
"config-alts": "Nahradit odkazy na sociální média",
|
||||
|
@ -525,7 +548,8 @@
|
|||
"maps": "Mapy",
|
||||
"videos": "Videa",
|
||||
"news": "Zprávy",
|
||||
"books": "Knihy"
|
||||
"books": "Knihy",
|
||||
"anon-view": "Anonymní pohled"
|
||||
},
|
||||
"lang_zh-TW": {
|
||||
"search": "搜尋",
|
||||
|
@ -542,7 +566,8 @@
|
|||
"config-block-url": "按網址屏蔽",
|
||||
"config-block-url-help": "使用正則表達式",
|
||||
"config-theme": "主題",
|
||||
"config-nojs": "顯示 NoJS 連結",
|
||||
"config-nojs": "在匿名視圖中刪除 Javascript",
|
||||
"config-anon-view": "顯示匿名查看鏈接",
|
||||
"config-dark": "深色模式",
|
||||
"config-safe": "安全搜尋",
|
||||
"config-alts": "將社群網站連結換掉",
|
||||
|
@ -569,7 +594,8 @@
|
|||
"maps": "地圖",
|
||||
"videos": "影片",
|
||||
"news": "新聞",
|
||||
"books": "書籍"
|
||||
"books": "書籍",
|
||||
"anon-view": "匿名視圖"
|
||||
},
|
||||
"lang_bg": {
|
||||
"search": "Търсене",
|
||||
|
@ -586,7 +612,8 @@
|
|||
"config-block-url": "Блокиране по url",
|
||||
"config-block-url-help": "Използвайте регулярно изражение",
|
||||
"config-theme": "Стил",
|
||||
"config-nojs": "Показване на връзки без JS",
|
||||
"config-nojs": "Премахнете Javascript в анонимен изглед",
|
||||
"config-anon-view": "Показване на анонимни връзки за преглед",
|
||||
"config-dark": "Тъмен режим",
|
||||
"config-safe": "Безопасно търсене",
|
||||
"config-alts": "Заменете връзките към социалните медии",
|
||||
|
@ -613,7 +640,8 @@
|
|||
"maps": "Видеоклипове",
|
||||
"videos": "Новини",
|
||||
"news": "Карти",
|
||||
"books": "Книги"
|
||||
"books": "Книги",
|
||||
"anon-view": "Анонимен изглед"
|
||||
},
|
||||
"lang_hi": {
|
||||
"search": "खोज",
|
||||
|
@ -630,7 +658,8 @@
|
|||
"config-block-url": "url द्वारा अवरोधित करें",
|
||||
"config-block-url-help": "रेगेक्स का प्रयोग करें",
|
||||
"config-theme": "विषय",
|
||||
"config-nojs": "NoJS लिंक दिखाएं",
|
||||
"config-nojs": "अनाम दृश्य में जावास्क्रिप्ट निकालें",
|
||||
"config-anon-view": "बेनामी देखें लिंक दिखाएं",
|
||||
"config-dark": "डार्क मोड",
|
||||
"config-safe": "सुरक्षित खोज",
|
||||
"config-alts": "सोशल मीडिया लिंक बदलें",
|
||||
|
@ -657,7 +686,8 @@
|
|||
"maps": "वीडियो",
|
||||
"videos": "मैप",
|
||||
"news": "समाचार",
|
||||
"books": "किताबें"
|
||||
"books": "किताबें",
|
||||
"anon-view": "अनाम दृश्य"
|
||||
},
|
||||
"lang_ja": {
|
||||
"search": "検索",
|
||||
|
@ -674,7 +704,8 @@
|
|||
"config-block-url": "でブロック",
|
||||
"config-block-url-help": "正規表現を使用",
|
||||
"config-theme": "テーマ",
|
||||
"config-nojs": "非JSリンクを表示",
|
||||
"config-nojs": "匿名ビューでJavascriptを削除する",
|
||||
"config-anon-view": "匿名のビューリンクを表示する",
|
||||
"config-dark": "ダークモード",
|
||||
"config-safe": "セーフサーチ",
|
||||
"config-alts": "ソーシャルメディアのリンクを置き換え",
|
||||
|
@ -701,7 +732,8 @@
|
|||
"maps": "地図",
|
||||
"videos": "動画",
|
||||
"news": "ニュース",
|
||||
"books": "書籍"
|
||||
"books": "書籍",
|
||||
"anon-view": "匿名ビュー"
|
||||
},
|
||||
"lang_ko": {
|
||||
"search": "검색",
|
||||
|
@ -718,7 +750,8 @@
|
|||
"config-block-url": "URL로 차단",
|
||||
"config-block-url-help": "정규 표현식 사용",
|
||||
"config-theme": "테마",
|
||||
"config-nojs": "Show NoJS Links",
|
||||
"config-nojs": "익명 보기에서 Javascript 제거",
|
||||
"config-anon-view": "익명 보기 링크 표시",
|
||||
"config-dark": "다크 모드",
|
||||
"config-safe": "세이프서치",
|
||||
"config-alts": "소설 미디어 주소 수정",
|
||||
|
@ -745,6 +778,7 @@
|
|||
"maps": "지도",
|
||||
"videos": "동영상",
|
||||
"news": "뉴스",
|
||||
"books": "도서"
|
||||
"books": "도서",
|
||||
"anon-view": "익명 보기"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,6 +148,10 @@
|
|||
<input type="text" name="block_url" id="config-block"
|
||||
placeholder="{{ translation['config-block-url-help'] }}" value="{{ config.block_url }}">
|
||||
</div>
|
||||
<div class="config-div config-div-anon-view">
|
||||
<label for="config-anon-view">{{ translation['config-anon-view'] }}: </label>
|
||||
<input type="checkbox" name="anon_view" id="config-anon-view" {{ 'checked' if config.anon_view else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-nojs">
|
||||
<label for="config-nojs">{{ translation['config-nojs'] }}: </label>
|
||||
<input type="checkbox" name="nojs" id="config-nojs" {{ 'checked' if config.nojs else '' }}>
|
||||
|
|
|
@ -3,6 +3,7 @@ from flask import Request
|
|||
import hashlib
|
||||
import os
|
||||
from requests import exceptions, get
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
||||
def gen_file_hash(path: str, static_file: str) -> str:
|
||||
|
@ -47,3 +48,14 @@ def check_for_update(version_url: str, current: str) -> int:
|
|||
has_update = ''
|
||||
|
||||
return has_update
|
||||
|
||||
|
||||
def get_abs_url(url, page_url):
|
||||
# Creates a valid absolute URL using a partial or relative URL
|
||||
if url.startswith('//'):
|
||||
return f'https:{url}'
|
||||
elif url.startswith('/'):
|
||||
return f'{urlparse(page_url).netloc}{url}'
|
||||
elif url.startswith('./'):
|
||||
return f'{page_url}{url[2:]}'
|
||||
return url
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
from app.models.config import Config
|
||||
from app.models.endpoint import Endpoint
|
||||
from bs4 import BeautifulSoup, NavigableString
|
||||
import copy
|
||||
from flask import current_app
|
||||
import html
|
||||
import os
|
||||
import urllib.parse as urlparse
|
||||
|
@ -183,11 +185,35 @@ def append_nojs(result: BeautifulSoup) -> None:
|
|||
|
||||
"""
|
||||
nojs_link = BeautifulSoup(features='html.parser').new_tag('a')
|
||||
nojs_link['href'] = f'/{Endpoint.window}?location=' + result['href']
|
||||
nojs_link['href'] = f'/{Endpoint.window}?nojs=1&location=' + result['href']
|
||||
nojs_link.string = ' NoJS Link'
|
||||
result.append(nojs_link)
|
||||
|
||||
|
||||
def append_anon_view(result: BeautifulSoup, config: Config) -> None:
|
||||
"""Appends an 'anonymous view' for a search result, where all site
|
||||
contents are viewed through Whoogle as a proxy.
|
||||
|
||||
Args:
|
||||
result: The search result to append an anon view link to
|
||||
nojs: Remove Javascript from Anonymous View
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
"""
|
||||
av_link = BeautifulSoup(features='html.parser').new_tag('a')
|
||||
nojs = 'nojs=1' if config.nojs else 'nojs=0'
|
||||
location = f'location={result["href"]}'
|
||||
av_link['href'] = f'/{Endpoint.window}?{nojs}&{location}'
|
||||
translation = current_app.config['TRANSLATIONS'][
|
||||
config.get_localization_lang()
|
||||
]
|
||||
av_link.string = f'{translation["config-anon-view"]}'
|
||||
av_link['class'] = 'anon-view'
|
||||
result.append(av_link)
|
||||
|
||||
|
||||
def add_ip_card(html_soup: BeautifulSoup, ip: str) -> BeautifulSoup:
|
||||
"""Adds the client's IP address to the search results
|
||||
if query contains keywords
|
||||
|
|
|
@ -56,6 +56,7 @@ class Search:
|
|||
"""
|
||||
def __init__(self, request, config, session_key, cookies_disabled=False):
|
||||
method = request.method
|
||||
self.request = request
|
||||
self.request_params = request.args if method == 'GET' else request.form
|
||||
self.user_agent = request.headers.get('User-Agent')
|
||||
self.feeling_lucky = False
|
||||
|
@ -115,6 +116,7 @@ class Search:
|
|||
mobile = 'Android' in self.user_agent or 'iPhone' in self.user_agent
|
||||
|
||||
content_filter = Filter(self.session_key,
|
||||
root_url=self.request.url_root,
|
||||
mobile=mobile,
|
||||
config=self.config)
|
||||
full_query = gen_query(self.query,
|
||||
|
|
|
@ -6,6 +6,7 @@ cffi==1.15.0
|
|||
chardet==3.0.4
|
||||
click==8.0.3
|
||||
cryptography==3.3.2
|
||||
cssutils==2.4.0
|
||||
defusedxml==0.7.1
|
||||
Flask==1.1.1
|
||||
Flask-Session==0.4.0
|
||||
|
|
Loading…
Reference in New Issue
Block a user