##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations.  All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
#    notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions, and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
#    in any manner possible. Zope includes a "Powered by Zope"
#    button that is installed by default. While it is not a license
#    violation to remove this button, it is requested that the
#    attribution remain. A significant investment has been put
#    into Zope, and this effort will continue if the Zope community
#    continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
#    features derived from or use of this software must display
#    the following acknowledgement:
#
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
#
#    In the event that the product being advertised includes an
#    intact Zope distribution (with copyright and license included)
#    then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
#    endorse or promote products derived from this software without
#    prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
#    the following acknowledgment:
#
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
#
#    Intact (re-)distributions of any official Zope release do not
#    require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
#    patches to official Zope releases.  Distributions that do not
#    clearly separate the patches from the original work must be clearly
#    labeled as unofficial distributions.  Modifications which do not
#    carry the name Zope may be packaged in any form, as long as they
#    conform to all of the clauses above.
#
#
# Disclaimer
#
#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations.  Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
#
# Copyright (c) 2000 Andy McKay
# All rights reserved.
#
# Distributed under the Zope Public License (above)
#
##############################################################################
#
# No result and IP Filtering added by Aleksander Salwa, ololo@webcraft.pl
# Added April 14, 2001
#
##############################################################################

__version__ = '1.2'

from Globals import HTMLFile
from Globals import MessageDialog
from Globals import Persistent

import OFS.SimpleItem
import Acquisition
import AccessControl.Role

import os
import string
import Globals # so I can get Globals data_dir
import time

manage_addFSCounterForm = HTMLFile('FSCounterAdd', globals())

def manage_addFSCounter(self, id, title='', REQUEST=None):
    ''' Adds a new object '''
    self._setObject(id, FSCounter(id, title))
    if REQUEST is not None:
            return self.manage_main(self, REQUEST)

class FSCounter(OFS.SimpleItem.Item, Persistent, Acquisition.Implicit, AccessControl.Role.RoleManager):
    meta_type = 'FSCounter'

    manage_main = HTMLFile('FSCounterEdit', globals())
    manage_help = HTMLFile('FSCounterHelp', globals())

    manage_options = (
        {'label': 'Edit', 'action': 'manage_main'},
        {'label': 'Security', 'action': 'manage_access'},
        {'label': 'Help', 'action': 'manage_help'},
            )

    __ac_permissions__=(
        ('View management screens', ('manage_tabs','manage_edit','reset','manage_help')),
        ('Change permissions', ('manage_access',) ),
        ('View', ('', 'index_html',) ),
        )

    def __init__(self, id, title =''):
        """initialise a new instance of FSCounter"""
        self.id = id
        self.title = title

        # well if people have two counters called the same thing in two different folders,
        # they will be in trouble. But this is just a quick product....
        self.filename = self.id + '.' + str(time.time()) + '.counter'

        # use cookie
        self.cookie_yn = 1
        self.cookie_name = self.filename

        # number of zero's to append eg: 000001 = 5
        self.padded_value = 5
        self.default_value = 'get_padded_images'

        # images folder
        self.images_folder = 'misc_/FSCounter'

        # addresses to ignore (no counter increase):
        # (tuple of (address, mask) tuples)
        # addresses and masks are stored as (long) integers - for better performance
        self.ignore_addrs = ()

        # make sure we reset
        self.reset()

    def manage_beforeDelete(self, item, container):
        ''' clean up '''
        self.delete()

    def manage_edit(self, title, cookie_yn=0, cookie_name='', padded_value='5', images_folder='/img', ignore_addrs=(), REQUEST=None):
        """edits the object"""
        self.title = title

        # will be there
        self.default_value = str(REQUEST['default_value'])

        self.padded_value = padded_value
        self.cookie_yn = cookie_yn
        self.cookie_name = cookie_name

        # hmmm crappy default
        if self.cookie_name == '': self.cookie_name = self.id
        self.images_folder = images_folder

        ignAdTmp=[]
        for addr_range in ignore_addrs:
            if addr_range=='':
                continue
            adr=string.split(addr_range, ':')[0]
            msk=string.split(addr_range, ':')[1]
            adrParts=string.split(adr, '.')
            mskParts=string.split(msk, '.')
            adrInt=(long(adrParts[0])<<24)+(int(adrParts[1])<<16)+(int(adrParts[2])<<8)+int(adrParts[3])
            mskInt=(long(mskParts[0])<<24)+(int(mskParts[1])<<16)+(int(mskParts[2])<<8)+int(mskParts[3])
            ignAdTmp.append((adrInt, mskInt))
        self.ignore_addrs=tuple(ignAdTmp)

        if REQUEST is not None:
            return MessageDialog(title = 'Edited', message = "Editing successful", action = './manage_main',)

    def write(self, count=0):
        ''' increment file '''
        value = self.read()

        outfile = open(str(Globals.data_dir) + os.sep + str(self.filename), 'wb')
        outfile.write(str(value + count))
        outfile.close()

        return int(value + count)

    def read(self):
        ''' read file '''
        try:
            infile = open(str(Globals.data_dir) + os.sep + str(self.filename), 'rb')
            value = int(infile.read())
            infile.close()
        except IOError:
            # error creating file
            value = 0

        return value

    def delete(self):
        ''' delete the object '''
        try: os.unlink(Globals.data_dir + os.sep + self.filename)
        except: pass # error deleting, oh well

    def reset(self, REQUEST=None):
        ''' reset cookie '''
        self.delete()
        self.write()
        if REQUEST is not None:
            return MessageDialog(title = 'Reset', message = "Reset to zero", action = './manage_main',)

    def increase(self, REQUEST=None, count=1):
        ''' increase '''
        return self.write(count=count)

    def get_value(self, value=None):
        ''' returns a value '''
        if value is None:
            value = self.read()
        return value

    def get_padded_value(self, value=None):
        ''' returns a padded value '''
        st = ''
        for x in range(self.padded_value): st = st + '0' # get a lot of 00000 's

        value = self.get_value(value=value)
        num_length = len(str(value))

        if self.padded_value <= num_length: return value
        else: return str(st[:int(self.padded_value - num_length)] + str(value))

    def get_null(self, value=None):
        return ' '

    def get_images(self, value=None):
        ''' returns images '''
        output  = ''
        value = self.get_value(value=value)
        for num in str(value):
            output = output + self.get_each_image(num)

        return output

    def get_each_image(self, num):
        ''' gets each image '''
        st = str('<img src="' + self.images_folder + '/' + num + '.gif" alt=' + num + '>')
        return st

    def get_padded_images(self,value=None):
        ''' returns images '''
        return self.get_images(value=self.get_padded_value(value=None))

    def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw):
        ''' standard_view '''
        if self.cookie_yn and self.REQUEST.has_key(self.cookie_name):
            value = self.read()
        else:
            if self.ignore_addrs:
                rAdrSplit=string.split(self.REQUEST.REMOTE_ADDR, '.')
                rAdrInt=(int(rAdrSplit[0])<<24)+(int(rAdrSplit[1])<<16)+(int(rAdrSplit[2])<<8)+int(rAdrSplit[3])
                for addr_range in self.ignore_addrs:
                    if rAdrInt&addr_range[1] == addr_range[0]:
                        value = self.read()
                        break
            else:
                value = self.increase()
                self.REQUEST.RESPONSE.setCookie(self.cookie_name, 1)

        method = getattr(self, self.default_value)
        return method(value=value)

    index_html = __call__