Show client IP for "my ip" searches (#469)

This introduces a new UI element for displaying the client IP
address when a search for "my ip" is used.

Note that this does not show the IP address seen by Google
if Whoogle is deployed remotely. It uses `request.remote_addr`
to display the client IP address in the UI, not the actual address
of the server (which is what Google sees in requests sent from
remote Whoogle instances).
main
Vansh Comar 2021-10-21 22:12:31 +05:30 committed by GitHub
parent aff7b6c72f
commit 771bf34ce9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 10 deletions

View File

@ -8,17 +8,18 @@ import uuid
from functools import wraps from functools import wraps
import waitress import waitress
from flask import jsonify, make_response, request, redirect, render_template, \
send_file, session, url_for
from requests import exceptions
from app import app from app import app
from app.models.config import Config from app.models.config import Config
from app.request import Request, TorError from app.request import Request, TorError
from app.utils.bangs import resolve_bang from app.utils.bangs import resolve_bang
from app.utils.misc import read_config_bool from app.utils.misc import read_config_bool
from app.utils.session import generate_user_key, valid_user_session from app.utils.results import add_ip_card
from app.utils.search import * from app.utils.search import *
from app.utils.session import generate_user_key, valid_user_session
from bs4 import BeautifulSoup as bsoup
from flask import jsonify, make_response, request, redirect, render_template, \
send_file, session, url_for
from requests import exceptions
# Load DDG bang json files only on init # Load DDG bang json files only on init
bang_json = json.load(open(app.config['BANG_FILE'])) bang_json = json.load(open(app.config['BANG_FILE']))
@ -250,6 +251,11 @@ def search():
# Return 503 if temporarily blocked by captcha # Return 503 if temporarily blocked by captcha
resp_code = 503 if has_captcha(str(response)) else 200 resp_code = 503 if has_captcha(str(response)) else 200
# Feature to display IP address
if search_util.check_kw_ip():
html_soup = bsoup(response, "html.parser")
response = add_ip_card(html_soup, request.remote_addr)
return render_template( return render_template(
'display.html', 'display.html',
query=urlparse.unquote(query), query=urlparse.unquote(query),
@ -275,7 +281,8 @@ def search():
query=urlparse.unquote(query), query=urlparse.unquote(query),
search_type=search_util.search_type, search_type=search_util.search_type,
mobile=g.user_request.mobile) mobile=g.user_request.mobile)
if 'isch' not in search_util.search_type else '')), resp_code if 'isch' not in
search_util.search_type else '')), resp_code
@app.route('/config', methods=['GET', 'POST', 'PUT']) @app.route('/config', methods=['GET', 'POST', 'PUT'])

View File

@ -186,3 +186,7 @@ path {
.search-bar-desktop { .search-bar-desktop {
color: var(--whoogle-dark-text) !important; color: var(--whoogle-dark-text) !important;
} }
.ip-text-div{
color: var(--whoogle-dark-secondary-text) !important;
}

View File

@ -174,3 +174,7 @@ path {
color: var(--whoogle-text); color: var(--whoogle-text);
border-bottom: 0px; border-bottom: 0px;
} }
.ip-text-div{
color: var(--whoogle-secondary-text) !important;
}

View File

@ -31,3 +31,11 @@ details summary {
height: 650px; height: 650px;
border: 0; border: 0;
} }
.ip-address-div {
padding-bottom: 0 !important;
}
.ip-text-div {
padding-top: 0 !important;
}

View File

@ -138,3 +138,45 @@ def append_nojs(result: BeautifulSoup) -> None:
nojs_link.string = 'NoJS Link: ' + nojs_link['href'] nojs_link.string = 'NoJS Link: ' + nojs_link['href']
result.append(BeautifulSoup('<br><hr><br>', 'html.parser')) result.append(BeautifulSoup('<br><hr><br>', 'html.parser'))
result.append(nojs_link) result.append(nojs_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
Args:
html_soup: The parsed search result containing the keywords
ip: ip address of the client
Returns:
BeautifulSoup
"""
if (not html_soup.select_one(".EY24We")
and html_soup.select_one(".OXXup").get_text().lower() == "all"):
# HTML IP card tag
ip_tag = html_soup.new_tag("div")
ip_tag["class"] = "ZINbbc xpd O9g5cc uUPGi"
# For IP Address html tag
ip_address = html_soup.new_tag("div")
ip_address["class"] = "kCrYT ip-address-div"
ip_address.string = ip
# Text below the IP address
ip_text = html_soup.new_tag("div")
ip_text.string = "Your public IP address"
ip_text["class"] = "kCrYT ip-text-div"
# Adding all the above html tags to the IP card
ip_tag.append(ip_address)
ip_tag.append(ip_text)
# Finding the element before which the IP card would be placed
f_link = html_soup.select_one(".BNeawe.vvjwJb.AP7Wnd")
ref_element = f_link.find_parent(class_="ZINbbc xpd O9g5cc" +
" uUPGi")
# Inserting the element
ref_element.insert_before(ip_tag)
return html_soup

View File

@ -1,12 +1,12 @@
import os import os
import re
from typing import Any from typing import Any
from bs4 import BeautifulSoup as bsoup
from cryptography.fernet import Fernet, InvalidToken
from flask import g
from app.filter import Filter, get_first_link from app.filter import Filter, get_first_link
from app.request import gen_query from app.request import gen_query
from bs4 import BeautifulSoup as bsoup
from cryptography.fernet import Fernet, InvalidToken
from flask import g
TOR_BANNER = '<hr><h1 style="text-align: center">You are using Tor</h1><hr>' TOR_BANNER = '<hr><h1 style="text-align: center">You are using Tor</h1><hr>'
CAPTCHA = 'div class="g-recaptcha"' CAPTCHA = 'div class="g-recaptcha"'
@ -54,6 +54,7 @@ class Search:
config: the current user config settings config: the current user config settings
session: the flask user session session: the flask user session
""" """
def __init__(self, request, config, session, cookies_disabled=False): def __init__(self, request, config, session, cookies_disabled=False):
method = request.method method = request.method
self.request_params = request.args if method == 'GET' else request.form self.request_params = request.args if method == 'GET' else request.form
@ -161,3 +162,14 @@ class Search:
link['href'] += param_str link['href'] += param_str
return str(formatted_results) return str(formatted_results)
def check_kw_ip(self) -> re.Match:
"""Checks for keywords related to 'my ip' in the query
Returns:
bool
"""
return re.search("([^a-z0-9]|^)my *[^a-z0-9] *(ip|internet protocol)" +
"($|( *[^a-z0-9] *(((addres|address|adres|" +
"adress)|a)? *$)))", self.query.lower())