diff --git a/LICENSES b/LICENSES index 84f71d4f9..94fdf6903 100644 --- a/LICENSES +++ b/LICENSES @@ -70,3 +70,4 @@ otherwise. - static/themes/default/icons/windows.png :: [[https://thenounproject.com/icon/1206946/download/color/000000/png][CC BY 3.0 US]] - static/themes/default/icons/gnu-linux.png :: [[https://upload.wikimedia.org/wikipedia/commons/9/95/Tux-icon-mono.svg][Public Domain]] - static/themes/default/icons/mediawiki.svg :: [[http://tango.freedesktop.org/][Public Domain]] +- static/themes/default/icons/searx.png :: [[https://github.com/asciimoo/searx/blob/master/searx/static/themes/simple/img/logo_searx_a.png][GPLv3+]] diff --git a/actions/searx b/actions/searx new file mode 100755 index 000000000..25fc2f07d --- /dev/null +++ b/actions/searx @@ -0,0 +1,99 @@ +#!/usr/bin/python3 +# -*- mode: python -*- +# +# This file is part of Plinth. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +""" +Configuration helper for searx. +""" + +import argparse +import os + +from plinth import action_utils +from plinth.utils import YAMLFile, gunzip + + +def parse_arguments(): + """Return parsed command line arguments as dictionary.""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(dest='subcommand', help='Sub command') + + subparsers.add_parser('enable', help='Enable searx') + subparsers.add_parser('disable', help='Disable searx') + subparsers.add_parser( + 'setup', help="Perform post-installation operations for Searx") + + subparsers.required = True + return parser.parse_args() + + +def _copy_uwsgi_configuration(): + """Copy the example uwsgi configuration shipped with Searx to the + appropriate uwsgi directory.""" + example_config = ('/usr/share/doc/searx/examples/' + 'uwsgi/apps-available/searx.ini') + destination = '/etc/uwsgi/apps-enabled/searx.ini' + + if not os.path.exists(destination): + os.symlink(example_config, destination) + action_utils.webserver_enable('uwsgi', kind='module') + + +def _generate_secret_key(): + """ Generate a secret key for the Searx installation.""" + settings_file = '/etc/searx/settings.yml' + + # Create settings file if not exists + if not os.path.exists(settings_file): + example_settings_file = '/usr/share/doc/searx/examples/settings.yml.gz' + gunzip(example_settings_file, settings_file) + + # Generate and set a secret key + with YAMLFile(settings_file) as settings: + secret_key = os.urandom(16).hex() + settings['server']['secret_key'] = secret_key + + action_utils.service_restart('uwsgi') + + +def subcommand_setup(_): + """Post installation actions for Searx""" + _copy_uwsgi_configuration() + _generate_secret_key() + + +def subcommand_enable(_): + """Enable web configuration and reload.""" + action_utils.webserver_enable('searx-plinth') + + +def subcommand_disable(_): + """Disable web configuration and reload.""" + action_utils.webserver_disable('searx-plinth') + + +def main(): + """Parse arguments and perform all duties.""" + arguments = parse_arguments() + + subcommand = arguments.subcommand.replace('-', '_') + subcommand_method = globals()['subcommand_' + subcommand] + subcommand_method(arguments) + + +if __name__ == '__main__': + main() diff --git a/data/etc/apache2/conf-available/searx-plinth.conf b/data/etc/apache2/conf-available/searx-plinth.conf new file mode 100644 index 000000000..69d92392f --- /dev/null +++ b/data/etc/apache2/conf-available/searx-plinth.conf @@ -0,0 +1,5 @@ + + Options FollowSymLinks Indexes + SetHandler uwsgi-handler + uWSGISocket /run/uwsgi/app/searx/socket + \ No newline at end of file diff --git a/data/etc/plinth/modules-enabled/searx b/data/etc/plinth/modules-enabled/searx new file mode 100644 index 000000000..d4cc7b9d2 --- /dev/null +++ b/data/etc/plinth/modules-enabled/searx @@ -0,0 +1 @@ +plinth.modules.searx diff --git a/plinth/modules/searx/__init__.py b/plinth/modules/searx/__init__.py new file mode 100644 index 000000000..6577a7bf9 --- /dev/null +++ b/plinth/modules/searx/__init__.py @@ -0,0 +1,119 @@ +# +# This file is part of Plinth. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +""" +Plinth module to configure Searx +""" + +from django.utils.translation import ugettext_lazy as _ + +from plinth import service as service_module +from plinth import action_utils, actions, frontpage +from plinth.menu import main_menu + +from .manifest import clients + +clients = clients + +version = 1 + +managed_services = ['searx'] + +managed_packages = [ + 'searx', 'uwsgi', 'uwsgi-plugin-python3', 'libapache2-mod-uwsgi' +] + +name = _('Searx') + +short_description = _('Web Search') + +description = [ + _('Searx is a privacy-respecting internet metasearch engine. ' + 'It aggregrates and displays results from multiple search engines.'), + _('Searx can be used to avoid tracking and profiling by search engines. ' + 'It stores no cookies by default. Additionally, Searx can be used over ' + 'Tor for online anonymity.'), + _('When enabled, Searx\'s web interface will be available from ' + '/searx.'), +] + +service = None + + +def init(): + """Intialize the module.""" + menu = main_menu.get('apps') + menu.add_urlname(name, 'glyphicon-search', 'searx:index', + short_description) + + global service + setup_helper = globals()['setup_helper'] + if setup_helper.get_state() != 'needs-setup': + service = service_module.Service(managed_services[0], name, ports=[ + 'http', 'https' + ], is_external=True, is_enabled=is_enabled, enable=enable, + disable=disable) + + if is_enabled(): + add_shortcut() + + +def setup(helper, old_version=None): + """Install and configure the module.""" + helper.install(managed_packages) + helper.call('setup', actions.superuser_run, 'searx', ['setup']) + helper.call('post', actions.superuser_run, 'searx', ['enable']) + global service + if service is None: + service = service_module.Service(managed_services[0], name, ports=[ + 'http', 'https' + ], is_external=True, is_enabled=is_enabled, enable=enable, + disable=disable) + helper.call('post', add_shortcut) + + +def add_shortcut(): + """Helper method to add a shortcut to the frontpage.""" + frontpage.add_shortcut('searx', name, short_description=short_description, + url='/searx', login_required=True) + + +def is_enabled(): + """Return whether the module is enabled.""" + return action_utils.webserver_is_enabled('searx-plinth') + + +def enable(): + """Enable the module.""" + actions.superuser_run('searx', ['enable']) + add_shortcut() + + +def disable(): + """Disable the module.""" + actions.superuser_run('searx', ['disable']) + frontpage.remove_shortcut('searx') + + +def diagnose(): + """Run diagnostics and return the results.""" + results = [] + + results.extend( + action_utils.diagnose_url_on_all('https://{host}/searx/', + check_certificate=False)) + + return results diff --git a/plinth/modules/searx/manifest.py b/plinth/modules/searx/manifest.py new file mode 100644 index 000000000..8cffa5df2 --- /dev/null +++ b/plinth/modules/searx/manifest.py @@ -0,0 +1,28 @@ +# +# This file is part of Plinth. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# + +from django.utils.translation import ugettext_lazy as _ + +from plinth.clients import validate + +clients = validate([{ + 'name': _('Searx'), + 'platforms': [{ + 'type': 'web', + 'url': '/searx' + }] +}]) diff --git a/plinth/modules/searx/urls.py b/plinth/modules/searx/urls.py new file mode 100644 index 000000000..a8bcc4f9b --- /dev/null +++ b/plinth/modules/searx/urls.py @@ -0,0 +1,32 @@ +# +# This file is part of Plinth. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +""" +URLs for the Searx module. +""" + +from django.conf.urls import url + +from plinth.modules import searx +from plinth.views import ServiceView + +urlpatterns = [ + url(r'^apps/searx/$', + ServiceView.as_view( + service_id='searx', diagnostics_module_name='searx', + description=searx.description, clients=searx.clients, + show_status_block=False), name='index'), +] diff --git a/plinth/utils.py b/plinth/utils.py index 1f971ab43..918548457 100644 --- a/plinth/utils.py +++ b/plinth/utils.py @@ -18,6 +18,7 @@ Miscellaneous utility methods. """ +import gzip import importlib import os import random @@ -136,3 +137,21 @@ def grep(pattern, file_name): return [ line.rstrip() for line in open(file_name) if re.search(pattern, line) ] + + +def gunzip(gzip_file, output_file): + """Utility to unzip a given gzip file and write it to an output file + + gzip_file: string path to a gzip file + output_file: string path to the output file + mode: an octal number to specify file permissions + """ + output_dir = os.path.dirname(output_file) + if not os.path.exists(output_dir): + os.makedirs(output_dir, mode=0o755) + + with gzip.open(gzip_file, 'rb') as f: + contents = f.read() + with open(output_file, 'wb') as f: + f.write(contents) + os.chmod(output_file, 0o644) diff --git a/static/themes/default/icons/searx.png b/static/themes/default/icons/searx.png new file mode 100644 index 000000000..2db081710 Binary files /dev/null and b/static/themes/default/icons/searx.png differ