#
# This file is part of Zaplet
# Copyright 1999 - 2001 Adam Feuer <adamf@pobox.com>
#
# Zaplet is free software; you can redistribute it and/or modify
# it under the terms of the Python License as published by the
# Python Software Foundation, or GNU General Public License as published
# by the Free Software Foundation (either version 2 of the License, or
# (at your option) any later version).
#
# Zaplet 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Zaplet; see the file COPYING-Zaplet. If not, write to the
# Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
#
# You should have received a copy of the Python License along
# with Zaplet; see the file COPYING.
#
#
# ui/actions.py
# adzapper User Interface - methods
#
# for use with adzapper filtering proxy

RCS_ID =  '$Id: actions.py,v 1.14 2001/09/02 04:47:16 adamf Exp $'

# standard modules
import re
import string
import StringIO
import sys
import signal
import cgi
import os
import urlparse

# adzapper modules
from debug import debug
import ui
import dtml
from html_table import html_table
from zaplet import zaplet_object,zaplet_engine
from adzapper.adzapper_engine import DENYALLOW,ALLOWDENY 
from config_file.rw_config_file import read_conf, write_conf, itemObj, _cmp_Obj


ERROR_ZAPLET_NOT_FOUND = "Error: zaplet not found.<p>\n"
ERROR_NO_SITE_ZAPLET_DIR = "Error: No site zaplet directory.<p>\n"
ERROR_WRITING_ZAPLET = "Error: Problem writing zaplet file. Zaplet not saved.<p>\n"
ERROR_NO_WEB_CONF = "Error: Web configuration is not enabled.<p>"

#BG_SHADE_COLOR='#F7F6CD'
BG_SHADE_COLOR='#F9F9ED'
NO_SHADE_COLOR='#FFFFFF'

FONTSPEC = '<font size=3 face="Arial, sans-serif" color="#000000">'

EDIT_ZAPLET_ADVANCED = 1


class uiactions:
    """process user interface actions"""

    def __init__(self,combined_engine):
        # need this to have access to zaplets and adzapper configuration
        self.ce = combined_engine


    ###############################################
    #
    #
    #
    def restart(self,args,data,restofpath=None,request=None):
        """restart adzapper"""

        ae = self.ce.adzapper
        if ae.web_configuration != 1:
            s = ERROR_NO_WEB_CONF
            return self._finishpage(s,args)

        if args['restart']=='yes':
            self.ce.restart()
#            sighuphandler = signal.getsignal(signal.SIGHUP)
#            sighuphandler(signal.SIGHUP,None)

            s = dtml.process_dtml('restarted.dtml',args,restofpath)

            return self._finishpage(s,args)



    ###############################################
    #
    #
    #
    def editzaplets(self,args,data,restofpath=None,request=None):
        """display list of zaplets, link to edit zaplet and new zaplet pages"""

        zlist = self.ce.zaplet.zaplet_list.keys()
        zlist.sort()

        ui.vars['title']='Edit Zaplets'
        s = "<h1>Edit Zaplets</h1>\n<p>"

        s = s + '<table width="100%">\n'
        shade = 0
        for zaplet in zlist:
            if zaplet == None:
                continue
            
            shade = not shade
            if shade:
                shade_color=BG_SHADE_COLOR
            else:
                shade_color=NO_SHADE_COLOR
            s = s + '  <tr valign="middle" bgcolor="%s">\n' % shade_color
            s = s + '     <td>' + FONTSPEC + '<a href="editzaplet?zaplet=' + zaplet + '">' + zaplet + '</a>&nbsp;</td>\n'

        s = s + '</table>\n'

        return self._finishpage(s,args)



    
    ###############################################
    #
    #
    #
    def newzaplet(self,args,data,restofpath=None,request=None):

        z = self._newzaplet()
        s = self._edit_zaplet(z)
        return self._finishpage(s,args)


    def _newzaplet(self):
        """make a new zaplet with all the fields filled out right"""
        # new zaplet
        z = zaplet_object.zaplet_obj()
        z.host = ''
        z.version = '0.7'
        return z


    ###############################################
    #
    #
    #
    def editzaplet(self,args,data,restofpath=None,request=None):
        """edit a single zaplet"""

        zname = args['zaplet']
        ui.vars['title']='Edit a Zaplet: ' + zname

        z = self.ce.zaplet.zaplet_list[zname]
        if z == None:
            s = ERROR_ZAPLET_NOT_FOUND
            return self._finishpage(s,args)

        s = self._edit_zaplet(z)

        # add advanced view url
        s = s + '<a href="/actions/editzapletadvanced?zaplet=' + zname +'">Edit Zaplet - Advanced View</a><p>\n'

        return self._finishpage(s,args)



    ###############################################
    #
    #
    #
    def editzapletadvanced(self,args,data,restofpath=None,request=None):
        """edit a single zaplet - advanced options"""

        zname = args['zaplet']
        ui.vars['title']='Edit a Zaplet - Advanced View: ' + zname

        z = self.ce.zaplet.zaplet_list[zname]
        if z == None:
            s = ERROR_ZAPLET_NOT_FOUND
            return self._finishpage(s,args)

        s = self._edit_zaplet(z,EDIT_ZAPLET_ADVANCED)

        # add regular view url
        s = s + '<a href="/actions/editzaplet?zaplet=' + zname + '">Edit zaplet - regular view</a><p>\n'

        return self._finishpage(s,args)



    ###############################################
    #
    #
    #
    def savezaplet(self,args,data,restofpath=None,request=None):
        """update zaplet in memory and write the zaplet to disk"""
        datastring=data.getvalue()

        if self.ce.zaplet.site_zaplet_dir == None:
            s = ERROR_NO_SITE_ZAPLET_DIR
            return self._finishpage(s,args)

        s = ""
        s = s + "<pre>\n"
        s = s + datastring + "\n"
        s = s + "</pre>\n"

        # ff == form fields
        ff=cgi.parse_qs(datastring,1)

        host = ff['host'][0] 

        # set page title
        args['title']='Save Zaplet: ' + host

        if self.ce.zaplet.zaplet_list.has_key(host):
            # old zaplet
            z = self.ce.zaplet.zaplet_list[host]
        else:
            # make new zaplet
            z = self._newzaplet()
            self.ce.zaplet.zaplet_list[host] = z
            z.host = host

        z.version = ff['version'][0]

        z.comments = []
        for comment in ff['comment']:
            if comment != '':
                z.comments.append(comment)

        for key0 in ("allow", "block"):
            for key1 in ("literal", "regex"):
                keyparts = (key0, key1)
                key = "%s_%s" % keyparts
                zkeyname = 'z.%s' % key
                exec('%s=[]' % zkeyname)
                zkey=eval(zkeyname)
                if ff.has_key(key):
                    for item in ff[key]:
                        if item != '':
                            zkey.append(item)



        if ff['block_everything'][0] == '1':
            z.block_everything = 1
        else:
            z.block_everything = 0

        if ff['allow_everything'][0] == '1':
            z.allow_everything = 1
        else:
            z.allow_everything = 0

        debug.debug(3,"block_popups_everything: %s\n" % ff['block_popups_everything'][0])
        if ff['block_popups_everything'][0] == '1':
            z.block_popups_everything = 1
        else:
            z.block_popups_everything = 0

        z.block_popups_literal = []
        for item in ff['block_popups_literal']:
            if item != '':
                z.block_popups_literal.append(item)

        z.block_popups_regex = []
        for item in ff['block_popups_regex']:
            if item != '':
                z.block_popups_regex.append(item)
        
        if z.compile() == 0:
            s = s + "Zaplet compiled.<br>\n"
        else:
            s = s + "Error compiling zaplet.<br>\n"

        # make XML string using zaplet self-representation
        zaplet_xml_str = z.xml_repr1()

        # make a version to display on a web page
        s = s + '<p>\n'
        s = s + z.xml_repr1_web()

        if self._writezaplet(z,zaplet_xml_str):
            s = s + ERROR_WRITING_ZAPLET
        else:
            s = s + "Zaplet saved.<p>\n"


        s = s + '<p>\n'
        s = s + 'zaplet file name: '
        zdir = os.path.join(z.dir,z.filename)
        s = s + zdir
        s = s + '\n<p>\n'

        return self._finishpage(s,args)



    ###############################################
    #
    #
    #
    def deletezaplet(self,args,data,restofpath=None,request=None):
        """delete zaplet in memory and delete zaplet from disk"""
        datastring=data.getvalue()

        zname = args['zaplet']
        ui.vars['title']='Delete Zaplet: ' + zname


        z = self.ce.zaplet.zaplet_list[zname]

        if self._deletezaplet(z):
            s = ERROR_WRITING_ZAPLET
        else:
            del(self.ce.zaplet.zaplet_list[zname])
            s = "Zaplet " + zname + " deleted.<p>\n"



        return self._finishpage(s,args)



    ###############################################
    #
    #
    #
    def editconfig(self,args,data,restofpath=None,request=None):
        """edit a adzapper configuration-- currently only display works."""

        ui.vars['title']='Edit adzapper configuration'

        ae = self.ce.adzapper

        if ae.web_configuration != 1:
            s = ERROR_NO_WEB_CONF
            return self._finishpage(s,args)

        fontspec = 'font size=3 face="Arial, sans-serif" color="#000000"'
        font = '<%s>\n' % fontspec

        s = '<h1>adzapper Configuration</h1>\n'

        s = s + '<form method="post" action="/actions/saveconfig">'

        s = s + '<table border=0 cellpadding=6 cellspacing=0 width="100%">\n'

        confxml = ae.confxml
        
        # for each key, make the html for that key,value pair
        # do it in order
        
        allkeys = confxml.keys()
        varObjList = []
        for key in allkeys:
            varObjList.append(confxml[key])
        varObjList.sort(_cmp_Obj)

        shade = 0
        for varObj in varObjList:
            field_key = varObj.key
            field_name = varObj.name
            if varObj.contents == None:
                value_list = ['']
            elif type(varObj.contents) == type([]):
                value_list = []
                for item in varObj.contents:
                    value_list.append(item.contents)
                value_list.append('')
            else:
                value_list = [varObj.contents]

            shade = not shade
            if shade:
                shade_color=BG_SHADE_COLOR
            else:
                shade_color=NO_SHADE_COLOR
                
            s = s + '  <tr valign="middle" bgcolor="%s">\n' % shade_color
            s = s + '    <td width="30%%">%s %s: </td>\n' % (font, field_name)
            s = s + '    <td width="60%">\n'
            
            for field_value in value_list:
                s1 = '      %s<input type="text" size="60" name="%s" value="%s"> <br>\n' % (font,field_key, field_value)
                s = s + s1
                
            s = s + '    </td>\n'
            s = s + '  </tr>\n\n'


        s = s + '</table>\n'

        s = s + '<input type="submit" value="Save">\n'

        s = s + '</form>\n'
        
        return self._finishpage(s,args)



    ###############################################
    #
    #
    #
    def saveconfig(self,args,data,restofpath=None,request=None):
        """update config in memory and write the adzapper.conf file to disk"""

        datastring=data.getvalue()

        ui.vars['title']='Save Configuration'

        ae = self.ce.adzapper
        confxml = ae.confxml

        if ae.web_configuration != 1:
            s = ERROR_NO_WEB_CONF
            return self._finishpage(s,args)

        s = ""
        s = s + "<pre>\n"
        s = s + datastring + "\n"
        s = s + "</pre>\n"

        # ff == form fields
        ff=cgi.parse_qs(datastring,1)

        ffkeys = ff.keys()
        for ffkey in ffkeys:
            if confxml.has_key(ffkey):
                if type(confxml[ffkey].contents) == type([]):
                    for item in ff[ffkey]:
                        if item == '':
                            ff[ffkey].remove(item)

                    itemlist = []
                    itemorder = 0
                    for item in ff[ffkey]:
                        itemlist.append(itemObj())
                        itemlist[-1].order = itemorder
                        itemorder = itemorder + 1
                        itemlist[-1].type='string'
                        itemlist[-1].contents=item
                    confxml[ffkey].contents = itemlist
                else:
                    confxml[ffkey].contents = ff[ffkey][0]

        s = s + '<p>\n'
        s = s + 'adzapper.conf filename: %s<p>\n' % ae.confxmlfile

        ae.activate_configuration(confxml)
        error=write_conf(confxml,ae.confxmlfile)  

        if error:
            s = s + 'Error writing adzapper.conf file.<p>\n'
        else:
            s = s + 'Configuration saved.<p>\n'
        return self._finishpage(s,args)



    ###############################################
    #
    #
    #
    def startpage(self,args,data,restofpath=None,request=None):
        """this is the page that appears in the main frame when you click on http://adzapper/ """
        ui.vars['title']=''
        s = ""

#        # make a link to the zaplet wizard
#        if self.ce.adzapper.last_url != '':
#            s = s + '<br>\n<br>\n'
#            s = s + '<a href="zapletwizard?url='+self.ce.adzapper.last_url+'">'
#            s = s + 'Click here to make a zaplet for ' + self.ce.adzapper.last_url + '</a>\n'

        debug.debug(6,"last url: %s" % self.ce.adzapper.last_url)
        return self._finishpage(s,args)




    ###############################################
    #
    #
    #
    def zapletwizard(self,args,data,restofpath=None,request=None):
        """easy way to make a zaplet... i hope :-) """

        self.ad_url = self.ce.adzapper.last_url

        s = dtml.process_dtml("zapletwizard.dtml",args,restofpath)
        return s


    ###############################################
    #
    #
    #
    def zapletwizard1(self,args,data,restofpath=None,request=None):
        """easy way to make a zaplet... i hope :-) """
        ui.vars['title']='Zaplet Wizard'
        s = ""
        s = s + "<h2>Zaplet wizard</h2>\n"

        if self.ad_url == '':
            s = s + "No last URL-- try reloading the ad image.<p>\n"
        else:
            url = self.ad_url
            
            s = s + "The Zaplet Wizard will help you create a new zaplet to block this ad: <p>\n"
            s = s + '<img src="' + url + '"><p>\n'
            
            s = s + '<table><tr><td><font size=4 face="Arial, sans-serif" color="#000000">Ad URL:</td>'
            s = s + '<td bgcolor="#99CCFF"><font size=4 face="Arial, sans-serif" color="#000000">' + url + '</td></tr></table> <p>\n'

            s = s + "Please select a server and literal string to block. <p>\n"


            (scheme, netloc, path, parameters, query, fragmentid) = urlparse.urlparse(url)

#            s = s + "scheme: " + scheme + "<br>\n"
#            s = s + "netloc: " + netloc + "<br>\n"
#            s = s + "path: " + path + "<br>\n"
#            s = s + "parameters: " + parameters + "<br>\n"
#            s = s + "query: " + query + "<br>\n"
#            s = s + "fragmentid: " + fragmentid +"<br>\n"
#
#            s = s + "<p>\n"


            s = s + '<form action="/actions/zwsave" method="post"> <p> \n'

            s = s + "<h2>Server:</h2>\n"
            
            srv_fields = string.split(netloc,'.')
            while (len(srv_fields) > 1):
                tmps = string.join(srv_fields,'.');
                if len(srv_fields) == 2:
                    checked = "checked"
                else:
                    checked = ""
                s = s + '<input type="radio" name="host" value="' + tmps + '" ' + checked + '> ' + tmps + '<br>\n'
                del srv_fields[0]

            s = s + "<p>\n"

            s = s + "<h2>Block literal:</h2>\n"

            path_fields = string.split(path, '/')
            tmps = path_fields[-1]
            s = s + '<input type="radio" name="block_literal" value="' + tmps + '"> ' + tmps + '<br>\n'
            while (len(path_fields) > 1):
                tmps = string.join(path_fields,'/');
                if len(path_fields) == 2:
                    checked = "checked"
                else:
                    checked = ""
                s = s + '<input type="radio" name="block_literal" value="' + tmps + '" ' + checked + '> ' + tmps + '<br>\n'
                del path_fields[len(path_fields)-1]

            s = s + "<p>\n"

            s = s + '<h2>Block everything from this server: </h2>\n'
            s = s + '<input type="radio" name="block_everything" value="1"> Yes<br>\n'
            s = s + '<input type="radio" name="block_everything" value="0" checked > No<br>\n'

            s = s + "<p>\n"

            s = s + '<input type="submit" value="Save and activate"> <br>\n'

            s = s + '</form> <p> \n'


            
        return self._finishpage(s,args)




    ###############################################
    #
    #
    #
    def zwsave(self,args,data,restofpath=None,request=None):
        """save the zaplet generated by the zaplet wizard"""
        datastring=data.getvalue()

        s = ""
        s = s + "<pre>\n"
        s = s + datastring +  "\n"
        s = s + "</pre>\n"

        # ff == form fields
        ff=cgi.parse_qs(datastring,1)

        host = ff['host'][0]
        block_literal = ff['block_literal'][0]
        block_everything = ff['block_everything'][0]

        if block_everything == '1':
            # block everything means don't allow block_literal
            block_literal = ''
            block_everything = 1
        else:
            block_everything = 0

        # set page title
        args['title']='Zaplet Wizard Save: ' + host

        s = s + host + "<p>\n"
        s = s + block_literal + "<p>\n"

        if self.ce.zaplet.zaplet_list.has_key(host):
            # old zaplet
            z = self.ce.zaplet.zaplet_list[host]
        else:
            # make new zaplet
            z = self._newzaplet()
            self.ce.zaplet.zaplet_list[host] = z
            z.host = host

        z.block_literal.append(block_literal)
        z.block_everything = block_everything

        if z.compile() == 0:
            s = s + "Zaplet compiled.<br>\n"
        else:
            s = s + "Error compiling zaplet.<br>\n"

        # make XML string using zaplet self-representation
        zaplet_xml_str = z.xml_repr1()

        # make XML string using new zaplet self-representation
        s = s + '<p>\n'
        s = s + z.xml_repr1_web()
        s = s + '<p>\n'


        if self._writezaplet(z,zaplet_xml_str):
            s = s + ERROR_WRITING_ZAPLET
        else:
            s = s + "Zaplet saved.<p>\n"


        s = s + '<p>\n'
        s = s + 'zaplet file name: '
        zdir = os.path.join(z.dir,z.filename)
        s = s + zdir
        s = s + '\n<p>\n'

        s = s + '<a href="/actions/editzaplet?zaplet=' + host + '">Edit zaplet ' + host + '</a> <p>\n'


        return self._finishpage(s,args)




    ###############################################
    #
    #
    #
    def status(self,args,data,restofpath=None,request=None):
        """Display adzapper status information"""

        ui.vars['title']='adzapper Status Page'

        s = '<h1>adzapper Status</h1>\n'

        s = s + '<pre>\n'

        s = s + debug.get_top_refcounts(20)

        s = s + '</pre>\n'

#        s = s + "last url: %s"%self.ce.adzapper.last_url + '<p>\n'

        return self._finishpage(s,args)

    ###############################################
    #
    #
    #
    def writenewzaplets(self,args,data,restofpath=None,request=None):
        """Display adzapper status information"""

        ui.vars['title']='Write New Zaplets Page'

        s = '<h1>Write New Zaplets</h1>\n'

        self.ce.adzapper.activate_configuration(self.ce.adzapper.confxml)

        zkeys = self.ce.zaplet.zaplet_list.keys()

        for key in zkeys:
            z = self.ce.zaplet.zaplet_list[key]

            # make XML string using zaplet self-representation
            s = s + z.xml_repr1_web()
            s = s + '<p>\n'

            if self._write_newformat_zaplet(z,z.xml_repr1()):
                s = s + ERROR_WRITING_ZAPLET + ' ' + key + '<p>\n'
            else:
                s = s + 'Zaplet ' + key + ' saved.<p>\n'


        return self._finishpage(s,args)







    ###########################################################
    #
    # utility routines - not actions
    #
    
    def _finishpage(self,htmlpage,args):
        """add the standard header and footer to the page and
        run dtml.replace_dtml_vars on it"""

        s = ui.vars['std_header'] + htmlpage + ui.vars['std_footer']
        s = dtml.replace_dtml_vars(s,args)
        return s



    ###############################################
    #
    #
    #
    def _writezaplet(self,zaplet,zaplet_string):
        """write the zaplet string to disk"""

        if zaplet.dir == None or zaplet.filename == None:
            # new zaplet, so no z.dir or z.filename...
            zaplet_filename = "%s.zap" % zaplet.host
            zaplet.dir = self.ce.zaplet.site_zaplet_dir
            zaplet.filename = zaplet_filename

        filename = os.path.join(zaplet.dir,zaplet.filename)
        debug.debug(3,"_writezaplet- writing %s" % zaplet.filename)

        try:
            file = open(filename,'w')
            file.write(zaplet_string)
            file.close()
            return 0
        except:
            return 1



    ###############################################
    #
    #
    #
    def _write_newformat_zaplet(self,zaplet,zaplet_string):
        """write the zaplet string to disk"""

        path = self.ce.adzapper.newformat_zaplet_dir
        
        debug.debug(3,"_write_newformat_zaplet- path %s" % path)        
        filename = os.path.join(path,zaplet.filename)
        debug.debug(3,"_write_newformat_zaplet- writing %s" % filename)
        debug.debug(3,"_write_newformat_zaplet- string %s" % zaplet_string)


        try:
            file = open(filename,'w')
            file.write(zaplet_string)
            file.close()
            return 0
        except:
            return 1




    ###############################################
    #
    #
    #
    def _deletezaplet(self,zaplet):
        """write the zaplet to disk"""

        filename = os.path.join(zaplet.dir,zaplet.filename)
        debug.debug(3,"_deletezaplet- deleting %s" % filename)

        try:
            os.remove(filename)
            return 0
        except:
            return 1


    ###############################################
    #
    #
    #
    def _web_escape(self,s):
        """escape a string for use on the web"""

        s = string.replace(s,'<','&lt;')
        s = string.replace(s,'>','&gt;')
        return s
    

    ###############################################
    #
    #
    #
    def _edit_zaplet(self,zaplet,options=0):
        """return an html form for editing zaplets-- must be passed a zaplet to edit"""

        z = zaplet

        s = ''

        if z.host == '':
            s = s + '<h1>New Zaplet</h1>\n'
        else:
            s = s + '<h1>Zaplet: ' + z.host + '</h1>\n'

        s = s + '<form action="savezaplet" method="post">\n'

        s = s + '<input type="submit" value="Save and activate">\n'

        shade = 0
        t = html_table(shade,FONTSPEC)

        t.new_row()
        t.new_cell('version: ')
        t.new_cell('<input name="version" type="text" size="5" value="'+ z.version + '"> ')

        t.new_row()
        t.new_cell('server: ')
        t.new_cell('<input name="host" type="text" size="40" value="'+ z.host + '">')

        # zaplet comments
        for comment in z.comments:
            t.new_row()
            t.new_cell('comment: ')
            t.new_cell('<input name="comment" type="text" size="40" value="' + comment + '">')
            
        # make an extra input field for comments
        t.new_row()
        t.new_cell('comment: ')
        t.new_cell('<input name="comment" type="text" size="40" value="">')

        t.new_row()
        ts = 'allow everything from this site: '
        t.new_cell(ts)
        if z.allow_everything == 0:
            no_checked = "checked"
            yes_checked = ""
        else:
            no_checked = ""
            yes_checked = "checked"
        ts = '<input type="radio" name="allow_everything" value="1" %s> Yes\n' % yes_checked
        ts = ts + '<input type="radio" name="allow_everything" value="0" %s> No\n' % no_checked
        t.new_cell(ts)


        key0 = "allow"
        for key1 in ("literal", "regex"):
            keyparts = (key0, key1)
            key = "%s_%s" % keyparts
            list = eval('z.%s' % key)
            for item in list:
                t.new_row()
                ts = key0 + ' ' + key1 + ': '
                t.new_cell(ts)
                t.new_cell('<input name="' + key + '" type="text" size="40" value="'+ item + '">')
            # make an extra input field for each
            t.new_row()
            ts = key0 + ' ' + key1 + ': '
            t.new_cell(ts)
            t.new_cell('<input name="' + key + '" type="text" size="40" value="">')


        t.new_row()
        ts = 'block everything from this site: '
        t.new_cell(ts)
        if z.block_everything == 0:
            no_checked = "checked"
            yes_checked = ""
        else:
            no_checked = ""
            yes_checked = "checked"
        ts = '<input type="radio" name="block_everything" value="1" %s> Yes\n' % yes_checked
        ts = ts + '<input type="radio" name="block_everything" value="0" %s> No\n' % no_checked
        t.new_cell(ts)


        key0 = "block"
        for key1 in ("literal", "regex"):
            keyparts = (key0, key1)
            key = "%s_%s" % keyparts
            list = eval('z.%s' % key)
            for item in list:
                t.new_row()
                ts = key0 + ' ' + key1 + ': '
                t.new_cell(ts)
                t.new_cell('<input name="' + key + '" type="text" size="40" value="'+ item + '">')
            # make an extra input field for each
            t.new_row()
            ts = key0 + ' ' + key1 + ': '
            t.new_cell(ts)
            t.new_cell('<input name="' + key + '" type="text" size="40" value="">')


        t.new_row()
        t.new_cell('Block all popups from this site:')
        if z.block_popups_everything == 0:
            no_checked = "checked"
            yes_checked = ""
        else:
            no_checked = ""
            yes_checked = "checked"
        ts = '<input type="radio" name="block_popups_everything" value="1" %s> Yes\n' % yes_checked
        ts = ts + '<input type="radio" name="block_popups_everything" value="0" %s> No\n' % no_checked
        t.new_cell(ts)


        for item in z.block_popups_literal:
            t.new_row()
            t.new_cell('Block popups from URLs that contain this literal:')
            t.new_cell('<input name="block_popups_literal" type="text" size="40" value="'+ item + '">')
        # make an extra input field
        t.new_row()
        t.new_cell('Block popups from URLs that contain this literal:')
        t.new_cell('<input name="block_popups_literal" type="text" size="40" value="">')

            
        for item in z.block_popups_regex:
            t.new_row()
            t.new_cell('Block popups from URLs that match this regular expression:')
            t.new_cell('<input name="block_popups_regex" type="text" size="40" value="'+ item + '">')
        # make an extra input field
        t.new_row()
        t.new_cell('Block popups from URLs that match this regular expression:')
        t.new_cell('<input name="block_popups_regex" type="text" size="40" value="">')
            
        s = s + t.string()

        if len(z.filters) > 0:
            for filter in z.filters:
                t1 = html_table(shade)
                t1.new_row()
                t1.new_cell('Match URL type: ' )
                t1.new_cell(filter.filter_match_url_type)
                    
                t1.new_row()
                t1.new_cell('Match URL: ')
                ts=filter.filter_match_url
                if ts == '' or ts == None:
                    ts = '&nbsp;'
                t1.new_cell(ts)

                t1.new_row()
                t1.new_cell('Match text type: ')
                t1.new_cell(filter.filter_match_text_type)

                t1.new_row()
                t1.new_cell('Match text: ')
                ts = self._web_escape(filter.filter_match_text)
                if ts == '' or ts == None:
                    ts = '&nbsp;'
                t1.new_cell(ts)

                t1.new_row()
                t1.new_cell('Replace text: ')
                ts = self._web_escape(filter.filter_replace_text)
                if ts == '' or ts == None:
                    ts = '&nbsp;'
                t1.new_cell(ts)

                s = s + '<p><p>\n' + t1.string()
        

        s = s + '<input type="submit" value="Save and activate">\n'

        s = s + '</form>\n'

        if z.host != '':
            s = s + '<form action="deletezaplet?zaplet=' + z.host + '" method="post">\n'
            s = s + '<input type="submit" value="Delete">\n'
            s = s + '</form>\n'

        s = s + '<p>\n'

        if (options == EDIT_ZAPLET_ADVANCED):
            s = s + 'zaplet file name: '
            if z.dir != None and z.filename != None:
                s = s + os.path.join(z.dir,z.filename)
            s = s + '\n<p>\n'

            # make XML string using new zaplet self-representation
            s = s + '<p>\n'
            s = s + z.xml_repr1_web()
            s = s + '<p>\n'

        return s








        
