FSCounter/changes.txt 100666 0 0 760 7346705404 15406 0 ustar 00unknown unknown 0 0 Version 1.2: - Fixed bug in IP Filtering if you upgrade the product from 1.0 - Put some sample images in the www folder and linked to them from the counter so that the first thing people get OTOB is an image. - removed lib/python/Products bit for INSTANCE_HOME users - add filename to edit screen. Version 1.1: Added in: - No result and IP Filtering added by Aleksander Salwa, ololo@webcraft.pl, Thanks! - changed '/' to os.sep - moved image into www file FSCounter/FSCounter.py 100666 0 0 25555 7346705424 15532 0 ustar 00unknown unknown 0 0 ############################################################################## # # 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('') 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__ FSCounter/FSCounterAdd.dtml 100666 0 0 1360 7346704623 16417 0 ustar 00unknown unknown 0 0
By andym, October 8, 2000.
This is a simple product to allow you to add a counter to a web page. Some ideas are based on ZCounter, but that uses a Zope object to store the data. Using a file is much more efficient.
<dtml-var>