@@ -22,11 +22,12 @@ if __name__ == '__main__':
2222 from os.path import realpath, dirname
2323 path.append(realpath(dirname(realpath(__file__)) + '/../'))
2424
25−import cStringIO
2625import hashlib
2726import hmac
2827import json
2928import os
29+import sys
30+
3031import requests
3132
3233from searx import logger
@@ -42,8 +43,6 @@ except:
4243 exit(1)
4344from cgi import escape
4445from datetime import datetime, timedelta
45−from urllib import urlencode
46−from urlparse import urlparse, urljoin
4746from werkzeug.contrib.fixers import ProxyFix
4847from flask import (
4948 Flask, request, render_template, url_for, Response, make_response,
@@ -52,7 +51,7 @@ from flask import (
5251from flask_babel import Babel, gettext, format_date, format_decimal
5352from flask.json import jsonify
5453from searx import settings, searx_dir, searx_debug
55−from searx.exceptions import SearxException, SearxParameterException
54+from searx.exceptions import SearxParameterException
5655from searx.engines import (
5756 categories, engines, engine_shortcuts, get_engines_stats, initialize_engines
5857)
@@ -69,6 +68,7 @@ from searx.autocomplete import searx_bang, backends as autocomplete_backends
6968from searx.plugins import plugins
7069from searx.preferences import Preferences, ValidationException
7170from searx.answerers import answerers
71+from searx.url_utils import urlencode, urlparse, urljoin
7272
7373# check if the pyopenssl package is installed.
7474# It is needed for SSL connection without trouble, see #298
@@ -78,6 +78,15 @@ except ImportError:
7878 logger.critical("The pyopenssl package has to be installed.\n"
7979 "Some HTTPS connections will fail")
8080
81+try:
82+ from cStringIO import StringIO
83+except:
84+ from io import StringIO
85+
86+
87+if sys.version_info[0] == 3:
88+ unicode = str
89+
8190# serve pages with HTTP/1.1
8291from werkzeug.serving import WSGIRequestHandler
8392WSGIRequestHandler.protocol_version = "HTTP/{}".format(settings['server'].get('http_protocol_version', '1.0'))
@@ -357,6 +366,8 @@ def render(template_name, override_theme=None, **kwargs):
357366
358367 kwargs['results_on_new_tab'] = request.preferences.get_value('results_on_new_tab')
359368
369+ kwargs['unicode'] = unicode
370+
360371 kwargs['scripts'] = set()
361372 for plugin in request.user_plugins:
362373 for script in plugin.js_dependencies:
@@ -375,7 +386,7 @@ def render(template_name, override_theme=None, **kwargs):
375386def pre_request():
376387 request.errors = []
377388
378− preferences = Preferences(themes, categories.keys(), engines, plugins)
389+ preferences = Preferences(themes, list(categories.keys()), engines, plugins)
379390 request.preferences = preferences
380391 try:
381392 preferences.parse_cookies(request.cookies)
@@ -479,10 +490,8 @@ def index():
479490 for result in results:
480491 if output_format == 'html':
481492 if 'content' in result and result['content']:
482− result['content'] = highlight_content(escape(result['content'][:1024]),
483− search_query.query.encode('utf-8'))
484− result['title'] = highlight_content(escape(result['title'] or u''),
485− search_query.query.encode('utf-8'))
493+ result['content'] = highlight_content(escape(result['content'][:1024]), search_query.query)
494+ result['title'] = highlight_content(escape(result['title'] or u''), search_query.query)
486495 else:
487496 if result.get('content'):
488497 result['content'] = html_to_text(result['content']).strip()
@@ -510,7 +519,7 @@ def index():
510519 result['publishedDate'] = format_date(result['publishedDate'])
511520
512521 if output_format == 'json':
513− return Response(json.dumps({'query': search_query.query,
522+ return Response(json.dumps({'query': search_query.query.decode('utf-8'),
514523 'number_of_results': number_of_results,
515524 'results': results,
516525 'answers': list(result_container.answers),
@@ -519,7 +528,7 @@ def index():
519528 'suggestions': list(result_container.suggestions)}),
520529 mimetype='application/json')
521530 elif output_format == 'csv':
522− csv = UnicodeWriter(cStringIO.StringIO())
531+ csv = UnicodeWriter(StringIO())
523532 keys = ('title', 'url', 'content', 'host', 'engine', 'score')
524533 csv.writerow(keys)
525534 for row in results:
@@ -527,7 +536,7 @@ def index():
527536 csv.writerow([row.get(key, '') for key in keys])
528537 csv.stream.seek(0)
529538 response = Response(csv.stream.read(), mimetype='application/csv')
530− cont_disp = 'attachment;Filename=searx_-_{0}.csv'.format(search_query.query.encode('utf-8'))
539+ cont_disp = 'attachment;Filename=searx_-_{0}.csv'.format(search_query.query)
531540 response.headers.add('Content-Disposition', cont_disp)
532541 return response
533542 elif output_format == 'rss':
@@ -578,7 +587,7 @@ def autocompleter():
578587 disabled_engines = request.preferences.engines.get_disabled()
579588
580589 # parse query
581− raw_text_query = RawTextQuery(request.form.get('q', '').encode('utf-8'), disabled_engines)
590+ raw_text_query = RawTextQuery(request.form.get('q', u'').encode('utf-8'), disabled_engines)
582591 raw_text_query.parse_query()
583592
584593 # check if search query is set
@@ -820,6 +829,7 @@ def page_not_found(e):
820829
821830
822831def run():
832+ logger.debug('starting webserver on %s:%s', settings['server']['port'], settings['server']['bind_address'])
823833 app.run(
824834 debug=searx_debug,
825835 use_debugger=searx_debug,