2
2
MoinMoin edit log class
4
This is used for accessing the global edit-log (e.g. by RecentChanges) as
5
well as for the local edit-log (e.g. PageEditor, info action).
8
* when we have items with separate data and metadata storage, we do not
9
need the local edit-log file any more (because everything in it will be
10
stored into the revision's metadata).
11
* maybe we can even get rid of the global edit-log as we know it now (and just
12
maintaining a cache of recent changes metadata)
14
@copyright: 2006 MoinMoin:ThomasWaldmann
4
15
@license: GNU GPL, see COPYING for details.
8
from logfile import LogFile
18
from MoinMoin import log
19
logging = log.getLogger(__name__)
21
from MoinMoin.logfile import LogFile
9
22
from MoinMoin import wikiutil, user, config
10
23
from MoinMoin.Page import Page
35
48
def is_from_current_user(self, request):
36
49
user = request.user
37
if user.id: return user.id==self.userid
38
return request.remote_addr==self.addr
51
return user.id == self.userid
52
return request.remote_addr == self.addr
40
54
def getEditorData(self, request):
41
55
""" Return a tuple of type id and string or Page object
50
64
result = 'ip', request.cfg.show_hosts and self.hostname or ''
52
if not self._usercache.has_key(self.userid):
66
if self.userid not in self._usercache:
53
67
self._usercache[self.userid] = user.User(request, self.userid, auth_method="editlog:53")
54
68
userdata = self._usercache[self.userid]
72
86
result = 'ip', request.cfg.show_hosts and self.hostname or ''
74
if not self._usercache.has_key(self.userid):
88
if self.userid not in self._usercache:
75
89
self._usercache[self.userid] = user.User(request, self.userid, auth_method="editlog:75")
76
90
userdata = self._usercache[self.userid]
77
91
if userdata.mailto_author and userdata.email:
96
110
aliasname = self._usercache[self.userid].aliasname
99
title = wikiutil.escape(aliasname + title)
113
title = aliasname + title
100
114
text = (request.formatter.interwikilink(1, title=title, generated=True, *info) +
101
115
request.formatter.text(name) +
102
116
request.formatter.interwikilink(0, title=title, *info))
105
119
aliasname = self._usercache[self.userid].aliasname
106
120
if not aliasname:
108
title = wikiutil.escape(aliasname + title)
122
title = aliasname + title
109
123
url = 'mailto:%s' % info
110
124
text = (request.formatter.url(1, url, css='mailto', title=title) +
111
125
request.formatter.text(name) +
112
126
request.formatter.url(0))
113
127
elif kind == 'ip':
129
idx = info.index('.')
117
title = wikiutil.escape('???' + title)
118
text = wikiutil.escape(info[:idx])
132
title = '???' + title
133
text = request.formatter.text(info[:idx])
120
raise "unknown EditorData type"
121
return '<span title="%s">%s</span>' % (title, text)
135
raise Exception("unknown EditorData type")
136
return (request.formatter.span(1, title=title) +
138
request.formatter.span(0))
124
141
class EditLog(LogFile):
126
def __init__(self, request, filename=None, buffer_size=65536, **kw):
142
""" Used for accessing the global edit-log (e.g. by RecentChanges) as
143
well as for the local edit-log (e.g. PageEditor, info action).
145
def __init__(self, request, filename=None, buffer_size=4096, **kw):
128
147
rootpagename = kw.get('rootpagename', None)
130
149
filename = Page(request, rootpagename).getPagePath('edit-log', isfile=1)
133
152
LogFile.__init__(self, filename, buffer_size)
134
153
self._NUM_FIELDS = 9
135
154
self._usercache = {}
137
156
# Used by antispam in order to show an internal name instead
138
157
# of a confusing userid
139
158
self.uid_override = kw.get('uid_override', None)
141
160
def add(self, request, mtime, rev, action, pagename, host=None, extra=u'', comment=u''):
142
""" Generate a line for the editlog.
144
If `host` is None, it's read from request vars.
147
host = request.remote_addr
149
if request.cfg.log_reverse_dns_lookups:
152
hostname = socket.gethostbyaddr(host)[0]
153
hostname = unicode(hostname, config.charset)
154
except (socket.error, UnicodeError), err:
161
""" Generate (and add) a line to the edit-log.
163
If `host` is None, it's read from request vars.
166
host = request.remote_addr
168
if request.cfg.log_reverse_dns_lookups:
171
hostname = socket.gethostbyaddr(host)[0]
172
hostname = unicode(hostname, config.charset)
173
except (socket.error, UnicodeError):
159
comment = wikiutil.clean_comment(comment)
160
user_id = request.user.valid and request.user.id or ''
162
if self.uid_override != None:
164
hostname = self.uid_override
167
line = u"\t".join((str(long(mtime)), # has to be long for py 2.2.x
170
wikiutil.quoteWikinameFS(pagename),
178
comment = wikiutil.clean_input(comment)
179
user_id = request.user.valid and request.user.id or ''
181
if self.uid_override is not None:
183
hostname = self.uid_override
186
line = u"\t".join((str(long(mtime)), # has to be long for py 2.2.x
189
wikiutil.quoteWikinameFS(pagename),
179
198
def parser(self, line):
180
""" Parser edit log line into fields """
199
""" Parse edit-log line into fields """
181
200
fields = line.strip().split('\t')
182
201
# Pad empty fields
183
202
missing = self._NUM_FIELDS - len(fields)
186
205
result = EditLogLine(self._usercache)
187
206
(result.ed_time_usecs, result.rev, result.action,
188
207
result.pagename, result.addr, result.hostname, result.userid,
189
result.extra, result.comment,) = fields[:self._NUM_FIELDS]
208
result.extra, result.comment, ) = fields[:self._NUM_FIELDS]
190
209
if not result.hostname:
191
210
result.hostname = result.addr
192
211
result.pagename = wikiutil.unquoteWikiname(result.pagename.encode('ascii'))
193
212
result.ed_time_usecs = long(result.ed_time_usecs or '0') # has to be long for py 2.2.x
196
215
def set_filter(self, **kw):
216
""" optionally filter for specific pagenames, addrs, hostnames, userids """
198
218
for field in ['pagename', 'addr', 'hostname', 'userid']:
199
if kw.has_key(field):
200
expr = "%s and x.%s == %s" % (expr, field, `kw[field]`)
202
if kw.has_key('ed_time_usecs'):
220
expr = "%s and x.%s == %s" % (expr, field, repr(kw[field]))
222
if 'ed_time_usecs' in kw:
203
223
expr = "%s and long(x.ed_time_usecs) == %s" % (expr, long(kw['ed_time_usecs'])) # must be long for py 2.2.x
205
225
self.filter = eval("lambda x: " + expr)
228
def news(self, oldposition):
229
""" What has changed in the edit-log since <oldposition>?
230
Returns edit-log final position() and list of changed item names.
232
if oldposition is None:
235
self.seek(oldposition)
238
items.append(line.pagename)
239
if line.action == 'SAVE/RENAME':
240
items.append(line.extra) # == old page name
242
newposition = self.position()
243
logging.log(logging.NOTSET, "editlog.news: new pos: %r new items: %r", newposition, items)
244
return newposition, items