Attachment 'PageComment2-094.py'
Download 1 # -*- coding: iso-8859-1 -*-
2 """
3 PageComment2.py Version 0.94 Nov. 20, 2005
4
5 This macro gives a form to post a new comment to the page and shows a list of the posted comments.
6
7 @copyright: 2005 by Seungik Lee <seungiklee<at>gmail.com> http://cds.icu.ac.kr/~silee/
8 @license: GPL
9
10 Usage: [[PageComment2]]
11
12 Features:
13
14 - Simple usage, just put [[PageComment2]] on any page.
15 - Lets anonymous users post a new comment with an input form.
16 - Shows a list of the posted comments.
17 - Support for comment deletion by given password.
18 - Support for administrative action, e.g.,
19 - to delete a comment without entering a given password
20
21 Parameters:
22
23 - pagename: the page name which the comments are retrieved for. by default the page itself.
24 If the user has no 'read' ACL for that page, it does not allow to insert/view comments.
25 e.g., pagename=AnotherPage
26
27 - section: the section name of the page. The comments in different sections are managed in separated sub pages.
28 Section name should be alphanumeric format ([a-zA-Z0-9] in regular expression).
29 If not, all the non-alphanumric characters are removed.
30 e.g., section=1, section=News, section=Opinion
31
32 - inputonly: shows input form only. list of the comments are shown to admin users only.
33 - inputonly=0; default, all list is shown to all users including anonymous users
34 - inputonly=1; shown to admin users only (who has the page delete privilege)
35
36 - commentonly: shows the list of comments only.
37 - commentonly=0; default, both of the list and input form will be shown
38 - commentonly=1; only the list of comments will be shown
39
40 - countonly: returns the number of the comments posted to this page
41 - countonly=0; default, normal form (input form; list of comments)
42 - countonly=1; just return the number of comments.
43 e.g., 'There are [[PageComments(countonly=1)]] comments here'
44
45 - rows: the # of rows of the textarea. default 2. e.g., rows=2
46
47 - cols: the # of columns of the textarea. default 60. e.g., cols=60
48
49 - maxlength: limitation on # of characters for comment text. default 0 (no limit). e.g., maxlength=500
50
51 - newerfirst: order of the list of comments.
52 - newerfirst=0: default, newer ones are listed at the end
53 - newerfirst=1: newer ones are listed at the top
54
55 - tablewidth: the width of the table format for PageComment2, default '' (none).
56 e.g., tablewidth=600, tablewidth=100%
57
58 Change Log
59
60 - Nov. 20, 2005 - Version 0.94
61 - some parameters are added
62 - some minor bugs are fixed
63
64 - Nov. 19, 2005 - Version 0.92
65 - some minor bugs are fixed
66 - 'olderfirst' parameter replaced with 'newerfirst'
67
68 - Nov. 19, 2005 - Version 0.91
69 - some parameters are added
70 - validates smiley markup
71 - modified view
72
73 - Nov. 18, 2005 - Version 0.90 (Release 2)
74 - No text data file support any more: Comment is stored in the sub wiki page.
75 - (does not compatible with Release 1: PageComment.py)
76 - Custom icon (smiley) can be inserted
77 - Pre-fill the name input field with his/her login name
78 - Logs at add/remove comments
79 - Added some parameters
80
81 - Oct. 08, 2005 - Version 0.82
82 - Changed the directory the data file stored to be secured
83
84 - Oct. 07, 2005 - Version 0.81
85 - Unicode encoding related bugs in deletecomment function are patched.
86 - Instruction bugs are patched.
87
88 - Oct. 06, 2005 - Version 0.80
89 - The initial version is released.
90
91
92 Notes
93
94 - 'Gallery.py' developed by Simon Ryan has inspired this macro.
95 - Thanks to many of the MoinMoin users for valuable comments.
96 - Visit http://moinmoin.wikiwikiweb.de/MacroMarket/PageComment2 for more detail
97
98 """
99
100 from MoinMoin import config, wikiutil
101 import StringIO, time, re
102 from MoinMoin.Page import Page
103 from MoinMoin.PageEditor import PageEditor
104 from MoinMoin.parser import wiki
105
106
107 class Globs:
108 # A quick place to plonk those shared variables
109
110 adminmsg = ''
111 datapagename = ''
112 pagename = ''
113 curpagename = ''
114 cursubname = ''
115 admin = ''
116 macro = ''
117 defaultacl = ''
118 defaulticon = ''
119 formid = 0
120
121 class Params:
122
123 rows = 0
124 cols = 0
125 maxlength = 0
126 newerfirst = 0
127 tablewidth = ''
128 commentfirst = 0
129 pagename = ''
130 commentonly = 0
131 inputonly = 0
132 countonly = 0
133 section = ''
134
135
136 def execute(macro, args):
137
138 # INITIALIZATION ----------------------------------------
139 getparams(args)
140 setglobalvalues(macro)
141
142 # internal variables
143 request = macro.request
144 _ = request.getText
145
146 if not Globs.pagename == Globs.curpagename:
147 if not macro.request.user.may.read(Globs.pagename):
148 return macro.formatter.rawHTML(u'PageComment: %s' % _('You are not allowed to view this page.'))
149 elif not Page(request, Globs.pagename).exists():
150 return macro.formatter.rawHTML(u'PageComment: %s' % _('This page is already deleted or was never created!'))
151
152
153 if Params.countonly:
154 html = len(fetchcomments())
155 return macro.formatter.rawHTML('%s' % html)
156
157 datapagename = Globs.datapagename
158
159 # form vals
160 comicon = Globs.defaulticon
161 comauthor = ''
162 comtext = ''
163 compasswd = ''
164 comrev = 0
165
166 addcommand = u'addcomment%d' % Globs.formid
167 delcommand = u'delcomment%d' % Globs.formid
168
169 action = macro.form.get('commentaction', [''])[0]
170
171 if action == addcommand:
172
173 # process form input for comment add
174 form_fields = {'comicon': Globs.defaulticon, 'comauthor': '', 'comtext': '', 'compasswd': '', 'comrev': 0}
175 required_fields = {'comauthor': _('Name'), 'comtext': _('Text'), 'compasswd': _('Password'), 'comrev': 'Rev. #'}
176
177 formvals, missingfields = getforminput(macro.form, form_fields, required_fields)
178
179 comicon = formvals['comicon']
180 comauthor = formvals['comauthor']
181 comtext = formvals['comtext']
182 compasswd = formvals['compasswd']
183 comrev = formvals['comrev']
184
185 if not len(missingfields) == len(required_fields):
186 if not missingfields:
187 flag = addcomment(macro, comicon, comauthor, comtext, compasswd, comrev)
188
189 if flag:
190 comicon = Globs.defaulticon
191 comauthor = ''
192 comtext = ''
193 compasswd = ''
194 comrev = 0
195 else:
196 message( _('Required attribute "%(attrname)s" missing') % { 'attrname': u', '.join(missingfields) } )
197
198 elif action == delcommand:
199
200 # process form input for comment delete
201 form_fields = {'delkey': '', 'delpasswd': ''}
202 required_fields = {'delkey': 'Comment Key', 'delpasswd': 'Password'}
203
204 formvals, missingfields = getforminput(macro.form, form_fields, required_fields)
205
206 delkey = formvals['delkey']
207 delpasswd = formvals['delpasswd']
208
209 if not len(missingfields) == len(required_fields):
210 if not missingfields:
211 deletecomment(macro, delkey, delpasswd)
212 else:
213 message( _('Required attribute "%(attrname)s" missing') % { 'attrname': u', '.join(missingfields) } )
214
215 # format output
216 html = []
217
218 html.append(u'<a name="pagecomment%d">' % Globs.formid)
219 html.append(u'<table class="pagecomment" %s>' % Params.tablewidth)
220 html.append(u'<tr><td style="border-width: 0px;">')
221 html.append(u'<font style="color: #aa0000;">%s</font>' % Globs.adminmsg)
222 html.append(u'</td></tr>')
223
224 if Params.commentfirst:
225 html.append(showcommentsection())
226 html.append(commentformsection(comauthor, comtext, compasswd, comicon, comrev))
227 else:
228 html.append(commentformsection(comauthor, comtext, compasswd, comicon, comrev))
229 html.append(showcommentsection())
230
231 html.append(u'</table>')
232
233 return macro.formatter.rawHTML(u'\n'.join(html))
234
235
236 def commentformsection(comauthor, comtext, compasswd, comicon, comrev):
237 html = []
238
239 if not Params.commentonly:
240 html.append(u'<tr><td style="border-width: 0px;">')
241 html.append(u'<table class="commentform"><tr><td style="border-width: 1px;">')
242 html.append(commentform(comauthor, comtext, compasswd, comicon, comrev))
243 html.append(u'</td></tr></table>')
244 html.append(u'</td></tr>')
245
246 return u'\n'.join(html)
247
248
249 def showcommentsection():
250 html = []
251 if (not Params.inputonly) or Globs.admin:
252 html.append(deleteform())
253 html.append(u'<tr><td style="border: 0px;">')
254 html.append(showcomment())
255 html.append(u'</td></tr>')
256 else:
257 html.append(u'<tr><td style="text-align: center; border: 0px; font-size: 0.8em; color: #aaaaaa;">(The posted comments are shown to administrators only.)</td></tr>')
258
259 return u'\n'.join(html)
260
261 def getforminput(form, inputfields, requiredfields):
262
263 formvals = {}
264 missingfields = []
265
266 for item in inputfields.keys():
267 if (not form.has_key(item)) and (item in requiredfields):
268 missingfields.append(requiredfields[item])
269 formvals[item] = form.get(item, [inputfields[item]])[0]
270
271 return formvals, missingfields
272
273 def getparams(args):
274 # process arguments
275
276 params = {}
277 if args:
278 # Arguments are comma delimited key=value pairs
279 sargs = args.split(',')
280
281 for item in sargs:
282 sitem = item.split('=')
283
284 if len(sitem) == 2:
285 key, value = sitem[0], sitem[1]
286 params[key.strip()] = value.strip()
287
288 Params.pagename = params.get('pagename', '')
289
290 Params.section = params.get('section', '')
291 if Params.section:
292 Params.section = getescapedsectionname(Params.section)
293
294 try:
295 Params.inputonly = int(params.get('inputonly', 0))
296 except ValueError:
297 Params.inputonly = 0
298
299 try:
300 Params.commentonly = int(params.get('commentonly', 0))
301 except ValueError:
302 Params.commentonly = 0
303
304 try:
305 Params.countonly = int(params.get('countonly', 0))
306 except ValueError:
307 Params.countonly = 0
308
309 try:
310 Params.newerfirst = int(params.get('newerfirst', 0))
311 except ValueError:
312 Params.newerfirst = 0
313
314 try:
315 Params.commentfirst = int(params.get('commentfirst', 0))
316 except ValueError:
317 Params.commentfirst = 0
318
319 try:
320 Params.rows = int(params.get('rows', 2))
321 except ValueError:
322 Params.rows = 2
323
324 try:
325 Params.cols = int(params.get('cols', 60))
326 except ValueError:
327 Params.cols = 60
328
329 try:
330 Params.maxlength = int(params.get('maxlength', 0))
331 except ValueError:
332 Params.maxlength = 0
333
334 Params.tablewidth = params.get('tablewidth', '')
335 if Params.tablewidth:
336 Params.tablewidth = ' width="%s" ' % Params.tablewidth
337
338 def setglobalvalues(macro):
339
340 # Global variables
341 Globs.macro = macro
342 Globs.defaultacl = u'#acl All:'
343 Globs.adminmsg = ''
344 Globs.defaulticon = ''
345
346 Globs.curpagename = macro.formatter.page.page_name
347
348 if Params.pagename:
349 Globs.pagename = Params.pagename
350 else:
351 Globs.pagename = Globs.curpagename
352
353 Globs.cursubname = Globs.curpagename.split('/')[-1]
354 Globs.datapagename = u'%s/%s%s' % (Globs.pagename, 'PageCommentData', Params.section)
355
356 # Figure out if we have delete privs
357 try:
358 if macro.request.user.may.delete(Globs.datapagename):
359 Globs.admin = 'true'
360 else:
361 Globs.admin = ''
362 except AttributeError:
363 Globs.admin = ''
364 pass
365
366 # set form id
367
368 formid = int(macro.form.get('formid', ['0'])[0])
369 formid += 1
370
371 Globs.formid = formid
372 macro.form['formid'] = ['%d' % formid]
373
374 def message(astring):
375 Globs.adminmsg = u'%s\n' % astring
376
377
378 def commentform(tmpauthor, tmptext, tmppasswd, tmpicon, comrev):
379 # A form for posting a new comment
380 request = Globs.macro.request
381 datapagename = Globs.datapagename
382 _ = request.getText
383
384 cellstyle = u'border-width: 0px; vertical-align: middle; font-size: 0.9em; line-height: 1em;'
385
386 pg = Page( request, datapagename )
387
388 if pg.exists():
389 comrev = pg.current_rev()
390 else:
391 comrev = 0
392
393 if request.user.valid:
394 html1 = [
395 u'<input type="hidden" value="%s" name="comauthor">' % request.user.name,
396 u'<input type="hidden" value="*" name="compasswd">',
397 u'<tr><td style="%s">%s: <i>%s</i></td>' % (cellstyle, _('Name'), request.user.name),
398 u'<td style="%s">%s: ****</td>' % (cellstyle, _('Password')),
399 ]
400 else:
401 html1 = [
402 u'<tr><td style="%s">%s: <input type="text" size="10" maxlength="20" name="comauthor" value="%s"></td>' % (cellstyle, _('Name'), tmpauthor),
403 u'<td style="%s">%s: <input type="password" size="6" maxlength="10" name="compasswd" value="%s"></td>' % (cellstyle, _('Password'), tmppasswd),
404 ]
405
406 html1 = u'\n'.join(html1)
407 html2 = [
408 u'<div id="commentform">',
409 u'<form action="%s#pagecomment%d" name="comment" METHOD="POST">' % (Globs.cursubname, Globs.formid),
410 u'<table class="addcommentform">',
411 u'%s' % html1,
412 # u'<td style="%s">Smiley: <input type="text" size="4" maxlength="4" name="comicon" value="%s"></td></tr>' % (cellstyle, tmpicon),
413 u'<td style="%s">Smiley: %s</td></tr>' % (cellstyle, getsmileymarkuplist(tmpicon)),
414 u'<tr><td colspan="3" style="%s"><textarea name="comtext" rows="%d" cols="%d">%s</textarea></td></tr>' % (cellstyle, Params.rows, Params.cols, tmptext),
415 u'<tr><td colspan="3" align="center" style="%s"><input type="submit" value="%s"></td></tr>' % (cellstyle, _('Save')),
416 u'</table>',
417 u'<input type="hidden" name="action" value="show" >',
418 u'<input type="hidden" name="comrev" value="%s">' % comrev,
419 u'<input type="hidden" name="commentaction" value="addcomment%d">' % Globs.formid,
420 u'</form>',
421 u'</div>',
422 ]
423
424
425 return u'\n'.join(html2)
426
427 def addcomment(macro, comicon, comauthor, comtext, compasswd, comrev):
428 # Add a comment with inputs
429
430 request = Globs.macro.request
431 cfg = request.cfg
432 _ = request.getText
433
434 # check input
435 if comicon and (not comicon in config.smileys.keys()):
436 message('Please use smiley markup only')
437 return 0
438
439 if Params.maxlength and (len(comtext) > Params.maxlength):
440 message('Comment text is limited to %d characters. (%d characters now)' % (Params.maxlength, len(comtext)) )
441 return 0
442
443 if not comtext.strip():
444 message('Please fill the comment text')
445 return 0
446
447 datapagename = Globs.datapagename
448
449 pg = PageEditor( request, datapagename )
450 pagetext = pg.get_raw_body()
451
452 comtext = convertdelimiter(comtext)
453
454 if request.user.valid:
455 comloginuser = 'TRUE'
456 comauthor = request.user.name
457 else:
458 comloginuser = ''
459 comauthor = convertdelimiter(comauthor)
460
461 newcomment = [
462 u'{{{',
463 u'%s' % comicon,
464 u'%s' % comauthor,
465 u'%s' % time.strftime(cfg.datetime_fmt, time.localtime(time.time())),
466 u'',
467 u'%s' % comtext,
468 u'}}}',
469 u'##PASSWORD %s' % compasswd,
470 u'##LOGINUSER %s' % comloginuser,
471 ]
472
473 newpagetext = u'%s\n\n%s' % (pagetext, u'\n'.join(newcomment))
474
475 if not pg.exists():
476 action = 'SAVENEW'
477 defaultacl = Globs.defaultacl
478 warnmessages = '\'\'\'\'\'DO NOT EDIT THIS PAGE!!\'\'\' This page is automatically generated by Page``Comment macro.\'\'\n----'
479 newpagetext = u'%s\n%s\n%s' % (defaultacl, warnmessages, newpagetext)
480 else:
481 action = 'SAVE'
482
483 newpagetext = pg.normalizeText( newpagetext )
484
485 comment = 'New comment by "%s"' % comauthor
486 pg._write_file(newpagetext, action, u'Modified by PageComment macro')
487 addLogEntry(request, 'COMNEW', Globs.pagename, comment)
488
489 # message(_('The comment is added'))
490 message(_('Thank you for your changes. Your attention to detail is appreciated.'))
491 return 1
492
493 def showcomment():
494
495 request = Globs.macro.request
496 _ = request.getText
497
498 commentlist = fetchcomments()
499
500 if Params.newerfirst:
501 commentlist.reverse()
502
503 html = []
504 cur_index = 0
505 cellstyle = u'border-width: 0px; border-top-width: 1px; vertical-align: top; font-size: 0.9em; line-height: 1em;'
506
507 html.append(u'<div id="commentlist"><table width="100%" class="commentlist">')
508
509 for item in commentlist:
510 if Globs.admin or (item['loginuser'] and request.user.valid and request.user.name == item['name']):
511 htmlcommentdel = [
512 u' <font style="font-size: 0.9em;">',
513 u'<a style="color: #aa0000;" href="javascript: requesttodeleteadmin%d(document.delform%d, \'%s\');" title="%s">X</a>' % (Globs.formid, Globs.formid, item['key'], _('Delete')),
514 u'</font>',
515 ]
516 elif item['loginuser']:
517 htmlcommentdel = []
518
519 else:
520 htmlcommentdel = [
521 u' <font style="font-size: 0.9em;">',
522 u'<a style="color: #aa0000;" href="javascript: requesttodelete%d(document.delform%d, \'%s\');" title="%s">X</a>' % (Globs.formid, Globs.formid, item['key'], _('Delete')),
523 u'</font>',
524 ]
525
526 htmlcomment = [
527 u'<tr><td class="commenticon" style="%s width: 20px;">%s</td>' % (cellstyle, getsmiley(item['icon'])),
528 u'<td class="commentauthor" style="%s"' % cellstyle,
529 u'>%s</td>' % converttext(item['name']),
530 u'<td style="%s width: 10px;"> </td>' % cellstyle,
531 u'<td class="commenttext" style="%s width: 100%%;">%s</td>' % (cellstyle, converttext(item['text'])),
532 u'<td class="commentdate" style="%s text-align: right; font-size: 0.8em; " nowrap>%s%s</td></tr>' % (cellstyle, item['date'].replace(' ', '<br>'), u''.join(htmlcommentdel)),
533 ]
534
535 html.append(u'\n'.join(htmlcomment))
536
537 html.append(u'</table></div>')
538
539 return u'\n'.join(html)
540
541 def getescapedsectionname(targettext):
542 regex = r'\W'
543 pattern = re.compile(regex, re.UNICODE)
544 sectionname = pattern.sub('', targettext)
545
546 return sectionname
547
548
549 def getsmiley(markup):
550
551 if markup in config.smileys.keys():
552 formatter = Globs.macro.formatter
553 return formatter.smiley(markup)
554 else:
555 return ''
556
557
558 def converttext(targettext):
559 # Converts some special characters of html to plain-text style
560 # What else to handle?
561
562 # targettext = targettext.strip()
563 targettext = targettext.replace(u'&', '&')
564 targettext = targettext.replace(u'>', '>')
565 targettext = targettext.replace(u'<', '<')
566 targettext = targettext.replace(u'\n', '<br>')
567 targettext = targettext.replace(u'"', '"')
568 targettext = targettext.replace(u'\t', ' ')
569 targettext = targettext.replace(u' ', ' ')
570
571 return targettext
572
573 def convertdelimiter(targettext):
574 # Converts delimeter to other string to avoid a crash
575
576 targettext = targettext.replace('{{{', '{ { {')
577 targettext = targettext.replace('}}}', '} } }')
578
579 return targettext
580
581
582 def deleteform():
583 # Javascript codes for deleting or restoring a comment
584
585 request = Globs.macro.request
586 _ = request.getText
587
588 htmlresult = []
589
590 html = [
591 '<script language="javascript">',
592 '<!--',
593 ]
594 htmlresult.append(u'\n'.join(html))
595
596 html = [
597 ' function requesttodeleteadmin%d(delform, comkey) {' % Globs.formid,
598 ' if (confirm("%s")) {;' % _('Really delete this page?'),
599 ' delform.delkey.value = comkey;',
600 ' delform.delpasswd.value = "****";',
601 ' delform.submit();',
602 ' }',
603 ' }',
604 ' function requesttodelete%d(delform, comkey) {' % Globs.formid,
605 ' var passwd = prompt("%s:", "");' % _('Please specify a password!'),
606 ' if(!(passwd == "" || passwd == null)) {',
607 ' delform.delkey.value = comkey;',
608 ' delform.delpasswd.value = passwd;',
609 ' delform.submit();',
610 ' }',
611 ' }',
612 ]
613
614 htmlresult.append(u'\n'.join(html))
615
616 html = [
617 '//-->',
618 '</script>',
619 '<form name="delform%d" action="%s#pagecomment%d" METHOD="post">' % (Globs.formid, Globs.cursubname, Globs.formid),
620 '<input type="hidden" value="show" name="action">',
621 '<input name="delpasswd" type="hidden" value="****">',
622 '<input name="delkey" type="hidden" value="">',
623 '<input type="hidden" name="commentaction" value="delcomment%s">' % Globs.formid,
624 '</form>',
625 ]
626 htmlresult.append(u'\n'.join(html))
627
628 return u'\n'.join(htmlresult)
629
630
631 def filtercomment(index='', name='', passwd=''):
632
633 # filter by index
634 if index:
635 filteredlist1 = fetchcomments(index, index)
636 else:
637 filteredlist1 = fetchcomments()
638
639 # filter by name
640 filteredlist2 = []
641 if name:
642 for item in filteredlist1:
643 if name == item['name']:
644 filteredlist2.append(item)
645 else:
646 filteredlist2 = filteredlist1
647
648 # filter by password
649 filteredlist3 = []
650 if passwd:
651 for item in filteredlist2:
652 if passwd == item['passwd']:
653 filteredlist3.append(item)
654 else:
655 filteredlist3 = filteredlist2
656
657 return filteredlist3
658
659
660 def fetchcomments(startindex=1, endindex=9999):
661
662 commentlist = []
663
664 request = Globs.macro.request
665 formatter = Globs.macro.formatter
666 datapagename = Globs.datapagename
667
668 pg = Page( request, datapagename )
669 pagetext = pg.get_raw_body()
670
671 regex = r'^(#acl\s*.*)$'
672 pattern = re.compile(regex, re.UNICODE + re.MULTILINE + re.IGNORECASE)
673 pagetext = pattern.sub('', pagetext)
674
675 regex = ur"""
676 ^[\{]{3}\n
677 ^(?P<icon>[^\n]*)\n
678 ^(?P<name>[^\n]*)\n
679 ^(?P<date>[^\n]*)\n\n
680 ^(?P<text>\s*.*?[^}]*)[\}]{3}[\n]*
681 ^[#]{2}PASSWORD[ ](?P<passwd>[^\n]*)[\n]*
682 ^[#]{2}LOGINUSER[ ](?P<loginuser>[^\n]*)[\n]*"""
683
684 pattern = re.compile(regex, re.UNICODE + re.MULTILINE + re.VERBOSE)
685 commentitems = pattern.findall(pagetext)
686
687 cur_index = 0
688
689 for item in commentitems:
690 comment = {}
691 cur_index += 1
692
693 if cur_index < startindex:
694 continue
695
696 comment['index'] = cur_index
697 comment['icon'] = item[0]
698 comment['name'] = item[1]
699 comment['date'] = item[2]
700 comment['text'] = item[3]
701 comment['passwd'] = item[4]
702 comment['loginuser'] = item[5]
703
704 # experimental
705 comment['key'] = comment['date'].strip()
706
707 commentlist.append(comment)
708
709 if cur_index >= endindex:
710 break
711
712 return commentlist
713
714 def deletecomment(macro, delkey, delpasswd):
715 # Deletes a comment with given index and password
716
717 request = Globs.macro.request
718 formatter = Globs.macro.formatter
719 datapagename = Globs.datapagename
720 _ = request.getText
721
722 pg = PageEditor( request, datapagename )
723 pagetext = pg.get_raw_body()
724
725 regex = ur"""
726 (?P<comblock>^[\{]{3}\n
727 ^(?P<icon>[^\n]*)\n
728 ^(?P<name>[^\n]*)\n
729 ^(?P<date>[^\n]*)[\n]+
730 ^(?P<text>\s*.*?[^}]*)[\}]{3}[\n]*
731 ^[#]{2}PASSWORD[ ](?P<passwd>[^\n]*)[\n]*
732 ^[#]{2}LOGINUSER[ ](?P<loginuser>[^\n]*)[\n$]*)"""
733
734 pattern = re.compile(regex, re.UNICODE + re.MULTILINE + re.VERBOSE)
735 commentitems = pattern.findall(pagetext)
736
737 for item in commentitems:
738
739 if delkey == item[3].strip():
740 comauthor = item[2]
741 if Globs.admin or (request.user.valid and request.user.name == comauthor) or delpasswd == item[5]:
742 newpagetext = pagetext.replace(item[0], '', 1)
743
744 action = 'SAVE'
745 comment = 'comment deleted by "%s"' % comauthor
746 pg._write_file(newpagetext, action, u'Modified by PageComment macro')
747 addLogEntry(request, 'COMDEL', Globs.pagename, comment)
748
749 message(_('The comment is deleted'))
750
751 return
752 else:
753 message(_('Sorry, wrong password.'))
754 return
755
756 message(_('No such comment'))
757
758
759 def addLogEntry(request, action, pagename, msg):
760 # Add an entry to the edit log on adding comments.
761 from MoinMoin.logfile import editlog
762 t = wikiutil.timestamp2version(time.time())
763 msg = unicode(msg)
764
765 # TODO: for now we simply write 2 logs, maybe better use some multilog stuff
766 # Write to global log
767 log = editlog.EditLog(request)
768 log.add(request, t, 99999999, action, pagename, request.remote_addr, msg)
769
770 # Write to local log
771 log = editlog.EditLog(request, rootpagename=pagename)
772 log.add(request, t, 99999999, action, pagename, request.remote_addr, msg)
773
774 def getsmileymarkuplist(defaulticon):
775
776 html = [
777 u'<select name="comicon">',
778 u' <option value=""></option>',
779 ]
780
781 for smiley in config.smileys.keys():
782 if defaulticon.strip() == smiley:
783 html.append(u' <option selected>%s</option>' % wikiutil.escape(smiley))
784 else:
785 html.append(u' <option>%s</option>' % wikiutil.escape(smiley))
786
787 html.append(u'</select>')
788
789 return u'\n'.join(html)
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.