From 56c732ab1029d6bacc14383f92e89aaadc496357 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Wed, 27 May 2015 22:46:57 +0530 Subject: [PATCH] privoxy: New web proxy application --- actions/privoxy | 102 ++++++++++++++++++ data/etc/plinth/modules-enabled/privoxy | 1 + plinth/modules/privoxy/__init__.py | 46 ++++++++ plinth/modules/privoxy/forms.py | 30 ++++++ plinth/modules/privoxy/templates/privoxy.html | 59 ++++++++++ plinth/modules/privoxy/urls.py | 28 +++++ plinth/modules/privoxy/views.py | 92 ++++++++++++++++ 7 files changed, 358 insertions(+) create mode 100755 actions/privoxy create mode 100644 data/etc/plinth/modules-enabled/privoxy create mode 100644 plinth/modules/privoxy/__init__.py create mode 100644 plinth/modules/privoxy/forms.py create mode 100644 plinth/modules/privoxy/templates/privoxy.html create mode 100644 plinth/modules/privoxy/urls.py create mode 100644 plinth/modules/privoxy/views.py diff --git a/actions/privoxy b/actions/privoxy new file mode 100755 index 000000000..60f1b2f70 --- /dev/null +++ b/actions/privoxy @@ -0,0 +1,102 @@ +#!/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 Privoxy server. +""" + +import argparse +import re + +import util + + +CONFIG_FILE = '/etc/privoxy/config' + + +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('setup', + help='Perform Privoxy configuration setup') + subparsers.add_parser('get-enabled', + help='Get whether Privoxy service is enabled') + subparsers.add_parser('enable', help='Enable Privoxy service') + subparsers.add_parser('disable', help='Disable Privoxy service') + subparsers.add_parser('is-running', + help='Get whether Privoxy daemon is running') + + return parser.parse_args() + + +def subcommand_setup(_): + """Setup configuration for the first time.""" + with open(CONFIG_FILE, 'r') as conffile: + lines = conffile.readlines() + + with open(CONFIG_FILE, 'w') as conffile: + written = False + for line in lines: + if re.match(r'#?listen-address', line) and not written: + conffile.write('listen-address [::]:8118\n') + written = True + else: + conffile.write(line) + + if not written: + conffile.write('listen-address [::]:8118') + + util.service_restart('privoxy') + + +def subcommand_get_enabled(_): + """Get whether service is enabled.""" + is_enabled = util.service_is_enabled('privoxy') + print('yes' if is_enabled else 'no') + + +def subcommand_enable(_): + """Start service.""" + util.service_enable('privoxy') + + +def subcommand_disable(_): + """Stop service.""" + util.service_disable('privoxy') + + +def subcommand_is_running(_): + """Get whether server is running.""" + running = util.service_is_running('privoxy') + print('yes' if running else 'no') + + +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/plinth/modules-enabled/privoxy b/data/etc/plinth/modules-enabled/privoxy new file mode 100644 index 000000000..6d7c306bf --- /dev/null +++ b/data/etc/plinth/modules-enabled/privoxy @@ -0,0 +1 @@ +plinth.modules.privoxy diff --git a/plinth/modules/privoxy/__init__.py b/plinth/modules/privoxy/__init__.py new file mode 100644 index 000000000..daa98c88b --- /dev/null +++ b/plinth/modules/privoxy/__init__.py @@ -0,0 +1,46 @@ +# +# 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 Privoxy. +""" + +from gettext import gettext as _ + +from plinth import actions +from plinth import cfg +from plinth import service as service_module + + +depends = ['plinth.modules.apps'] + +service = None + + +def init(): + """Intialize the module.""" + menu = cfg.main_menu.get('apps:index') + menu.add_urlname(_('Web Proxy (Privoxy)'), 'glyphicon-cloud-upload', + 'privoxy:index', 50) + + output = actions.run('privoxy', ['get-enabled']) + enabled = (output.strip() == 'yes') + + global service + service = service_module.Service( + 'privoxy', _('Privoxy Web Proxy'), + is_external=False, enabled=enabled) diff --git a/plinth/modules/privoxy/forms.py b/plinth/modules/privoxy/forms.py new file mode 100644 index 000000000..04029ce88 --- /dev/null +++ b/plinth/modules/privoxy/forms.py @@ -0,0 +1,30 @@ +# +# 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 . +# + +""" +Forms for configuring Privoxy. +""" + +from django import forms +from gettext import gettext as _ + + +class PrivoxyForm(forms.Form): + """Privoxy configuration form.""" + enabled = forms.BooleanField( + label=_('Enable Privoxy'), + required=False) diff --git a/plinth/modules/privoxy/templates/privoxy.html b/plinth/modules/privoxy/templates/privoxy.html new file mode 100644 index 000000000..c8ab5758c --- /dev/null +++ b/plinth/modules/privoxy/templates/privoxy.html @@ -0,0 +1,59 @@ +{% extends "base.html" %} +{% comment %} +# +# 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 . +# +{% endcomment %} + +{% load bootstrap %} + +{% block content %} + +

Web Proxy (Privoxy)

+ +

Privoxy is a non-caching web proxy with advanced filtering + capabilities for enhancing privacy, modifying web page data and HTTP + headers, controlling access, and removing ads and other obnoxious + Internet junk.

+ +

You can use Privoxy by modifying your browser proxy settings to + your {{ cfg.box_name }} hostname (or IP address) with port 8118. + While using Privoxy, you can see its configuration details and + documentation + at http://config.privoxy.org/ + or http://p.p

+ +

Status

+ +

+ {% if status.is_running %} + Privoxy is running + {% else %} + Privoxy is not running + {% endif %} +

+ +

Configuration

+ +
+ {% csrf_token %} + + {{ form|bootstrap }} + + +
+ +{% endblock %} diff --git a/plinth/modules/privoxy/urls.py b/plinth/modules/privoxy/urls.py new file mode 100644 index 000000000..52d8cf353 --- /dev/null +++ b/plinth/modules/privoxy/urls.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 . +# + +""" +URLs for the Privoxy module. +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( + 'plinth.modules.privoxy.views', + url(r'^apps/privoxy/$', 'index', name='index'), + ) diff --git a/plinth/modules/privoxy/views.py b/plinth/modules/privoxy/views.py new file mode 100644 index 000000000..ae5198a00 --- /dev/null +++ b/plinth/modules/privoxy/views.py @@ -0,0 +1,92 @@ +# +# 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 for configuring Privoxy Server. +""" + +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.template.response import TemplateResponse +from gettext import gettext as _ +import logging + +from .forms import PrivoxyForm +from plinth import actions +from plinth import package +from plinth.modules import privoxy + +logger = logging.getLogger(__name__) + + +def on_install(): + """Notify that the service is now enabled.""" + actions.superuser_run('privoxy', ['setup']) + + +@login_required +@package.required(['privoxy'], on_install=on_install) +def index(request): + """Serve configuration page.""" + status = get_status() + + form = None + + if request.method == 'POST': + form = PrivoxyForm(request.POST, prefix='privoxy') + # pylint: disable=E1101 + if form.is_valid(): + _apply_changes(request, status, form.cleaned_data) + status = get_status() + form = PrivoxyForm(initial=status, prefix='privoxy') + else: + form = PrivoxyForm(initial=status, prefix='privoxy') + + return TemplateResponse(request, 'privoxy.html', + {'title': _('Web Proxy (Privoxy)'), + 'status': status, + 'form': form}) + + +def get_status(): + """Get the current settings from server.""" + output = actions.run('privoxy', ['get-enabled']) + enabled = (output.strip() == 'yes') + + output = actions.superuser_run('privoxy', ['is-running']) + is_running = (output.strip() == 'yes') + + status = {'enabled': enabled, + 'is_running': is_running} + + return status + + +def _apply_changes(request, old_status, new_status): + """Apply the changes.""" + modified = False + + if old_status['enabled'] != new_status['enabled']: + sub_command = 'enable' if new_status['enabled'] else 'disable' + actions.superuser_run('privoxy', [sub_command]) + privoxy.service.notify_enabled(None, new_status['enabled']) + modified = True + + if modified: + messages.success(request, _('Configuration updated')) + else: + messages.info(request, _('Setting unchanged'))