Merge remote-tracking branch 'upstream/main' into fix/invalid-token-401

This commit is contained in:
Ben Busby 2022-04-18 12:59:13 -06:00
commit 9ed2c592ea
No known key found for this signature in database
GPG Key ID: B9B7231E01D924A1
12 changed files with 273 additions and 75 deletions

View File

@ -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.

View File

@ -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'

View File

@ -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

View File

@ -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',

View File

@ -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;

View File

@ -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;

View File

@ -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": "익명 보기"
}
}

View File

@ -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 '' }}>

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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