Attachment 'passlog-1.1.py'

Download

   1 """
   2     MoinMoin - PassLog class Version 1.1, 27.01.2013
   3     
   4     This is used for accessing the wiki pass-log.
   5     
   6     To be installed wiki/data/plugin/logfile along with the 
   7     standard __init__.py for plugin modules.
   8 
   9     @copyright: 2013 Ian Riley <ian.riley@internode.on.net>
  10 
  11     History:
  12         
  13         Version 1.1 - 27.01.2013: accommodated print view in link_to function.
  14     
  15         Version 1.0 - 4.01.2013: initial version.
  16     
  17     Based on: editlog
  18     
  19     @copyright: 2006 MoinMoin:ThomasWaldmann
  20     @license: GNU GPL, see COPYING for details.
  21 """
  22 
  23 import time
  24 from MoinMoin import log
  25 logging = log.getLogger(__name__)
  26 
  27 from MoinMoin.logfile import LogFile
  28 from MoinMoin import wikiutil, config
  29 from MoinMoin.user import User
  30 from MoinMoin.Page import Page
  31 
  32 def makeCode(length=16):
  33     from string import digits, ascii_letters
  34     from random import choice
  35     return ''.join([choice(digits+ascii_letters) for i in range(length)])
  36 
  37 class PassLogLine:
  38     """
  39     Given the following attributes
  40 
  41     pass_time_usecs
  42     pagename
  43     action
  44     userid
  45     username
  46     addr
  47     hostname
  48     passcode
  49     lifespan (days)
  50     """
  51     def __init__(self, usercache):
  52         self._usercache = usercache
  53         
  54     def __repr__(self, user = None):
  55         return 'Dated: % s Page: %s Pass: %s Expires: %s' % (
  56                                                 self.dated(user),
  57                                                 self.pagename,
  58                                                 self.passcode,
  59                                                 self.expiry_date(user))
  60 
  61     def expiry_usecs(self):
  62         return (self.pass_time_usecs + 
  63                 wikiutil.timestamp2version(int(self.lifespan) * 86400))
  64                
  65     def expiry_days(self):
  66         if self.is_current():
  67             d = (self.expiry_usecs() - wikiutil.timestamp2version(time.time()))
  68             days = wikiutil.version2timestamp(d) / 86400
  69             if days <= 1.0:
  70                 result  = '<1 day'
  71             elif days < 1.5:
  72                 result = '1 day'
  73             else:
  74                 result = '%s days' % int(days + 0.5)
  75         else:
  76             result = ''
  77         return result
  78    
  79     def _dated(self, time_usecs, user = None):
  80         t = wikiutil.version2timestamp(time_usecs)
  81         if user:
  82             return user.getFormattedDateTime(t)
  83         else:
  84             return time.strftime("%Y-%m-%d %H:%M:%S GMT", time.gmtime(t))
  85             
  86     def expiry_date(self, user = None):
  87         return self._dated(self.expiry_usecs(), user)
  88 
  89     def dated(self, user = None):
  90         return self._dated(self.pass_time_usecs, user)
  91             
  92     def link_to(self, request, **kw):
  93         page = Page(request, self.pagename)
  94         text = kw.get('text', '')
  95         print_mode = kw.get('print_mode', 0)
  96         querystr = 'action=GuestPass&pass=%s' % self.passcode
  97         if print_mode:
  98             querystr += '&print=1'
  99             link = page.link_to_raw(request, text=text, querystr=querystr)
 100         else:
 101             link = page.link_to(request, text=text, querystr=querystr)
 102         return link
 103 
 104     def is_current(self):
 105         return wikiutil.timestamp2version(time.time()) < self.expiry_usecs()
 106         
 107     def is_passable(self, request):
 108         page = Page(request, self.pagename)
 109         user = User(request, self.userid) # the user who created the pass
 110         # check pagename, even if used as filter 
 111         return (page.exists() and 
 112                 (self.pagename == request.page.page_name) and 
 113                 user.may.read(self.pagename))
 114     
 115     def is_read_allowed(self, request):
 116         return self.is_current() and self.is_passable(request)
 117 
 118 class PassLog(LogFile):
 119     """ Used for accessing wiki pass-log.
 120     """
 121     def __init__(self, request, filename=None, buffer_size=4096, **kw):
 122         if filename is None:
 123             rootpagename = kw.get('rootpagename', None)
 124             if rootpagename:
 125                 filename = Page(request, rootpagename).getPagePath('pass-log', isfile=1)
 126             else:
 127                 filename = request.rootpage.getPagePath('pass-log', isfile=1)
 128         if filename:
 129             LogFile.__init__(self, filename, buffer_size)
 130   	    
 131   	    self._NUM_FIELDS = 9
 132         self._usercache = {}
 133         
 134     def add(self, request, pass_time_usecs, action, pagename, username, 
 135             host=None, passcode = '', lifespan=30):
 136         """ Generate (and add) a line to the pass-log.
 137 
 138         If `host` is None, it's read from request vars.
 139         """
 140         if request.cfg.log_remote_addr or self.force_ip:
 141             if host is None:
 142                 host = request.remote_addr or ''
 143 
 144             if request.cfg.log_reverse_dns_lookups:
 145                 import socket
 146                 try:
 147                     hostname = socket.gethostbyaddr(host)[0]
 148                     hostname = unicode(hostname, config.charset)
 149                 except (socket.error, UnicodeError):
 150                     hostname = host
 151             else:
 152                 hostname = host
 153         else:
 154             host = ''
 155             hostname = ''
 156 
 157         userid = request.user.valid and request.user.id or ''
 158             
 159         if not passcode:
 160             passcode = makeCode()
 161 
 162         line = u"\t".join((str(long(pass_time_usecs)),
 163                            wikiutil.quoteWikinameFS(pagename),
 164                            action,
 165                            userid,
 166                            username,
 167                            host,
 168                            hostname,
 169                            passcode,
 170                            str(lifespan)
 171                            )) + "\n"
 172         self._add(line)
 173         return self.parser(line)
 174 
 175     def parser(self, line):
 176         """ Parse pass-log line into fields """
 177         fields = line.strip().split('\t')
 178         # Pad empty fields
 179         missing = self._NUM_FIELDS - len(fields)
 180         if missing:
 181             fields.extend([''] * missing)
 182         result = PassLogLine(self._usercache)
 183         (result.pass_time_usecs,
 184          result.pagename, result.action,
 185          result.userid, result.username,
 186          result.addr, result.hostname,
 187          result.passcode, result.lifespan ) = fields[:self._NUM_FIELDS]
 188         if not result.hostname:
 189             result.hostname = result.addr
 190         result.pagename = wikiutil.unquoteWikiname(result.pagename.encode('ascii'))
 191         result.pass_time_usecs = long(result.pass_time_usecs or '0')
 192         return result
 193 
 194     def set_filter(self, **kw):
 195         """ optionally filter for specific pagenames, userids, passcodes"""
 196         expr = "1"
 197         for field in ['pagename', 'userid', 'passcode']:
 198             if field in kw and kw[field]: # treat empty as non-existant
 199                 expr = "%s and x.%s == %s" % (expr, field, repr(kw[field]))
 200 
 201         if 'pass_time_usecs' in kw:
 202             expr = "%s and long(x.ed_time_usecs) == %s" % (expr, long(kw['pass_time_usecs']))
 203 
 204         self.filter = eval("lambda x: " + expr)

You are not allowed to attach a file to this page.