Attachment 'PageComment2-092.py'

Download

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

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.
  • [get | view] (2008-04-30 13:57:43, 45.4 KB) [[attachment:PageComment2-0.981-only_logged_in_user.py]]
  • [get | view] (2005-11-18 08:51:22, 19.1 KB) [[attachment:PageComment2-090.py]]
  • [get | view] (2005-11-18 16:50:49, 21.6 KB) [[attachment:PageComment2-091.py]]
  • [get | view] (2005-11-19 06:31:25, 21.8 KB) [[attachment:PageComment2-092.py]]
  • [get | view] (2005-11-20 07:24:45, 26.0 KB) [[attachment:PageComment2-094.py]]
  • [get | view] (2005-11-20 08:56:20, 26.1 KB) [[attachment:PageComment2-095.py]]
  • [get | view] (2005-11-29 20:06:02, 31.4 KB) [[attachment:PageComment2-096.py]]
  • [get | view] (2006-01-05 08:41:48, 44.6 KB) [[attachment:PageComment2-097.py]]
  • [get | view] (2006-04-17 13:35:45, 45.4 KB) [[attachment:PageComment2-098.py]]
  • [get | view] (2006-05-02 00:31:43, 45.4 KB) [[attachment:PageComment2-0981.py]]
  • [get | view] (2008-01-29 19:38:32, 45.4 KB) [[attachment:PageComment2-099-moin16.py]]
  • [get | view] (2007-05-01 15:51:21, 46.5 KB) [[attachment:PageComment2-099-rg.py]]
  • [get | view] (2008-02-19 19:41:42, 45.4 KB) [[attachment:PageComment2-0991-moin16.py]]
  • [get | view] (2008-02-27 14:38:41, 45.8 KB) [[attachment:PageComment2-0992-moin16.py]]
  • [get | view] (2011-07-19 13:47:24, 47.7 KB) [[attachment:PageComment2-0993-moin193.py]]
  • [get | view] (2007-05-01 15:52:09, 1.6 KB) [[attachment:PageComment2-981-099-rg.diff.gz]]
  • [get | view] (2005-11-29 19:59:21, 42.1 KB) [[attachment:snap-pagecomment2.jpg]]
 All files | Selected Files: delete move to page copy to page

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