| 
				
			 | 
			
			
				@@ -52,6 +52,7 @@ from flask import ( 
			 | 
		
	
		
			
			| 
				52
			 | 
			
				52
			 | 
			
			
				 from flask_babel import Babel, gettext, format_date, format_decimal 
			 | 
		
	
		
			
			| 
				53
			 | 
			
				53
			 | 
			
			
				 from flask.json import jsonify 
			 | 
		
	
		
			
			| 
				54
			 | 
			
				54
			 | 
			
			
				 from searx import settings, searx_dir, searx_debug 
			 | 
		
	
		
			
			| 
				
			 | 
			
				55
			 | 
			
			
				+from searx.exceptions import SearxException, SearxParameterException 
			 | 
		
	
		
			
			| 
				55
			 | 
			
				56
			 | 
			
			
				 from searx.engines import ( 
			 | 
		
	
		
			
			| 
				56
			 | 
			
				57
			 | 
			
			
				     categories, engines, engine_shortcuts, get_engines_stats, initialize_engines 
			 | 
		
	
		
			
			| 
				57
			 | 
			
				58
			 | 
			
			
				 ) 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -400,6 +401,33 @@ def pre_request(): 
			 | 
		
	
		
			
			| 
				400
			 | 
			
				401
			 | 
			
			
				             request.user_plugins.append(plugin) 
			 | 
		
	
		
			
			| 
				401
			 | 
			
				402
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				402
			 | 
			
				403
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				
			 | 
			
				404
			 | 
			
			
				+def index_error(output_format, error_message): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				405
			 | 
			
			
				+    if output_format == 'json': 
			 | 
		
	
		
			
			| 
				
			 | 
			
				406
			 | 
			
			
				+        return Response(json.dumps({'error': error_message}), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				407
			 | 
			
			
				+                        mimetype='application/json') 
			 | 
		
	
		
			
			| 
				
			 | 
			
				408
			 | 
			
			
				+    elif output_format == 'csv': 
			 | 
		
	
		
			
			| 
				
			 | 
			
				409
			 | 
			
			
				+        response = Response('', mimetype='application/csv') 
			 | 
		
	
		
			
			| 
				
			 | 
			
				410
			 | 
			
			
				+        cont_disp = 'attachment;Filename=searx.csv' 
			 | 
		
	
		
			
			| 
				
			 | 
			
				411
			 | 
			
			
				+        response.headers.add('Content-Disposition', cont_disp) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				412
			 | 
			
			
				+        return response 
			 | 
		
	
		
			
			| 
				
			 | 
			
				413
			 | 
			
			
				+    elif output_format == 'rss': 
			 | 
		
	
		
			
			| 
				
			 | 
			
				414
			 | 
			
			
				+        response_rss = render( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				415
			 | 
			
			
				+            'opensearch_response_rss.xml', 
			 | 
		
	
		
			
			| 
				
			 | 
			
				416
			 | 
			
			
				+            results=[], 
			 | 
		
	
		
			
			| 
				
			 | 
			
				417
			 | 
			
			
				+            q=request.form['q'] if 'q' in request.form else '', 
			 | 
		
	
		
			
			| 
				
			 | 
			
				418
			 | 
			
			
				+            number_of_results=0, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				419
			 | 
			
			
				+            base_url=get_base_url(), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				420
			 | 
			
			
				+            error_message=error_message 
			 | 
		
	
		
			
			| 
				
			 | 
			
				421
			 | 
			
			
				+        ) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				422
			 | 
			
			
				+        return Response(response_rss, mimetype='text/xml') 
			 | 
		
	
		
			
			| 
				
			 | 
			
				423
			 | 
			
			
				+    else: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				424
			 | 
			
			
				+        # html 
			 | 
		
	
		
			
			| 
				
			 | 
			
				425
			 | 
			
			
				+        request.errors.append(gettext('search error')) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				426
			 | 
			
			
				+        return render( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				427
			 | 
			
			
				+            'index.html', 
			 | 
		
	
		
			
			| 
				
			 | 
			
				428
			 | 
			
			
				+        ) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				429
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				430
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				403
			 | 
			
				431
			 | 
			
			
				 @app.route('/search', methods=['GET', 'POST']) 
			 | 
		
	
		
			
			| 
				404
			 | 
			
				432
			 | 
			
			
				 @app.route('/', methods=['GET', 'POST']) 
			 | 
		
	
		
			
			| 
				405
			 | 
			
				433
			 | 
			
			
				 def index(): 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -408,10 +436,19 @@ def index(): 
			 | 
		
	
		
			
			| 
				408
			 | 
			
				436
			 | 
			
			
				     Supported outputs: html, json, csv, rss. 
			 | 
		
	
		
			
			| 
				409
			 | 
			
				437
			 | 
			
			
				     """ 
			 | 
		
	
		
			
			| 
				410
			 | 
			
				438
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				
			 | 
			
				439
			 | 
			
			
				+    # output_format 
			 | 
		
	
		
			
			| 
				
			 | 
			
				440
			 | 
			
			
				+    output_format = request.form.get('format', 'html') 
			 | 
		
	
		
			
			| 
				
			 | 
			
				441
			 | 
			
			
				+    if output_format not in ['html', 'csv', 'json', 'rss']: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				442
			 | 
			
			
				+        output_format = 'html' 
			 | 
		
	
		
			
			| 
				
			 | 
			
				443
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				444
			 | 
			
			
				+    # check if there is query 
			 | 
		
	
		
			
			| 
				411
			 | 
			
				445
			 | 
			
			
				     if request.form.get('q') is None: 
			 | 
		
	
		
			
			| 
				412
			 | 
			
				
			 | 
			
			
				-        return render( 
			 | 
		
	
		
			
			| 
				413
			 | 
			
				
			 | 
			
			
				-            'index.html', 
			 | 
		
	
		
			
			| 
				414
			 | 
			
				
			 | 
			
			
				-        ) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				446
			 | 
			
			
				+        if output_format == 'html': 
			 | 
		
	
		
			
			| 
				
			 | 
			
				447
			 | 
			
			
				+            return render( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				448
			 | 
			
			
				+                'index.html', 
			 | 
		
	
		
			
			| 
				
			 | 
			
				449
			 | 
			
			
				+            ) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				450
			 | 
			
			
				+        else: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				451
			 | 
			
			
				+            return index_error(output_format, 'No query'), 400 
			 | 
		
	
		
			
			| 
				415
			 | 
			
				452
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				416
			 | 
			
				453
			 | 
			
			
				     # search 
			 | 
		
	
		
			
			| 
				417
			 | 
			
				454
			 | 
			
			
				     search_query = None 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -421,20 +458,24 @@ def index(): 
			 | 
		
	
		
			
			| 
				421
			 | 
			
				458
			 | 
			
			
				         # search = Search(search_query) #  without plugins 
			 | 
		
	
		
			
			| 
				422
			 | 
			
				459
			 | 
			
			
				         search = SearchWithPlugins(search_query, request) 
			 | 
		
	
		
			
			| 
				423
			 | 
			
				460
			 | 
			
			
				         result_container = search.search() 
			 | 
		
	
		
			
			| 
				424
			 | 
			
				
			 | 
			
			
				-    except: 
			 | 
		
	
		
			
			| 
				425
			 | 
			
				
			 | 
			
			
				-        request.errors.append(gettext('search error')) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				461
			 | 
			
			
				+    except Exception as e: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				462
			 | 
			
			
				+        # log exception 
			 | 
		
	
		
			
			| 
				426
			 | 
			
				463
			 | 
			
			
				         logger.exception('search error') 
			 | 
		
	
		
			
			| 
				427
			 | 
			
				
			 | 
			
			
				-        return render( 
			 | 
		
	
		
			
			| 
				428
			 | 
			
				
			 | 
			
			
				-            'index.html', 
			 | 
		
	
		
			
			| 
				429
			 | 
			
				
			 | 
			
			
				-        ) 
			 | 
		
	
		
			
			| 
				430
			 | 
			
				464
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				
			 | 
			
				465
			 | 
			
			
				+        # is it an invalid input parameter or something else ? 
			 | 
		
	
		
			
			| 
				
			 | 
			
				466
			 | 
			
			
				+        if (issubclass(e.__class__, SearxParameterException)): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				467
			 | 
			
			
				+            return index_error(output_format, e.message), 400 
			 | 
		
	
		
			
			| 
				
			 | 
			
				468
			 | 
			
			
				+        else: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				469
			 | 
			
			
				+            return index_error(output_format, gettext('search error')), 500 
			 | 
		
	
		
			
			| 
				
			 | 
			
				470
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				471
			 | 
			
			
				+    # results 
			 | 
		
	
		
			
			| 
				431
			 | 
			
				472
			 | 
			
			
				     results = result_container.get_ordered_results() 
			 | 
		
	
		
			
			| 
				
			 | 
			
				473
			 | 
			
			
				+    number_of_results = result_container.results_number() 
			 | 
		
	
		
			
			| 
				
			 | 
			
				474
			 | 
			
			
				+    if number_of_results < result_container.results_length(): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				475
			 | 
			
			
				+        number_of_results = 0 
			 | 
		
	
		
			
			| 
				432
			 | 
			
				476
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				433
			 | 
			
				477
			 | 
			
			
				     # UI 
			 | 
		
	
		
			
			| 
				434
			 | 
			
				478
			 | 
			
			
				     advanced_search = request.form.get('advanced_search', None) 
			 | 
		
	
		
			
			| 
				435
			 | 
			
				
			 | 
			
			
				-    output_format = request.form.get('format', 'html') 
			 | 
		
	
		
			
			| 
				436
			 | 
			
				
			 | 
			
			
				-    if output_format not in ['html', 'csv', 'json', 'rss']: 
			 | 
		
	
		
			
			| 
				437
			 | 
			
				
			 | 
			
			
				-        output_format = 'html' 
			 | 
		
	
		
			
			| 
				438
			 | 
			
				479
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				439
			 | 
			
				480
			 | 
			
			
				     # output 
			 | 
		
	
		
			
			| 
				440
			 | 
			
				481
			 | 
			
			
				     for result in results: 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -470,10 +511,6 @@ def index(): 
			 | 
		
	
		
			
			| 
				470
			 | 
			
				511
			 | 
			
			
				                 else: 
			 | 
		
	
		
			
			| 
				471
			 | 
			
				512
			 | 
			
			
				                     result['publishedDate'] = format_date(result['publishedDate']) 
			 | 
		
	
		
			
			| 
				472
			 | 
			
				513
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				473
			 | 
			
				
			 | 
			
			
				-    number_of_results = result_container.results_number() 
			 | 
		
	
		
			
			| 
				474
			 | 
			
				
			 | 
			
			
				-    if number_of_results < result_container.results_length(): 
			 | 
		
	
		
			
			| 
				475
			 | 
			
				
			 | 
			
			
				-        number_of_results = 0 
			 | 
		
	
		
			
			| 
				476
			 | 
			
				
			 | 
			
			
				- 
			 | 
		
	
		
			
			| 
				477
			 | 
			
				514
			 | 
			
			
				     if output_format == 'json': 
			 | 
		
	
		
			
			| 
				478
			 | 
			
				515
			 | 
			
			
				         return Response(json.dumps({'query': search_query.query, 
			 | 
		
	
		
			
			| 
				479
			 | 
			
				516
			 | 
			
			
				                                     'number_of_results': number_of_results, 
			 |