index.php (15235B)
1 <!doctype html>
2 <html>
3
4 <!-- Process input (if given) -->
5 <?php
6
7 /* Load Configuration */
8 include("config/config.php");
9 include("lib/read_mappings.php");
10
11 /* Fetch and sanitize search query via GET request
12 * Allow both "query" and "q"
13 */
14 $_GET = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);
15 if (!is_null($_GET["query"])) {
16 $query = rawurldecode($_GET["query"]);
17 } else if (!is_null($_GET["q"])) {
18 $query = rawurldecode($_GET["q"]);
19 } else {
20 $query = null;
21 }
22
23 /* Handle Fallback Search Engine via cookie or GET argument
24 * Fallback is always defined in config/configs.php
25 */
26 if (!is_null($_GET["fallback"])) {
27 $fallback = $_GET["fallback"];
28 } elseif (!is_null($_COOKIE["fallback"])) {
29 $fallback = $_COOKIE["fallback"];
30 /* refresh cookie */
31 header(
32 "Set-Cookie: " .
33 "fallback=" . $fallback . "; " .
34 "Max-Age=" . 31536000 . "; " . /* 60 x 60 x 24 x 365 = 1 year */
35 "Domain=" . $_SERVER["SERVER_NAME"] . "; " .
36 "SameSite=Strict;"
37 );
38 }
39
40 if (strlen($query) > 0) {
41
42 /* Find keywords (only first one is considered) */
43 $keyword = preg_replace(
44 '/^.*?\!([A-Za-z0-9_\-\.]+).*$/',
45 '${1}',
46 $query
47 );
48 $keyword = strtolower($keyword);
49
50 /* Based on given keyword, choose a search engine or the fallback */
51 if (array_search($keyword, array_keys($searchkeys)) !== false) {
52 $search = $searchkeys[$keyword];
53 } else {
54 $search = $fallback;
55 }
56
57 /* Strip keyword from search term */
58 $search_term = preg_replace(
59 '/\![A-Za-z0-9_\-\.]+/',
60 '',
61 $query
62 );
63
64 /* Remove preceding and trailing spaces */
65 $search_term = preg_replace(
66 '/^\s+|\s+$/',
67 '',
68 $search_term
69 );
70
71 /* Construct search query */
72 $target = str_replace(
73 '%s',
74 rawurlencode($search_term),
75 $searches[$search]["query"]
76 );
77
78 /* Redirect to target search engine: 307 - Temporary Redirect */
79 header("Location: " . $target, true, 307);
80 die();
81 }
82
83 ?>
84
85 <!-- Head -->
86 <head>
87 <meta charset=utf-8>
88 <meta name=viewport content="width=device-width,initial-scale=1">
89 <link rel=icon href=/assets/img/favicon.png type=image/png>
90 <link rel=icon href=/assets/img/favicon.ico type=x-image/ico>
91 <link rel=stylesheet href=/assets/css/simple.min.css media=all>
92 <link rel=stylesheet href=/assets/css/custom.css>
93 <link rel="manifest" href="manifest.json">
94 <link
95 rel="search"
96 type="application/opensearchdescription+xml"
97 href="/opensearch.xml"
98 title="serĉi - search with !keywords"
99 >
100 <script async src=/assets/js/filter_engines.js></script>
101 <title>serĉi - search with !keywords</title>
102 </head>
103
104 <!-- Body -->
105 <body>
106
107 <!-- Header -->
108 <header>
109 <nav>
110 <a href="#engines">
111 Engines
112 </a>
113 <a href="#faqs">
114 FAQs
115 </a>
116 <a href="https://src.jayvii.de/pub/serci/" target="_blank">
117 Development
118 </a>
119 </nav>
120 <h1>serĉi</h1>
121 <p>Search with Keywords</p>
122 </header>
123
124 <!-- Search Bar -->
125 <form id="searchform" action="/" method="get">
126 <input
127 id="searchbar"
128 name="query"
129 type="text"
130 autofocus
131 placeholder="I am thinking about... !keyword"
132 alt="Search the web"
133 onkeydown="if(event.keyCode===13)return this.form.submit(),!1"
134 >
135 <input
136 name="fallback"
137 id="fallback"
138 type="hidden"
139 value="<?php echo $fallback; ?>"
140 >
141 <input
142 id="searchbutton"
143 name="submit"
144 type="submit"
145 value="🔎 Search"
146 >
147 </form>
148
149 <!-- Description -->
150 <div class="description">
151 <strong style="font-size: 133%;">
152 The keyword engine for power users that sits on top of your
153 favorite search engines!
154 </strong>
155 <p>
156 Have all your favorite search providers right at your finger
157 tips all the time and use them directly via
158 <code>!keywords</code> within your search query. Serĉi uses
159 your favorite search engine as fallback, whenever you do not
160 provide a keyword.
161 </p>
162 <a href="#engines" class="button">
163 Explore
164 </a>
165 <a href="#faqs" class="button">
166 Learn more
167 </a>
168 </div>
169
170 <!-- Search Engine Lists -->
171 <h3 id="engines">Available Search Engines</h3>
172
173 <p>
174 This serĉi instance supports
175 <mark><?php echo count($searches); ?> search engines</mark> within
176 <mark><?php echo count($categories); ?> categories</mark> and
177 <mark><?php echo count($searchkeys); ?> keywords</mark>.
178 </p>
179
180 <!-- Search Engine Filterbar -->
181 <input
182 id="engines_filterbar"
183 name="engines"
184 type="text"
185 placeholder="Filter available Search Engines..."
186 oninput="filter_engines('engines_filterbar');"
187 >
188 <noscript>
189 <div class="notice">
190 <p>
191 Exploring the available search engines with the filter bar
192 above as well as choosing your fallback search engine
193 requires javascript.
194 <strong>However, using serĉi itself does not</strong>!
195 </p>
196 <p>
197 Read the <a href="#faqs">FAQs</a> on how to choose a
198 fallback search engine when javascript or cookies are
199 disabled.
200 </p>
201 </div>
202 </noscript>
203
204 <!-- Search Engine Category Buttons -->
205 <details id="categories">
206 <summary>Categories</summary>
207
208 <div class="row">
209
210 <!-- Always insert a "Fallback" category button -->
211 <button
212 onclick="filter_category('Fallback');"
213 title="Search Engine that is choosen as fallback"
214 >
215 #Fallback
216 </button>
217
218 <!-- List all configured categories -->
219 <?php
220 foreach (array_keys($categories) as $cid) {
221 $cat_name = $categories[$cid]["name"];
222 ?>
223 <button
224 onclick="filter_category('<?php echo $cat_name; ?>');"
225 title="<?php echo $categories[$cid]["description"]; ?>"
226 >
227 <?php echo "#" . $cat_name; ?>
228 </button>
229 <?php
230 }
231 ?>
232
233 </div>
234
235 </details>
236
237 <!-- Search Engine List -->
238 <?php
239 foreach (array_keys($searches) as $sid) {
240 $search = $searches[$sid];
241 ?>
242 <article
243 id="<?php echo $sid; ?>"
244 class="<?php if ($sid == $fallback) { echo "selected"; }?>"
245 >
246 <!-- Entry-Head -->
247 <h3>
248 <a href="<?php echo $search["website"]; ?>" target="_blank">
249 <?php echo $search["name"]; ?>
250 </a>
251 </h3>
252
253 <!-- Entry-Description -->
254 <p><?php echo $search["description"]; ?></p>
255
256 <!-- Entry-Categories -->
257 <div class="categories">
258
259 <?php
260 /* If current entry is the fallback search, add the Mark */
261 if ($sid == $fallback) {
262 ?>
263 <mark id="fallback_marker">#Fallback</mark>
264 <?php
265 }
266 ?>
267
268 <?php
269 /* List all categories of current entry */
270 foreach ($search["categories"] as $cid) {
271 ?>
272 <mark title="<?php echo $categories[$cid]["description"];?>">
273 <?php echo "#" . $categories[$cid]["name"]; ?>
274 </mark>
275 <?php
276 }
277 ?>
278
279 </div>
280
281 <!-- Entry-Keywords -->
282 <strong>Keywords: </strong>
283 <code>
284 <?php
285 echo "!" .
286 implode(
287 "</code><code>!",
288 $search["keywords"]
289 );
290 ?>
291 </code>
292 <br><br>
293
294 <!-- "Make-Fallback" Button -->
295 <button onclick="make_fallback('<?php echo $sid; ?>')">
296 Choose as fallback
297 </button>
298
299 </article>
300 <?php
301 }
302 ?>
303
304 <!-- FAQs / About-Section -->
305 <section id="faqs">
306
307 <?php
308 /* Random entry from search array: used within examples below */
309 $rsi = array_rand($searches, 1);
310 ?>
311
312 <h3>About serĉi</h3>
313
314 <!-- meaning of name -->
315 <details>
316 <summary>What does serĉi mean?</summary>
317 <p>
318 It is the Esperanto term for "to search".This may not be the
319 most creative name for such a software project but to the
320 best of my knowledge, it is a unique one.
321 </p>
322 </details>
323
324 <!-- what are keywords -->
325 <details>
326 <summary>What are keywords?</summary>
327 <p>
328 An idea lent from the search Engine
329 <a href="https://duckduckgo.com/bangs" target="_blank">
330 DuckDuckGo
331 </a>, which has been utilized by many others since. They
332 call their keywords bangs, but it is the same concept and
333 usability. In essence, keywords are shortcuts for searching
334 on other websites.
335 </p>
336 <p>
337 For example, you can conduct a search on the website
338 <a
339 href="<?php echo $searches[$rsi]["website"]; ?>"
340 target="_blank"
341 >
342 <?php echo $searches[$rsi]["name"]; ?>
343 </a>
344 directly from <?php echo $_SERVER["SERVER_NAME"]; ?> by
345 adding the keyword
346 <code>!<?php echo $searches[$rsi]["keywords"][0]; ?></code>
347 to your search query.
348 </p>
349 <p>
350 You can find all keywords associated with each search engine
351 in the <a href="#engines">list above</a>.
352 </p>
353 </details>
354
355 <!-- how to use -->
356 <details>
357 <summary>How can I use serĉi?</summary>
358 <p>
359 You can try serĉi directly
360 <a href="#searchbar">on this site</a> or
361 <a
362 href="https://src.jayvii.de/pub/serci/#hosting"
363 target="_blank"
364 >
365 host it yourself
366 </a>!
367 It barely needs any server resources, no database or lots of
368 RAM. serĉi has minimal footprint (also on user data: there
369 are <strong>none</strong>).
370 </p>
371 <p>
372 Either type your search directly into the
373 <a href="#searchbar">search bar at the very top</a>
374 or add the search to your browser by rightclicking in the
375 URL-bar of your web browser and choose
376 <emph>add serĉi - Search with !keywords</emph>.
377 </p>
378 <p>
379 Some browsers (for example Firefox on Android / Fennec)
380 allow to configure custom search engines via a so-called
381 search URL. Simply list following URL as
382 <emph>search-URL</emph> there and choose it as your fallback
383 search option:
384 </p>
385 <pre>https://<?php echo $_SERVER["SERVER_NAME"]; ?>/?q=%s</pre>
386 <p>
387 You can also choose the fallback search engine, used by
388 serĉi as fallback, when no keyword is given, through the URL
389 instead of choosing it from the
390 <a href="#engines">list above</a>, in case you do not want
391 serĉi to store any cookie on your device. For example, if
392 you wanted to use
393 <a
394 href="<?php echo $searches[$rsi]["website"]; ?>"
395 target="_blank"
396 >
397 <?php echo $searches[$rsi]["name"]; ?>
398 </a>
399 as your fallback search, you could use following search-URL:
400 </p>
401 <pre><?php
402 echo "https://" . $_SERVER["SERVER_NAME"] .
403 "/?fallback=" . $rsi . "&q=%s";
404 ?></pre>
405 </details>
406
407 <!-- no js or cookies -->
408 <details>
409 <summary>
410 Choosing a fallback search without cookies or Javascript
411 </summary>
412 <p>
413 You can simply choose a fallback search by adding the
414 <code>fallback</code> URL parameter. For example, if you
415 wanted to use
416 <a
417 href="<?php echo $searches[$rsi]["website"]; ?>"
418 target="_blank"
419 >
420 <?php echo $searches[$rsi]["name"]; ?>
421 </a>
422 as your fallback search, you can simply add
423 <code>/?fallback=<?php echo $rsi; ?></code> to the serĉi
424 URL:
425 <br>
426 <a href="/?fallback=<?php echo $rsi; ?>">
427 <?php
428 echo "https://" . $_SERVER["SERVER_NAME"] .
429 "/?fallback=" . $rsi;
430 ?>
431 </a>
432 </p>
433 </details>
434
435 </section>
436
437 </body>
438
439 </html>