Compare commits

...

50 Commits

Author SHA1 Message Date
Fijxu 4bbd44cb35 Merge remote-tracking branch 'librey/main' into librey
lolxdxdxddddddddddddddddddddddddddddddddddddddd
2023-08-29 21:38:06 -04:00
Ahwx 8f9b9803f2
fix: vuln within image parsing (merge pull request #31 from codedipper/nibH3YzJ)
irresponsible disclosure
2023-08-29 20:17:24 +02:00
Revvy 33240c4d21 fix high-severity vulnerability 2023-08-29 14:07:50 -04:00
Ahwx 3b23c4d099
fix: docker attributes variable format (merge pull request #30 from nohoster/patch-1)
Fix variable format.
2023-08-29 19:46:40 +02:00
Ahwx d64ce8f4dd
fix: unable to create organisation package (merge pull request #29 from BluenationStudio/main)
fix unable to create organization package
2023-08-29 19:45:02 +02:00
nohoster a2f94fb0ca
Fix variable format.
The format was wrong, it had a misplaced "}". It should be fine now.
2023-08-29 14:04:15 +00:00
Jakub Doboš 1330453370
fix unable to create organization package 2023-08-29 10:09:18 +02:00
Ahwx 1c4e9eafde
feat: adding docker stuff (merge pull request #24 from BluenationStudio/main)
Start building docker images from the repo on ghcr
2023-08-29 10:00:17 +02:00
Ahwx 79e61a792b
feat: adding librex.nohost.network (merge pull request #28 from nohoster/main)
Updated my instance to LibreY
2023-08-29 09:58:58 +02:00
nohoster 08bb5b5d49
Update instances.json 2023-08-29 01:53:33 +00:00
nohoster da95ec8c9e
Update README.md 2023-08-29 01:51:35 +00:00
Ahwx 07588b7d73
feat: adding instance & fix: formatting (merge pull request #27 from codedipper/main)
add instance, fix formatting
2023-08-29 01:16:50 +02:00
Revvy 304c3738cc add instances, fix formatting 2023-08-28 18:46:29 -04:00
Ahwx 7f61a54141
fix: some padding (merge pull request #26 from osarthak/update)
fixed active sub-search-button, did-you-mean, small footer
2023-08-29 00:35:38 +02:00
osarthak e6c0bfda33 fixed sub-search-button border padding, did-you-mean on mobile, smaller footer 2023-08-27 15:55:17 +05:30
Jakub Doboš 06ee3f06e8 build docker image 2023-08-27 00:04:26 +02:00
Ahwx 3ae47a1cfc
feat: load balancing and cooldowns (merge pull request #19 from davidovski/load_balancing)
Load balancing and Cooldowns
2023-08-26 11:06:24 +02:00
davidovski 98707900bf Fix language config variable not working 2023-08-26 00:42:44 +01:00
davidovski a87b78095f Fix missing quote in docker build script 2023-08-25 23:15:17 +01:00
davidovski ccc0d78dee Fixed incorrect use of function_exists 2023-08-25 19:09:06 +01:00
davidovski 11e11192a4 Do not persist if apcu is not installed 2023-08-25 19:03:11 +01:00
davidovski 8bae58c2b2 Add php8-apcu to dependencies 2023-08-25 18:06:12 +01:00
davidovski b8047b2982 add default for request_cooldown 2023-08-25 17:53:59 +01:00
davidovski 039e549d4c Change default timeout to 25 minutes 2023-08-25 17:48:45 +01:00
davidovski f50022f780 added request cooldowns for google 2023-08-25 17:39:08 +01:00
davidovski 0fd041a353 Add timeouts for failing instances 2023-08-25 16:23:53 +01:00
Ahwx 2c36d28a2f
refactor(*): everything (merge pull request #18 from davidovski/the_refactor)
Major Refactor
2023-08-25 14:45:49 +02:00
davidovski a7d1836eff Fixed fallback not occuring when special result 2023-08-25 11:36:19 +01:00
davidovski 723887bfc0 Fix typo in variable name for instances 2023-08-25 00:12:19 +01:00
davidovski 04e0183d79 Fix missing arg error 2023-08-25 00:10:03 +01:00
davidovski 036b10efe7 Add hl back into google query 2023-08-25 00:03:12 +01:00
davidovski 508ac0c576 Use cookie frontend over config frontend 2023-08-24 15:45:45 +01:00
davidovski 5ce0f2ccd0 fix video and image search 2023-08-24 03:57:11 +01:00
davidovski 1b694e0882 Fix frontends being parsed from config 2023-08-23 10:55:51 +01:00
davidovski 8ede57f4f4 fix issue with not actually using duckduckgo 2023-08-23 02:32:47 +01:00
davidovski 1e15006067 Remove duplicate nfb parameter 2023-08-23 00:54:10 +01:00
davidovski 14cdccb83f add theme to query parameter 2023-08-23 00:51:23 +01:00
davidovski 1b898c6614 fallback on all queries 2023-08-23 00:46:21 +01:00
davidovski 649b0065e3 make some options editable via url parameters 2023-08-23 00:46:21 +01:00
davidovski b3693add93 use correct parameter for search query 2023-08-23 00:46:21 +01:00
davidovski 89c957e92c Make settings.php use opts 2023-08-23 00:46:21 +01:00
davidovski 6c253bcb47 put all settings in single "opts" array 2023-08-23 00:46:21 +01:00
davidovski 4941a6aa58 use engine request for torrent search 2023-08-23 00:46:21 +01:00
davidovski 0bd726d897 moved files 2023-08-23 00:46:21 +01:00
davidovski f4a80135bd ensure url remaisn the same when switching types 2023-08-23 00:46:21 +01:00
davidovski 34fdaac058 use same logic for search and api 2023-08-23 00:46:21 +01:00
davidovski 19627c94c9 add bittorrent and tor to be enginerequest types 2023-08-23 00:46:21 +01:00
davidovski 74da63dab2 Make search categories type of request 2023-08-23 00:46:21 +01:00
davidovski f59f94fdd5 include different print and fetch functions for search 2023-08-23 00:46:21 +01:00
davidovski fd93a0e154 Add EngineRequest class 2023-08-23 00:46:21 +01:00
42 changed files with 1302 additions and 1410 deletions

31
.github/workflows/docker-image.yml vendored Normal file
View File

@ -0,0 +1,31 @@
name: Docker Image CI
on:
push:
branches: [ "main" ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
permissions: write-all
steps:
- uses: actions/checkout@v3
- uses: docker/login-action@v2.1.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: owner
uses: ASzc/change-string-case-action@v5
with:
string: ${{ github.repository_owner }}
- id: repo
uses: ASzc/change-string-case-action@v5
with:
string: ${{ github.event.repository.name }}
- uses: docker/build-push-action@v4
with:
context: .
file: Dockerfile
push: true
tags: |
ghcr.io/${{ steps.owner.outputs.lowercase }}/${{ steps.repo.outputs.lowercase }}:latest

View File

@ -25,13 +25,14 @@ You can access the full list of LibreX and LibreY instances on one of the follow
| [librex.me](https://librex.me/) | [](http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/) | [](http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/) | 🇨🇦 CA |
| [librex.revvy.de](https://librex.revvy.de/) | [](http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/) | [](http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/) | 🇨🇦 CA |
| [search.davidovski.xyz](https://search.davidovski.xyz/) | ❌ | ❌ | 🇬🇧 GB |
| [librey.nohost.network](https://librey.nohost.network/) | ❌ | ❌ | 🇲🇽 MX |
<br>
### About LibreY
LibreY gives you text results from DuckDuckGo or Google, images from Qwant, and torrents from i.e. Ahmia and popular torrent sites without spying on you.
<br>LibreY doesn't save any type of data about the user, there are no logs (except NGINX logs if the host sets them), no caches.
<br>LibreY doesn't save **any** type of data about the user, there are no logs (except NGINX logs if the host sets them).
### LibreY compared to other metasearch engines

56
api.php
View File

@ -1,9 +1,10 @@
<?php
$config = require "config.php";
require "misc/tools.php";
require "misc/search_engine.php";
if (!isset($_REQUEST["q"]))
{
$opts = load_opts();
if (!$opts->query) {
echo "<p>Example API request: <a href=\"./api.php?q=gentoo&p=2&t=0\">./api.php?q=gentoo&p=2&t=0</a></p>
<br/>
<p>\"q\" is the keyword</p>
@ -16,54 +17,7 @@
die();
}
$query = $_REQUEST["q"];
$query_encoded = urlencode($query);
$page = isset($_REQUEST["p"]) ? (int) $_REQUEST["p"] : 0;
$type = isset($_REQUEST["t"]) ? (int) $_REQUEST["t"] : 0;
$results = array();
switch ($type)
{
case 0:
$engine=$config->preferred_engines['text'];
if (is_null($engine))
$engine = "google";
require "engines/$engine/text.php";
$results = get_text_results($query, $page);
break;
case 1:
require "engines/qwant/image.php";
$results = get_image_results($query_encoded, $page);
break;
case 2:
require "engines/invidious/video.php";
$results = get_video_results($query_encoded);
break;
case 3:
if ($config->disable_bittorent_search)
$results = array("error" => "disabled");
else
{
require "engines/bittorrent/merge.php";
$results = get_merged_torrent_results($query_encoded);
}
break;
case 4:
if ($config->disable_hidden_service_search)
$results = array("error" => "disabled");
else
{
require "engines/ahmia/hidden_service.php";
$results = get_hidden_service_results($query_encoded);
}
break;
default:
require "engines/google/text.php";
$results = get_text_results($query_encoded, $page);
break;
}
$results = fetch_search_results($opts, false);
header("Content-Type: application/json");
echo json_encode($results);
?>

View File

@ -4,13 +4,9 @@
// e.g.: fr -> https://google.fr/
"google_domain" => "com",
// Google results will be in this language
"google_language_site" => "",
"google_language_results" => "",
"google_number_of_results" => 10,
// You can set a language for results in wikipedia
"wikipedia_language" => "en",
// Results will be in this language
"language" => "",
"number_of_results" => 10,
// You can use any Invidious instance here
"invidious_instance_for_video_results" => "https://invidious.snopyta.org",
@ -21,7 +17,11 @@
"disable_hidden_service_search" => false,
// Fallback to another librex instance if google search fails
"instance_fallback" => false, // This might generate a 504 Gateway Timeout error, we are looking into this.
// This may greatly increase the time it takes to get a result, if a direct search is not possible
"instance_fallback" => true,
// how long in minutes to put google/other instances on cooldown if they aren't responding
"request_cooldown" => 25,
/*
Preset privacy friendly frontends for users, these can be overwritten by users in the settings
@ -31,74 +31,74 @@
"frontends" => array(
"invidious" => array(
"instance_url" => "",
"project_url" => "https://docs.invidious.io/instances/",
"project_url" => "https://docs.invidious.io/instances/",
"original_name" => "YouTube",
"original_url" => "youtube.com"
),
"rimgo" => array(
"instance_url" => "",
"project_url" => "https://codeberg.org/video-prize-ranch/rimgo#instances",
"project_url" => "https://codeberg.org/video-prize-ranch/rimgo#instances",
"original_name" => "Imgur",
"original_url" => "imgur.com"
),
"scribe" => array(
"instance_url" => "",
"project_url" => "https://git.sr.ht/~edwardloveall/scribe/tree/main/docs/instances.md",
"project_url" => "https://git.sr.ht/~edwardloveall/scribe/tree/main/docs/instances.md",
"original_name" => "Medium",
"original_url" => "medium.com"
),
"gothub" => array(
"instance_url" => "",
"project_url" => "https://codeberg.org/gothub/gothub#instances",
"project_url" => "https://codeberg.org/gothub/gothub#instances",
"original_name" => "GitHub",
"original_url" => "github.com"
),
"nitter" => array(
"instance_url" => "",
"project_url" => "https://github.com/zedeus/nitter/wiki/Instances",
"project_url" => "https://github.com/zedeus/nitter/wiki/Instances",
"original_name" => "Twitter",
"original_url" => "twitter.com"
),
"libreddit" => array(
"instance_url" => "",
"project_url" => "https://github.com/libreddit/libreddit-instances/blob/master/instances.md",
"project_url" => "https://github.com/libreddit/libreddit-instances/blob/master/instances.md",
"original_name" => "Reddit",
"original_url" => "reddit.com"
),
"proxitok" => array(
"instance_url" => "",
"project_url" => "https://github.com/pablouser1/ProxiTok/wiki/Public-instances",
"project_url" => "https://github.com/pablouser1/ProxiTok/wiki/Public-instances",
"original_name" => "TikTok",
"original_url" => "tiktok.com"
),
"wikiless" => array(
"instance_url" => "",
"project_url" => "https://github.com/Metastem/wikiless#instances",
"project_url" => "https://github.com/Metastem/wikiless#instances",
"original_name" => "Wikipedia",
"original_url" => "wikipedia.org"
),
"quetre" => array(
"instance_url" => "",
"project_url" => "https://github.com/zyachel/quetre#instances",
"project_url" => "https://github.com/zyachel/quetre#instances",
"original_name" => "Quora",
"original_url" => "quora.com"
),
"libremdb" => array(
"instance_url" => "",
"project_url" => "https://github.com/zyachel/libremdb#instances",
"project_url" => "https://github.com/zyachel/libremdb#instances",
"original_name" => "IMDb",
"original_url" => "imdb.com"
),
"breezewiki" => array(
"instance_url" => "",
"project_url" => "https://docs.breezewiki.com/Links.html",
"project_url" => "https://docs.breezewiki.com/Links.html",
"original_name" => "Fandom",
"original_url" => "fandom.com"
),
"anonymousoverflow" => array(
"instance_url" => "",
"project_url" => "https://github.com/httpjamesm/AnonymousOverflow#clearnet-instances",
"project_url" => "https://github.com/httpjamesm/AnonymousOverflow#clearnet-instances",
"original_name" => "StackOverflow",
"original_url" => "stackoverflow.com"
),
@ -115,10 +115,10 @@
"original_url" => "goodreads.com"
)
),
"preferred_engines" => array(
/* replace with "text" => "duckduckgo" to use duckduckgo instead
* (recommended if being ratelimited */
"text" => "google"
@ -150,8 +150,9 @@
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS | CURLPROTO_HTTP,
CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTPS | CURLPROTO_HTTP,
CURLOPT_MAXREDIRS => 5,
CURLOPT_TIMEOUT => 18,
CURLOPT_VERBOSE => false
CURLOPT_TIMEOUT => 3,
CURLOPT_VERBOSE => false,
CURLOPT_FOLLOWLOCATION => true
)
);
?>

View File

@ -23,7 +23,7 @@ export CONFIG_GOOGLE_DOMAIN="${CONFIG_GOOGLE_DOMAIN:-"com"}"
export CONFIG_GOOGLE_LANGUAGE_SITE="${CONFIG_GOOGLE_LANGUAGE_SITE:-"en"}"
export CONFIG_GOOGLE_LANGUAGE_RESULTS="${CONFIG_GOOGLE_LANGUAGE_RESULTS:-"en"}"
export CONFIG_GOOGLE_NUMBER_OF_RESULTS="${CONFIG_GOOGLE_NUMBER_OF_RESULTS:-"10"}"
export CONFIG_INSTANCE_FALLBACK="${CONFIG_INSTANCE_FALLBACK}:-true}
export CONFIG_INSTANCE_FALLBACK="${CONFIG_INSTANCE_FALLBACK:-true}"
export CONFIG_INVIDIOUS_INSTANCE="${CONFIG_INVIDIOUS_INSTANCE:-"invidious.snopyta.org"}"
export CONFIG_HIDDEN_SERVICE_SEARCH=${CONFIG_HIDDEN_SERVICE_SEARCH:-false}
export CONFIG_DISABLE_BITTORRENT_SEARCH=${CONFIG_DISABLE_BITTORRENT_SEARCH:-false}

View File

@ -56,7 +56,7 @@ ENV CURLOPT_VERBOSE=true
# Install PHP-FPM using Alpine's package manager, apk
# Configure PHP-FPM to listen on a Unix socket instead of a TCP port, which is more secure and efficient
RUN apk add php8 php8-fpm php8-dom php8-curl php8-json --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing &&\
RUN apk add php8 php8-fpm php8-dom php8-curl php8-json php8-apcu --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing &&\
sed -i 's/^\s*listen = 127.0.0.1:9000/listen = \/run\/php8\/php-fpm8.sock/' ${WWW_CONFIG} &&\
sed -i 's/^\s*;\s*listen.owner = nobody/listen.owner = nginx/' ${WWW_CONFIG} &&\
sed -i 's/^\s*;\s*listen.group = nobody/listen.group = nginx/' ${WWW_CONFIG} &&\

View File

@ -1,53 +1,40 @@
<?php
function get_hidden_service_results($query)
{
global $config;
require "engines/text/text.php";
$url = "https://ahmia.fi/search/?q=$query";
$response = request($url);
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//ol[@class='searchResults']//li[@class='result']") as $result)
{
$url = "http://" . $xpath->evaluate(".//cite", $result)[0]->textContent;
$title = remove_special($xpath->evaluate(".//h4", $result)[0]->textContent);
$description = $xpath->evaluate(".//p", $result)[0]->textContent;
array_push($results,
array (
"title" => $title ? htmlspecialchars($title) : "No description provided",
"url" => htmlspecialchars($url),
"base_url" => htmlspecialchars(get_base_url($url)),
"description" => htmlspecialchars($description)
)
);
class TorSearch extends EngineRequest {
public function get_request_url() {
return "https://ahmia.fi/search/?q=" . urlencode($this->query);
}
return $results;
}
public function get_results() {
$response = curl_multi_getcontent($this->ch);
$results = array();
$xpath = get_xpath($response);
function print_hidden_service_results($results)
{
echo "<div class=\"text-result-container\">";
if (!$xpath)
return $results;
foreach($results as $result)
{
$title = $result["title"];
$url = $result["url"];
$base_url = $result["base_url"];
$description = $result["description"];
foreach($xpath->query("//ol[@class='searchResults']//li[@class='result']") as $result)
{
$url = "http://" . $xpath->evaluate(".//cite", $result)[0]->textContent;
$title = remove_special($xpath->evaluate(".//h4", $result)[0]->textContent);
$description = $xpath->evaluate(".//p", $result)[0]->textContent;
echo "<div class=\"text-result-wrapper\">";
echo "<a href=\"$url\">";
echo "$base_url";
echo "<h2>$title</h2>";
echo "</a>";
echo "<span>$description</span>";
echo "</div>";
array_push($results,
array (
"title" => $title ? htmlspecialchars($title) : "No description provided",
"url" => htmlspecialchars($url),
"base_url" => htmlspecialchars(get_base_url($url)),
"description" => htmlspecialchars($description)
)
);
}
return $results;
}
echo "</div>";
public static function print_results($results) {
TextSearch::print_results($results);
}
}
?>

View File

@ -1,34 +1,40 @@
<?php
$_1337x_url = "https://1337x.to/search/$query/1/";
function get_1337x_results($response)
{
global $config;
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//table/tbody/tr") as $result)
{
$name = $xpath->evaluate(".//td[@class='coll-1 name']/a", $result)[1]->textContent;
$magnet = "./engines/bittorrent/get_magnet_1337x.php?url=https://1337x.to" . $xpath->evaluate(".//td[@class='coll-1 name']/a/@href", $result)[1]->textContent;
$size_unformatted = explode(" ", $xpath->evaluate(".//td[contains(@class, 'coll-4 size')]", $result)[0]->textContent);
$size = $size_unformatted[0] . " " . preg_replace("/[0-9]+/", "", $size_unformatted[1]);
$seeders = $xpath->evaluate(".//td[@class='coll-2 seeds']", $result)[0]->textContent;
$leechers = $xpath->evaluate(".//td[@class='coll-3 leeches']", $result)[0]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "1337x.to"
)
);
class _1337xRequest extends EngineRequest {
public function get_request_url() {
$query = urlencode($this->query);
return "https://1337x.to/search/$query/1/";
}
return $results;
public function get_results() {
$response = curl_multi_getcontent($this->ch);
$xpath = get_xpath($response);
$results = array();
if (!$xpath)
return $results;
foreach($xpath->query("//table/tbody/tr") as $result) {
$name = $xpath->evaluate(".//td[@class='coll-1 name']/a", $result)[1]->textContent;
$magnet = "./engines/bittorrent/get_magnet_1337x.php?url=https://1337x.to" . $xpath->evaluate(".//td[@class='coll-1 name']/a/@href", $result)[1]->textContent;
$size_unformatted = explode(" ", $xpath->evaluate(".//td[contains(@class, 'coll-4 size')]", $result)[0]->textContent);
$size = $size_unformatted[0] . " " . preg_replace("/[0-9]+/", "", $size_unformatted[1]);
$seeders = $xpath->evaluate(".//td[@class='coll-2 seeds']", $result)[0]->textContent;
$leechers = $xpath->evaluate(".//td[@class='coll-3 leeches']", $result)[0]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "1337x.to"
)
);
}
return $results;
}
}
?>

View File

@ -1,89 +1,48 @@
<?php
class TorrentSearch extends EngineRequest {
public function __construct($opts, $mh) {
parent::__construct($opts, $mh);
function get_merged_torrent_results($query)
{
global $config;
require "engines/bittorrent/thepiratebay.php";
require "engines/bittorrent/rutor.php";
require "engines/bittorrent/yts.php";
require "engines/bittorrent/torrentgalaxy.php";
require "engines/bittorrent/1337x.php";
require "engines/bittorrent/sukebei.php";
require "engines/bittorrent/thepiratebay.php";
require "engines/bittorrent/rutor.php";
require "engines/bittorrent/nyaa.php";
require "engines/bittorrent/yts.php";
require "engines/bittorrent/torrentgalaxy.php";
require "engines/bittorrent/1337x.php";
require "engines/bittorrent/sukebei.php";
$query = urlencode($query);
$torrent_urls = array(
$thepiratebay_url,
$rutor_url,
$nyaa_url,
$yts_url,
$torrentgalaxy_url,
$_1337x_url,
$sukebei_url
);
$mh = curl_multi_init();
$chs = $results = array();
foreach ($torrent_urls as $url)
{
$ch = curl_init($url);
curl_setopt_array($ch, $config->curl_settings);
array_push($chs, $ch);
curl_multi_add_handle($mh, $ch);
$this->requests = array(
new PirateBayRequest($opts, $mh),
new _1337xRequest($opts, $mh),
new NyaaRequest($opts, $mh),
new RutorRequest($opts, $mh),
new SukebeiRequest($opts, $mh),
new TorrentGalaxyRequest($opts, $mh),
new YTSRequest($opts, $mh),
);
}
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running);
for ($i=0; count($chs)>$i; $i++)
{
$response = curl_multi_getcontent($chs[$i]);
switch ($i)
{
case 0:
$results = array_merge($results, get_thepiratebay_results($response));
break;
case 1:
$results = array_merge($results, get_rutor_results($response));
break;
case 2:
$results = array_merge($results, get_nyaa_results($response));
break;
case 3:
$results = array_merge($results, get_yts_results($response));
break;
case 4:
$results = array_merge($results, get_torrentgalaxy_results($response));
break;
case 5:
$results = array_merge($results, get_1337x_results($response));
break;
case 6:
$results = array_merge($results, get_sukebei_results($response));
break;
public function get_results() {
$results = array();
foreach ($this->requests as $request) {
if ($request->successful())
$results = array_merge($results, $request->get_results());
}
$seeders = array_column($results, "seeders");
array_multisort($seeders, SORT_DESC, $results);
return $results;
}
$seeders = array_column($results, "seeders");
array_multisort($seeders, SORT_DESC, $results);
return $results;
}
public static function print_results($results) {
echo "<div class=\"text-result-container\">";
function print_merged_torrent_results($results)
{
echo "<div class=\"text-result-container\">";
if (empty($results)) {
echo "<p>There are no results. Please try different keywords!</p>";
return;
}
if (!empty($results))
{
foreach($results as $result)
{
foreach($results as $result) {
$source = $result["source"];
$name = $result["name"];
$magnet = $result["magnet"];
@ -101,11 +60,9 @@
echo "$size</span>";
echo "</div>";
}
}
else
echo "<p>There are no results. Please try different keywords!</p>";
echo "</div>";
echo "</div>";
}
}
?>

View File

@ -1,35 +1,53 @@
<?php
$nyaa_url = "https://nyaa.si/?q=$query";
class NyaaRequest extends EngineRequest {
public $SOURCE = "nyaa.si";
function get_nyaa_results($response)
{
global $config;
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//tbody/tr") as $result)
{
$name = $xpath->evaluate(".//td[@colspan='2']//a[not(contains(@class, 'comments'))]/@title", $result)[0]->textContent;
$centered = $xpath->evaluate(".//td[@class='text-center']", $result);
$magnet = $xpath->evaluate(".//a[2]/@href", $centered[0])[0]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $config->bittorent_trackers;
$size = $centered[1]->textContent;
$seeders = $centered[3]->textContent;
$leechers = $centered[4]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "nyaa.si"
)
);
public function get_request_url() {
return "https://$this->SOURCE/?q=" . urlencode($this->query);
}
return $results;
public function get_results() {
$response = curl_multi_getcontent($this->ch);
$xpath = get_xpath($response);
$results = array();
if (!$xpath)
return $results;
foreach($xpath->query("//tbody/tr") as $result)
{
$name_node = $xpath->evaluate(".//td[@colspan='2']//a[not(contains(@class, 'comments'))]/@title", $result);
if ($name_node->length > 0) {
$name = $name_node[0]->textContent;
} else {
$name = "";
}
$centered = $xpath->evaluate(".//td[@class='text-center']", $result);
$magnet_node = $xpath->evaluate(".//a[2]/@href", $centered[0]);
if ($magnet_node->length > 0) {
$magnet = $magnet_node[0]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $this->opts->bittorent_trackers;
} else {
$magnet = "";
}
$size = $centered[1]->textContent;
$seeders = $centered[3]->textContent;
$leechers = $centered[4]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => $this->SOURCE
)
);
}
return $results;
}
}
?>

View File

@ -1,36 +1,41 @@
<?php
$rutor_url = "http://rutor.info/search/$query";
function get_rutor_results($response)
{
global $config;
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//table/tr[@class='gai' or @class='tum']") as $result)
{
$name = $xpath->evaluate(".//td/a", $result)[2]->textContent;
$magnet = $xpath->evaluate(".//td/a/@href", $result)[1]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $config->bittorent_trackers;
$td = $xpath->evaluate(".//td", $result);
$size = $td[count($td) == 5 ? 3 : 2]->textContent;
$seeders = $xpath->evaluate(".//span", $result)[0]->textContent;
$leechers = $xpath->evaluate(".//span", $result)[1]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) filter_var($seeders, FILTER_SANITIZE_NUMBER_INT),
"leechers" => (int) filter_var($leechers, FILTER_SANITIZE_NUMBER_INT),
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "rutor.info"
)
);
class RutorRequest extends EngineRequest {
public function get_request_url() {
return "http://rutor.info/search/" . urlencode($this->query);
}
return $results;
public function get_results() {
$response = curl_multi_getcontent($this->ch);
$xpath = get_xpath($response);
$results = array();
if (!$xpath)
return $results;
foreach($xpath->query("//table/tr[@class='gai' or @class='tum']") as $result)
{
$name = $xpath->evaluate(".//td/a", $result)[2]->textContent;
$magnet = $xpath->evaluate(".//td/a/@href", $result)[1]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $this->opts->bittorrent_trackers;
$td = $xpath->evaluate(".//td", $result);
$size = $td[count($td) == 5 ? 3 : 2]->textContent;
$seeders = $xpath->evaluate(".//span", $result)[0]->textContent;
$leechers = $xpath->evaluate(".//span", $result)[1]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) filter_var($seeders, FILTER_SANITIZE_NUMBER_INT),
"leechers" => (int) filter_var($leechers, FILTER_SANITIZE_NUMBER_INT),
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "rutor.info"
)
);
}
return $results;
}
}
?>

View File

@ -1,44 +1,6 @@
<?php
$sukebei_url = "https://sukebei.nyaa.si/?q=$query";
function get_sukebei_results($response)
{
global $config;
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//tbody/tr") as $result)
{
$name_node = $xpath->evaluate(".//td[@colspan='2']//a[not(contains(@class, 'comments'))]/@title", $result);
if ($name_node->length > 0) {
$name = $name_node[0]->textContent;
} else {
$name = "";
}
$centered = $xpath->evaluate(".//td[@class='text-center']", $result);
$magnet_node = $xpath->evaluate(".//a[2]/@href", $centered[0]);
if ($magnet_node->length > 0) {
$magnet = $magnet_node[0]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $config->bittorent_trackers;
} else {
$magnet = "";
}
$size = $centered[1]->textContent;
$seeders = $centered[3]->textContent;
$leechers = $centered[4]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "sukebei.nyaa.si"
)
);
}
return $results;
include "engines/bittorrent/nyaa.php";
class SukebeiRequest extends NyaaRequest {
public $SOURCE = "sukebei.nyaa.si";
}
?>

View File

@ -1,44 +1,46 @@
<?php
class PirateBayRequest extends EngineRequest {
public function get_request_url() {
return "https://apibay.org/q.php?q=" . urlencode($this->query);
}
$thepiratebay_url = "https://apibay.org/q.php?q=$query";
public function get_results() {
$response = curl_multi_getcontent($this->ch);
$results = array();
$json_response = json_decode($response, true);
function get_thepiratebay_results($response)
{
global $config;
$results = array();
$json_response = json_decode($response, true);
if (empty($json_response))
{
return $results;
}
foreach ($json_response as $response)
{
$size = human_filesize($response["size"]);
$hash = $response["info_hash"];
$name = $response["name"];
$seeders = (int) $response["seeders"];
$leechers = (int) $response["leechers"];
$magnet = "magnet:?xt=urn:btih:$hash&dn=$name" . $this->opts->bittorrent_trackers;
if ($name == "No results returned")
break;
array_push($results,
array (
"size" => htmlspecialchars($size),
"name" => htmlspecialchars($name),
"seeders" => (int) htmlspecialchars($seeders),
"leechers" => (int) htmlspecialchars($leechers),
"magnet" => htmlspecialchars($magnet),
"source" => "thepiratebay.org"
)
);
}
if (empty($json_response))
{
return $results;
}
foreach ($json_response as $response)
{
$size = human_filesize($response["size"]);
$hash = $response["info_hash"];
$name = $response["name"];
$seeders = (int) $response["seeders"];
$leechers = (int) $response["leechers"];
$magnet = "magnet:?xt=urn:btih:$hash&dn=$name" . $config->bittorent_trackers;
if ($name == "No results returned")
break;
array_push($results,
array (
"size" => htmlspecialchars($size),
"name" => htmlspecialchars($name),
"seeders" => (int) htmlspecialchars($seeders),
"leechers" => (int) htmlspecialchars($leechers),
"magnet" => htmlspecialchars($magnet),
"source" => "thepiratebay.org"
)
);
}
return $results;
}
?>

View File

@ -1,34 +1,41 @@
<?php
$torrentgalaxy_url = "https://torrentgalaxy.to/torrents.php?search=$query#results";
function get_torrentgalaxy_results($response)
{
global $config;
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//div[@class='tgxtablerow txlight']") as $result)
{
$name = $xpath->evaluate(".//div[contains(@class, 'clickable-row')]", $result)[0]->textContent;
$magnet = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/a/@href", $result)[1]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $config->bittorent_trackers;
$size = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/span", $result)[0]->textContent;
$seeders = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/span/font", $result)[1]->textContent;
$leechers = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/span/font", $result)[2]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "torrentgalaxy.to"
)
);
class TorrentGalaxyRequest extends EngineRequest {
public function get_request_url() {
$query = urlencode($this->query);
return "https://torrentgalaxy.to/torrents.php?search=$query#results";
}
return $results;
public function get_results() {
$response = curl_multi_getcontent($this->ch);
$xpath = get_xpath($response);
$results = array();
if (!$xpath)
return $results;
foreach($xpath->query("//div[@class='tgxtablerow txlight']") as $result)
{
$name = $xpath->evaluate(".//div[contains(@class, 'clickable-row')]", $result)[0]->textContent;
$magnet = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/a/@href", $result)[1]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $this->opts->bittorrent_trackers;
$size = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/span", $result)[0]->textContent;
$seeders = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/span/font", $result)[1]->textContent;
$leechers = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/span/font", $result)[2]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "torrentgalaxy.to"
)
);
}
return $results;
}
}
?>

View File

@ -1,14 +1,18 @@
<?php
$yts_url = "https://yts.mx/api/v2/list_movies.json?query_term=$query";
class YTSRequest extends EngineRequest {
public function get_request_url() {
return "https://yts.mx/api/v2/list_movies.json?query_term=" . urlencode($this->query);
}
function get_yts_results($response)
{
global $config;
$results = array();
$json_response = json_decode($response, true);
public function get_results() {
$response = curl_multi_getcontent($this->ch);
global $config;
$results = array();
$json_response = json_decode($response, true);
if ($json_response["status"] != "ok" || $json_response["data"]["movie_count"] == 0)
return $results;
if ($json_response["status"] == "ok" && $json_response["data"]["movie_count"] != 0)
{
foreach ($json_response["data"]["movies"] as $movie)
{
$name = $movie["title"];
@ -22,24 +26,22 @@
$leechers = $torrent["peers"];
$size = $torrent["size"];
$magnet = "magnet:?xt=urn:btih:$hash&dn=$name_encoded$config->bittorent_trackers";
$magnet = "magnet:?xt=urn:btih:$hash&dn=$name_encoded$this->opts->bittorrent_trackers";
array_push($results,
array (
"size" => htmlspecialchars($size),
"name" => htmlspecialchars($name),
"seeders" => htmlspecialchars($seeders),
"leechers" => htmlspecialchars($leechers),
"magnet" => htmlspecialchars($magnet),
"source" => "yts.mx"
)
);
array_push($results,
array (
"size" => htmlspecialchars($size),
"name" => htmlspecialchars($name),
"seeders" => htmlspecialchars($seeders),
"leechers" => htmlspecialchars($leechers),
"magnet" => htmlspecialchars($magnet),
"source" => "yts.mx"
)
);
}
}
}
return $results;
return $results;
}
}
?>

View File

@ -1,204 +0,0 @@
<?php
function get_text_results($query, $page)
{
global $config;
$mh = curl_multi_init();
$query_encoded = urlencode($query);
$results = array();
// $domain = $config->google_domain;
$domain = 'com';
$site_language = isset($_COOKIE["google_language_site"]) ? trim(htmlspecialchars($_COOKIE["google_language_site"])) : $config->google_language_site;
$results_language = isset($_COOKIE["google_language_results"]) ? trim(htmlspecialchars($_COOKIE["google_language_results"])) : $config->google_language_results;
$number_of_results = isset($_COOKIE["google_number_of_results"]) ? trim(htmlspecialchars($_COOKIE["google_number_of_results"])) : $config->google_number_of_results;
$url = "https://html.duckduckgo.$domain/html/?q=$query_encoded&kd=-1&s=" . 3 * $page;
if (3 > strlen($site_language) && 0 < strlen($site_language))
$url .= "&hl=$site_language";
if (3 > strlen($results_language) && 0 < strlen($results_language))
$url .= "&lr=lang_$results_language";
if (3 > strlen($number_of_results) && 0 < strlen($number_of_results))
$url .= "&num=$number_of_results";
if (isset($_COOKIE["safe_search"]))
$url .= "&safe=medium";
$google_ch = curl_init($url);
curl_setopt_array($google_ch, $config->curl_settings);
curl_multi_add_handle($mh, $google_ch);
$special_search = $page ? 0 : check_for_special_search($query);
$special_ch = null;
$url = null;
if ($special_search != 0)
{
switch ($special_search)
{
case 1:
$url = "https://cdn.moneyconvert.net/api/latest.json";
break;
case 2:
$split_query = explode(" ", $query);
$reversed_split_q = array_reverse($split_query);
$word_to_define = $reversed_split_q[1];
$url = "https://api.dictionaryapi.dev/api/v2/entries/en/$word_to_define";
break;
case 5:
$url = "https://wttr.in/@" . $_SERVER["REMOTE_ADDR"] . "?format=j1";
break;
case 6:
$url = "https://check.torproject.org/torbulkexitlist";
break;
case 7:
$wikipedia_language = isset($_COOKIE["wikipedia_language"]) ? trim(htmlspecialchars($_COOKIE["wikipedia_language"])) : $config->wikipedia_language;
if (in_array($wikipedia_language, json_decode(file_get_contents("static/misc/wikipedia_langs.json"), true)))
$url = "https://$wikipedia_language.wikipedia.org/w/api.php?format=json&action=query&prop=extracts%7Cpageimages&exintro&explaintext&redirects=1&pithumbsize=500&titles=$query_encoded";
break;
}
if ($url != NULL)
{
$special_ch = curl_init($url);
curl_setopt_array($special_ch, $config->curl_settings);
curl_multi_add_handle($mh, $special_ch);
}
}
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running);
if (curl_getinfo($google_ch)['http_code'] != '200')
{
require "engines/librex/text.php";
return get_librex_results($query, $page);
}
if ($special_search != 0)
{
$special_result = null;
switch ($special_search)
{
case 1:
require "engines/special/currency.php";
$special_result = currency_results($query, curl_multi_getcontent($special_ch));
break;
case 2:
require "engines/special/definition.php";
$special_result = definition_results($query, curl_multi_getcontent($special_ch));
break;
case 3:
require "engines/special/ip.php";
$special_result = ip_result();
break;
case 4:
require "engines/special/user_agent.php";
$special_result = user_agent_result();
break;
case 5:
require "engines/special/weather.php";
$special_result = weather_results(curl_multi_getcontent($special_ch));
break;
case 6:
require "engines/special/tor.php";
$special_result = tor_result(curl_multi_getcontent($special_ch));
break;
case 7:
require "engines/special/wikipedia.php";
$special_result = wikipedia_results($query, curl_multi_getcontent($special_ch));
break;
}
if ($special_result != null)
array_push($results, $special_result);
}
$xpath = get_xpath(curl_multi_getcontent($google_ch));
foreach($xpath->query("/html/body/div[1]/div[". count($xpath->query('/html/body/div[1]/div')) ."]/div/div/div/div") as $result)
{
$url = $xpath->evaluate(".//h2[@class='result__title']//a/@href", $result)[0];
if ($url == null)
continue;
if (!empty($results)) // filter duplicate results, ignore special result
{
if (!array_key_exists("special_response", end($results)))
if (end($results)["url"] == $url->textContent)
continue;
}
$url = $url->textContent;
$url = check_for_privacy_frontend($url);
$title = $xpath->evaluate(".//h2[@class='result__title']", $result)[0];
$description = $xpath->evaluate(".//a[@class='result__snippet']", $result)[0];
array_push($results,
array (
"title" => htmlspecialchars($title->textContent),
"url" => htmlspecialchars($url),
"base_url" => htmlspecialchars(get_base_url($url)),
"description" => $description == null ?
"No description was provided for this site." :
htmlspecialchars($description->textContent)
)
);
}
return $results;
}
function print_text_results($results)
{
$special = $results[0];
if (array_key_exists("special_response", $special))
{
$response = $special["special_response"]["response"];
$source = $special["special_response"]["source"];
echo "<p class=\"special-result-container\">";
if (array_key_exists("image", $special["special_response"]))
{
$image_url = $special["special_response"]["image"];
echo "<img src=\"image_proxy.php?url=$image_url\">";
}
echo $response;
if ($source)
echo "<a href=\"$source\" target=\"_blank\">$source</a>";
echo "</p>";
array_shift($results);
}
echo "<div class=\"text-result-container\">";
foreach($results as $result)
{
$title = $result["title"];
$url = $result["url"];
$base_url = $result["base_url"];
$description = $result["description"];
echo "<div class=\"text-result-wrapper\">";
echo "<a href=\"$url\">";
echo "$base_url";
echo "<h2>$title</h2>";
echo "</a>";
echo "<span>$description</span>";
echo "</div>";
}
echo "</div>";
}
?>

View File

@ -1,226 +0,0 @@
<?php
function get_text_results($query, $page)
{
global $config;
$mh = curl_multi_init();
$query_encoded = str_replace("%22", "\"", urlencode($query));
$results = array();
$domain = $config->google_domain;
$site_language = isset($_COOKIE["google_language_site"]) ? trim(htmlspecialchars($_COOKIE["google_language_site"])) : $config->google_language_site;
$results_language = isset($_COOKIE["google_language_results"]) ? trim(htmlspecialchars($_COOKIE["google_language_results"])) : $config->google_language_results;
$number_of_results = isset($_COOKIE["google_number_of_results"]) ? trim(htmlspecialchars($_COOKIE["google_number_of_results"])) : $config->google_number_of_results;
$url = "https://www.google.$domain/search?q=$query_encoded&nfpr=1&start=$page";
error_log($url);
if (3 > strlen($site_language) && 0 < strlen($site_language))
$url .= "&hl=$site_language";
if (3 > strlen($results_language) && 0 < strlen($results_language))
$url .= "&lr=lang_$results_language";
if (3 > strlen($number_of_results) && 0 < strlen($number_of_results))
$url .= "&num=$number_of_results";
if (isset($_COOKIE["safe_search"]))
$url .= "&safe=medium";
$google_ch = curl_init($url);
curl_setopt_array($google_ch, $config->curl_settings);
curl_multi_add_handle($mh, $google_ch);
$special_search = $page ? 0 : check_for_special_search($query);
$special_ch = null;
$url = null;
if ($special_search != 0)
{
switch ($special_search)
{
case 1:
$url = "https://cdn.moneyconvert.net/api/latest.json";
break;
case 2:
$split_query = explode(" ", $query);
$reversed_split_q = array_reverse($split_query);
$word_to_define = $reversed_split_q[1];
$url = "https://api.dictionaryapi.dev/api/v2/entries/en/$word_to_define";
break;
case 5:
$url = "https://wttr.in/@" . $_SERVER["REMOTE_ADDR"] . "?format=j1";
break;
case 6:
$url = "https://check.torproject.org/torbulkexitlist";
break;
case 7:
$wikipedia_language = isset($_COOKIE["wikipedia_language"]) ? trim(htmlspecialchars($_COOKIE["wikipedia_language"])) : $config->wikipedia_language;
if (in_array($wikipedia_language, json_decode(file_get_contents("static/misc/wikipedia_langs.json"), true)))
$url = "https://$wikipedia_language.wikipedia.org/w/api.php?format=json&action=query&prop=extracts%7Cpageimages&exintro&explaintext&redirects=1&pithumbsize=500&titles=$query_encoded";
break;
}
if ($url != NULL)
{
$special_ch = curl_init($url);
curl_setopt_array($special_ch, $config->curl_settings);
curl_multi_add_handle($mh, $special_ch);
}
}
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running);
if (curl_getinfo($google_ch)['http_code'] != '200')
{
require "engines/librex/text.php";
return get_librex_results($query, $page);
}
$special_result = array();
if ($special_search != 0)
{
switch ($special_search)
{
case 1:
require "engines/special/currency.php";
$special_result = currency_results($query, curl_multi_getcontent($special_ch));
break;
case 2:
require "engines/special/definition.php";
$special_result = definition_results($query, curl_multi_getcontent($special_ch));
break;
case 3:
require "engines/special/ip.php";
$special_result = ip_result();
break;
case 4:
require "engines/special/user_agent.php";
$special_result = user_agent_result();
break;
case 5:
require "engines/special/weather.php";
$special_result = weather_results(curl_multi_getcontent($special_ch));
break;
case 6:
require "engines/special/tor.php";
$special_result = tor_result(curl_multi_getcontent($special_ch));
break;
case 7:
require "engines/special/wikipedia.php";
$special_result = wikipedia_results($query, curl_multi_getcontent($special_ch));
break;
}
}
$xpath = get_xpath(curl_multi_getcontent($google_ch));
$didyoumean = $xpath->query(".//a[@class='gL9Hy']")[0];
if (!is_null($didyoumean))
$special_result["did_you_mean"] = $didyoumean->textContent;
if (!empty($special_result))
array_push($results, $special_result);
foreach($xpath->query("//div[@id='search']//div[contains(@class, 'g')]") as $result)
{
$url = $xpath->evaluate(".//div[@class='yuRUbf']//a/@href", $result)[0];
if ($url == null)
continue;
if (!empty($results)) // filter duplicate results, ignore special result
{
if (!array_key_exists("special_response", end($results)))
if (end($results)["url"] == $url->textContent)
continue;
}
$url = $url->textContent;
$url = check_for_privacy_frontend($url);
$title = $xpath->evaluate(".//h3", $result)[0];
$description = $xpath->evaluate(".//div[contains(@class, 'VwiC3b')]", $result)[0];
array_push($results,
array (
"title" => htmlspecialchars($title->textContent),
"url" => htmlspecialchars($url),
"base_url" => htmlspecialchars(get_base_url($url)),
"description" => $description == null ?
"No description was provided for this site." :
htmlspecialchars($description->textContent)
)
);
}
return $results;
}
function print_text_results($results)
{
if (empty($results))
return;
$special = $results[0];
if (array_key_exists("did_you_mean", $special))
{
$didyoumean = $special["did_you_mean"];
$new_url = "/search.php?q=" . urlencode($didyoumean);
echo "<p class=\"did-you-mean\">Did you mean ";
echo "<a href=\"$new_url\">$didyoumean</a>";
echo "?</p>";
}
if (array_key_exists("special_response", $special))
{
$response = $special["special_response"]["response"];
$source = $special["special_response"]["source"];
echo "<p class=\"special-result-container\">";
if (array_key_exists("image", $special["special_response"]))
{
$image_url = $special["special_response"]["image"];
echo "<img src=\"image_proxy.php?url=$image_url\">";
}
echo $response;
if ($source)
echo "<a href=\"$source\" target=\"_blank\">$source</a>";
echo "</p>";
}
echo "<div class=\"text-result-container\">";
foreach($results as $result)
{
if (!array_key_exists("title", $result))
continue;
$title = $result["title"];
$url = $result["url"];
$base_url = $result["base_url"];
$description = $result["description"];
echo "<div class=\"text-result-wrapper\">";
echo "<a href=\"$url\">";
echo "$base_url";
echo "<h2>$title</h2>";
echo "</a>";
echo "<span>$description</span>";
echo "</div>";
}
echo "</div>";
}
?>

View File

@ -1,68 +1,67 @@
<?php
function get_video_results($query)
{
global $config;
$instance_url = $config->invidious_instance_for_video_results;
$url = "$instance_url/api/v1/search?q=$query";
$response = request($url);
$json_response = json_decode($response, true);
$results = array();
foreach ($json_response as $response)
{
if ($response["type"] == "video")
{
$title = $response["title"];
$url = "https://youtube.com/watch?v=" . $response["videoId"];
$url = check_for_privacy_frontend($url);
$uploader = $response["author"];
$views = $response["viewCount"];
$date = $response["publishedText"];
$thumbnail = $instance_url . "/vi/" . explode("/vi/" ,$response["videoThumbnails"][4]["url"])[1];
array_push($results,
array (
"title" => htmlspecialchars($title),
"url" => htmlspecialchars($url),
"base_url" => htmlspecialchars(get_base_url($url)),
"uploader" => htmlspecialchars($uploader),
"views" => htmlspecialchars($views),
"date" => htmlspecialchars($date),
"thumbnail" => htmlspecialchars($thumbnail)
)
);
}
class VideoSearch extends EngineRequest {
public function get_request_url() {
$this->instance_url = $this->opts->invidious_instance_for_video_results;
$query = urlencode($this->query);
return "$this->instance_url/api/v1/search?q=$query";
}
return $results;
}
public function get_results() {
$results = array();
$response = curl_multi_getcontent($this->ch);
$json_response = json_decode($response, true);
function print_video_results($results)
{
echo "<div class=\"text-result-container\">";
foreach ($json_response as $response) {
if ($response["type"] == "video") {
$title = $response["title"];
$url = "https://youtube.com/watch?v=" . $response["videoId"];
$url = check_for_privacy_frontend($url, $this->opts);
$uploader = $response["author"];
$views = $response["viewCount"];
$date = $response["publishedText"];
$thumbnail = $this->instance_url . "/vi/" . explode("/vi/" ,$response["videoThumbnails"][4]["url"])[1];
foreach($results as $result)
{
$title = $result["title"];
$url = $result["url"];
$base_url = $result["base_url"];
$uploader = $result["uploader"];
$views = $result["views"];
$date = $result["date"];
$thumbnail = $result["thumbnail"];
echo "<div class=\"text-result-wrapper\">";
echo "<a href=\"$url\">";
echo "$base_url";
echo "<h2>$title</h2>";
echo "<img class=\"video-img\" src=\"image_proxy.php?url=$thumbnail\">";
echo "<br>";
echo "<span>$uploader - $date - $views views</span>";
echo "</a>";
echo "</div>";
array_push($results,
array (
"title" => htmlspecialchars($title),
"url" => htmlspecialchars($url),
"base_url" => htmlspecialchars(get_base_url($url)),
"uploader" => htmlspecialchars($uploader),
"views" => htmlspecialchars($views),
"date" => htmlspecialchars($date),
"thumbnail" => htmlspecialchars($thumbnail)
)
);
}
}
echo "</div>";
return $results;
}
public static function print_results($results) {
echo "<div class=\"text-result-container\">";
foreach($results as $result) {
$title = $result["title"];
$url = $result["url"];
$base_url = $result["base_url"];
$uploader = $result["uploader"];
$views = $result["views"];
$date = $result["date"];
$thumbnail = $result["thumbnail"];
echo "<div class=\"text-result-wrapper\">";
echo "<a href=\"$url\">";
echo "$base_url";
echo "<h2>$title</h2>";
echo "<img class=\"video-img\" src=\"image_proxy.php?url=$thumbnail\">";
echo "<br>";
echo "<span>$uploader - $date - $views views</span>";
echo "</a>";
echo "</div>";
}
echo "</div>";
}
}
?>

View File

@ -0,0 +1,68 @@
<?php
class LibreXFallback extends EngineRequest {
public function __construct($instance, $opts, $mh) {
$this->instance = $instance;
parent::__construct($opts, $mh);
}
public function get_request_url() {
return $this->instance . "api.php?" . opts_to_params($this->opts);
}
public function get_results() {
$response = curl_exec($this->ch);
$response = json_decode($response, true);
if (!$response)
return array();
return array_values($response);
}
}
function load_instances($cooldowns) {
$instances_json = json_decode(file_get_contents("instances.json"), true);
if (empty($instances_json["instances"]))
return array();
$instances = array_map(fn($n) => $n['clearnet'], array_filter($instances_json['instances'], fn($n) => !is_null($n['clearnet'])));
$instances = array_filter($instances, fn($n) => !has_cooldown($n, $cooldowns));
shuffle($instances);
return $instances;
}
function get_librex_results($opts) {
if (!$opts->do_fallback)
return array();
$cooldowns = $opts->cooldowns;
$instances = load_instances($cooldowns);
$results = array();
$tries = 0;
do {
$tries++;
$instance = array_pop($instances);
if (parse_url($instance)["host"] == parse_url($_SERVER['HTTP_HOST'])["host"])
continue;
$librex_request = new LibreXFallback($instance, $opts, null);
$results = $librex_request->get_results();
if (count($results) > 1)
return $results;
// on fail then do this
$timeout = ($opts->request_cooldown ?? "1") * 60;
$cooldowns = set_cooldown($instance, $timeout, $cooldowns);
} while (!empty($instances));
return array();
}
?>

View File

@ -1,53 +0,0 @@
<?php
function get_librex_results($query, $page)
{
global $config;
if (isset($_REQUEST["nfb"]) && $_REQUEST["nfb"] == "1")
return array();
if (!$config->instance_fallback)
return array();
$instances_json = json_decode(file_get_contents("instances.json"), true);
if (empty($instances_json["instances"]))
return array();
$instances = array_map(fn($n) => $n['clearnet'], array_filter($instances_json['instances'], fn($n) => !is_null($n['clearnet'])));
shuffle($instances);
$query_encoded = urlencode($query);
$results = array();
$tries = 0;
do {
$tries++;
$instance = array_pop($instances);
if (parse_url($instance)["host"] == parse_url($_SERVER['HTTP_HOST'])["host"])
continue;
$url = $instance . "api.php?q=$query_encoded&p=$page&t=0&nfb=1";
$librex_ch = curl_init($url);
curl_setopt_array($librex_ch, $config->curl_settings);
copy_cookies($librex_ch);
$response = curl_exec($librex_ch);
curl_close($librex_ch);
$code = curl_getinfo($librex_ch)["http_code"];
$results = json_decode($response, true);
} while ( !empty($instances) && ($results == null || count($results) <= 1));
if (empty($instances))
return array();
return array_values($results);
}
?>

View File

@ -1,60 +1,63 @@
<?php
function get_image_results($query, $page)
{
global $config;
$page = $page / 10 + 1; // qwant has a different page system
$url = "https://lite.qwant.com/?q=$query&t=images&p=$page";
$response = request($url);
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//a[@rel='noopener']") as $result)
{
$image = $xpath->evaluate(".//img", $result)[0];
if ($image)
{
$encoded_url = $result->getAttribute("href");
$encoded_url_split1 = explode("==/", $encoded_url)[1];
$encoded_url_split2 = explode("?position", $encoded_url_split1)[0];
$real_url = urldecode(base64_decode($encoded_url_split2));
$real_url = check_for_privacy_frontend($real_url);
$alt = $image->getAttribute("alt");
$thumbnail = urlencode($image->getAttribute("src"));
array_push($results,
array (
"thumbnail" => urldecode(htmlspecialchars($thumbnail)),
"alt" => htmlspecialchars($alt),
"url" => htmlspecialchars($real_url)
)
);
}
class QwantImageSearch extends EngineRequest {
public function get_request_url() {
$page = $this->page / 10 + 1; // qwant has a different page system
$query = urlencode($this->query);
return "https://lite.qwant.com/?q=$query&t=images&p=$page";
}
return $results;
}
public function get_results() {
$results = array();
$xpath = get_xpath(curl_multi_getcontent($this->ch));
function print_image_results($results)
{
echo "<div class=\"image-result-container\">";
if (!$xpath)
return $results;
foreach($results as $result)
{
$thumbnail = urlencode($result["thumbnail"]);
$alt = $result["alt"];
$url = $result["url"];
foreach($xpath->query("//a[@rel='noopener']") as $result)
{
$image = $xpath->evaluate(".//img", $result)[0];
echo "<a title=\"$alt\" href=\"$url\" target=\"_blank\">";
echo "<img src=\"image_proxy.php?url=$thumbnail\">";
echo "</a>";
if ($image)
{
$encoded_url = $result->getAttribute("href");
$encoded_url_split1 = explode("==/", $encoded_url)[1];
$encoded_url_split2 = explode("?position", $encoded_url_split1)[0];
$real_url = urldecode(base64_decode($encoded_url_split2));
$real_url = check_for_privacy_frontend($real_url, $this->opts);
$alt = $image->getAttribute("alt");
$thumbnail = urlencode($image->getAttribute("src"));
array_push($results,
array (
"thumbnail" => urldecode(htmlspecialchars($thumbnail)),
"alt" => htmlspecialchars($alt),
"url" => htmlspecialchars($real_url)
)
);
}
}
echo "</div>";
return $results;
}
public static function print_results($results) {
echo "<div class=\"image-result-container\">";
foreach($results as $result)
{
$thumbnail = urlencode($result["thumbnail"]);
$alt = $result["alt"];
$url = $result["url"];
echo "<a title=\"$alt\" href=\"$url\" target=\"_blank\">";
echo "<img src=\"image_proxy.php?url=$thumbnail\">";
echo "</a>";
}
echo "</div>";
}
}
?>

View File

@ -1,18 +1,24 @@
<?php
function currency_results($query, $response)
{
$split_query = explode(" ", $query);
$base_currency = strtoupper($split_query[1]);
$currency_to_convert = strtoupper($split_query[3]);
$amount_to_convert = floatval($split_query[0]);
class CurrencyRequest extends EngineRequest {
public function get_request_url() {
return "https://cdn.moneyconvert.net/api/latest.json";
}
$json_response = json_decode($response, true);
$rates = $json_response["rates"];
public function get_results() {
$response = curl_multi_getcontent($this->ch);
if (array_key_exists($base_currency, $rates) && array_key_exists($currency_to_convert, $rates))
{
$split_query = explode(" ", $this->query);
$base_currency = strtoupper($split_query[1]);
$currency_to_convert = strtoupper($split_query[3]);
$amount_to_convert = floatval($split_query[0]);
$json_response = json_decode($response, true);
$rates = $json_response["rates"];
if (!array_key_exists($base_currency, $rates) || !array_key_exists($currency_to_convert, $rates))
return array();
$base_currency_response = $rates[$base_currency];
$currency_to_convert_response = $rates[$currency_to_convert];
@ -26,6 +32,6 @@
"source" => $source
)
);
}
}
}
?>

View File

@ -1,9 +1,15 @@
<?php
function definition_results($query, $response)
{
$split_query = explode(" ", $query);
class DefinitionRequest extends EngineRequest {
public function get_request_url() {
$split_query = explode(" ", $this->query);
$reversed_split_q = array_reverse($split_query);
$word_to_define = $reversed_split_q[1];
return "https://api.dictionaryapi.dev/api/v2/entries/en/$word_to_define";
}
public function get_results() {
$response = curl_multi_getcontent($this->ch);
$json_response = json_decode($response, true);
@ -20,5 +26,6 @@
);
}
}
}
?>

View File

@ -1,11 +1,12 @@
<?php
function ip_result()
{
class IPRequest extends EngineRequest {
function get_results() {
return array(
"special_response" => array(
"response" => $_SERVER["REMOTE_ADDR"],
"source" => null
)
);
}
}
?>

View File

@ -0,0 +1,91 @@
<?php
function check_for_special_search($query) {
if (isset($_COOKIE["disable_special"]))
return 0;
$query_lower = strtolower($query);
$split_query = explode(" ", $query);
if (strpos($query_lower, "to") && count($split_query) >= 4) // currency
{
$amount_to_convert = floatval($split_query[0]);
if ($amount_to_convert != 0)
return 1;
}
else if (strpos($query_lower, "mean") && count($split_query) >= 2) // definition
{
return 2;
}
else if (strpos($query_lower, "my") !== false)
{
if (strpos($query_lower, "ip"))
{
return 3;
}
else if (strpos($query_lower, "user agent") || strpos($query_lower, "ua"))
{
return 4;
}
}
else if (strpos($query_lower, "weather") !== false)
{
return 5;
}
else if ($query_lower == "tor")
{
return 6;
}
else if (3 > count(explode(" ", $query))) // wikipedia
{
return 7;
}
return 0;
}
function get_special_search_request($opts, $mh) {
if ($opts->page != 0)
return null;
$special_search = check_for_special_search($opts->query);
$special_request = null;
$url = null;
if ($special_search == 0)
return null;
switch ($special_search) {
case 1:
require "engines/special/currency.php";
$special_request = new CurrencyRequest($opts, $mh);
break;
case 2:
require "engines/special/definition.php";
$special_request = new DefinitionRequest($opts, $mh);
break;
case 3:
require "engines/special/ip.php";
$special_request = new IPRequest($opts, $mh);
break;
case 4:
require "engines/special/user_agent.php";
$special_request = new UserAgentRequest($opts, $mh);
break;
case 5:
require "engines/special/weather.php";
$special_request = new WeatherRequest($opts, $mh);
break;
case 6:
require "engines/special/tor.php";
$special_request = new TorRequest($opts, $mh);
break;
case 7:
require "engines/special/wikipedia.php";
$special_request = new WikipediaRequest($opts, $mh);
break;
}
return $special_request;
}
?>

View File

@ -1,18 +1,22 @@
<?php
function tor_result($response)
{
$formatted_response = "It seems like you are not using Tor";
if (strpos($response, $_SERVER["REMOTE_ADDR"]) !== false)
{
$formatted_response = "It seems like you are using Tor";
}
class TorRequest extends EngineRequest {
public function get_request_url() {
return "https://check.torproject.org/torbulkexitlist";
}
public function get_results() {
$response = curl_multi_getcontent($ch);
$formatted_response = strpos($response, $_SERVER["REMOTE_ADDR"]) ? "It seems like you are using Tor" : "It seems like you are not using Tor";
$source = "https://check.torproject.org";
return array(
"special_response" => array(
"response" => $formatted_response,
"source" => $source
)
);
}
}
?>

View File

@ -1,11 +1,12 @@
<?php
function user_agent_result()
{
class UserAgentRequest extends EngineRequest {
function get_results() {
return array(
"special_response" => array(
"response" => $_SERVER["HTTP_USER_AGENT"],
"source" => null
)
);
}
}
?>

View File

@ -1,26 +1,31 @@
<?php
function weather_results($response)
{
class WeatherRequest extends EngineRequest {
public function get_request_url () {
return "https://wttr.in/@" . $_SERVER["REMOTE_ADDR"] . "?format=j1";
}
public function get_results() {
$response = curl_multi_getcontent($this->ch);
$json_response = json_decode($response, true);
if ($json_response)
{
$current_weather = $json_response["current_condition"][0];
if (!$json_response)
return array();
$temp_c = $current_weather["temp_C"];
$temp_f = $current_weather["temp_F"];
$description = $current_weather["weatherDesc"][0]["value"];
$current_weather = $json_response["current_condition"][0];
$formatted_response = "$description - $temp_c °C | $temp_f °F";
$temp_c = $current_weather["temp_C"];
$temp_f = $current_weather["temp_F"];
$description = $current_weather["weatherDesc"][0]["value"];
$source = "https://wttr.in";
return array(
"special_response" => array(
"response" => htmlspecialchars($formatted_response),
"source" => $source
)
);
}
$formatted_response = "$description - $temp_c °C | $temp_f °F";
$source = "https://wttr.in";
return array(
"special_response" => array(
"response" => htmlspecialchars($formatted_response),
"source" => $source
)
);
}
}
?>

View File

@ -1,21 +1,28 @@
<?php
function wikipedia_results($query, $response)
{
global $config;
class WikipediaRequest extends EngineRequest {
public function get_request_url() {
$this->wikipedia_language = $this->opts->language;
$query_encoded = urlencode($this->query);
$query_encoded = urlencode($query);
if (!in_array($this->wikipedia_language, json_decode(file_get_contents("static/misc/wikipedia_langs.json"), true)))
$this->wikipedia_language = "en";
$json_response = json_decode($response, true);
return "https://$this->wikipedia_language.wikipedia.org/w/api.php?format=json&action=query&prop=extracts%7Cpageimages&exintro&explaintext&redirects=1&pithumbsize=500&titles=$query_encoded";
}
$first_page = array_values($json_response["query"]["pages"])[0];
public function get_results() {
$response = curl_multi_getcontent($this->ch);
$json_response = json_decode($response, true);
$first_page = array_values($json_response["query"]["pages"])[0];
if (array_key_exists("missing", $first_page))
return array();
if (!array_key_exists("missing", $first_page))
{
$description = substr($first_page["extract"], 0, 250) . "...";
$wikipedia_language = isset($_COOKIE["wikipedia_language"]) ? trim(htmlspecialchars($_COOKIE["wikipedia_language"])) : $config->wikipedia_language;
$source = check_for_privacy_frontend("https://$wikipedia_language.wikipedia.org/wiki/$query");
$source = check_for_privacy_frontend("https://$this->wikipedia_language.wikipedia.org/wiki/$this->query", $this->opts);
$response = array(
"special_response" => array(
"response" => htmlspecialchars($description),
@ -23,8 +30,7 @@
)
);
if (array_key_exists("thumbnail", $first_page))
{
if (array_key_exists("thumbnail", $first_page)) {
$image_url = $first_page["thumbnail"]["source"];
$response["special_response"]["image"] = $image_url;
}

View File

@ -0,0 +1,64 @@
<?php
class DuckDuckGoRequest extends EngineRequest {
function get_request_url()
{
$query_encoded = str_replace("%22", "\"", urlencode($this->query));
$results = array();
$domain = 'com';
$results_language = $this->opts->language;
$number_of_results = $this->opts->number_of_results;
$url = "https://html.duckduckgo.$domain/html/?q=$query_encoded&kd=-1&s=" . 3 * $this->page;
if (3 > strlen($results_language) && 0 < strlen($results_language))
$url .= "&lr=lang_$results_language";
if (3 > strlen($number_of_results) && 0 < strlen($number_of_results))
$url .= "&num=$number_of_results";
if (isset($_COOKIE["safe_search"]))
$url .= "&safe=medium";
return $url;
}
public function get_results() {
$results = array();
$xpath = get_xpath(curl_multi_getcontent($this->ch));
foreach($xpath->query("/html/body/div[1]/div[". count($xpath->query('/html/body/div[1]/div')) ."]/div/div/div/div") as $result)
{
$url = $xpath->evaluate(".//h2[@class='result__title']//a/@href", $result)[0];
if ($url == null)
continue;
if (!empty($results)) // filter duplicate results
{
if (end($results)["url"] == $url->textContent)
continue;
}
$url = $url->textContent;
$url = check_for_privacy_frontend($url, $this->opts);
$title = $xpath->evaluate(".//h2[@class='result__title']", $result)[0];
$description = $xpath->evaluate(".//a[@class='result__snippet']", $result)[0];
array_push($results,
array (
"title" => htmlspecialchars($title->textContent),
"url" => htmlspecialchars($url),
"base_url" => htmlspecialchars(get_base_url($url)),
"description" => $description == null ?
"No description was provided for this site." :
htmlspecialchars($description->textContent)
)
);
}
return $results;
}
}
?>

76
engines/text/google.php Normal file
View File

@ -0,0 +1,76 @@
<?php
class GoogleRequest extends EngineRequest {
public function get_request_url() {
$query_encoded = str_replace("%22", "\"", urlencode($this->query));
$results = array();
$domain = $this->opts->google_domain;
$results_language = $this->opts->language;
$number_of_results = $this->opts->number_of_results;
$url = "https://www.google.$domain/search?q=$query_encoded&nfpr=1&start=$this->page";
if (3 > strlen($results_language) && 0 < strlen($results_language)) {
$url .= "&lr=lang_$results_language";
$url .= "&hl=$results_language";
}
if (3 > strlen($number_of_results) && 0 < strlen($number_of_results))
$url .= "&num=$number_of_results";
if (isset($_COOKIE["safe_search"]))
$url .= "&safe=medium";
return $url;
}
public function get_results() {
$results = array();
$xpath = get_xpath(curl_multi_getcontent($this->ch));
if (!$xpath)
return $results;
$didyoumean = $xpath->query(".//a[@class='gL9Hy']")[0];
if (!is_null($didyoumean))
array_push($results, array(
"did_you_mean" => $didyoumean->textContent
));
foreach($xpath->query("//div[@id='search']//div[contains(@class, 'g')]") as $result) {
$url = $xpath->evaluate(".//div[@class='yuRUbf']//a/@href", $result)[0];
if ($url == null)
continue;
if (!empty($results)) // filter duplicate results, ignore special result
{
if (end($results)["url"] == $url->textContent)
continue;
}
$url = $url->textContent;
$url = check_for_privacy_frontend($url, $this->opts);
$title = $xpath->evaluate(".//h3", $result)[0];
$description = $xpath->evaluate(".//div[contains(@class, 'VwiC3b')]", $result)[0];
array_push($results,
array (
"title" => htmlspecialchars($title->textContent),
"url" => htmlspecialchars($url),
"base_url" => htmlspecialchars(get_base_url($url)),
"description" => $description == null ?
"No description was provided for this site." :
htmlspecialchars($description->textContent)
)
);
}
return $results;
}
}
?>

145
engines/text/text.php Normal file
View File

@ -0,0 +1,145 @@
<?php
class TextSearch extends EngineRequest {
public function __construct($opts, $mh) {
$this->query = $opts->query;
$this->page = $opts->page;
$this->opts = $opts;
$this->engine = $opts->preferred_engines["text"] ?? "google";
$query_parts = explode(" ", $this->query);
$last_word_query = end($query_parts);
if (substr($this->query, 0, 1) == "!" || substr($last_word_query, 0, 1) == "!")
check_ddg_bang($this->query, $opts);
if (has_cooldown($this->engine, $this->opts->cooldowns))
return;
if ($this->engine == "google") {
require "engines/text/google.php";
$this->engine_request = new GoogleRequest($opts, $mh);
}
if ($this->engine == "duckduckgo") {
require "engines/text/duckduckgo.php";
$this->engine_request = new DuckDuckGoRequest($opts, $mh);
}
require "engines/special/special.php";
$this->special_request = get_special_search_request($opts, $mh);
}
public function get_results() {
if (!$this->engine_request)
return array();
$results = $this->engine_request->get_results();
if ($this->special_request) {
$special_result = $this->special_request->get_results();
if ($special_result)
$results = array_merge(array($special_result), $results);
}
if (count($results) <= 1)
set_cooldown($this->engine, ($opts->request_cooldown ?? "1") * 60, $this->opts->cooldowns);
return $results;
}
public static function print_results($results) {
if (empty($results))
return;
$special = $results[0];
if (array_key_exists("did_you_mean", $special))
{
$didyoumean = $special["did_you_mean"];
$new_url = "/search.php?q=" . urlencode($didyoumean);
echo "<p class=\"did-you-mean\">Did you mean ";
echo "<a href=\"$new_url\">$didyoumean</a>";
echo "?</p>";
}
if (array_key_exists("special_response", $special))
{
$response = $special["special_response"]["response"];
$source = $special["special_response"]["source"];
echo "<p class=\"special-result-container\">";
if (array_key_exists("image", $special["special_response"]))
{
$image_url = $special["special_response"]["image"];
echo "<img src=\"image_proxy.php?url=$image_url\">";
}
echo $response;
if ($source)
echo "<a href=\"$source\" target=\"_blank\">$source</a>";
echo "</p>";
}
echo "<div class=\"text-result-container\">";
foreach($results as $result)
{
if (!array_key_exists("title", $result))
continue;
$title = $result["title"];
$url = $result["url"];
$base_url = $result["base_url"];
$description = $result["description"];
echo "<div class=\"text-result-wrapper\">";
echo "<a href=\"$url\">";
echo "$base_url";
echo "<h2>$title</h2>";
echo "</a>";
echo "<span>$description</span>";
echo "</div>";
}
echo "</div>";
}
}
function check_ddg_bang($query, $opts)
{
$bangs_json = file_get_contents("static/misc/ddg_bang.json");
$bangs = json_decode($bangs_json, true);
if (substr($query, 0, 1) == "!")
$search_word = substr(explode(" ", $query)[0], 1);
else
$search_word = substr(end(explode(" ", $query)), 1);
$bang_url = null;
foreach($bangs as $bang)
{
if ($bang["t"] == $search_word)
{
$bang_url = $bang["u"];
break;
}
}
if ($bang_url)
{
$bang_query_array = explode("!" . $search_word, $query);
$bang_query = trim(implode("", $bang_query_array));
$request_url = str_replace("{{{s}}}", str_replace('%26quot%3B','%22', urlencode($bang_query)), $bang_url);
$request_url = check_for_privacy_frontend($request_url, $opts);
header("Location: " . $request_url);
die();
}
}
?>

View File

@ -6,7 +6,7 @@
$url = $_REQUEST["url"];
$requested_root_domain = get_root_domain($url);
$allowed_domains = array("qwant.com", "wikimedia.org", get_root_domain($config->invidious_instance_for_video_results));
$allowed_domains = array("s2.qwant.com", "s1.qwant.com", "upload.wikimedia.org", get_root_domain($config->invidious_instance_for_video_results));
if (in_array($requested_root_domain, $allowed_domains))
{

View File

@ -2,22 +2,22 @@
"instances": [
{
"clearnet": "https://search.ahwx.org/",
"tor": "http://hyy7rcvknwb22v4nnoar635wntiwr4uwzhiuyimemyl4fz6k7tahj5id.onion",
"tor": "http://hyy7rcvknwb22v4nnoar635wntiwr4uwzhiuyimemyl4fz6k7tahj5id.onion/",
"i2p": null,
"country": "NL",
"librey": true
},
{
"clearnet": "https://librex.me/",
"tor": "http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion",
"i2p": "http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p",
"tor": "http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/",
"i2p": "http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/",
"country": "CA",
"librey": true
},
{
"clearnet": "https://librex.revvy.de/",
"tor": "http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion",
"i2p": "http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p",
"tor": "http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/",
"i2p": "http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/",
"country": "CA",
"librey": true
},
@ -28,6 +28,13 @@
"country": "CL",
"librey": true
},
{
"clearnet": "https://librey.org/",
"tor": "http://jxhkfulu6wpdl4apuy4dyivuowmpprvsd7e3el2z73crq7fmyv7rjkyd.onion/",
"i2p": null,
"country": "US",
"librey": true
},
{
"clearnet": "https://search.davidovski.xyz/",
"tor": null,
@ -63,6 +70,13 @@
"country": "DE",
"librey": true
},
{
"clearnet": "https://librex.nohost.network/",
"tor": null,
"i2p": null,
"country": "MX",
"librey": true
},
{
"clearnet": "https://lx.vern.cc/",
"tor": "http://lx.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion/",
@ -133,13 +147,6 @@
"country": "DE",
"librey": false
},
{
"clearnet": "https://librex.nohost.network/",
"tor": null,
"i2p": null,
"country": "MX",
"librey": false
},
{
"clearnet": "https://librex.pardesicat.xyz/",
"tor": null,

View File

@ -19,7 +19,7 @@
foreach($instances as $instance) {
$hostname = parse_url($instance["clearnet"])["host"];
$country = get_country_emote($instance["country"]) . $instnace["country"];
$country = get_country_emote($instance["country"]) . $instance["country"];
$is_tor = !is_null($instance["tor"]);
$is_i2p = !is_null($instance["i2p"]);

22
misc/cooldowns.php Normal file
View File

@ -0,0 +1,22 @@
<?php
function load_cooldowns() {
if (function_exists("apcu_fetch"))
return apcu_exists("cooldowns") ? apcu_fetch("cooldowns") : array();
return array();
}
function save_cooldowns($cooldowns) {
if (function_exists("apcu_store"))
apcu_store("cooldowns", $cooldowns);
}
function set_cooldown($instance, $timeout, $cooldowns) {
$cooldowns[$instance] = time() + $timeout;
save_cooldowns($cooldowns);
return $cooldowns;
}
function has_cooldown($instance, $cooldowns) {
return ($cooldowns[$instance] ?? 0) > time();
}
?>

View File

@ -8,9 +8,6 @@
<link rel="stylesheet" type="text/css" href="static/css/styles.css"/>
<link title="LibreY search" type="application/opensearchdescription+xml" href="opensearch.xml?method=POST" rel="search"/>
<link rel="stylesheet" type="text/css" href="<?php
echo "static/css/";
if (isset($_COOKIE["theme"]))
echo htmlspecialchars($_COOKIE["theme"] . ".css");
else
echo "dark.css";
$theme = $_REQUEST["theme"] ?? trim(htmlspecialchars($_COOKIE["theme"] ?? "dark"));
echo "static/css/" . $theme . ".css";
?>"/>

144
misc/search_engine.php Normal file
View File

@ -0,0 +1,144 @@
<?php
abstract class EngineRequest {
function __construct($opts, $mh) {
$this->query = $opts->query;
$this->page = $opts->page;
$this->opts = $opts;
$url = $this->get_request_url();
if (!$url)
return;
$this->ch = curl_init($url);
if ($opts->curl_settings)
curl_setopt_array($this->ch, $opts->curl_settings);
if ($mh)
curl_multi_add_handle($mh, $this->ch);
}
public function get_request_url() {
return "";
}
public function successful() {
return curl_getinfo($this->ch)['http_code'] == '200';
}
abstract function get_results();
static public function print_results($results){}
}
function load_opts() {
$opts = require "config.php";
$opts->request_cooldown ??= 25;
$opts->query = trim($_REQUEST["q"] ?? "");
$opts->type = (int) ($_REQUEST["t"] ?? 0);
$opts->page = (int) ($_REQUEST["p"] ?? 0);
$opts->theme = $_REQUEST["theme"] ?? trim(htmlspecialchars($_COOKIE["theme"] ?? "dark"));
$opts->safe_search = (int) ($_REQUEST["safe"] ?? 0) == 1 || isset($_COOKIE["safe_search"]);
$opts->disable_special = (int) ($_REQUEST["ns"] ?? 0) == 1 || isset($_COOKIE["disable_special"]);
$opts->disable_frontends = (int) ($_REQUEST["nf"] ?? 0) == 1 || isset($_COOKIE["disable_frontends"]);
$opts->language = $_REQUEST["lang"] ?? trim(htmlspecialchars($_COOKIE["language"] ?? $opts->language));
$opts->do_fallback = (int) ($_REQUEST["nfb"] ?? 0) == 0;
if (!$opts->instance_fallback) {
$opts->do_fallback = false;
}
$opts->number_of_results ??= trim(htmlspecialchars($_COOKIE["number_of_results"]));
foreach (array_keys($opts->frontends ?? array()) as $frontend) {
$opts->frontends[$frontend]["instance_url"] = $_COOKIE[$frontend] ?? $opts->frontends[$frontend]["instance_url"];
}
return $opts;
}
function opts_to_params($opts) {
$query = urlencode($opts->query);
$params = "";
$params .= "p=$opts->page";
$params .= "&q=$query";
$params .= "&t=$opts->type";
$params .= "&nfb=" . ($opts->do_fallback ? 0 : 1);
$params .= "&safe=" . ($opts->safe_search ? 1 : 0);
$params .= "&nf=" . ($opts->disable_frontends ? 1 : 0);
$params .= "&ns=" . ($opts->disable_special ? 1 : 0);
return $params;
}
function init_search($opts, $mh) {
switch ($opts->type)
{
case 1:
require "engines/qwant/image.php";
return new QwantImageSearch($opts, $mh);
case 2:
require "engines/invidious/video.php";
return new VideoSearch($opts, $mh);
case 3:
if ($opts->disable_bittorent_search) {
echo "<p class=\"text-result-container\">The host disabled this feature! :C</p>";
break;
}
require "engines/bittorrent/merge.php";
return new TorrentSearch($opts, $mh);
case 4:
if ($opts->disable_hidden_service_search) {
echo "<p class=\"text-result-container\">The host disabled this feature! :C</p>";
break;
}
require "engines/ahmia/hidden_service.php";
return new TorSearch($opts, $mh);
default:
require "engines/text/text.php";
return new TextSearch($opts, $mh);
}
}
function fetch_search_results($opts, $do_print) {
require "misc/cooldowns.php";
$opts->cooldowns = load_cooldowns();
$start_time = microtime(true);
$mh = curl_multi_init();
$search_category = init_search($opts, $mh);
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running);
$results = $search_category->get_results();
if (count($results) <= 1) {
require "engines/librex/fallback.php";
$results = get_librex_results($opts);
}
if (!$do_print)
return $results;
print_elapsed_time($start_time);
$search_category->print_results($results);
return $results;
}
?>

View File

@ -1,69 +1,43 @@
<?php
function get_base_url($url)
{
function get_base_url($url) {
$split_url = explode("/", $url);
$base_url = $split_url[0] . "//" . $split_url[2] . "/";
return $base_url;
}
function get_root_domain($url)
{
$split_url = explode("/", $url);
$base_url = $split_url[2];
$base_url_main_split = explode(".", strrev($base_url));
$root_domain = strrev($base_url_main_split[1]) . "." . strrev($base_url_main_split[0]);
return $root_domain;
function get_root_domain($url) {
return parse_url($url, PHP_URL_HOST);
}
function try_replace_with_frontend($url, $frontend, $original)
{
global $config;
$frontends = $config->frontends;
function try_replace_with_frontend($url, $frontend, $original, $opts) {
$frontends = $opts->frontends;
if (isset($_COOKIE[$frontend]) || !empty($frontends[$frontend]["instance_url"]))
{
if (isset($_COOKIE[$frontend]))
$frontend = $_COOKIE[$frontend];
else if (!empty($frontends[$frontend]["instance_url"]))
$frontend = $frontends[$frontend]["instance_url"];
if (array_key_exists($frontend, $opts->frontends)) {
$frontend = $frontends[$frontend]["instance_url"];
if (empty(trim($frontend)))
return $url;
if (strpos($url, "wikipedia.org") !== false)
{
if (strpos($url, "wikipedia.org") !== false) {
$wiki_split = explode(".", $url);
if (count($wiki_split) > 1)
{
if (count($wiki_split) > 1) {
$lang = explode("://", $wiki_split[0])[1];
$url = $frontend . explode($original, $url)[1] . (strpos($url, "?") !== false ? "&" : "?") . "lang=" . $lang;
}
}
else if (strpos($url, "fandom.com") !== false)
{
} else if (strpos($url, "fandom.com") !== false) {
$fandom_split = explode(".", $url);
if (count($fandom_split) > 1)
{
if (count($fandom_split) > 1) {
$wiki_name = explode("://", $fandom_split[0])[1];
$url = $frontend . "/" . $wiki_name . explode($original, $url)[1];
}
}
else if (strpos($url, "gist.github.com") !== false)
{
} else if (strpos($url, "gist.github.com") !== false) {
$gist_path = explode("gist.github.com", $url)[1];
$url = $frontend . "/gist" . $gist_path;
}
else if (strpos($url, "stackexchange.com") !== false)
{
} else if (strpos($url, "stackexchange.com") !== false) {
$se_domain = explode(".", explode("://", $url)[1])[0];
$se_path = explode("stackexchange.com", $url)[1];
$url = $frontend . "/exchange" . "/" . $se_domain . $se_path;
}
else
{
} else {
$url = $frontend . explode($original, $url)[1];
}
@ -74,26 +48,18 @@
return $url;
}
function check_for_privacy_frontend($url)
{
global $config;
if (isset($_COOKIE["disable_frontends"]))
function check_for_privacy_frontend($url, $opts) {
if ($opts->disable_frontends)
return $url;
foreach($config->frontends as $frontend => $data)
{
foreach($opts->frontends as $frontend => $data) {
$original = $data["original_url"];
if (strpos($url, $original))
{
$url = try_replace_with_frontend($url, $frontend, $original);
if (strpos($url, $original)) {
$url = try_replace_with_frontend($url, $frontend, $original, $opts);
break;
}
else if (strpos($url, "stackexchange.com"))
{
$url = try_replace_with_frontend($url, "anonymousoverflow", "stackexchange.com");
} else if (strpos($url, "stackexchange.com")) {
$url = try_replace_with_frontend($url, "anonymousoverflow", "stackexchange.com", $opts);
break;
}
}
@ -101,88 +67,10 @@
return $url;
}
function check_ddg_bang($query)
{
function get_xpath($response) {
if (!$response)
return null;
$bangs_json = file_get_contents("static/misc/ddg_bang.json");
$bangs = json_decode($bangs_json, true);
if (substr($query, 0, 1) == "!")
$search_word = substr(explode(" ", $query)[0], 1);
else
$search_word = substr(end(explode(" ", $query)), 1);
$bang_url = null;
foreach($bangs as $bang)
{
if ($bang["t"] == $search_word)
{
$bang_url = $bang["u"];
break;
}
}
if ($bang_url)
{
$bang_query_array = explode("!" . $search_word, $query);
$bang_query = trim(implode("", $bang_query_array));
$request_url = str_replace("{{{s}}}", str_replace('%26quot%3B','%22', urlencode($bang_query)), $bang_url);
$request_url = check_for_privacy_frontend($request_url);
header("Location: " . $request_url);
die();
}
}
function check_for_special_search($query)
{
if (isset($_COOKIE["disable_special"]))
return 0;
$query_lower = strtolower($query);
$split_query = explode(" ", $query);
if (strpos($query_lower, "to") && count($split_query) >= 4) // currency
{
$amount_to_convert = floatval($split_query[0]);
if ($amount_to_convert != 0)
return 1;
}
else if (strpos($query_lower, "mean") && count($split_query) >= 2) // definition
{
return 2;
}
else if (strpos($query_lower, "my") !== false)
{
if (strpos($query_lower, "ip"))
{
return 3;
}
else if (strpos($query_lower, "user agent") || strpos($query_lower, "ua"))
{
return 4;
}
}
else if (strpos($query_lower, "weather") !== false)
{
return 5;
}
else if ($query_lower == "tor")
{
return 6;
}
else if (3 > count(explode(" ", $query))) // wikipedia
{
return 7;
}
return 0;
}
function get_xpath($response)
{
$htmlDom = new DOMDocument;
@$htmlDom->loadHTML($response);
$xpath = new DOMXPath($htmlDom);
@ -190,9 +78,8 @@
return $xpath;
}
function request($url)
{
global $config;
function request($url) {
$config ??= require "config.php";
$ch = curl_init($url);
curl_setopt_array($ch, $config->curl_settings);
@ -201,28 +88,24 @@
return $response;
}
function human_filesize($bytes, $dec = 2)
{
function human_filesize($bytes, $dec = 2) {
$size = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
$factor = floor((strlen($bytes) - 1) / 3);
return sprintf("%.{$dec}f ", $bytes / pow(1024, $factor)) . @$size[$factor];
}
function remove_special($string)
{
function remove_special($string) {
$string = preg_replace("/[\r\n]+/", "\n", $string);
return trim(preg_replace("/\s+/", ' ', $string));
}
function print_elapsed_time($start_time)
{
function print_elapsed_time($start_time) {
$end_time = number_format(microtime(true) - $start_time, 2, '.', '');
echo "<p id=\"time\">Fetched the results in $end_time seconds</p>";
}
function print_next_page_button($text, $page, $query, $type)
{
function print_next_page_button($text, $page, $query, $type) {
echo "<form class=\"page\" action=\"search.php\" target=\"_top\" method=\"get\" autocomplete=\"off\">";
echo "<input type=\"hidden\" name=\"p\" value=\"" . $page . "\" />";
echo "<input type=\"hidden\" name=\"q\" value=\"$query\" />";
@ -231,15 +114,13 @@
echo "</form>";
}
function copy_cookies($curl)
{
function copy_cookies($curl) {
if (array_key_exists("HTTP_COOKIE", $_SERVER))
curl_setopt( $curl, CURLOPT_COOKIE, $_SERVER['HTTP_COOKIE'] );
}
function get_country_emote($code)
{
function get_country_emote($code) {
$emoji = [];
foreach(str_split($code) as $c) {
if(($o = ord($c)) > 64 && $o % 32 < 27) {

View File

@ -1,14 +1,34 @@
<?php
<?php
require "misc/header.php";
$config = require "config.php";
require "misc/tools.php";
require "misc/search_engine.php";
$opts = load_opts();
function print_page_buttons($type, $query, $page) {
if ($type > 1)
return;
echo "<div class=\"next-page-button-wrapper\">";
if ($page != 0)
{
print_next_page_button("&lt;&lt;", 0, $query, $type);
print_next_page_button("&lt;", $page - 10, $query, $type);
}
for ($i=$page / 10; $page / 10 + 10 > $i; $i++)
print_next_page_button($i + 1, $i * 10, $query, $type);
print_next_page_button("&gt;", $page + 10, $query, $type);
echo "</div>";
}
?>
<title>
<?php
$query = trim($_REQUEST["q"]);
echo $query;
echo $opts->query;
?> - LibreY</title>
</head>
<body>
@ -16,21 +36,18 @@
<h1 class="logomobile"><a class="no-decoration" href="./">Libre<span class="Y">Y</span></a></h1>
<input type="text" name="q"
<?php
$query_encoded = urlencode($query);
if (1 > strlen($query) || strlen($query) > 256)
if (1 > strlen($opts->query) || strlen($opts->query) > 256)
{
header("Location: ./");
die();
}
echo "value=\"" . htmlspecialchars($query) . "\"";
echo "value=\"" . htmlspecialchars($opts->query) . "\"";
?>
>
<br>
<?php
$type = isset($_REQUEST["t"]) ? (int) $_REQUEST["t"] : 0;
echo "<button class=\"hide\" name=\"t\" value=\"$type\"/></button>";
echo "<button class=\"hide\" name=\"t\" value=\"$opts->type\"/></button>";
?>
<button type="submit" class="hide"></button>
<input type="hidden" name="p" value="0">
@ -42,107 +59,21 @@
{
$category_index = array_search($category, $categories);
if (($config->disable_bittorent_search && $category_index == 3) ||
($config->disable_hidden_service_search && $category_index ==4))
if (($opts->disable_bittorent_search && $category_index == 3) ||
($opts->disable_hidden_service_search && $category_index ==4))
{
continue;
}
echo "<a " . (($category_index == $type) ? "class=\"active\" " : "") . "href=\"./search.php?q=" . $query . "&p=0&t=" . $category_index . "\"><img src=\"static/images/" . $category . "_result.png\" alt=\"" . $category . " result\" />" . ucfirst($category) . "</a>";
echo "<a " . (($category_index == $opts->type) ? "class=\"active\" " : "") . "href=\"./search.php?q=" . urlencode($opts->query) . "&p=0&t=" . $category_index . "\"><img src=\"static/images/" . $category . "_result.png\" alt=\"" . $category . " result\" />" . ucfirst($category) . "</a>";
}
?>
</div>
<hr>
</form>
<?php
$page = isset($_REQUEST["p"]) ? (int) $_REQUEST["p"] : 0;
$start_time = microtime(true);
switch ($type)
{
case 0:
$engine=$config->preferred_engines['text'];
if (is_null($engine))
$engine = "google";
$query_parts = explode(" ", $query);
$last_word_query = end($query_parts);
if (substr($query, 0, 1) == "!" || substr($last_word_query, 0, 1) == "!")
check_ddg_bang($query);
require "engines/$engine/text.php";
$results = get_text_results($query, $page);
print_elapsed_time($start_time);
print_text_results($results);
break;
case 1:
require "engines/qwant/image.php";
$results = get_image_results($query_encoded, $page);
print_elapsed_time($start_time);
print_image_results($results);
break;
case 2:
require "engines/invidious/video.php";
$results = get_video_results($query_encoded);
print_elapsed_time($start_time);
print_video_results($results);
break;
case 3:
if ($config->disable_bittorent_search)
echo "<p class=\"text-result-container\">The host disabled this feature! :C</p>";
else
{
require "engines/bittorrent/merge.php";
$results = get_merged_torrent_results($query_encoded);
print_elapsed_time($start_time);
print_merged_torrent_results($results);
}
break;
case 4:
if ($config->disable_hidden_service_search)
echo "<p class=\"text-result-container\">The host disabled this feature! :C</p>";
else
{
require "engines/ahmia/hidden_service.php";
$results = get_hidden_service_results($query_encoded);
print_elapsed_time($start_time);
print_hidden_service_results($results);
}
break;
default:
$query_parts = explode(" ", $query);
$last_word_query = end($query_parts);
if (substr($query, 0, 1) == "!" || substr($last_word_query, 0, 1) == "!")
check_ddg_bang($query);
require "engines/google/text.php";
$results = get_text_results($query, $page);
print_elapsed_time($start_time);
print_text_results($results);
break;
}
if (2 > $type)
{
echo "<div class=\"next-page-button-wrapper\">";
if ($page != 0)
{
print_next_page_button("&lt;&lt;", 0, $query, $type);
print_next_page_button("&lt;", $page - 10, $query, $type);
}
for ($i=$page / 10; $page / 10 + 10 > $i; $i++)
print_next_page_button($i + 1, $i * 10, $query, $type);
print_next_page_button("&gt;", $page + 10, $query, $type);
echo "</div>";
}
fetch_search_results($opts, true);
print_page_buttons($opts->type, $opts->query, $opts->page);
?>
<?php require "misc/footer.php"; ?>

View File

@ -1,40 +1,35 @@
<?php
$config = require "config.php";
require "misc/search_engine.php";
$opts = load_opts();
// Reset all cookies when resetting, or before saving new cookies
if (isset($_REQUEST["reset"]) || isset($_REQUEST["save"]))
{
if (isset($_SERVER["HTTP_COOKIE"]))
{
$cookies = explode(";", $_SERVER["HTTP_COOKIE"]);
foreach($cookies as $cookie)
{
$parts = explode("=", $cookie);
$name = trim($parts[0]);
setcookie($name, "", time() - 1000, '/');
}
}
// Reset all cookies when resetting, or before saving new cookies
if (isset($_REQUEST["reset"]) || isset($_REQUEST["save"])) {
if (isset($_SERVER["HTTP_COOKIE"])) {
$cookies = explode(";", $_SERVER["HTTP_COOKIE"]);
foreach($cookies as $cookie) {
$parts = explode("=", $cookie);
$name = trim($parts[0]);
setcookie($name, "", time() - 1000);
}
}
}
// save new cookies
if (isset($_REQUEST["save"]))
{
foreach($_POST as $key=>$value)
{
if (empty($value) || $key === "save")
continue;
if (isset($_REQUEST["save"])) {
foreach($_POST as $key=>$value) {
if (!empty($value)) {
setcookie($key, $value, time() + (86400 * 90), '/');
} else {
setcookie($key, "", time() - 1000);
}
}
}
setcookie($key, $value, time() + (86400 * 90), '/');
}
}
if (isset($_REQUEST["save"]) || isset($_REQUEST["reset"]))
{
header("Location: ./");
die();
}
require "misc/header.php";
if (isset($_REQUEST["save"]) || isset($_REQUEST["reset"])) {
header("Location: ./");
die();
}
require "misc/header.php";
?>
<title>LibreY - Settings</title>
@ -64,10 +59,9 @@
<option value=\"ubuntu\">Ubuntu</option>
<option value=\"tokyo_night\">Tokyo night</option>";
if (isset($_COOKIE["theme"]))
{
$cookie_theme = $_COOKIE["theme"];
$themes = str_replace($cookie_theme . "\"", $cookie_theme . "\" selected", $themes);
if (isset($_COOKIE["theme"])) {
$theme = $opts->theme;
$themes = str_replace($theme . "\"", $theme . "\" selected", $themes);
}
echo $themes;
@ -76,19 +70,19 @@
</div>
<div>
<label>Disable special queries (e.g.: currency conversion)</label>
<input type="checkbox" name="disable_special" <?php echo isset($_COOKIE["disable_special"]) ? "checked" : ""; ?> >
<input type="checkbox" name="disable_special" <?php echo $opts->disable_special ? "checked" : ""; ?> >
</div>
<h2>Privacy friendly frontends</h2>
<p>For an example if you want to view YouTube without getting spied on, click on "Invidious", find the instance that is most suitable for you then paste it in (correct format: https://example.com)</p>
<div class="settings-textbox-container">
<?php
foreach($config->frontends as $frontend => $data)
foreach($opts->frontends as $frontend => $data)
{
echo "<div>";
echo "<a for=\"$frontend\" href=\"" . $data["project_url"] . "\" target=\"_blank\">" . ucfirst($frontend) . "</a>";
echo "<input type=\"text\" name=\"$frontend\" placeholder=\"Replace " . $data["original_name"] . "\" value=";
echo isset($_COOKIE["$frontend"]) ? htmlspecialchars($_COOKIE["$frontend"]) : $data["instance_url"];
echo htmlspecialchars($opts->frontends["$frontend"]["instance_url"] ?? "");
echo ">";
echo "</div>";
}
@ -96,43 +90,25 @@
</div>
<div>
<label>Disable frontends</label>
<input type="checkbox" name="disable_frontends" <?php echo isset($_COOKIE["disable_frontends"]) ? "checked" : ""; ?> >
<input type="checkbox" name="disable_frontends" <?php echo $opts->disable_frontends ? "checked" : ""; ?> >
</div>
<h2>Search settings</h2>
<div class="settings-textbox-container">
<div>
<span>Site language</span>
<span>Language</span>
<?php
echo "<input type=\"text\" name=\"google_language_site\" placeholder=\"E.g.: en\" value=\"";
echo isset($_COOKIE["google_language_site"]) ? htmlspecialchars($_COOKIE["google_language_site"]) : $config->google_language_site;
?>">
</div>
<div>
<span>Results language</span>
<?php
echo "<input type=\"text\" name=\"google_language_results\" placeholder=\"E.g.: de\" value=\"";
echo isset($_COOKIE["google_language_results"]) ? htmlspecialchars($_COOKIE["google_language_results"]) : $config->google_language_results;
?>">
// TODO make this a dropdown
echo "<input type=\"text\" name=\"language\" placeholder=\"any\" value=\"" . htmlspecialchars($opts->language ?? "") . "\">";
?>
</div>
<div>
<label>Number of results per page</label>
<input type="number" name="google_number_of_results" value="<?php echo isset($_COOKIE["google_number_of_results"]) ? $_COOKIE["google_number_of_results"] : $config->google_number_of_results; ?>" >
<input type="number" name="number_of_results" value="<?php echo htmlspecialchars($opts->number_of_results ?? "10") ?>" >
</div>
<div>
<label>Safe search</label>
<input type="checkbox" name="safe_search" <?php echo isset($_COOKIE["safe_search"]) ? "checked" : ""; ?> >
</div>
</div>
<h2>Wikipedia settings</h2>
<div class="settings-textbox-container">
<div>
<span>Results language</span>
<?php
echo "<input type=\"text\" name=\"wikipedia_language\" placeholder=\"E.g.: en\" value=\"";
echo isset($_COOKIE["wikipedia_language"]) ? htmlspecialchars($_COOKIE["wikipedia_language"]) : $config->wikipedia_language;
?>">
<input type="checkbox" name="safe_search" <?php echo $opts->safe_search ? "checked" : ""; ?> >
</div>
</div>

View File

@ -32,13 +32,13 @@ a,
.special-result-container a,
.did-you-mean a,
.sub-search-button-wrapper a,
.sub-search-button-wrapper a:visited{
.sub-search-button-wrapper a:visited {
color: #bd93f9;
}
.sub-search-button-wrapper .active {
border-bottom: 2px #bd93f9 solid;
padding-bottom: 6px;
padding-bottom: 10px;
}
a:hover,
@ -119,6 +119,7 @@ a:hover,
.sub-search-button-wrapper {
margin-left: 165px;
margin-bottom: 10px;
}
.search-button-wrapper button:hover,
@ -136,9 +137,9 @@ a:hover,
border: none;
background-color: inherit;
font-size: 15px;
margin-right: 14px;
cursor: pointer;
text-decoration: none;
margin-right: 20px;
cursor: pointer;
text-decoration: none;
}
.sub-search-button-wrapper img {
@ -303,8 +304,7 @@ a[title] {
width: 100vw;
left: 0;
background-color: var(--footer-bg);
padding-top: 15px;
padding-bottom: 15px;
padding: 10px;
border-top: 1px solid var(--border);
text-align: center;
}
@ -477,4 +477,12 @@ a[title] {
.next-page-button-wrapper {
margin-top: 30px;
}
}
.text-result-container,
#time,
.next-page-button-wrapper,
.did-you-mean {
margin-left: 20px;
}
}