#!/usr/bin/env python
#-----------------------------------------------------------------------------
# Name:        privoxymon.py
# Purpose:     A GNOME2 applet for monitoring and controlling the Privoxy HTTP
#              proxy server.
#
# Author:      Gary Cramblitt
#
# Created:     2003/17/02
# RCS-ID:      $Id: privoxymon.py $
# Copyright:   (c) 2003
# Licence:     GNU Public License (GPL)
#
# This software has been developed and tested on RedHat 8.0 with
# GNOME 2.0.2 and Python 2.2.
#
# Installation:
# Download and install the following dependencies (if not already installed)
# The specific versions I am using are shown, but you can probably use later
# versions (or possibly earlier ones):
##    privoxy-3.0.0-2.i386.rpm
##    python-2.2.1-17.i386.rpm
##    python-devel-2.2.1-17.i386.rpm
##    gnome-python2-1.99.11-8.i386.rpm
##    gnome-python2-applet-1.99.11-8.i386.rpm
##    gnome-python2-bonobo-1.99.11-8.i386.rpm
##    orbit-python-1.99.0-4.i386.rpm    ?? is this really a dependency?
##    python-optik-1.3-2.noarch.rpm     ?? is this really a dependency?
##    pygtk2-1.99.12-7.i386.rpm
##    pygtk2-devel-1.99.12-7.i386.rpm
#
#   Privoxy must be installed and running on your system.
#
#   Copy this module (privoxymon.py) and (GNOME_privoxymon.server) to
#   a suitable directory, for example /usr/local/src/privoxy-mon.
#   Make this module executable, for example
#       chmod a+x privoxymon.py
#   Edit GNOME_privoxymon.server.  Change the first "location"
#   line so it points to privoxymon.py in the directory where you
#   put it.  For example,
#       location="/usr/local/src/privoxy-mon/privoxymon.py">
#   Copy GNOME_privoxymon.server to the bonobo/servers directory
#   on your system (You'll need root privilege to do this),
#   for example
#       cp GNOME_provoxymon.server /usr/lib/bonobo/servers
#   Restart X.
#   Right-click on the GNOME applet panel in lower right corner,
#   choose Add to Panel -> Utility -> Privoxy Monitor
#   Privoxymon icon should appear in the panel.  Right-click on it
#   to operate Privoxymon.
#
# Known Problems/TODO:
#   1)  When starting Privoxymon, you may get a segmentation fault.
#       Try starting it again; it should work every other time you start it.
#       Anybody know why?
#   2)  Preferences are not implemented yet.  Change the "m_browser"
#       variable below to suit you.  If you don't have Privoxy running
#       as a local server, you may also have to change the "proxy"
#       variable below.
#   3)  Would like to add a timer to periodically check the status of
#       Privoxy, but how do I remove the timer when Privoxymon is
#       destroyed?
#   4)  Where is the documentation and/or source code for
#       gnome-python2-applet-1.99.11-8.i386.rpm
#   5)  How do I load icons so they automatically size themselves to user's
#       panel preference?
#-----------------------------------------------------------------------------

# Import GNOME stuff.
import gnome
import gnome.ui

# Import the GNOME applet routines:
import gnome.applet

# Import the Gtk+ routines:
import gtk

# Import urllib so we can talk to the Privoxy server.
import urllib

# Import regular expression library.
import re
import string

import os

# Browser to use for configuring Privoxy.
# Most people should set this to "mozilla".
m_browser = "phoenix"

# Create an image to be shown inside the applet:
m_image = gtk.Image()

# Create a URL opener that goes through the Privoxy proxy server.
proxy = {'http': r'http://localhost.localdomain:8118'}
m_urlopener = urllib.URLopener(proxies = proxy)

def about_cb(widget, data):
    about = gnome.ui.About("Privoxy Monitor","0.0.1", 
        "(c) 2003 Gary Cramblitt\nThis software is released under the GNU Public License.",
        "Applet for controlling Privoxy HTTP proxy server.",
        ["Gary Cramblitt"],[""])
    about.show()
    return gtk.TRUE
    
def get_privoxy_status():
    m_urlopener.cleanup()
    try:
        f = m_urlopener.open(r'http://config.privoxy.org/toggle?mini=y')
        status = re.search(r'\<title\>(?P<flag>.)', f.read())
        f.close()
        flag = string.lower(status.group("flag"))
        if flag == "e":
            m_image.set_from_stock("gtk-yes",gtk.ICON_SIZE_LARGE_TOOLBAR)
        else:
            m_image.set_from_stock("gtk-no",gtk.ICON_SIZE_LARGE_TOOLBAR)
    except:
        m_image.set_from_stock("gtk-stop",gtk.ICON_SIZE_LARGE_TOOLBAR)
    m_urlopener.cleanup()
    return TRUE

def enable_cb(widget, data):
    f = m_urlopener.open("http://config.privoxy.org/toggle?set=enable")
    get_privoxy_status()
    return gtk.TRUE
    
def disable_cb(widget, data):
    f = m_urlopener.open("http://config.privoxy.org/toggle?set=disable")
    get_privoxy_status()
    return gtk.TRUE
    
def privoxy_status_cb(widget, data):
    get_privoxy_status()
    return gtk.TRUE

def privoxy_config_cb(widget, data):
    os.spawnlp(os.P_NOWAIT, m_browser, m_browser, r"http://config.privoxy.org/")
    return gtk.TRUE
    
# In order for this menu to appear in the standard 3rd mouse button
# menu (the one with Remove and Move), the name of the popup menu must
# be "button3".
menu = """
        <popup name="button3">
            <menuitem name="Item 1" verb="About" label="About..."
                pixtype="stock" pixname="gnome-stock-about"/>
            <menuitem name="Item 2" verb="Preferences" label="Preferences"
                pixtype="stock" pixname="gtk-preferences"/>
            <menuitem name="Item 3" verb="Enable" label="Enable"
                pixtype="stock" pixname="gtk-yes"/>
            <menuitem name="Item 4" verb="Disable" label="Disable"
                pixtype="stock" pixname="gtk-no"/>
            <menuitem name="Item 5" verb="Status" label="Status"
                pixtype="stock" pixname="gnome-stock-about"/>
            <menuitem name="Item 6" verb="Config" label="Configure Privoxy"
                pixtype="stock" pixname="gnome-stock-about"/>
        </popup>
"""
    
def privoxymon_factory(applet, iid):
	# Set up menu.
    applet.setup_menu(menu, [
        ("About", about_cb),
        ("Enable", enable_cb),
        ("Disable", disable_cb),
        ("Status", privoxy_status_cb),
        ("Config", privoxy_config_cb)], None)

    # Initialize the image.
    m_image.set_from_stock("gtk-stop",gtk.ICON_SIZE_LARGE_TOOLBAR)

    # Add the image to the applet.
    applet.add(m_image)
    
	# Set the tooltip text for the applet.
    tooltips = gtk.Tooltips()
    tooltips.set_tip(applet, "Privoxy Monitor","Right-click for options")

	# Show the applet.
    applet.show_all()

    # Display the status of Privoxy.
    get_privoxy_status()
    
##    # Here is how to add a timer which could be used to update the
##    # status, but how to cancel the timer when we exit?
##    gtk.timeout_add(120,timer_cb)
##    applet.connect("destroy",quit_cb)
    
    return gtk.TRUE

# Create the applet.  When user adds the applet to the
# applet panel, Bonobo uses the GNOME_privoxymon.server file to
# locate the privoxymon.py file.  Because of the #!/usr/bin/env python
# command at the start of this file, python starts, 
# and executes this command, which creates an instance of a gnome
# applet and then invokes privoxymon_factory function above.
gnome.applet.bonobo_factory("OAFIID:GNOME_PrivoxyMon_Factory",
                            gnome.applet.Applet.__gtype__,
                            "PrivoxyMon", "0", privoxymon_factory)

def main():

	# Get into the Gtk main-loop.
	gtk.main()
	return 0

# This is plain old Python, so you should understand this:
if __name__ == '__main__': main()
