Compare commits
29 changed files with 599 additions and 1283 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -1,5 +1,3 @@
|
||||||
/bin
|
/bin
|
||||||
/obj
|
/obj
|
||||||
config.ini
|
config.ini
|
||||||
|
|
||||||
/result
|
|
||||||
|
|
@ -12,7 +12,7 @@ RUN apk add --no-cache \
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY . /app
|
COPY . /app
|
||||||
|
|
||||||
RUN git clone https://git.bwaaa.space/beaker /tmp/beaker && \
|
RUN git clone https://git.bwaaa.monster/beaker /tmp/beaker && \
|
||||||
cd /tmp/beaker && \
|
cd /tmp/beaker && \
|
||||||
make && make install && \
|
make && make install && \
|
||||||
rm -rf /tmp/beaker
|
rm -rf /tmp/beaker
|
||||||
|
|
|
||||||
3
Makefile
3
Makefile
|
|
@ -7,9 +7,8 @@ GIT_HASH := $(shell git rev-parse --short HEAD)
|
||||||
GIT_DATE := $(shell git log -1 --format='%ad' --date='format:%y.%m.%d')
|
GIT_DATE := $(shell git log -1 --format='%ad' --date='format:%y.%m.%d')
|
||||||
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
|
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
|
||||||
GIT_REMOTE := $(shell git remote get-url origin)
|
GIT_REMOTE := $(shell git remote get-url origin)
|
||||||
GIT_TAG := $(shell git describe --tags --exact-match HEAD 2>/dev/null)
|
|
||||||
|
|
||||||
VERSION := $(if $(GIT_TAG),$(GIT_TAG),$(GIT_DATE)+$(GIT_HASH)_$(GIT_BRANCH))
|
VERSION := $(GIT_DATE)+$(GIT_HASH)_$(GIT_BRANCH)
|
||||||
|
|
||||||
CFLAGS := -Wall -Wextra -O2 -Isrc -DVERSION='"$(VERSION)"' -DGIT_REMOTE='"$(GIT_REMOTE)"'
|
CFLAGS := -Wall -Wextra -O2 -Isrc -DVERSION='"$(VERSION)"' -DGIT_REMOTE='"$(GIT_REMOTE)"'
|
||||||
|
|
||||||
|
|
|
||||||
36
README.md
36
README.md
|
|
@ -11,7 +11,7 @@ Create a config.ini, there is an example included in the root. Or if you install
|
||||||
## Dependencies
|
## Dependencies
|
||||||
- libxml2
|
- libxml2
|
||||||
- libcurl (may be replaced in the future with curl-impersonate)
|
- libcurl (may be replaced in the future with curl-impersonate)
|
||||||
- beaker [(source)](https://git.bwaaa.space/beaker/)
|
- beaker [(source)](https://git.bwaaa.monster/beaker/)
|
||||||
|
|
||||||
## First Setup
|
## First Setup
|
||||||
Depending on your system, you may first need to install libcurl and libxml2.
|
Depending on your system, you may first need to install libcurl and libxml2.
|
||||||
|
|
@ -47,32 +47,6 @@ On Alpine, `shadow` is needed for the user creation process during the install.
|
||||||
# xbps-install -S libxml2-devel libcurl-devel
|
# xbps-install -S libxml2-devel libcurl-devel
|
||||||
```
|
```
|
||||||
|
|
||||||
### NixOS
|
|
||||||
Add the flake to your inputs and import the module. That is all you need.
|
|
||||||
Here's an example of using the modules in a flake:
|
|
||||||
```nix
|
|
||||||
# flake.nix
|
|
||||||
{
|
|
||||||
inputs = {
|
|
||||||
omnisearch = {
|
|
||||||
url = "git+https://git.bwaaa.monster/omnisearch";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs = { self, nixpkgs, omnisearch, ... }: {
|
|
||||||
nixosConfigurations.mySystem = nixpkgs.lib.nixosSystem {
|
|
||||||
modules = [
|
|
||||||
omnisearch.nixosModules.default
|
|
||||||
{
|
|
||||||
services.omnisearch.enable = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### macOS (Homebrew)
|
### macOS (Homebrew)
|
||||||
```
|
```
|
||||||
$ brew install libxml2 curl openssl pkg-config
|
$ brew install libxml2 curl openssl pkg-config
|
||||||
|
|
@ -87,7 +61,7 @@ On macOS the build uses `pkg-config` to discover `libxml2`, `libcurl` and OpenSS
|
||||||
|
|
||||||
Install libbeaker:
|
Install libbeaker:
|
||||||
```
|
```
|
||||||
$ git clone https://git.bwaaa.space/beaker
|
$ git clone https://git.bwaaa.monster/beaker
|
||||||
$ cd beaker
|
$ cd beaker
|
||||||
$ make
|
$ make
|
||||||
# make install
|
# make install
|
||||||
|
|
@ -97,7 +71,7 @@ On macOS `beaker` installs to `/usr/local/` by default and installs `libbeaker.d
|
||||||
|
|
||||||
And then install omnisearch:
|
And then install omnisearch:
|
||||||
```
|
```
|
||||||
$ git clone https://git.bwaaa.space/omnisearch
|
$ git clone https://git.bwaaa.monster/omnisearch
|
||||||
$ cd omnisearch
|
$ cd omnisearch
|
||||||
$ make
|
$ make
|
||||||
# make install-<init>
|
# make install-<init>
|
||||||
|
|
@ -115,7 +89,7 @@ You need Docker or Podman and Docker Compose installed on your system.
|
||||||
Run the container:
|
Run the container:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ git clone https://git.bwaaa.space/omnisearch
|
$ git clone https://git.bwaaa.monster/omnisearch
|
||||||
$ cd omnisearch
|
$ cd omnisearch
|
||||||
$ docker compose up -d --build
|
$ docker compose up -d --build
|
||||||
```
|
```
|
||||||
|
|
@ -139,6 +113,6 @@ $ git merge origin/master
|
||||||
If there are conflicts in the files you modified, resolve them manually. You should also make the changes to the cloned repository, and then run the install command again if you installed omnisearch. Changes made directly to the configuration/assets folder will be overwritten on reinstall.
|
If there are conflicts in the files you modified, resolve them manually. You should also make the changes to the cloned repository, and then run the install command again if you installed omnisearch. Changes made directly to the configuration/assets folder will be overwritten on reinstall.
|
||||||
|
|
||||||
## Contribution
|
## Contribution
|
||||||
Generate a patch with ```git format-patch HEAD~1``` and email to [frostinator33@airmail.cc](mailto:frostinator33@airmail.cc), beginning the subject line with [PATCH omnisearch]
|
Generate a patch with ```git format-patch HEAD~1``` and email to [gabriel@bwaaa.monster](mailto:gabriel@bwaaa.monster), beginning the subject line with [PATCH omnisearch]
|
||||||
|
|
||||||
*If you are sending a revised version of a previous patch, please use [PATCH omnisearch v2, v3, etc].*
|
*If you are sending a revised version of a previous patch, please use [PATCH omnisearch v2, v3, etc].*
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,8 @@ port = 8087
|
||||||
[engines]
|
[engines]
|
||||||
# Use * for all engines, or specify comma-separated list (e.g., ddg,yahoo)
|
# Use * for all engines, or specify comma-separated list (e.g., ddg,yahoo)
|
||||||
# Use *,-engine to exclude specific engines (e.g., *,-startpage)
|
# Use *,-engine to exclude specific engines (e.g., *,-startpage)
|
||||||
# Available engines: ddg, startpage, yahoo, mojeek, yacy
|
# Available engines: ddg, startpage, yahoo, mojeek
|
||||||
engines="*"
|
engines="*"
|
||||||
# YaCy instance to use for the yacy engine (optional, default: http://127.0.0.1:8090)
|
|
||||||
# Requires "yacy" to be in the engines list above.
|
|
||||||
#yacy_instance = http://127.0.0.1:8090
|
|
||||||
|
|
||||||
[rate_limit]
|
[rate_limit]
|
||||||
# Rate limit searches per interval
|
# Rate limit searches per interval
|
||||||
|
|
|
||||||
43
flake.lock
generated
43
flake.lock
generated
|
|
@ -1,43 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"beaker-src": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1790704008,
|
|
||||||
"narHash": "sha256-Al/BE7uVRSmUGF/t1m0pWxF9jNgzdCVUrc5ZHkcPiQg=",
|
|
||||||
"ref": "refs/heads/master",
|
|
||||||
"rev": "10be7f581fb828e74f064ea7ad4fb0534ee8540a",
|
|
||||||
"revCount": 46,
|
|
||||||
"shallow": false,
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://git.bwaaa.space/beaker"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"shallow": false,
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://git.bwaaa.space/beaker"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1791456040,
|
|
||||||
"narHash": "sha256-gRZ/s8WQJ2CsXdhcDVQH34qxuL0MuMCOs3aBiK1Prsw=",
|
|
||||||
"rev": "e7439b6b14ad3cc35d05608ebca9bce01a25f5f8",
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.11pre1087755.e7439b6b14ad/nixexprs.tar.zst?lastModified=1791456040&rev=e7439b6b14ad3cc35d05608ebca9bce01a25f5f8"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.zst"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"beaker-src": "beaker-src",
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
||||||
76
flake.nix
76
flake.nix
|
|
@ -1,76 +0,0 @@
|
||||||
{
|
|
||||||
inputs = {
|
|
||||||
nixpkgs.url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.zst";
|
|
||||||
beaker-src = {
|
|
||||||
url = "git+https://git.bwaaa.space/beaker?shallow=0";
|
|
||||||
flake = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs =
|
|
||||||
{
|
|
||||||
self,
|
|
||||||
nixpkgs,
|
|
||||||
beaker-src,
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
supportedSystems = [
|
|
||||||
"x86_64-linux"
|
|
||||||
"aarch64-linux"
|
|
||||||
];
|
|
||||||
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
formatter = forAllSystems (system: nixpkgs.legacyPackages.${system}.nixfmt);
|
|
||||||
packages = forAllSystems (
|
|
||||||
system:
|
|
||||||
let
|
|
||||||
pkgs = import nixpkgs { inherit system; };
|
|
||||||
|
|
||||||
beaker = pkgs.stdenv.mkDerivation {
|
|
||||||
pname = "beaker";
|
|
||||||
version = "git";
|
|
||||||
src = beaker-src;
|
|
||||||
makeFlags = [
|
|
||||||
"INSTALL_PREFIX=$(out)/"
|
|
||||||
"LDCONFIG=true"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
default = pkgs.stdenv.mkDerivation {
|
|
||||||
pname = "omnisearch";
|
|
||||||
version = "git";
|
|
||||||
src = ./.;
|
|
||||||
|
|
||||||
buildInputs = [
|
|
||||||
pkgs.libxml2.dev
|
|
||||||
pkgs.curl.dev
|
|
||||||
pkgs.openssl
|
|
||||||
beaker
|
|
||||||
];
|
|
||||||
|
|
||||||
preBuild = ''
|
|
||||||
makeFlagsArray+=(
|
|
||||||
"PREFIX=$out"
|
|
||||||
"CFLAGS=-Wall -Wextra -O2 -Isrc -I${pkgs.libxml2.dev}/include/libxml2 -I${beaker}/include/beaker.h"
|
|
||||||
"LIBS=-lbeaker -lcurl -lxml2 -lpthread -lm -lssl -lcrypto"
|
|
||||||
)
|
|
||||||
'';
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p $out/bin $out/share/omnisearch
|
|
||||||
install -Dm755 bin/omnisearch $out/bin/omnisearch
|
|
||||||
cp -r templates static locales -t $out/share/omnisearch/
|
|
||||||
'';
|
|
||||||
|
|
||||||
meta = {
|
|
||||||
description = "Lightweight metasearch engine in C";
|
|
||||||
platforms = pkgs.lib.platforms.linux;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
nixosModules.default = import ./module.nix self;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -21,8 +21,6 @@ display_language_label = "Display Language"
|
||||||
language_desc = "Choose your preferred language."
|
language_desc = "Choose your preferred language."
|
||||||
engines_label = "Search Engines"
|
engines_label = "Search Engines"
|
||||||
engines_desc = "Choose which search engines to use. Only engines enabled on the server are shown."
|
engines_desc = "Choose which search engines to use. Only engines enabled on the server are shown."
|
||||||
default_engine_label = "Default Search Engine"
|
|
||||||
all_engines_option = "All enabled engines"
|
|
||||||
save_settings_button = "Save Settings"
|
save_settings_button = "Save Settings"
|
||||||
no_results = "No results found"
|
no_results = "No results found"
|
||||||
error_images = "Error fetching images"
|
error_images = "Error fetching images"
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,6 @@ display_language_label = "Display Language"
|
||||||
language_desc = "Choose your preferred language."
|
language_desc = "Choose your preferred language."
|
||||||
engines_label = "Search Engines"
|
engines_label = "Search Engines"
|
||||||
engines_desc = "Choose which search engines to use. Only engines enabled on the server are shown."
|
engines_desc = "Choose which search engines to use. Only engines enabled on the server are shown."
|
||||||
default_engine_label = "Default Search Engine"
|
|
||||||
all_engines_option = "All enabled engines"
|
|
||||||
save_settings_button = "Save Settings"
|
save_settings_button = "Save Settings"
|
||||||
no_results = "No results found"
|
no_results = "No results found"
|
||||||
error_images = "Error fetching images"
|
error_images = "Error fetching images"
|
||||||
|
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
[Meta]
|
|
||||||
Id = "fi_fi"
|
|
||||||
Name = "Suomi"
|
|
||||||
Direction = "ltr"
|
|
||||||
|
|
||||||
[Keys]
|
|
||||||
search_placeholder = "Hae netistä..."
|
|
||||||
search_button = "Hae"
|
|
||||||
surprise_me_button = "Kokeilen onneani"
|
|
||||||
all_tab = "Kaikki"
|
|
||||||
images_tab = "Kuvat"
|
|
||||||
settings_tab = "Asetukset"
|
|
||||||
settings_title = "Asetukset"
|
|
||||||
theme_label = "Ulkonäkö"
|
|
||||||
theme_desc = "Valitse haluamasi väriteema."
|
|
||||||
theme_system = "Järjestelmä"
|
|
||||||
theme_light = "Vaalea"
|
|
||||||
theme_dark = "Tumma"
|
|
||||||
language_label = "Kieli"
|
|
||||||
display_language_label = "Näyttökieli"
|
|
||||||
language_desc = "Valitse haluamasi kieli."
|
|
||||||
engines_label = "Hakukoneet"
|
|
||||||
engines_desc = "Valitse mitä hakukoneita käytetään. Vain palvelimella käyttöön otetut hakukoneet näytetään."
|
|
||||||
default_engine_label = "Oletushakukone"
|
|
||||||
all_engines_option = "Kaikki valitut hakukoneet"
|
|
||||||
save_settings_button = "Tallenna asetukset"
|
|
||||||
no_results = "Ei tuloksia"
|
|
||||||
error_images = "Virhe kuvien haussa"
|
|
||||||
rate_limit = "Hidasta hieman! Sinulta on tullut liian monta hakupyyntöä!"
|
|
||||||
warning_fetch_error = "pyyntö epäonnistui ennen kuin OmniSearch ehti lukea hakutuloksia."
|
|
||||||
warning_parse_mismatch = "palautti hakutulokset muodossa jota OmniSearch ei osaa jäsentää."
|
|
||||||
warning_blocked = "palautti captchan tai muun estosivun hakutulosten sijaan."
|
|
||||||
read_more = "Lue Lisää"
|
|
||||||
view_cached = "Välimuistissa"
|
|
||||||
view_image = "Kuva"
|
|
||||||
visit_site = "Sivu"
|
|
||||||
142
module.nix
142
module.nix
|
|
@ -1,142 +0,0 @@
|
||||||
self:
|
|
||||||
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.services.omnisearch;
|
|
||||||
pkg = cfg.package;
|
|
||||||
|
|
||||||
finalConfigFile =
|
|
||||||
if cfg.configFile != null then
|
|
||||||
cfg.configFile
|
|
||||||
else
|
|
||||||
pkgs.writeText "omnisearch.ini" ''
|
|
||||||
[server]
|
|
||||||
host = ${cfg.settings.server.host}
|
|
||||||
port = ${toString cfg.settings.server.port}
|
|
||||||
domain = ${cfg.settings.server.domain}
|
|
||||||
${lib.optionalString (cfg.settings.server.locale != null) "locale = ${cfg.settings.server.locale}"}
|
|
||||||
|
|
||||||
[proxy]
|
|
||||||
${lib.optionalString (cfg.settings.proxy.proxy != null) "proxy = \"${cfg.settings.proxy.proxy}\""}
|
|
||||||
${lib.optionalString (
|
|
||||||
cfg.settings.proxy.list_file != null
|
|
||||||
) "list_file = ${cfg.settings.proxy.list_file}"}
|
|
||||||
max_retries = ${toString cfg.settings.proxy.max_retries}
|
|
||||||
randomize_username = ${lib.boolToString cfg.settings.proxy.randomize_username}
|
|
||||||
randomize_password = ${lib.boolToString cfg.settings.proxy.randomize_password}
|
|
||||||
|
|
||||||
[cache]
|
|
||||||
dir = ${cfg.settings.cache.dir}
|
|
||||||
ttl_search = ${toString cfg.settings.cache.ttl_search}
|
|
||||||
ttl_infobox = ${toString cfg.settings.cache.ttl_infobox}
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.omnisearch = {
|
|
||||||
enable = lib.mkEnableOption "OmniSearch metasearch engine";
|
|
||||||
|
|
||||||
package = lib.mkOption {
|
|
||||||
type = lib.types.package;
|
|
||||||
default = self.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
|
||||||
description = "The omnisearch package to use.";
|
|
||||||
};
|
|
||||||
|
|
||||||
configFile = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.path;
|
|
||||||
default = null;
|
|
||||||
description = "Path to a custom config.ini. Overrides 'settings'.";
|
|
||||||
};
|
|
||||||
|
|
||||||
settings = {
|
|
||||||
server = {
|
|
||||||
host = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "0.0.0.0";
|
|
||||||
};
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.port;
|
|
||||||
default = 8087;
|
|
||||||
};
|
|
||||||
domain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "http://localhost:${toString cfg.settings.server.port}";
|
|
||||||
};
|
|
||||||
locale = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.str;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
proxy = {
|
|
||||||
proxy = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.str;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
list_file = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.str;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
max_retries = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 3;
|
|
||||||
};
|
|
||||||
randomize_username = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
randomize_password = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
cache = {
|
|
||||||
dir = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "/var/cache/omnisearch";
|
|
||||||
};
|
|
||||||
ttl_search = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 3600;
|
|
||||||
};
|
|
||||||
ttl_infobox = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 86400;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
systemd.services.omnisearch = {
|
|
||||||
description = "OmniSearch Service";
|
|
||||||
after = [ "network.target" ];
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
ExecStart = "${pkg}/bin/omnisearch";
|
|
||||||
|
|
||||||
WorkingDirectory = "/var/lib/omnisearch";
|
|
||||||
StateDirectory = "omnisearch";
|
|
||||||
CacheDirectory = "omnisearch";
|
|
||||||
|
|
||||||
BindReadOnlyPaths = [
|
|
||||||
"${pkg}/share/omnisearch/templates:/var/lib/omnisearch/templates"
|
|
||||||
"${pkg}/share/omnisearch/static:/var/lib/omnisearch/static"
|
|
||||||
"${pkg}/share/omnisearch/locales:/var/lib/omnisearch/locales"
|
|
||||||
"${finalConfigFile}:/var/lib/omnisearch/config.ini"
|
|
||||||
];
|
|
||||||
|
|
||||||
DynamicUser = true;
|
|
||||||
ProtectSystem = "strict";
|
|
||||||
ProtectHome = true;
|
|
||||||
PrivateTmp = true;
|
|
||||||
Restart = "always";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
251
src/Config.c
251
src/Config.c
|
|
@ -1,189 +1,120 @@
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CONFIG_STRING,
|
|
||||||
CONFIG_INTEGER,
|
|
||||||
CONFIG_BOOLEAN,
|
|
||||||
} ConfigValueType;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char *section;
|
|
||||||
const char *key;
|
|
||||||
ConfigValueType type;
|
|
||||||
size_t offset;
|
|
||||||
size_t size;
|
|
||||||
} ConfigOption;
|
|
||||||
|
|
||||||
#define STRING_OPTION(section_name, key_name, field) \
|
|
||||||
{section_name, key_name, CONFIG_STRING, offsetof(Config, field), \
|
|
||||||
sizeof(((Config *)0)->field)}
|
|
||||||
#define INTEGER_OPTION(section_name, key_name, field) \
|
|
||||||
{section_name, key_name, CONFIG_INTEGER, offsetof(Config, field), 0}
|
|
||||||
#define BOOLEAN_OPTION(section_name, key_name, field) \
|
|
||||||
{section_name, key_name, CONFIG_BOOLEAN, offsetof(Config, field), 0}
|
|
||||||
|
|
||||||
static const ConfigOption CONFIG_OPTIONS[] = {
|
|
||||||
STRING_OPTION("server", "host", host),
|
|
||||||
INTEGER_OPTION("server", "port", port),
|
|
||||||
STRING_OPTION("server", "locale", default_locale),
|
|
||||||
STRING_OPTION("proxy", "proxy", proxy),
|
|
||||||
STRING_OPTION("proxy", "list_file", proxy_list_file),
|
|
||||||
INTEGER_OPTION("proxy", "max_retries", max_proxy_retries),
|
|
||||||
BOOLEAN_OPTION("proxy", "randomize_username", randomize_username),
|
|
||||||
BOOLEAN_OPTION("proxy", "randomize_password", randomize_password),
|
|
||||||
STRING_OPTION("cache", "dir", cache_dir),
|
|
||||||
INTEGER_OPTION("cache", "ttl_search", cache_ttl_search),
|
|
||||||
INTEGER_OPTION("cache", "ttl_infobox", cache_ttl_infobox),
|
|
||||||
INTEGER_OPTION("cache", "ttl_image", cache_ttl_image),
|
|
||||||
STRING_OPTION("engines", "engines", engines),
|
|
||||||
STRING_OPTION("engines", "yacy_instance", yacy_instance),
|
|
||||||
INTEGER_OPTION("rate_limit", "search_requests", rate_limit_search_requests),
|
|
||||||
INTEGER_OPTION("rate_limit", "search_interval", rate_limit_search_interval),
|
|
||||||
INTEGER_OPTION("rate_limit", "images_requests", rate_limit_images_requests),
|
|
||||||
INTEGER_OPTION("rate_limit", "images_interval", rate_limit_images_interval),
|
|
||||||
};
|
|
||||||
|
|
||||||
void config_set_defaults(Config *config) {
|
|
||||||
if (!config) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*config = (Config){
|
|
||||||
.host = DEFAULT_HOST,
|
|
||||||
.port = DEFAULT_PORT,
|
|
||||||
.default_locale = "en_gb",
|
|
||||||
.max_proxy_retries = DEFAULT_MAX_PROXY_RETRIES,
|
|
||||||
.cache_dir = DEFAULT_CACHE_DIR,
|
|
||||||
.cache_ttl_search = DEFAULT_CACHE_TTL_SEARCH,
|
|
||||||
.cache_ttl_infobox = DEFAULT_CACHE_TTL_INFOBOX,
|
|
||||||
.cache_ttl_image = DEFAULT_CACHE_TTL_IMAGE,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *trim(char *value) {
|
|
||||||
while (*value == ' ' || *value == '\t') {
|
|
||||||
value++;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *end = value + strlen(value);
|
|
||||||
while (end > value && (end[-1] == ' ' || end[-1] == '\t')) {
|
|
||||||
end--;
|
|
||||||
}
|
|
||||||
*end = '\0';
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *unquote(char *value) {
|
|
||||||
size_t length = strlen(value);
|
|
||||||
if (length >= 2 && (value[0] == '"' || value[0] == '\'') &&
|
|
||||||
value[length - 1] == value[0]) {
|
|
||||||
value[length - 1] = '\0';
|
|
||||||
return value + 1;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_integer(const char *value, int *result) {
|
|
||||||
char *end;
|
|
||||||
errno = 0;
|
|
||||||
long parsed = strtol(value, &end, 10);
|
|
||||||
|
|
||||||
if (value == end || *end != '\0' || errno == ERANGE || parsed < INT_MIN ||
|
|
||||||
parsed > INT_MAX) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
*result = (int)parsed;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_boolean(const char *value, int *result) {
|
|
||||||
if (strcmp(value, "1") == 0 || strcasecmp(value, "true") == 0 ||
|
|
||||||
strcasecmp(value, "yes") == 0 || strcasecmp(value, "on") == 0) {
|
|
||||||
*result = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (strcmp(value, "0") == 0 || strcasecmp(value, "false") == 0 ||
|
|
||||||
strcasecmp(value, "no") == 0 || strcasecmp(value, "off") == 0) {
|
|
||||||
*result = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_option(Config *config, const char *section, const char *key,
|
|
||||||
const char *value) {
|
|
||||||
size_t option_count = sizeof(CONFIG_OPTIONS) / sizeof(CONFIG_OPTIONS[0]);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < option_count; i++) {
|
|
||||||
const ConfigOption *option = &CONFIG_OPTIONS[i];
|
|
||||||
if (strcmp(section, option->section) != 0 ||
|
|
||||||
strcmp(key, option->key) != 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *destination = (char *)config + option->offset;
|
|
||||||
if (option->type == CONFIG_STRING) {
|
|
||||||
snprintf(destination, option->size, "%s", value);
|
|
||||||
} else if (option->type == CONFIG_INTEGER) {
|
|
||||||
parse_integer(value, destination);
|
|
||||||
} else {
|
|
||||||
parse_boolean(value, destination);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int load_config(const char *filename, Config *config) {
|
int load_config(const char *filename, Config *config) {
|
||||||
if (!filename || !config) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *file = fopen(filename, "r");
|
FILE *file = fopen(filename, "r");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char line[1024];
|
char line[512];
|
||||||
char section[64] = "";
|
char section[64] = "";
|
||||||
|
|
||||||
while (fgets(line, sizeof(line), file)) {
|
while (fgets(line, sizeof(line), file)) {
|
||||||
line[strcspn(line, "\r\n")] = '\0';
|
line[strcspn(line, "\r\n")] = 0;
|
||||||
char *content = trim(line);
|
|
||||||
|
|
||||||
if (*content == '\0' || *content == '#' || *content == ';') {
|
if (line[0] == '\0' || line[0] == '#' || line[0] == ';') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*content == '[') {
|
if (line[0] == '[') {
|
||||||
char *end = strchr(content + 1, ']');
|
char *end = strchr(line, ']');
|
||||||
if (end) {
|
if (end) {
|
||||||
*end = '\0';
|
*end = '\0';
|
||||||
snprintf(section, sizeof(section), "%s", trim(content + 1));
|
snprintf(section, sizeof(section), "%.*s", (int)(sizeof(section) - 1),
|
||||||
|
line + 1);
|
||||||
|
section[sizeof(section) - 1] = '\0';
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *delimiter = strchr(content, '=');
|
char *delimiter = strchr(line, '=');
|
||||||
if (!delimiter) {
|
if (delimiter) {
|
||||||
continue;
|
*delimiter = '\0';
|
||||||
}
|
char *key = line;
|
||||||
|
char *value = delimiter + 1;
|
||||||
|
|
||||||
*delimiter = '\0';
|
while (*key == ' ' || *key == '\t')
|
||||||
char *key = trim(content);
|
key++;
|
||||||
char *value = unquote(trim(delimiter + 1));
|
while (*value == ' ' || *value == '\t')
|
||||||
set_option(config, section, key, value);
|
value++;
|
||||||
|
|
||||||
|
char *key_end = key + strlen(key) - 1;
|
||||||
|
while (key_end > key && (*key_end == ' ' || *key_end == '\t')) {
|
||||||
|
*key_end = '\0';
|
||||||
|
key_end--;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *value_end = value + strlen(value) - 1;
|
||||||
|
while (value_end > value && (*value_end == ' ' || *value_end == '\t' ||
|
||||||
|
*value_end == '"' || *value_end == '\'')) {
|
||||||
|
*value_end = '\0';
|
||||||
|
value_end--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*value == ' ' || *value == '\t')
|
||||||
|
value++;
|
||||||
|
while (*value == '"' || *value == '\'')
|
||||||
|
value++;
|
||||||
|
|
||||||
|
if (strcmp(section, "server") == 0) {
|
||||||
|
if (strcmp(key, "host") == 0) {
|
||||||
|
strncpy(config->host, value, sizeof(config->host) - 1);
|
||||||
|
config->host[sizeof(config->host) - 1] = '\0';
|
||||||
|
} else if (strcmp(key, "port") == 0) {
|
||||||
|
config->port = atoi(value);
|
||||||
|
} else if (strcmp(key, "locale") == 0) {
|
||||||
|
strncpy(config->default_locale, value,
|
||||||
|
sizeof(config->default_locale) - 1);
|
||||||
|
config->default_locale[sizeof(config->default_locale) - 1] = '\0';
|
||||||
|
}
|
||||||
|
} else if (strcmp(section, "proxy") == 0) {
|
||||||
|
if (strcmp(key, "proxy") == 0) {
|
||||||
|
strncpy(config->proxy, value, sizeof(config->proxy) - 1);
|
||||||
|
config->proxy[sizeof(config->proxy) - 1] = '\0';
|
||||||
|
} else if (strcmp(key, "list_file") == 0) {
|
||||||
|
strncpy(config->proxy_list_file, value,
|
||||||
|
sizeof(config->proxy_list_file) - 1);
|
||||||
|
config->proxy_list_file[sizeof(config->proxy_list_file) - 1] = '\0';
|
||||||
|
} else if (strcmp(key, "max_retries") == 0) {
|
||||||
|
config->max_proxy_retries = atoi(value);
|
||||||
|
} else if (strcmp(key, "randomize_username") == 0) {
|
||||||
|
config->randomize_username = atoi(value);
|
||||||
|
} else if (strcmp(key, "randomize_password") == 0) {
|
||||||
|
config->randomize_password = atoi(value);
|
||||||
|
}
|
||||||
|
} else if (strcmp(section, "cache") == 0) {
|
||||||
|
if (strcmp(key, "dir") == 0) {
|
||||||
|
strncpy(config->cache_dir, value, sizeof(config->cache_dir) - 1);
|
||||||
|
config->cache_dir[sizeof(config->cache_dir) - 1] = '\0';
|
||||||
|
} else if (strcmp(key, "ttl_search") == 0) {
|
||||||
|
config->cache_ttl_search = atoi(value);
|
||||||
|
} else if (strcmp(key, "ttl_infobox") == 0) {
|
||||||
|
config->cache_ttl_infobox = atoi(value);
|
||||||
|
} else if (strcmp(key, "ttl_image") == 0) {
|
||||||
|
config->cache_ttl_image = atoi(value);
|
||||||
|
}
|
||||||
|
} else if (strcmp(section, "engines") == 0) {
|
||||||
|
if (strcmp(key, "engines") == 0) {
|
||||||
|
strncpy(config->engines, value, sizeof(config->engines) - 1);
|
||||||
|
config->engines[sizeof(config->engines) - 1] = '\0';
|
||||||
|
}
|
||||||
|
} else if (strcmp(section, "rate_limit") == 0) {
|
||||||
|
if (strcmp(key, "search_requests") == 0) {
|
||||||
|
config->rate_limit_search_requests = atoi(value);
|
||||||
|
} else if (strcmp(key, "search_interval") == 0) {
|
||||||
|
config->rate_limit_search_interval = atoi(value);
|
||||||
|
} else if (strcmp(key, "images_requests") == 0) {
|
||||||
|
config->rate_limit_images_requests = atoi(value);
|
||||||
|
} else if (strcmp(key, "images_interval") == 0) {
|
||||||
|
config->rate_limit_images_interval = atoi(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = ferror(file) ? -1 : 0;
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return result;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
#define DEFAULT_CACHE_TTL_INFOBOX 86400
|
#define DEFAULT_CACHE_TTL_INFOBOX 86400
|
||||||
#define DEFAULT_CACHE_TTL_IMAGE 604800
|
#define DEFAULT_CACHE_TTL_IMAGE 604800
|
||||||
#define DEFAULT_MAX_PROXY_RETRIES 3
|
#define DEFAULT_MAX_PROXY_RETRIES 3
|
||||||
#define DEFAULT_YACY_INSTANCE "http://127.0.0.1:8090"
|
|
||||||
|
|
||||||
#define BUFFER_SIZE_SMALL 256
|
#define BUFFER_SIZE_SMALL 256
|
||||||
#define BUFFER_SIZE_MEDIUM 512
|
#define BUFFER_SIZE_MEDIUM 512
|
||||||
|
|
@ -47,14 +46,12 @@ typedef struct {
|
||||||
int cache_ttl_infobox;
|
int cache_ttl_infobox;
|
||||||
int cache_ttl_image;
|
int cache_ttl_image;
|
||||||
char engines[512];
|
char engines[512];
|
||||||
char yacy_instance[512];
|
|
||||||
int rate_limit_search_requests;
|
int rate_limit_search_requests;
|
||||||
int rate_limit_search_interval;
|
int rate_limit_search_interval;
|
||||||
int rate_limit_images_requests;
|
int rate_limit_images_requests;
|
||||||
int rate_limit_images_interval;
|
int rate_limit_images_interval;
|
||||||
} Config;
|
} Config;
|
||||||
|
|
||||||
void config_set_defaults(Config *config);
|
|
||||||
int load_config(const char *filename, Config *config);
|
int load_config(const char *filename, Config *config);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
38
src/Main.c
38
src/Main.c
|
|
@ -12,7 +12,6 @@
|
||||||
#include "Routes/Home.h"
|
#include "Routes/Home.h"
|
||||||
#include "Routes/ImageProxy.h"
|
#include "Routes/ImageProxy.h"
|
||||||
#include "Routes/Images.h"
|
#include "Routes/Images.h"
|
||||||
#include "Routes/Info.h"
|
|
||||||
#include "Routes/Search.h"
|
#include "Routes/Search.h"
|
||||||
#include "Routes/Settings.h"
|
#include "Routes/Settings.h"
|
||||||
#include "Routes/SettingsSave.h"
|
#include "Routes/SettingsSave.h"
|
||||||
|
|
@ -66,8 +65,23 @@ int main() {
|
||||||
|
|
||||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
|
||||||
Config cfg;
|
Config cfg = {.host = DEFAULT_HOST,
|
||||||
config_set_defaults(&cfg);
|
.port = DEFAULT_PORT,
|
||||||
|
.default_locale = "en_gb",
|
||||||
|
.proxy = "",
|
||||||
|
.proxy_list_file = "",
|
||||||
|
.max_proxy_retries = DEFAULT_MAX_PROXY_RETRIES,
|
||||||
|
.randomize_username = 0,
|
||||||
|
.randomize_password = 0,
|
||||||
|
.cache_dir = DEFAULT_CACHE_DIR,
|
||||||
|
.cache_ttl_search = DEFAULT_CACHE_TTL_SEARCH,
|
||||||
|
.cache_ttl_infobox = DEFAULT_CACHE_TTL_INFOBOX,
|
||||||
|
.cache_ttl_image = DEFAULT_CACHE_TTL_IMAGE,
|
||||||
|
.engines = "",
|
||||||
|
.rate_limit_search_requests = 0,
|
||||||
|
.rate_limit_search_interval = 0,
|
||||||
|
.rate_limit_images_requests = 0,
|
||||||
|
.rate_limit_images_interval = 0};
|
||||||
|
|
||||||
if (load_config("config.ini", &cfg) != 0) {
|
if (load_config("config.ini", &cfg) != 0) {
|
||||||
fprintf(stderr, "[WARN] Could not load config file, using defaults\n");
|
fprintf(stderr, "[WARN] Could not load config file, using defaults\n");
|
||||||
|
|
@ -87,23 +101,6 @@ int main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_engines_config(cfg.engines);
|
apply_engines_config(cfg.engines);
|
||||||
configure_yacy_engine(cfg.yacy_instance);
|
|
||||||
|
|
||||||
if (cfg.yacy_instance[0] != '\0') {
|
|
||||||
int yacy_enabled = 0;
|
|
||||||
for (int i = 0; i < ENGINE_COUNT; i++) {
|
|
||||||
if (strcmp(ENGINE_REGISTRY[i].id, "yacy") == 0) {
|
|
||||||
yacy_enabled = ENGINE_REGISTRY[i].enabled;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!yacy_enabled) {
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
"[INFO] YaCy instance configured but the yacy engine is not "
|
|
||||||
"enabled (add it to the engines list, e.g. engines=\"*,yacy\")\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cache_init(cfg.cache_dir) != 0) {
|
if (cache_init(cfg.cache_dir) != 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
|
@ -139,7 +136,6 @@ int main() {
|
||||||
set_handler("/search", results_handler);
|
set_handler("/search", results_handler);
|
||||||
set_handler("/images", images_handler);
|
set_handler("/images", images_handler);
|
||||||
set_handler("/proxy", image_proxy_handler);
|
set_handler("/proxy", image_proxy_handler);
|
||||||
set_handler("/info", info_handler);
|
|
||||||
set_handler("/settings", settings_handler);
|
set_handler("/settings", settings_handler);
|
||||||
set_handler("/save_settings", settings_save_handler);
|
set_handler("/save_settings", settings_save_handler);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,12 +76,14 @@ int images_handler(UrlParams *params) {
|
||||||
if (!error_images_msg)
|
if (!error_images_msg)
|
||||||
error_images_msg = "Error fetching images";
|
error_images_msg = "Error fetching images";
|
||||||
|
|
||||||
StringMatrix pagination;
|
char ***pager_matrix = NULL;
|
||||||
string_matrix_build_pagination(page, images_href_builder, (void *)raw_query,
|
int *pager_inner_counts = NULL;
|
||||||
&pagination);
|
int pager_count =
|
||||||
if (pagination.count > 0) {
|
build_pagination(page, images_href_builder, (void *)raw_query,
|
||||||
context_set_array_of_arrays(&ctx, "pagination_links", pagination.rows,
|
&pager_matrix, &pager_inner_counts);
|
||||||
pagination.count, pagination.field_counts);
|
if (pager_count > 0) {
|
||||||
|
context_set_array_of_arrays(&ctx, "pagination_links", pager_matrix,
|
||||||
|
pager_count, pager_inner_counts);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *display_query = url_decode_query(raw_query);
|
char *display_query = url_decode_query(raw_query);
|
||||||
|
|
@ -89,9 +91,8 @@ int images_handler(UrlParams *params) {
|
||||||
|
|
||||||
if (!raw_query || strlen(raw_query) == 0) {
|
if (!raw_query || strlen(raw_query) == 0) {
|
||||||
send_redirect("/");
|
send_redirect("/");
|
||||||
string_matrix_free(&pagination);
|
if (display_query)
|
||||||
free(display_query);
|
free(display_query);
|
||||||
free(locale);
|
|
||||||
free_context(&ctx);
|
free_context(&ctx);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -127,9 +128,7 @@ int images_handler(UrlParams *params) {
|
||||||
snprintf(response, sizeof(response), "<h1>%s</h1>", rate_limit_msg);
|
snprintf(response, sizeof(response), "<h1>%s</h1>", rate_limit_msg);
|
||||||
send_response(response);
|
send_response(response);
|
||||||
free(request_cache_key);
|
free(request_cache_key);
|
||||||
string_matrix_free(&pagination);
|
|
||||||
free(display_query);
|
free(display_query);
|
||||||
free(locale);
|
|
||||||
free_context(&ctx);
|
free_context(&ctx);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -148,37 +147,37 @@ int images_handler(UrlParams *params) {
|
||||||
snprintf(error_html, sizeof(error_html), "<h1>%s</h1>", error_images_msg);
|
snprintf(error_html, sizeof(error_html), "<h1>%s</h1>", error_images_msg);
|
||||||
send_response(error_html);
|
send_response(error_html);
|
||||||
free(request_cache_key);
|
free(request_cache_key);
|
||||||
string_matrix_free(&pagination);
|
|
||||||
free(display_query);
|
free(display_query);
|
||||||
free(locale);
|
|
||||||
free_context(&ctx);
|
free_context(&ctx);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringMatrix images;
|
char ***image_matrix = malloc(sizeof(char **) * result_count);
|
||||||
string_matrix_init(&images);
|
int *inner_counts = malloc(sizeof(int) * result_count);
|
||||||
|
|
||||||
for (int i = 0; i < result_count; i++) {
|
if (!image_matrix || !inner_counts) {
|
||||||
const char *values[IMAGE_RESULT_FIELDS] = {
|
if (image_matrix)
|
||||||
results[i].thumbnail_url,
|
free(image_matrix);
|
||||||
results[i].title,
|
if (inner_counts)
|
||||||
results[i].page_url,
|
free(inner_counts);
|
||||||
results[i].full_url,
|
free_image_results(results, result_count);
|
||||||
};
|
free(request_cache_key);
|
||||||
if (string_matrix_append(&images, values, IMAGE_RESULT_FIELDS) != 0) {
|
free(display_query);
|
||||||
string_matrix_free(&images);
|
free_context(&ctx);
|
||||||
string_matrix_free(&pagination);
|
return -1;
|
||||||
free_image_results(results, result_count);
|
|
||||||
free(request_cache_key);
|
|
||||||
free(display_query);
|
|
||||||
free(locale);
|
|
||||||
free_context(&ctx);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
context_set_array_of_arrays(&ctx, "images", images.rows, images.count,
|
for (int i = 0; i < result_count; i++) {
|
||||||
images.field_counts);
|
image_matrix[i] = malloc(sizeof(char *) * IMAGE_RESULT_FIELDS);
|
||||||
|
image_matrix[i][0] = strdup(results[i].thumbnail_url);
|
||||||
|
image_matrix[i][1] = strdup(results[i].title);
|
||||||
|
image_matrix[i][2] = strdup(results[i].page_url);
|
||||||
|
image_matrix[i][3] = strdup(results[i].full_url);
|
||||||
|
inner_counts[i] = IMAGE_RESULT_FIELDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
context_set_array_of_arrays(&ctx, "images", image_matrix, result_count,
|
||||||
|
inner_counts);
|
||||||
|
|
||||||
char *rendered = render_template("images.html", &ctx);
|
char *rendered = render_template("images.html", &ctx);
|
||||||
if (rendered) {
|
if (rendered) {
|
||||||
|
|
@ -188,13 +187,27 @@ int images_handler(UrlParams *params) {
|
||||||
send_response("<h1>Error rendering image results</h1>");
|
send_response("<h1>Error rendering image results</h1>");
|
||||||
}
|
}
|
||||||
|
|
||||||
string_matrix_free(&images);
|
for (int i = 0; i < result_count; i++) {
|
||||||
string_matrix_free(&pagination);
|
for (int j = 0; j < IMAGE_RESULT_FIELDS; j++)
|
||||||
|
free(image_matrix[i][j]);
|
||||||
|
free(image_matrix[i]);
|
||||||
|
}
|
||||||
|
free(image_matrix);
|
||||||
|
free(inner_counts);
|
||||||
|
|
||||||
|
if (pager_count > 0) {
|
||||||
|
for (int i = 0; i < pager_count; i++) {
|
||||||
|
for (int j = 0; j < LINK_FIELD_COUNT; j++)
|
||||||
|
free(pager_matrix[i][j]);
|
||||||
|
free(pager_matrix[i]);
|
||||||
|
}
|
||||||
|
free(pager_matrix);
|
||||||
|
free(pager_inner_counts);
|
||||||
|
}
|
||||||
|
|
||||||
free_image_results(results, result_count);
|
free_image_results(results, result_count);
|
||||||
free(request_cache_key);
|
free(request_cache_key);
|
||||||
free(display_query);
|
free(display_query);
|
||||||
free(locale);
|
|
||||||
free_context(&ctx);
|
free_context(&ctx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
#include "Info.h"
|
|
||||||
#include "../Config.h"
|
|
||||||
#include "../Scraping/Scraping.h"
|
|
||||||
#include "../Utility/Utility.h"
|
|
||||||
#include <beaker.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
static int append_json(char *buf, size_t size, size_t *used, const char *format,
|
|
||||||
...) {
|
|
||||||
if (*used >= size) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
int written = vsnprintf(buf + *used, size - *used, format, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
if (written < 0 || (size_t)written >= size - *used) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
*used += (size_t)written;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int info_handler(UrlParams *params) {
|
|
||||||
(void)params;
|
|
||||||
extern Config global_config;
|
|
||||||
|
|
||||||
char json[INITIAL_BUFFER_SIZE];
|
|
||||||
size_t used = 0;
|
|
||||||
|
|
||||||
if (append_json(json, sizeof(json), &used, "{\"version\":\"%s\",", VERSION) !=
|
|
||||||
0 ||
|
|
||||||
append_json(json, sizeof(json), &used, "\"git_remote\":\"%s\",",
|
|
||||||
GIT_REMOTE) != 0 ||
|
|
||||||
append_json(json, sizeof(json), &used, "\"locale\":\"%s\",",
|
|
||||||
global_config.default_locale) != 0 ||
|
|
||||||
append_json(json, sizeof(json), &used, "\"engines\":[") != 0) {
|
|
||||||
send_response("Failed to build instance info");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int first = 1;
|
|
||||||
for (int i = 0; i < ENGINE_COUNT; i++) {
|
|
||||||
if (!ENGINE_REGISTRY[i].enabled) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (append_json(json, sizeof(json), &used,
|
|
||||||
"%s{\"id\":\"%s\",\"name\":\"%s\"}", first ? "" : ",",
|
|
||||||
ENGINE_REGISTRY[i].id, ENGINE_REGISTRY[i].name) != 0) {
|
|
||||||
send_response("Failed to build instance info");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (append_json(json, sizeof(json), &used, "]}") != 0) {
|
|
||||||
send_response("Failed to build instance info");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
serve_data(json, used, "application/json");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
#ifndef INFO_H
|
|
||||||
#define INFO_H
|
|
||||||
|
|
||||||
#include <beaker.h>
|
|
||||||
|
|
||||||
int info_handler(UrlParams *params);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -140,31 +140,29 @@ static InfoBox fetch_currency_wrapper(char *query) {
|
||||||
return fetch_currency_data(query);
|
return fetch_currency_data(query);
|
||||||
}
|
}
|
||||||
char *get_base_url(const char *input) {
|
char *get_base_url(const char *input) {
|
||||||
if (!input)
|
if (!input) return NULL;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
const char *start = input;
|
const char *start = input;
|
||||||
|
|
||||||
const char *protocol_pos = strstr(input, "://");
|
const char *protocol_pos = strstr(input, "://");
|
||||||
if (protocol_pos) {
|
if (protocol_pos) {
|
||||||
start = protocol_pos + 3;
|
start = protocol_pos + 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *end = start;
|
const char *end = start;
|
||||||
while (*end && *end != '/' && *end != '?' && *end != '#') {
|
while (*end && *end != '/' && *end != '?' && *end != '#') {
|
||||||
end++;
|
end++;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len = end - start;
|
size_t len = end - start;
|
||||||
|
|
||||||
char *domain = (char *)malloc(len + 1);
|
char *domain = (char *)malloc(len + 1);
|
||||||
if (!domain)
|
if (!domain) return NULL;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
strncpy(domain, start, len);
|
strncpy(domain, start, len);
|
||||||
domain[len] = '\0';
|
domain[len] = '\0';
|
||||||
|
|
||||||
return domain;
|
return domain;
|
||||||
}
|
}
|
||||||
static int is_calculator_query(const char *query) {
|
static int is_calculator_query(const char *query) {
|
||||||
if (!query)
|
if (!query)
|
||||||
|
|
@ -251,65 +249,88 @@ static void *infobox_thread_func(void *arg) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_infobox_to_collection(InfoBox *infobox,
|
static int add_infobox_to_collection(InfoBox *infobox, char ****collection,
|
||||||
StringMatrix *collection) {
|
int **inner_counts, int current_count) {
|
||||||
const char *values[INFOBOX_FIELD_COUNT] = {
|
*collection =
|
||||||
infobox->title, infobox->thumbnail_url, infobox->extract,
|
(char ***)realloc(*collection, sizeof(char **) * (current_count + 1));
|
||||||
infobox->url, infobox->url,
|
*inner_counts =
|
||||||
};
|
(int *)realloc(*inner_counts, sizeof(int) * (current_count + 1));
|
||||||
return string_matrix_append(collection, values, INFOBOX_FIELD_COUNT);
|
|
||||||
|
(*collection)[current_count] =
|
||||||
|
(char **)malloc(sizeof(char *) * INFOBOX_FIELD_COUNT);
|
||||||
|
(*collection)[current_count][0] =
|
||||||
|
infobox->title ? strdup(infobox->title) : NULL;
|
||||||
|
(*collection)[current_count][1] =
|
||||||
|
infobox->thumbnail_url ? strdup(infobox->thumbnail_url) : NULL;
|
||||||
|
(*collection)[current_count][2] =
|
||||||
|
infobox->extract ? strdup(infobox->extract) : NULL;
|
||||||
|
(*collection)[current_count][3] = infobox->url ? strdup(infobox->url) : NULL;
|
||||||
|
(*collection)[current_count][4] = infobox->url ? strdup(infobox->url) : NULL;
|
||||||
|
(*inner_counts)[current_count] = INFOBOX_FIELD_COUNT;
|
||||||
|
|
||||||
|
return current_count + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_warning_to_collection(const char *engine_name,
|
static int add_warning_to_collection(const char *engine_name,
|
||||||
const char *warning_message,
|
const char *warning_message,
|
||||||
StringMatrix *collection) {
|
char ****collection, int **inner_counts,
|
||||||
const char *values[] = {engine_name, warning_message};
|
int current_count) {
|
||||||
return string_matrix_append(collection, values, 2);
|
char ***new_collection =
|
||||||
}
|
(char ***)malloc(sizeof(char **) * (current_count + 1));
|
||||||
|
int *new_inner_counts =
|
||||||
|
(int *)malloc(sizeof(int) * (current_count + 1));
|
||||||
|
|
||||||
static void free_user_engine_list(char **user_engines, int user_engine_count) {
|
if (!new_collection || !new_inner_counts) {
|
||||||
for (int i = 0; i < user_engine_count; i++)
|
free(new_collection);
|
||||||
free(user_engines[i]);
|
free(new_inner_counts);
|
||||||
free(user_engines);
|
return current_count;
|
||||||
}
|
|
||||||
|
|
||||||
static void free_search_results(SearchResult **all_results, ScrapeJob *jobs,
|
|
||||||
int job_count) {
|
|
||||||
for (int i = 0; i < job_count; i++) {
|
|
||||||
for (int j = 0; all_results[i] && j < jobs[i].results_count; j++) {
|
|
||||||
free(all_results[i][j].url);
|
|
||||||
free(all_results[i][j].title);
|
|
||||||
free(all_results[i][j].snippet);
|
|
||||||
}
|
|
||||||
free(all_results[i]);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void free_infobox_results(InfoBoxThreadData *data) {
|
if (*collection && current_count > 0) {
|
||||||
for (int i = 0; i < HANDLER_COUNT; i++) {
|
memcpy(new_collection, *collection, sizeof(char **) * current_count);
|
||||||
free_infobox(&data[i].result);
|
|
||||||
}
|
}
|
||||||
|
if (*inner_counts && current_count > 0) {
|
||||||
|
memcpy(new_inner_counts, *inner_counts, sizeof(int) * current_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(*collection);
|
||||||
|
free(*inner_counts);
|
||||||
|
|
||||||
|
*collection = new_collection;
|
||||||
|
*inner_counts = new_inner_counts;
|
||||||
|
|
||||||
|
(*collection)[current_count] = (char **)malloc(sizeof(char *) * 2);
|
||||||
|
if (!(*collection)[current_count])
|
||||||
|
return current_count;
|
||||||
|
|
||||||
|
(*collection)[current_count][0] = strdup(engine_name ? engine_name : "");
|
||||||
|
(*collection)[current_count][1] =
|
||||||
|
strdup(warning_message ? warning_message : "");
|
||||||
|
|
||||||
|
if (!(*collection)[current_count][0] || !(*collection)[current_count][1]) {
|
||||||
|
free((*collection)[current_count][0]);
|
||||||
|
free((*collection)[current_count][1]);
|
||||||
|
free((*collection)[current_count]);
|
||||||
|
return current_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*inner_counts)[current_count] = 2;
|
||||||
|
return current_count + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *warning_message_for_job(const ScrapeJob *job,
|
static const char *warning_message_for_job(const ScrapeJob *job, const char *locale) {
|
||||||
const char *locale) {
|
|
||||||
switch (job->status) {
|
switch (job->status) {
|
||||||
case SCRAPE_STATUS_FETCH_ERROR: {
|
case SCRAPE_STATUS_FETCH_ERROR: {
|
||||||
const char *msg = beaker_get_locale_value(locale, "warning_fetch_error");
|
const char *msg = beaker_get_locale_value(locale, "warning_fetch_error");
|
||||||
return msg ? msg
|
return msg ? msg : "request failed before OmniSearch could read search results.";
|
||||||
: "request failed before OmniSearch could read search results.";
|
|
||||||
}
|
}
|
||||||
case SCRAPE_STATUS_PARSE_MISMATCH: {
|
case SCRAPE_STATUS_PARSE_MISMATCH: {
|
||||||
const char *msg = beaker_get_locale_value(locale, "warning_parse_mismatch");
|
const char *msg = beaker_get_locale_value(locale, "warning_parse_mismatch");
|
||||||
return msg ? msg
|
return msg ? msg : "returned search results in a format OmniSearch could not parse.";
|
||||||
: "returned search results in a format OmniSearch could not "
|
|
||||||
"parse.";
|
|
||||||
}
|
}
|
||||||
case SCRAPE_STATUS_BLOCKED: {
|
case SCRAPE_STATUS_BLOCKED: {
|
||||||
const char *msg = beaker_get_locale_value(locale, "warning_blocked");
|
const char *msg = beaker_get_locale_value(locale, "warning_blocked");
|
||||||
return msg ? msg
|
return msg ? msg : "returned a captcha or another blocking page instead of search results.";
|
||||||
: "returned a captcha or another blocking page instead of "
|
|
||||||
"search results.";
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -363,8 +384,8 @@ static int engine_allowed_for_user(const SearchEngine *eng, char **user_ids,
|
||||||
static char *build_search_href(const char *query, const char *engine_id,
|
static char *build_search_href(const char *query, const char *engine_id,
|
||||||
int page) {
|
int page) {
|
||||||
const char *safe_query = query ? query : "";
|
const char *safe_query = query ? query : "";
|
||||||
int use_engine =
|
int use_engine = engine_id && engine_id[0] != '\0' &&
|
||||||
engine_id && engine_id[0] != '\0' && !engine_id_matches(engine_id, "all");
|
!engine_id_matches(engine_id, "all");
|
||||||
size_t needed = strlen("/search?q=") + strlen(safe_query) + 1;
|
size_t needed = strlen("/search?q=") + strlen(safe_query) + 1;
|
||||||
|
|
||||||
if (use_engine)
|
if (use_engine)
|
||||||
|
|
@ -416,18 +437,13 @@ int results_handler(UrlParams *params) {
|
||||||
extern Config global_config;
|
extern Config global_config;
|
||||||
TemplateContext ctx = new_context();
|
TemplateContext ctx = new_context();
|
||||||
char *raw_query = "";
|
char *raw_query = "";
|
||||||
char selected_engine_id[32];
|
const char *selected_engine_id = "all";
|
||||||
char *default_engine = get_default_search_engine();
|
|
||||||
snprintf(selected_engine_id, sizeof(selected_engine_id), "%s",
|
|
||||||
default_engine);
|
|
||||||
free(default_engine);
|
|
||||||
int page = 1;
|
int page = 1;
|
||||||
int btnI = 0;
|
int btnI = 0;
|
||||||
|
|
||||||
char **user_engines = NULL;
|
char **user_engines = NULL;
|
||||||
int user_engine_count = 0;
|
int user_engine_count = 0;
|
||||||
int has_user_pref =
|
int has_user_pref = (get_user_engines(&user_engines, &user_engine_count) == 0);
|
||||||
(get_user_engines(&user_engines, &user_engine_count) == 0);
|
|
||||||
|
|
||||||
if (params) {
|
if (params) {
|
||||||
for (int i = 0; i < params->count; i++) {
|
for (int i = 0; i < params->count; i++) {
|
||||||
|
|
@ -438,8 +454,7 @@ int results_handler(UrlParams *params) {
|
||||||
if (parsed > 1)
|
if (parsed > 1)
|
||||||
page = parsed;
|
page = parsed;
|
||||||
} else if (strcmp(params->params[i].key, "engine") == 0) {
|
} else if (strcmp(params->params[i].key, "engine") == 0) {
|
||||||
snprintf(selected_engine_id, sizeof(selected_engine_id), "%s",
|
selected_engine_id = params->params[i].value;
|
||||||
params->params[i].value);
|
|
||||||
} else if (strcmp(params->params[i].key, "btnI") == 0) {
|
} else if (strcmp(params->params[i].key, "btnI") == 0) {
|
||||||
btnI = atoi(params->params[i].value);
|
btnI = atoi(params->params[i].value);
|
||||||
}
|
}
|
||||||
|
|
@ -456,11 +471,9 @@ int results_handler(UrlParams *params) {
|
||||||
beaker_set_locale(&ctx, locale);
|
beaker_set_locale(&ctx, locale);
|
||||||
|
|
||||||
const char *rate_limit_msg = beaker_get_locale_value(locale, "rate_limit");
|
const char *rate_limit_msg = beaker_get_locale_value(locale, "rate_limit");
|
||||||
if (!rate_limit_msg)
|
if (!rate_limit_msg) rate_limit_msg = "Slow down! Too many searches from you!";
|
||||||
rate_limit_msg = "Slow down! Too many searches from you!";
|
|
||||||
const char *no_results_msg = beaker_get_locale_value(locale, "no_results");
|
const char *no_results_msg = beaker_get_locale_value(locale, "no_results");
|
||||||
if (!no_results_msg)
|
if (!no_results_msg) no_results_msg = "No results found";
|
||||||
no_results_msg = "No results found";
|
|
||||||
|
|
||||||
char page_str[16];
|
char page_str[16];
|
||||||
snprintf(page_str, sizeof(page_str), "%d", page);
|
snprintf(page_str, sizeof(page_str), "%d", page);
|
||||||
|
|
@ -478,24 +491,18 @@ int results_handler(UrlParams *params) {
|
||||||
|
|
||||||
if (!raw_query || strlen(raw_query) == 0) {
|
if (!raw_query || strlen(raw_query) == 0) {
|
||||||
send_redirect("/");
|
send_redirect("/");
|
||||||
free(locale);
|
if (has_user_pref) {
|
||||||
free_user_engine_list(user_engines, user_engine_count);
|
for (int i = 0; i < user_engine_count; i++)
|
||||||
|
free(user_engines[i]);
|
||||||
|
free(user_engines);
|
||||||
|
}
|
||||||
free_context(&ctx);
|
free_context(&ctx);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SearchEngine *selected_engine = find_enabled_engine(selected_engine_id);
|
const SearchEngine *selected_engine = find_enabled_engine(selected_engine_id);
|
||||||
if (selected_engine &&
|
if (!selected_engine)
|
||||||
!engine_allowed_for_user(selected_engine, user_engines, user_engine_count,
|
selected_engine_id = "all";
|
||||||
has_user_pref)) {
|
|
||||||
selected_engine = NULL;
|
|
||||||
}
|
|
||||||
if (selected_engine) {
|
|
||||||
snprintf(selected_engine_id, sizeof(selected_engine_id), "%s",
|
|
||||||
selected_engine->id);
|
|
||||||
} else {
|
|
||||||
snprintf(selected_engine_id, sizeof(selected_engine_id), "all");
|
|
||||||
}
|
|
||||||
|
|
||||||
context_set(&ctx, "selected_engine", selected_engine_id);
|
context_set(&ctx, "selected_engine", selected_engine_id);
|
||||||
char *search_href = build_search_href(raw_query, selected_engine_id, 1);
|
char *search_href = build_search_href(raw_query, selected_engine_id, 1);
|
||||||
|
|
@ -521,6 +528,13 @@ int results_handler(UrlParams *params) {
|
||||||
infobox_data[i].result = (InfoBox){NULL};
|
infobox_data[i].result = (InfoBox){NULL};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (page == 1) {
|
||||||
|
for (int i = 0; i < HANDLER_COUNT; i++) {
|
||||||
|
pthread_create(&infobox_threads[i], NULL, infobox_thread_func,
|
||||||
|
&infobox_data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ScrapeJob jobs[ENGINE_COUNT];
|
ScrapeJob jobs[ENGINE_COUNT];
|
||||||
SearchResult *all_results[ENGINE_COUNT];
|
SearchResult *all_results[ENGINE_COUNT];
|
||||||
|
|
||||||
|
|
@ -578,8 +592,11 @@ int results_handler(UrlParams *params) {
|
||||||
snprintf(response, sizeof(response), "<h1>%s</h1>", rate_limit_msg);
|
snprintf(response, sizeof(response), "<h1>%s</h1>", rate_limit_msg);
|
||||||
send_response(response);
|
send_response(response);
|
||||||
free(request_cache_key);
|
free(request_cache_key);
|
||||||
free(locale);
|
if (has_user_pref) {
|
||||||
free_user_engine_list(user_engines, user_engine_count);
|
for (int i = 0; i < user_engine_count; i++)
|
||||||
|
free(user_engines[i]);
|
||||||
|
free(user_engines);
|
||||||
|
}
|
||||||
free_context(&ctx);
|
free_context(&ctx);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -598,14 +615,15 @@ int results_handler(UrlParams *params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter_engine_count > 1) {
|
if (filter_engine_count > 1) {
|
||||||
StringMatrix filter_matrix;
|
char ***filter_matrix = NULL;
|
||||||
string_matrix_init(&filter_matrix);
|
int *filter_inner_counts = NULL;
|
||||||
|
int filter_count = 0;
|
||||||
char *all_href = build_search_href(raw_query, "all", 1);
|
char *all_href = build_search_href(raw_query, "all", 1);
|
||||||
const char *all_values[LINK_FIELD_COUNT] = {
|
|
||||||
all_href, "All",
|
|
||||||
selected_engine ? "engine-filter" : "engine-filter active"};
|
|
||||||
|
|
||||||
string_matrix_append(&filter_matrix, all_values, LINK_FIELD_COUNT);
|
filter_count = add_link_to_collection(
|
||||||
|
all_href, "All",
|
||||||
|
selected_engine ? "engine-filter" : "engine-filter active",
|
||||||
|
&filter_matrix, &filter_inner_counts, filter_count);
|
||||||
free(all_href);
|
free(all_href);
|
||||||
|
|
||||||
for (int i = 0; i < ENGINE_COUNT; i++) {
|
for (int i = 0; i < ENGINE_COUNT; i++) {
|
||||||
|
|
@ -621,24 +639,22 @@ int results_handler(UrlParams *params) {
|
||||||
? "engine-filter active"
|
? "engine-filter active"
|
||||||
: "engine-filter";
|
: "engine-filter";
|
||||||
|
|
||||||
const char *filter_values[LINK_FIELD_COUNT] = {
|
filter_count = add_link_to_collection(filter_href, ENGINE_REGISTRY[i].name,
|
||||||
filter_href, ENGINE_REGISTRY[i].name, filter_class};
|
filter_class, &filter_matrix,
|
||||||
string_matrix_append(&filter_matrix, filter_values, LINK_FIELD_COUNT);
|
&filter_inner_counts, filter_count);
|
||||||
free(filter_href);
|
free(filter_href);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter_matrix.count > 0) {
|
if (filter_count > 0) {
|
||||||
context_set_array_of_arrays(&ctx, "engine_filters", filter_matrix.rows,
|
context_set_array_of_arrays(&ctx, "engine_filters", filter_matrix,
|
||||||
filter_matrix.count,
|
filter_count, filter_inner_counts);
|
||||||
filter_matrix.field_counts);
|
for (int i = 0; i < filter_count; i++) {
|
||||||
}
|
for (int j = 0; j < LINK_FIELD_COUNT; j++)
|
||||||
string_matrix_free(&filter_matrix);
|
free(filter_matrix[i][j]);
|
||||||
}
|
free(filter_matrix[i]);
|
||||||
|
}
|
||||||
if (page == 1) {
|
free(filter_matrix);
|
||||||
for (int i = 0; i < HANDLER_COUNT; i++) {
|
free(filter_inner_counts);
|
||||||
pthread_create(&infobox_threads[i], NULL, infobox_thread_func,
|
|
||||||
&infobox_data[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -656,12 +672,27 @@ int results_handler(UrlParams *params) {
|
||||||
for (int i = 0; i < engine_idx; i++) {
|
for (int i = 0; i < engine_idx; i++) {
|
||||||
if (jobs[i].results_count > 0 && all_results[i][0].url) {
|
if (jobs[i].results_count > 0 && all_results[i][0].url) {
|
||||||
char *redirect_url = strdup(all_results[i][0].url);
|
char *redirect_url = strdup(all_results[i][0].url);
|
||||||
free_search_results(all_results, jobs, engine_idx);
|
for (int j = 0; j < enabled_engine_count; j++) {
|
||||||
if (page == 1)
|
for (int k = 0; k < jobs[j].results_count; k++) {
|
||||||
free_infobox_results(infobox_data);
|
free(all_results[j][k].url);
|
||||||
|
free(all_results[j][k].title);
|
||||||
|
free(all_results[j][k].snippet);
|
||||||
|
}
|
||||||
|
free(all_results[j]);
|
||||||
|
}
|
||||||
|
if (page == 1) {
|
||||||
|
for (int j = 0; j < HANDLER_COUNT; j++) {
|
||||||
|
if (infobox_data[j].success) {
|
||||||
|
free_infobox(&infobox_data[j].result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
free(request_cache_key);
|
free(request_cache_key);
|
||||||
free(locale);
|
if (has_user_pref) {
|
||||||
free_user_engine_list(user_engines, user_engine_count);
|
for (int i = 0; i < user_engine_count; i++)
|
||||||
|
free(user_engines[i]);
|
||||||
|
free(user_engines);
|
||||||
|
}
|
||||||
free_context(&ctx);
|
free_context(&ctx);
|
||||||
if (redirect_url) {
|
if (redirect_url) {
|
||||||
send_redirect(redirect_url);
|
send_redirect(redirect_url);
|
||||||
|
|
@ -670,37 +701,54 @@ int results_handler(UrlParams *params) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free_search_results(all_results, jobs, engine_idx);
|
for (int i = 0; i < enabled_engine_count; i++) {
|
||||||
if (page == 1)
|
free(all_results[i]);
|
||||||
free_infobox_results(infobox_data);
|
}
|
||||||
|
if (page == 1) {
|
||||||
|
for (int i = 0; i < HANDLER_COUNT; i++) {
|
||||||
|
if (infobox_data[i].success) {
|
||||||
|
free_infobox(&infobox_data[i].result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
free(request_cache_key);
|
free(request_cache_key);
|
||||||
free(locale);
|
if (has_user_pref) {
|
||||||
free_user_engine_list(user_engines, user_engine_count);
|
for (int i = 0; i < user_engine_count; i++)
|
||||||
|
free(user_engines[i]);
|
||||||
|
free(user_engines);
|
||||||
|
}
|
||||||
free_context(&ctx);
|
free_context(&ctx);
|
||||||
char no_results_html[128];
|
char no_results_html[128];
|
||||||
snprintf(no_results_html, sizeof(no_results_html), "<h1>%s</h1>",
|
snprintf(no_results_html, sizeof(no_results_html), "<h1>%s</h1>", no_results_msg);
|
||||||
no_results_msg);
|
|
||||||
send_response(no_results_html);
|
send_response(no_results_html);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringMatrix infobox_matrix;
|
char ***infobox_matrix = NULL;
|
||||||
string_matrix_init(&infobox_matrix);
|
int *infobox_inner_counts = NULL;
|
||||||
|
int infobox_count = 0;
|
||||||
|
|
||||||
if (page == 1) {
|
if (page == 1) {
|
||||||
for (int i = 0; i < HANDLER_COUNT; i++) {
|
for (int i = 0; i < HANDLER_COUNT; i++) {
|
||||||
if (infobox_data[i].success) {
|
if (infobox_data[i].success) {
|
||||||
add_infobox_to_collection(&infobox_data[i].result, &infobox_matrix);
|
infobox_count =
|
||||||
|
add_infobox_to_collection(&infobox_data[i].result, &infobox_matrix,
|
||||||
|
&infobox_inner_counts, infobox_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (infobox_matrix.count > 0) {
|
if (infobox_count > 0) {
|
||||||
context_set_array_of_arrays(&ctx, "infoboxes", infobox_matrix.rows,
|
context_set_array_of_arrays(&ctx, "infoboxes", infobox_matrix,
|
||||||
infobox_matrix.count,
|
infobox_count, infobox_inner_counts);
|
||||||
infobox_matrix.field_counts);
|
for (int i = 0; i < infobox_count; i++) {
|
||||||
|
for (int j = 0; j < INFOBOX_FIELD_COUNT; j++)
|
||||||
|
free(infobox_matrix[i][j]);
|
||||||
|
free(infobox_matrix[i]);
|
||||||
|
}
|
||||||
|
free(infobox_matrix);
|
||||||
|
free(infobox_inner_counts);
|
||||||
}
|
}
|
||||||
string_matrix_free(&infobox_matrix);
|
|
||||||
|
|
||||||
int warning_count = 0;
|
int warning_count = 0;
|
||||||
for (int i = 0; i < enabled_engine_count; i++) {
|
for (int i = 0; i < enabled_engine_count; i++) {
|
||||||
|
|
@ -709,33 +757,35 @@ int results_handler(UrlParams *params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (warning_count > 0) {
|
if (warning_count > 0) {
|
||||||
StringMatrix warning_matrix;
|
char ***warning_matrix = NULL;
|
||||||
string_matrix_init(&warning_matrix);
|
int *warning_inner_counts = NULL;
|
||||||
|
int warning_index = 0;
|
||||||
|
|
||||||
for (int i = 0; i < enabled_engine_count; i++) {
|
for (int i = 0; i < enabled_engine_count; i++) {
|
||||||
const char *warning_message = warning_message_for_job(&jobs[i], locale);
|
const char *warning_message = warning_message_for_job(&jobs[i], locale);
|
||||||
if (!warning_message)
|
if (!warning_message)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (jobs[i].http_status >= 400) {
|
warning_index = add_warning_to_collection(
|
||||||
char warning_with_status[BUFFER_SIZE_LARGE];
|
jobs[i].engine->name, warning_message, &warning_matrix,
|
||||||
snprintf(warning_with_status, sizeof(warning_with_status),
|
&warning_inner_counts, warning_index);
|
||||||
"%s (HTTP %ld)", warning_message, jobs[i].http_status);
|
}
|
||||||
add_warning_to_collection(jobs[i].engine->name, warning_with_status,
|
|
||||||
&warning_matrix);
|
if (warning_index > 0) {
|
||||||
} else {
|
context_set_array_of_arrays(&ctx, "engine_warnings", warning_matrix,
|
||||||
add_warning_to_collection(jobs[i].engine->name, warning_message,
|
warning_index, warning_inner_counts);
|
||||||
&warning_matrix);
|
}
|
||||||
|
|
||||||
|
if (warning_matrix) {
|
||||||
|
for (int i = 0; i < warning_index; i++) {
|
||||||
|
free(warning_matrix[i][0]);
|
||||||
|
free(warning_matrix[i][1]);
|
||||||
|
free(warning_matrix[i]);
|
||||||
}
|
}
|
||||||
|
free(warning_matrix);
|
||||||
}
|
}
|
||||||
|
if (warning_inner_counts)
|
||||||
if (warning_matrix.count > 0) {
|
free(warning_inner_counts);
|
||||||
context_set_array_of_arrays(&ctx, "engine_warnings", warning_matrix.rows,
|
|
||||||
warning_matrix.count,
|
|
||||||
warning_matrix.field_counts);
|
|
||||||
}
|
|
||||||
|
|
||||||
string_matrix_free(&warning_matrix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int total_results = 0;
|
int total_results = 0;
|
||||||
|
|
@ -744,8 +794,33 @@ int results_handler(UrlParams *params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (total_results > 0) {
|
if (total_results > 0) {
|
||||||
StringMatrix results_matrix;
|
char ***results_matrix = (char ***)malloc(sizeof(char **) * total_results);
|
||||||
string_matrix_init(&results_matrix);
|
int *results_inner_counts = (int *)malloc(sizeof(int) * total_results);
|
||||||
|
if (!results_matrix || !results_inner_counts) {
|
||||||
|
char *html = render_template("results.html", &ctx);
|
||||||
|
if (html) {
|
||||||
|
send_response(html);
|
||||||
|
free(html);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < enabled_engine_count; i++)
|
||||||
|
free(all_results[i]);
|
||||||
|
if (page == 1) {
|
||||||
|
for (int i = 0; i < HANDLER_COUNT; i++) {
|
||||||
|
if (infobox_data[i].success) {
|
||||||
|
free_infobox(&infobox_data[i].result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(request_cache_key);
|
||||||
|
if (has_user_pref) {
|
||||||
|
for (int i = 0; i < user_engine_count; i++)
|
||||||
|
free(user_engines[i]);
|
||||||
|
free(user_engines);
|
||||||
|
}
|
||||||
|
free_context(&ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int unique_count = 0;
|
||||||
UrlHashTable url_table;
|
UrlHashTable url_table;
|
||||||
url_hash_init(&url_table);
|
url_hash_init(&url_table);
|
||||||
|
|
||||||
|
|
@ -762,45 +837,61 @@ int results_handler(UrlParams *params) {
|
||||||
|
|
||||||
url_hash_insert(&url_table, display_url);
|
url_hash_insert(&url_table, display_url);
|
||||||
|
|
||||||
|
results_matrix[unique_count] =
|
||||||
|
(char **)malloc(sizeof(char *) * RESULT_FIELD_COUNT);
|
||||||
|
if (!results_matrix[unique_count]) {
|
||||||
|
free(all_results[i][j].url);
|
||||||
|
free(all_results[i][j].title);
|
||||||
|
free(all_results[i][j].snippet);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
char *pretty_url = pretty_display_url(display_url);
|
char *pretty_url = pretty_display_url(display_url);
|
||||||
char *base_url = get_base_url(display_url);
|
char *base_url = get_base_url(display_url);
|
||||||
const char *values[RESULT_FIELD_COUNT] = {
|
|
||||||
display_url,
|
results_matrix[unique_count][0] = strdup(display_url);
|
||||||
pretty_url,
|
results_matrix[unique_count][1] = strdup(pretty_url);
|
||||||
all_results[i][j].title ? all_results[i][j].title : "Untitled",
|
results_matrix[unique_count][2] = all_results[i][j].title
|
||||||
all_results[i][j].snippet ? all_results[i][j].snippet : "",
|
? strdup(all_results[i][j].title)
|
||||||
base_url,
|
: strdup("Untitled");
|
||||||
"",
|
results_matrix[unique_count][3] =
|
||||||
};
|
all_results[i][j].snippet ? strdup(all_results[i][j].snippet)
|
||||||
int append_result =
|
: strdup("");
|
||||||
string_matrix_append(&results_matrix, values, RESULT_FIELD_COUNT);
|
results_matrix[unique_count][4] = strdup(base_url ? base_url : "");
|
||||||
|
results_matrix[unique_count][5] = strdup("");
|
||||||
|
|
||||||
|
results_inner_counts[unique_count] = RESULT_FIELD_COUNT;
|
||||||
|
|
||||||
free(pretty_url);
|
free(pretty_url);
|
||||||
free(base_url);
|
free(base_url);
|
||||||
free(all_results[i][j].url);
|
free(all_results[i][j].url);
|
||||||
free(all_results[i][j].title);
|
free(all_results[i][j].title);
|
||||||
free(all_results[i][j].snippet);
|
free(all_results[i][j].snippet);
|
||||||
if (append_result != 0) {
|
|
||||||
continue;
|
unique_count++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
free(all_results[i]);
|
free(all_results[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
context_set_array_of_arrays(&ctx, "results", results_matrix.rows,
|
context_set_array_of_arrays(&ctx, "results", results_matrix, unique_count,
|
||||||
results_matrix.count,
|
results_inner_counts);
|
||||||
results_matrix.field_counts);
|
|
||||||
|
|
||||||
StringMatrix pager_matrix;
|
char ***pager_matrix = NULL;
|
||||||
SearchHrefData href_data = {.query = raw_query,
|
int *pager_inner_counts = NULL;
|
||||||
.engine_id = selected_engine_id};
|
SearchHrefData href_data = { .query = raw_query, .engine_id = selected_engine_id };
|
||||||
int pagination_result = string_matrix_build_pagination(
|
int pager_count = build_pagination(page, search_href_builder,
|
||||||
page, search_href_builder, &href_data, &pager_matrix);
|
&href_data, &pager_matrix,
|
||||||
|
&pager_inner_counts);
|
||||||
|
|
||||||
if (pagination_result == 0 && pager_matrix.count > 0) {
|
if (pager_count > 0) {
|
||||||
context_set_array_of_arrays(&ctx, "pagination_links", pager_matrix.rows,
|
context_set_array_of_arrays(&ctx, "pagination_links", pager_matrix,
|
||||||
pager_matrix.count,
|
pager_count, pager_inner_counts);
|
||||||
pager_matrix.field_counts);
|
for (int i = 0; i < pager_count; i++) {
|
||||||
|
for (int j = 0; j < LINK_FIELD_COUNT; j++)
|
||||||
|
free(pager_matrix[i][j]);
|
||||||
|
free(pager_matrix[i]);
|
||||||
|
}
|
||||||
|
free(pager_matrix);
|
||||||
|
free(pager_inner_counts);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *html = render_template("results.html", &ctx);
|
char *html = render_template("results.html", &ctx);
|
||||||
|
|
@ -809,8 +900,13 @@ int results_handler(UrlParams *params) {
|
||||||
free(html);
|
free(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
string_matrix_free(&pager_matrix);
|
for (int i = 0; i < unique_count; i++) {
|
||||||
string_matrix_free(&results_matrix);
|
for (int j = 0; j < RESULT_FIELD_COUNT; j++)
|
||||||
|
free(results_matrix[i][j]);
|
||||||
|
free(results_matrix[i]);
|
||||||
|
}
|
||||||
|
free(results_matrix);
|
||||||
|
free(results_inner_counts);
|
||||||
url_hash_free(&url_table);
|
url_hash_free(&url_table);
|
||||||
} else {
|
} else {
|
||||||
char *html = render_template("results.html", &ctx);
|
char *html = render_template("results.html", &ctx);
|
||||||
|
|
@ -819,15 +915,26 @@ int results_handler(UrlParams *params) {
|
||||||
free(html);
|
free(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_search_results(all_results, jobs, engine_idx);
|
for (int i = 0; i < enabled_engine_count; i++) {
|
||||||
|
free(all_results[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(request_cache_key);
|
free(request_cache_key);
|
||||||
|
|
||||||
if (page == 1)
|
if (page == 1) {
|
||||||
free_infobox_results(infobox_data);
|
for (int i = 0; i < HANDLER_COUNT; i++) {
|
||||||
|
if (infobox_data[i].success) {
|
||||||
|
free_infobox(&infobox_data[i].result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
free(locale);
|
free(locale);
|
||||||
free_user_engine_list(user_engines, user_engine_count);
|
if (has_user_pref) {
|
||||||
|
for (int i = 0; i < user_engine_count; i++)
|
||||||
|
free(user_engines[i]);
|
||||||
|
free(user_engines);
|
||||||
|
}
|
||||||
free_context(&ctx);
|
free_context(&ctx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -34,14 +34,6 @@ int settings_handler(UrlParams *params) {
|
||||||
int user_engine_count = 0;
|
int user_engine_count = 0;
|
||||||
int has_user_pref =
|
int has_user_pref =
|
||||||
(get_user_engines(&user_engines, &user_engine_count) == 0);
|
(get_user_engines(&user_engines, &user_engine_count) == 0);
|
||||||
char *default_engine = get_default_search_engine();
|
|
||||||
|
|
||||||
if (strcmp(default_engine, "all") != 0 && has_user_pref &&
|
|
||||||
!user_engines_contains(default_engine, user_engines,
|
|
||||||
user_engine_count)) {
|
|
||||||
free(default_engine);
|
|
||||||
default_engine = strdup("all");
|
|
||||||
}
|
|
||||||
|
|
||||||
int enabled_count = 0;
|
int enabled_count = 0;
|
||||||
for (int i = 0; i < ENGINE_COUNT; i++) {
|
for (int i = 0; i < ENGINE_COUNT; i++) {
|
||||||
|
|
@ -71,13 +63,11 @@ int settings_handler(UrlParams *params) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
engine_data[idx] = malloc(sizeof(char *) * 4);
|
engine_data[idx] = malloc(sizeof(char *) * 3);
|
||||||
engine_data[idx][0] = (char *)ENGINE_REGISTRY[i].id;
|
engine_data[idx][0] = (char *)ENGINE_REGISTRY[i].id;
|
||||||
engine_data[idx][1] = (char *)ENGINE_REGISTRY[i].name;
|
engine_data[idx][1] = (char *)ENGINE_REGISTRY[i].name;
|
||||||
engine_data[idx][2] = is_selected ? "checked" : "";
|
engine_data[idx][2] = is_selected ? "checked" : "";
|
||||||
engine_data[idx][3] =
|
engine_inner[idx] = 3;
|
||||||
strcmp(default_engine, ENGINE_REGISTRY[i].id) == 0 ? "selected" : "";
|
|
||||||
engine_inner[idx] = 4;
|
|
||||||
|
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +78,6 @@ int settings_handler(UrlParams *params) {
|
||||||
context_set(&ctx, "query", query);
|
context_set(&ctx, "query", query);
|
||||||
context_set(&ctx, "theme", theme);
|
context_set(&ctx, "theme", theme);
|
||||||
context_set(&ctx, "locale", locale);
|
context_set(&ctx, "locale", locale);
|
||||||
context_set(&ctx, "default_engine", default_engine);
|
|
||||||
context_set_array_of_arrays(&ctx, "locales", locale_data, locale_count,
|
context_set_array_of_arrays(&ctx, "locales", locale_data, locale_count,
|
||||||
inner_counts);
|
inner_counts);
|
||||||
|
|
||||||
|
|
@ -143,7 +132,6 @@ int settings_handler(UrlParams *params) {
|
||||||
send_response(rendered_html);
|
send_response(rendered_html);
|
||||||
|
|
||||||
free(rendered_html);
|
free(rendered_html);
|
||||||
free(default_engine);
|
|
||||||
free(theme);
|
free(theme);
|
||||||
free(locale);
|
free(locale);
|
||||||
free_context(&ctx);
|
free_context(&ctx);
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,6 @@ int settings_save_handler(UrlParams *params) {
|
||||||
const char *theme = "";
|
const char *theme = "";
|
||||||
const char *locale = "";
|
const char *locale = "";
|
||||||
const char *query = "";
|
const char *query = "";
|
||||||
const char *default_engine = "all";
|
|
||||||
int default_engine_present = 0;
|
|
||||||
int engines_present = 0;
|
int engines_present = 0;
|
||||||
char selected_ids[ENGINE_COUNT][32];
|
char selected_ids[ENGINE_COUNT][32];
|
||||||
int selected_count = 0;
|
int selected_count = 0;
|
||||||
|
|
@ -24,9 +22,6 @@ int settings_save_handler(UrlParams *params) {
|
||||||
locale = params->params[i].value;
|
locale = params->params[i].value;
|
||||||
} else if (strcmp(params->params[i].key, "q") == 0) {
|
} else if (strcmp(params->params[i].key, "q") == 0) {
|
||||||
query = params->params[i].value;
|
query = params->params[i].value;
|
||||||
} else if (strcmp(params->params[i].key, "default_engine") == 0) {
|
|
||||||
default_engine = params->params[i].value;
|
|
||||||
default_engine_present = 1;
|
|
||||||
} else if (strcmp(params->params[i].key, "engines_present") == 0) {
|
} else if (strcmp(params->params[i].key, "engines_present") == 0) {
|
||||||
engines_present = 1;
|
engines_present = 1;
|
||||||
} else if (strncmp(params->params[i].key, "engine_", 7) == 0 &&
|
} else if (strncmp(params->params[i].key, "engine_", 7) == 0 &&
|
||||||
|
|
@ -63,31 +58,6 @@ int settings_save_handler(UrlParams *params) {
|
||||||
false, false);
|
false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (default_engine_present) {
|
|
||||||
const char *validated_default = "all";
|
|
||||||
|
|
||||||
for (int i = 0; i < ENGINE_COUNT; i++) {
|
|
||||||
if (!ENGINE_REGISTRY[i].enabled ||
|
|
||||||
strcmp(default_engine, ENGINE_REGISTRY[i].id) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int selected = !engines_present;
|
|
||||||
for (int j = 0; j < selected_count; j++) {
|
|
||||||
if (strcmp(selected_ids[j], ENGINE_REGISTRY[i].id) == 0) {
|
|
||||||
selected = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selected)
|
|
||||||
validated_default = ENGINE_REGISTRY[i].id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_cookie("default_engine", validated_default,
|
|
||||||
"Fri, 31 Dec 2038 23:59:59 GMT", "/", false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
char redirect_url[512];
|
char redirect_url[512];
|
||||||
snprintf(redirect_url, sizeof(redirect_url), "/settings?q=%s", query);
|
snprintf(redirect_url, sizeof(redirect_url), "/settings?q=%s", query);
|
||||||
send_redirect(redirect_url);
|
send_redirect(redirect_url);
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue