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