<?php

/**
 * choose.php - ChooSE your search engine
 *
 * Let users choose their favorite search engine! Instead of providing
 * a link to a particular web search one can use choose.php which allows
 * users to choose a preferred search engine.
 * The script is meant to be used for instance in blog posts and comments
 * (e.g. "Have you tried to look it up? Most search engines provide good
 * results, see https://wox.at/s/choose.php?q=what+does+RTFM+mean") or in
 * electronic mail communication (for this purpose the script produces a
 * a link to itself to be copied into the message).
 *
 * (License + History: see also end of file)
 *
 * @author     Andreas Schamanek <https://andreas.schamanek.net>
 * @license    GPL <http://www.gnu.org/licenses/gpl.html>
 * @copyright  (c) 2009-2016 Andreas Schamanek
 *
 */

error_reporting(0);

$version '2017-04-18';

// file names and paths (example if NO rewriting rules are set)
// $me='https://wox.at/s/choose.php'; // Link to your installation of choose.php
// $mesuffix='?q=';                   // query suffix which choose.php parses
// $c_action="$me";                   // form action of main form ("c_choose")

// file names and paths (example if rewriting rules are set)
// see https://wox.at/as/_/choose_php for Apache rewriting rules
$me='https://wox.at/s';               // Link to your installation of choose.php
$mesuffix='/';                        // suffix is done by rewriting rules
$c_action="$me/";                     // form action of main form ("c_choose")

// CSS for ChooSE (requires absolute addressing if rewriting is used)
$c_css="$me/choose.css";

// provide a link for users to suggest another search engine
// e.g. a mail address 'mailto:pleaseadd@example.net' or
// a web page 'https://example.com/suggest-another-se'
$c_suggest='mailto:as2013+choose2add@schamanek.net';

// link to feature "add to your search engines" (firefox search engine XML)
$c_ffseadd="$me/choose-ffse.xml";

// $formkey is a secret string to check if our own form was used
$formkey='32a56b07'// you might want to choose your own string here
$formkey=$formkey.date('Y-m-d'); // makes 1 form valid for up to 24 hours
// we generate a sufficiently safe yet short checksum string
$formkey=str_pad(dechex(abs(crc32($formkey))),8'0'STR_PAD_LEFT);

// homepage of choose.php with source code and instructions
$choose='https://wox.at/as/_/choose_php'// if in doubt leave unchanged

// -------------------------------------
// List of definitions of search engines

$engine['google']['text']='Google';
$engine['google']['title']='Google.com verbatim search';
$engine['google']['url']='https://www.google.com/search?tbs=li:1&q=';
$engine['google']['accesskey']='G'// F and S are not recommended

$engine['bing']['text']='Bing';
$engine['bing']['title']='Microsoft Bing (former MSN Search)';
$engine['bing']['url']='https://www.bing.com/search?q=';
$engine['bing']['accesskey']='B';

$engine['ask']['text']='Ask';
$engine['ask']['title']='Ask.com Search';
$engine['ask']['url']='http://www.ask.com/web?q=';
$engine['ask']['accesskey']='A';

$engine['startpage']['text']='startPage';
$engine['startpage']['title']='privacy-aware, SSL protected search &quot;enhanced by Google&quot;';
$engine['startpage']['url']='https://startpage.com/do/search?q=';
$engine['startpage']['accesskey']='P';

$engine['duckduckgo']['text']='dUckduckgo';
$engine['duckduckgo']['title']='privacy-aware meta &amp; and crowd-sourced search';
$engine['duckduckgo']['url']='https://duckduckgo.com/?q=';
$engine['duckduckgo']['accesskey']='U';

$engine['qwant']['text']='Qwant';
$engine['qwant']['title']='France based, privacy-aware search engine';
$engine['qwant']['url']='https://lite.qwant.com/?q=';
$engine['qwant']['accesskey']='Q';

// SearX: Much recommended open-source, self-hostable meta search engine
// Run it yourself [ https://asciimoo.github.io/searx/ ] or use one of the
// public instances [ https://github.com/asciimoo/searx/wiki/Searx-instances ]
//$engine['searx']['text']='searX<sup>m</sup>';
//$engine['searx']['title']='<a href="https://asciimoo.github.io/searx/">Open-source, self-hostable meta search engine</a>';
//$engine['searx']['url']='https://searx.at/?q=';
//$engine['searx']['accesskey']='X';

$engine['dogpile']['text']='Dogpile<sup>m</sup>';
$engine['dogpile']['title']='Meta search; searches Google, Yahoo, Bing, and Ask';
$engine['dogpile']['url']='https://www.dogpile.com/search/web?q=';
$engine['dogpile']['accesskey']='D';

$engine['metager']['text']='MetaGer<sup>m</sup>';
$engine['metager']['title']='MetaGer - German meta search engine';
$engine['metager']['url']='https://metager.de/meta/cgi-bin/meta.ger1?eingabe=';
$engine['metager']['accesskey']='M';

$engine['ecosia']['text']='Ecosia<sup>e</sup>';
$engine['ecosia']['title']='Eco friendly search supporting protection of rainforests; searches Bing';
$engine['ecosia']['url']='https://www.ecosia.org/search.php?q=';
$engine['ecosia']['accesskey']='E';

# removed 2014-05-07, redirects to Ecosia
#$engine['znout']['text']='Znout<sup>e</sup>';
#$engine['znout']['title']='CO<sub>2</sub> neutral search using Google.com';
#$engine['znout']['url']='http://us.znout.org/search.php?q=';
#$engine['znout']['accesskey']='Z';

$engine['blackle']['text']='Blackle<sup>e</sup>';
$engine['blackle']['title']='Black Google Custom web search';
$engine['blackle']['url']='http://www.google.com/cse?cx=013269018370076798483%3A8eec3papwpi&q=';
$engine['blackle']['accesskey']='H';

$engine['exalead']['text']='exaLead';
$engine['exalead']['title']='France based search engine';
$engine['exalead']['url']='http://www.exalead.com/search?q=';
$engine['exalead']['accesskey']='L';

$engine['yandex']['text']='Yandex';
$engine['yandex']['title']='Popular Russian search engine';
$engine['yandex']['url']='https://yandex.com/yandsearch?text=';
$engine['yandex']['accesskey']='Y';

$engine['yahoo']['text']='yahoo';
$engine['yahoo']['title']='Yahoo.com Yahoo! Search powered by Microsoft Bing';
$engine['yahoo']['url']='https://search.yahoo.com/search?p=';
$engine['yahoo']['accesskey']='';

# removed 2014-05-07, doesn't work for me, neither Yippy nor Clusty
# 2016-03-30: Yippy reappeared
# 2016-09-11: Yippy removed since it does not provide GET
#$engine['yippy']['text']='yippy<sup>m</sup>';
#$engine['yippy']['title']='Clustering meta search, uncertain status';
#$engine['yippy']['url']='http://new2.yippy.com/search?query=';
#$engine['yippy']['accesskey']='';

$engine['ixquick']['text']='ixquick<sup>m</sup>';
$engine['ixquick']['title']='Meta search engine, uncertain future';
$engine['ixquick']['url']='https://ixquick.eu/do/metasearch.pl?query=';
$engine['ixquick']['accesskey']='';


/*
$engine['']['text']='';
$engine['']['title']='';
$engine['']['url']='';
$engine['']['accesskey']='X'; // F and S are not recommended
*/

$enginedefault='searx';

// the field to set a focus on (w/ Javascript) if ?q= is set
// (if ?q= is empty focus is on "c_query")
$focus='c_engine_1';

function 
sl($str) { return get_magic_quotes_gpc() ? stripslashes($str) : $str; }
function 
hsc($str) { return htmlspecialchars($strENT_NOQUOTES); }
function 
hscq($str) { return htmlspecialchars($str); }

isset(
$_REQUEST['c_query']) && $query hsc(sl($_REQUEST['c_query']));
isset(
$_REQUEST['c_engine']) && $chosen $_REQUEST['c_engine'];

// if a search engine has been chosen and all is set
// redirect user to chosen engine

if (!empty($query) && ($_POST['c_submit'] == 'Search')
    && (
$_POST['c_key'] == $formkey) && (!empty($chosen)) ) {
    
$redirect $engine[$chosen]['url']
        . 
urlencode(sl($_REQUEST['c_query']));
    
header("Location: $redirect");
    exit();
}

// if a generic search was requested strip slashes (sl), encode + prepare,
// else reset variables to point to the script itself

$q = isset($_REQUEST['q']) ? sl($_REQUEST['q']) : '';
if (!empty(
$q)) {
    
$qu urlencode(hsc($q));
    
$linktext strlen($qu) > 49 ?
        
"$me$mesuffix".substr($qu,0,48).'...'
        
"$me$mesuffix".$qu;
    
$link "$me$mesuffix".$qu;
} else {
    
$linktext $me;
    
$link $me;
    
// while we are here
    
$focus 'c_query';
}
$q=hscq($q);

// build list of options/search engines

$options ''$engine_number 0;
// see if user has a favorite engine
$e = isset($_REQUEST['e']) ? sl($_REQUEST['e']) : $enginedefault;
// check that it is valid
(!isset($engine[$e]) || empty($engine[$e])) && $e $enginedefault;

foreach (
$engine as $engine_k => $engine_v) {
    
$engine_number++;
    
$checked = ($e == $engine_k) ? ' checked="checked"' '';

    if (isset(
$_REQUEST['ext'])) {
        
// show extended list of options
        
$engine_text preg_replace('/<su[bp]>.<\/su[bp]>/','',$engine_v['text']);
        
$options .= '<label class="choice" for="c_engine_' $engine_number
        
"\"><span class=\"option\"\n"
        
'><input id="c_engine_' $engine_number '" name="c_engine" '
        
"type=\"radio\" value=\"$engine_k\""
        
. (($engine_v['accesskey'] == '') ? '' " accesskey=\"$engine_v[accesskey]\"")
        . 
"$checked\n/> <a href=\"$engine_v[url]\"> $engine_text</a>: $engine_v[title] "
        
"[<a href=\"$c_action?e=$engine_k\" title=\"Access key + URL with "
        
"pre-selection for $engine_text\">"
        
. (($engine_v['accesskey'] == '') ? '<span class="nokey">no key</span>' $engine_v['accesskey'])
        . 
"</a>]</span></label><br>\n";
    } else {
        
// show default compact list of options
        
$options .= '<label class="choice" for="c_engine_' $engine_number
        
'" title="' strip_tags($engine_v['title'])
        . ((
$engine_v['accesskey'] == '') ? '">' " [$engine_v[accesskey]]\">")
        . 
"<span class=\"option\"\n"
        
'><input id="c_engine_' $engine_number '" name="c_engine" '
        
"type=\"radio\" value=\"$engine_k\""
        
. (($engine_v['accesskey'] == '') ? '' " accesskey=\"$engine_v[accesskey]\"")
        . 
"$checked\n/> $engine_v[text]</span></label>\n";
    }
}

// prepare rest of HTML form

// $c_suggest: ignore the whole thing if not set
if (isset($c_suggest) and !empty($c_suggest)) {
    
$c_suggesttext="<b>&middot;</b> <a href=\"$c_suggest\">suggest another</a>";
} else {
    
$c_suggesttext='';
}

// throw out all the HTML from head to footer

echo <<<EOT
<!doctype html><html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>ChooSE your search engine</title>
 <link rel="stylesheet" type="text/css" href="
$c_css" media="all">
 <link title="ChooSE your search engine" type="application/opensearchdescription+xml" rel="search" href="
$c_ffseadd">
 <script type="text/javascript">
  function AddFFse(url){window.external.AddSearchProvider(url);}
 </script>
</head>
<body onLoad="updateLink()">

<center><div class="choose">
 <h1>ChooSE your search engine</h1>
 <form id="c_choose" name="c_choose" method="post" action="
$c_action">
 <table><tr class="query">
  <td class="l">Search for</td>
  <td><input id="c_query" name="c_query" type="text" size="59" maxlength="510" value="
$q" accesskey="F" onKeyUp="updateLink()" onMouseMove="updateLink()"
  /><!--[if IE]><input type="text" style="display: none;" disabled="disabled" size="1" /><![endif]--></td>
  </tr><tr class="engine">
  <td class="l">with</td>
  <td class="engine">
$options
  </td></tr></table>
  <input type="hidden" name="c_key" value="
$formkey" />
  <p><input class="button" type="submit" name="c_submit" value="Search" accesskey="S" /></p>
 </form>
</div>

<div id="c_link"><a href="
$link"><code>$linktext</code></a></div>

<div id="footer">
 press alt-shift-g for google, alt-shift-b for bing, ... enter to search (ff&amp;ie)
<br />
 <a href="
$me" title="ChooSE your search engine" rel="sidebar">bookmark</a>
 <b>&middot;</b> <a href="javascript:AddFFse('
$c_ffseadd')">add to your search engines</a>
 <b>&middot;</b> <a id="c_linkext" href="
$me?ext">extended list</a>
 
$c_suggesttext
<br />
 <a href="
$choose" title="ChooSE">ChooSE</a> v$version
 (c) <a href="https://wox.at/as/" title="Go to homepage of Andreas Schamanek">andreas schamanek</a>
</div>
</center>
<script type="text/javascript">
document.forms['c_choose'].elements['
$focus'].focus();
function updateLink() {
 q = new String();
 q = encodeURI(document.c_choose.c_query.value);
 q = q.replace(/\+/g,'%2B').replace(/%20/g,'+').replace(/\?/g,'%3F').replace(/&/g,'%26').replace(/#/g,'%23');
 if(q.length == 0) return;
 if(q.length > 49) {t=q.substring(0,48)+"...";} else {t=q;}
 // the following lines should correspond to the affected HTML code
 t1 = '<a href="
$me$mesuffix'+q+'"><code>$me$mesuffix'+t+'</code></a>';
 document.getElementById('c_link').innerHTML = t1;
 document.getElementById('c_linkext').href = '
$me$mesuffix'+q+'?ext';
}
</script>

</body></html>

EOT;

/*
 * License
 *
 * This script is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This script is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this script; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA

 * History
 *
 * 2009-11-30  first buggy "punish me" alpha release candidate
 * 2010-05-30  code cleanup, added ask.com, made source available too
 * 2010-06-22  fixed and cleaned up some paths and file names
 * 2010-06-23  added sl() to stripslashes() only if magic_quotes_gpc is set
 * 2010-07-05  improved handling of '&'
 * 2010-07-19  fixed handling of '&' and '+', removed Clusty search option
 * 2010-07-27  fixed fix relating handling '+' (bug introduced 2010-07-19)
 * 2010-11-05  re-added Clusty as Yippy search, added blekko.com search
 * 2010-11-05  added support for search options with no accesskey defined
 * 2010-11-05  fixed handling of '#'
 * 2011-01-21  Forestle search superseded by Ecosia.org; updated Blackle
 * 2011-05-25  added Yandex - popular Russian search engine
 * 2011-06-06  added encoding of "?"; added https://encrypted.google.com/
 * 2012-01-22  update ?ext link dynamically to include search text
 * 2012-03-02  removed Scroogle + Yauba, added DuckDuckGo + StartPage
 * 2012-04-01  added <link type=opensearchdescription+xml to headers
 * 2015-03-17  fixed encoding bug, changed URL for dogpile
 * 2015-05-22  Blekko is gone
 * 2016-03-30  added Qwant, updated Ixquick, re-added Yippy
 * 2016-09-11  added Searx provided by searx.me, re-removed Yippy
 * 2016-10-10  changed several links to https
 * 2017-04-18  replaced JavaScript bookmark me code with rel="sidebar"
 *
 */