Attachment 'PageComment2-096.py'

Download

   1 # -*- coding: iso-8859-1 -*-
   2 """
   3     PageComment2.py  Version 0.96  Nov. 29, 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         - commentfirst: shows comment list before the input form.
  56             - commentfirst=0: default, the input form first
  57             - commentfirst=1: comment list first
  58             
  59         - articleview: shows comment list in an article view.
  60             - articleview=0: default, list in table view
  61             - articleview=1: list in article view
  62   
  63         - tablewidth: the width of the table format for PageComment2, default '' (none). 
  64             e.g., tablewidth=600, tablewidth=100%
  65   
  66         - smileylist: shows smiley options with drop-down list box
  67             - smileylist=0: default, a part of the smiley in radio button
  68             - smileylist=1: smiley in drop-down list box
  69         
  70         - nosmiley: shows no smiley
  71             - nosmiley=0: default, shows smiley selection
  72             - nosmiley=1: no smiley selection
  73           
  74     Change Log
  75         
  76         - Nov. 29, 2005 - Version 0.96
  77             - some format parameters are added
  78             - random password feature is added
  79 
  80         - Nov. 20, 2005 - Version 0.95
  81             - some minor bugs are fixed
  82         
  83         - Nov. 20, 2005 - Version 0.94
  84             - some parameters are added
  85             - some minor bugs are fixed
  86         
  87         - Nov. 19, 2005 - Version 0.92
  88             - some minor bugs are fixed
  89             - 'olderfirst' parameter replaced with 'newerfirst'
  90         
  91         - Nov. 19, 2005 - Version 0.91
  92             - some parameters are added
  93             - validates smiley markup
  94             - modified view
  95         
  96         - Nov. 18, 2005 - Version 0.90 (Release 2)
  97             - No text data file support any more: Comment is stored in the sub wiki page.
  98             - (does not compatible with Release 1: PageComment.py)
  99             - Custom icon (smiley) can be inserted
 100             - Pre-fill the name input field with his/her login name
 101             - Logs at add/remove comments
 102             - Added some parameters    
 103         
 104         - Oct. 08, 2005 - Version 0.82
 105             - Changed the directory the data file stored to be secured
 106         
 107         - Oct. 07, 2005 - Version 0.81 
 108             - Unicode encoding related bugs in deletecomment function are patched. 
 109             - Instruction bugs are patched. 
 110         
 111         - Oct. 06, 2005 - Version 0.80 
 112             - The initial version is released.
 113 
 114 
 115     Notes
 116         
 117         - 'Gallery.py' developed by Simon Ryan has inspired this macro.
 118         - Thanks to many of the MoinMoin users for valuable comments.
 119         - Visit http://moinmoin.wikiwikiweb.de/MacroMarket/PageComment2 for more detail
 120 
 121 """
 122 
 123 from MoinMoin import config, wikiutil
 124 import StringIO, time, re
 125 from MoinMoin.Page import Page
 126 from MoinMoin.PageEditor import PageEditor
 127 from MoinMoin.parser import wiki
 128 
 129 
 130 class Globs:
 131     # A quick place to plonk those shared variables
 132     
 133     adminmsg = ''
 134     datapagename = ''
 135     pagename = ''
 136     curpagename = ''
 137     cursubname = ''
 138     admin = ''
 139     macro = ''
 140     defaultacl = ''
 141     defaulticon = ''        
 142     formid = 0
 143     smileys = []
 144 
 145 class Params:
 146 
 147     rows = 0
 148     cols = 0
 149     maxlength = 0
 150     newerfirst = 0
 151     tablewidth = ''
 152     commentfirst = 0
 153     pagename = ''
 154     commentonly = 0
 155     inputonly = 0
 156     countonly = 0
 157     section = ''
 158     articleview = 0
 159 
 160 
 161 def execute(macro, args):
 162 
 163     # INITIALIZATION ----------------------------------------
 164     getparams(args)
 165     setglobalvalues(macro)
 166     
 167     # internal variables
 168     request = macro.request
 169     _ = request.getText
 170     
 171     if not Globs.pagename == Globs.curpagename:
 172         if not macro.request.user.may.read(Globs.pagename):
 173             return macro.formatter.rawHTML(u'PageComment: %s' % _('You are not allowed to view this page.'))
 174         elif not Page(request, Globs.pagename).exists():
 175             return macro.formatter.rawHTML(u'PageComment: %s' % _('This page is already deleted or was never created!'))
 176 
 177     
 178     if Params.countonly:
 179         html = len(fetchcomments())
 180         return macro.formatter.rawHTML('%s' % html)
 181     
 182     datapagename = Globs.datapagename
 183     
 184     # form vals
 185     comicon = Globs.defaulticon
 186     comauthor = ''
 187     comtext = ''
 188     compasswd = ''
 189     comrev = 0
 190     comautopass = ''
 191     
 192     addcommand = u'addcomment%d' % Globs.formid
 193     delcommand = u'delcomment%d' % Globs.formid
 194     
 195     action = macro.form.get('commentaction', [''])[0]
 196     
 197     if action == addcommand:
 198     
 199         # process form input for comment add
 200         form_fields = {'comicon': Globs.defaulticon, 'comauthor': '', 'comtext': '', 'compasswd': '', 'comrev': 0, 'autopasswd': ''}
 201         required_fields = {'comauthor': _('Name'), 'comtext': _('Text'), 'compasswd': _('Password'), 'comrev': 'Rev. #'}
 202         
 203         formvals, missingfields = getforminput(macro.form, form_fields, required_fields)
 204         
 205         comicon = formvals['comicon']
 206         comauthor = formvals['comauthor']
 207         comtext = formvals['comtext']
 208         compasswd = formvals['compasswd']
 209         comrev = formvals['comrev']
 210         comautopass = formvals['autopasswd']
 211     	
 212         if not len(missingfields) == len(required_fields):
 213             if not missingfields:
 214                 flag = addcomment(macro, comicon, comauthor, comtext, compasswd, comrev, comautopass)
 215                 
 216                 if flag:
 217                     comicon = Globs.defaulticon
 218                     comauthor = ''
 219                     comtext = ''
 220                     compasswd = ''
 221                     comrev = 0
 222             else:
 223                 message( _('Required attribute "%(attrname)s" missing') % { 'attrname': u', '.join(missingfields) } )
 224     
 225     elif action == delcommand:
 226     
 227         # process form input for comment delete
 228         form_fields = {'delkey': '', 'delpasswd': ''}
 229         required_fields = {'delkey': 'Comment Key', 'delpasswd': 'Password'}
 230         
 231         formvals, missingfields = getforminput(macro.form, form_fields, required_fields)
 232         
 233         delkey = formvals['delkey']
 234         delpasswd = formvals['delpasswd']
 235         
 236         if not len(missingfields) == len(required_fields):
 237             if not missingfields:
 238                 deletecomment(macro, delkey, delpasswd)
 239             else:
 240                 message( _('Required attribute "%(attrname)s" missing') % { 'attrname': u', '.join(missingfields) } )
 241     
 242     # format output
 243     html = []
 244     
 245     html.append(u'<div id="pagecomment">')
 246     html.append(u'<a name="pagecomment%d"></a>' % Globs.formid)
 247     html.append(u'<table class="pagecomment" %s>' % Params.tablewidth)
 248     html.append(u'<tr><td colspan="5" style="border-width: 0px;">')
 249     html.append(u'<font color="#aa0000">%s</font>' % Globs.adminmsg)
 250     html.append(u'</td></tr>')
 251 
 252     if Params.commentfirst:
 253         html.append(showcommentsection())
 254         html.append(commentformsection(comauthor, comtext, compasswd, comicon, comrev, comautopass))
 255     else:
 256         html.append(commentformsection(comauthor, comtext, compasswd, comicon, comrev, comautopass))
 257         html.append(showcommentsection())
 258 
 259     html.append(u'</table>')
 260     html.append(u'</div>')
 261     
 262     return macro.formatter.rawHTML(u'\n'.join(html))
 263 
 264 
 265 def commentformsection(comauthor, comtext, compasswd, comicon, comrev, autopass):
 266     html = []
 267     
 268     if not Params.commentonly:
 269         html.append(u'<tr><td style="border-width: 0px;" colspan="5">')
 270         html.append(u'<table class="commentform"><tr><td style="border-width: 1px;">')
 271         html.append(commentform(comauthor, comtext, compasswd, comicon, comrev, autopass))
 272         html.append(u'</td></tr></table>')
 273         html.append(u'</td></tr>')
 274     
 275     return u'\n'.join(html)
 276 
 277 
 278 def showcommentsection():
 279     html = []
 280     if (not Params.inputonly) or Globs.admin:
 281         html.append(deleteform())
 282         html.append(showcomment())
 283     else:
 284         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>')
 285 
 286     return u'\n'.join(html)
 287 
 288 def getforminput(form, inputfields, requiredfields):
 289     
 290     formvals = {}
 291     missingfields = []
 292     
 293     for item in inputfields.keys():
 294         formvals[item] = form.get(item, [inputfields[item]])[0]
 295         if (not formvals[item]) and (item in requiredfields):
 296             missingfields.append(requiredfields[item])
 297         
 298     return formvals, missingfields
 299 
 300 def getparams(args):
 301     # process arguments
 302     
 303     params = {}
 304     if args:
 305         # Arguments are comma delimited key=value pairs
 306         sargs = args.split(',')
 307     
 308         for item in sargs:
 309             sitem = item.split('=')
 310         
 311             if len(sitem) == 2:
 312                 key, value = sitem[0], sitem[1]
 313                 params[key.strip()] = value.strip()
 314 
 315     Params.pagename = params.get('pagename', '')
 316     
 317     Params.section = params.get('section', '')
 318     if Params.section:
 319         Params.section = getescapedsectionname(Params.section)
 320 
 321     try:
 322         Params.inputonly = int(params.get('inputonly', 0))
 323     except ValueError:
 324         Params.inputonly = 0
 325 
 326     try:
 327         Params.commentonly = int(params.get('commentonly', 0))
 328     except ValueError:
 329         Params.commentonly = 0
 330 
 331     try:
 332         Params.countonly = int(params.get('countonly', 0))
 333     except ValueError:
 334         Params.countonly = 0
 335 
 336     try:
 337         Params.newerfirst = int(params.get('newerfirst', 0))
 338     except ValueError:
 339         Params.newerfirst = 0
 340         
 341     try:
 342         Params.commentfirst = int(params.get('commentfirst', 0))
 343     except ValueError:
 344         Params.commentfirst = 0
 345 
 346     try:
 347         Params.articleview = int(params.get('articleview', 0))
 348     except ValueError:
 349         Params.articleview = 0
 350         
 351     try:
 352         Params.smileylist = int(params.get('smileylist', 0))
 353     except ValueError:
 354         Params.smileylist = 0
 355         
 356     try:
 357         Params.nosmiley = int(params.get('nosmiley', 0))
 358     except ValueError:
 359         Params.nosmiley = 0
 360 
 361     try:
 362         Params.rows = int(params.get('rows', 2))
 363     except ValueError:
 364         Params.rows = 2
 365 
 366     try:
 367         Params.cols = int(params.get('cols', 60))
 368     except ValueError:
 369         Params.cols = 60
 370 
 371     try:
 372         Params.maxlength = int(params.get('maxlength', 0))
 373     except ValueError:
 374         Params.maxlength = 0
 375         
 376     Params.tablewidth = params.get('tablewidth', '')
 377     if Params.tablewidth:
 378         Params.tablewidth = ' width="%s" ' % Params.tablewidth
 379 
 380 def setglobalvalues(macro):
 381     
 382     # Global variables
 383     Globs.macro = macro
 384     Globs.defaultacl = u'#acl All:'
 385     Globs.adminmsg = ''
 386     Globs.defaulticon = ''
 387     Globs.smileys = [':)', ':))', ':(', ';)', ':\\', '|)', 'X-(', 'B)']
 388     
 389     Globs.curpagename = macro.formatter.page.page_name
 390     
 391     if Params.pagename:
 392         Globs.pagename = Params.pagename
 393     else:
 394         Globs.pagename = Globs.curpagename
 395         
 396     Globs.cursubname = Globs.curpagename.split('/')[-1]
 397     Globs.datapagename = u'%s/%s%s' % (Globs.pagename, 'PageCommentData', Params.section)
 398 
 399     # Figure out if we have delete privs
 400     try:
 401         if macro.request.user.may.delete(Globs.datapagename):
 402             Globs.admin = 'true'
 403         else:
 404             Globs.admin = ''
 405     except AttributeError:
 406         Globs.admin = ''
 407         pass
 408 
 409     # set form id
 410     
 411     formid = int(macro.form.get('formid', ['0'])[0])
 412     formid += 1
 413     
 414     Globs.formid = formid
 415     macro.form['formid'] = ['%d' % formid]  
 416 
 417 def message(astring):
 418     Globs.adminmsg = u'PageComment: %s\n' % astring
 419 
 420 
 421 def commentform(tmpauthor, tmptext, tmppasswd, tmpicon, comrev, tmpautopass):
 422     # A form for posting a new comment
 423     request = Globs.macro.request
 424     datapagename = Globs.datapagename
 425     _ = request.getText
 426     
 427     cellstyle = u'border-width: 0px; vertical-align: middle; font-size: 0.9em;'
 428     
 429     pg = Page( request, datapagename )
 430     
 431     if pg.exists():
 432         comrev = pg.current_rev()
 433     else:
 434         comrev = 0
 435     
 436     if not Params.nosmiley:
 437         if not Params.smileylist:
 438             iconlist = getsmileymarkupradio(tmpicon)
 439         else:
 440             iconlist = getsmileymarkuplist(tmpicon)
 441     else:
 442         iconlist = ''
 443     
 444     initName = ''
 445     initPass = ''
 446     initText = ''
 447 
 448     if not tmpauthor:
 449         import socket
 450         host = request.remote_addr
 451                 
 452         try:
 453             hostname = socket.gethostbyaddr(host)[0]
 454         except socket.error:
 455             hostname = host
 456 
 457         tmpauthor = hostname.split('.')[0]
 458         initName = tmpauthor
 459     
 460     if not tmppasswd:
 461         tmppasswd = nicepass()
 462         initPass = tmppasswd
 463     elif tmpautopass and tmpautopass == tmppasswd:
 464         tmppasswd = nicepass()
 465         initPass = tmppasswd
 466     
 467     if not tmptext:
 468         tmptext = u'Add your comment'
 469         initText = tmptext
 470     elif tmptext and tmptext == u'Add your comment':
 471         initText = tmptext
 472     
 473     if request.user.valid:
 474         html1 = [
 475             u'<input type="hidden" value="%s" name="comauthor">' % request.user.name,
 476 		    u'<input type="hidden" value="*" name="compasswd">',
 477     		]
 478     else:
 479         html1 = [
 480             u'<input type="text" style="font-size: 9pt;" size="6" maxlength="20" name="comauthor" value="%(author)s" onfocus="if (this.value==\'%(msg)s\') {this.value=\'\';};" onblur="if (this.value==\'\') {this.value=\'%(msg)s\';};">' % { 'msg': initName, 'cellstyle': cellstyle, 'author': tmpauthor },
 481     		u'<input type="password" style="font-size: 9pt;" size="4" maxlength="10" name="compasswd" value="%(passwd)s" onfocus="if (this.value==\'%(msg)s\') {this.value=\'\';};" onblur="if (this.value==\'\') {this.value=\'%(msg)s\';};">' % { 'msg': initPass, 'passwd': tmppasswd  },
 482     		u'<input type="hidden" value="%s" name="autopasswd">' % initPass,
 483     		]
 484     
 485     html1 = u'\n'.join(html1)
 486     scripthtml = u'onfocus="if (this.value==\'%(msg)s\') {this.value=\'\';};" onblur="if (this.value==\'\') {this.value=\'%(msg)s\';};"' % {'msg': initText }
 487     html2 = [
 488         u'<form action="%s#pagecomment%d" name="comment" METHOD="POST">' % (Globs.cursubname, Globs.formid),
 489         u'<table class="addcommentform">',
 490 		u'<tr>',
 491 		u'<td style="%s"><textarea name="comtext" rows="%d" cols="%d" style="font-size: 9pt;" ' % (cellstyle, Params.rows, Params.cols),
 492         u'%s>%s</textarea></td>' % (scripthtml, tmptext),
 493         u'<td style="%s vertical-align: bottom;"><input type="submit" value="%s" style="font-size: 9pt; height:3em;"></td>' % (cellstyle, _('Save')),
 494         u'</tr>',
 495         u'<tr><td style="%s">' % cellstyle,
 496         u'%s' % html1,
 497         u'%s' % iconlist,
 498         u'</td></tr>',
 499 		u'</table>',
 500 		u'<input type="hidden" name="action" value="show" >',
 501 		u'<input type="hidden" name="comrev" value="%s">' % comrev,
 502 		u'<input type="hidden" name="commentaction" value="addcomment%d">' % Globs.formid,
 503 		u'</form>',
 504         ]
 505     
 506     
 507     return u'\n'.join(html2)
 508       
 509 def addcomment(macro, comicon, comauthor, comtext, compasswd, comrev, comautopass):
 510     # Add a comment with inputs
 511     
 512     request = Globs.macro.request
 513     cfg = request.cfg
 514     _ = request.getText
 515     
 516     # check input
 517     if comicon and (not comicon in config.smileys.keys()):
 518         message('Please use smiley markup only')
 519         return 0
 520 
 521     if Params.maxlength and (len(comtext) > Params.maxlength):
 522         message('Comment text is limited to %d characters. (%d characters now)' % (Params.maxlength, len(comtext)) )
 523         return 0
 524     
 525     if not comtext.strip() or comtext == u'Add your comment':
 526         message('Please fill the comment text')
 527         return 0
 528     
 529     datapagename = Globs.datapagename
 530     
 531     pg = PageEditor( request, datapagename )
 532     pagetext = pg.get_raw_body()
 533     
 534     comtext = convertdelimiter(comtext)
 535     
 536     if request.user.valid:
 537         comloginuser = 'TRUE'
 538         comauthor = request.user.name
 539     else:
 540         comloginuser = ''
 541         comauthor = convertdelimiter(comauthor)
 542     
 543     newcomment = [
 544         u'{{{',
 545         u'%s' % comicon,
 546         u'%s' % comauthor,
 547         u'%s' % time.strftime(cfg.datetime_fmt, time.localtime(time.time())),
 548         u'',
 549         u'%s' % comtext,
 550         u'}}}',
 551         u'##PASSWORD %s' % compasswd,
 552         u'##LOGINUSER %s' % comloginuser,
 553         ]
 554         
 555     newpagetext = u'%s\n\n%s' % (pagetext, u'\n'.join(newcomment))
 556 
 557     if not pg.exists():
 558         action = 'SAVENEW'
 559         defaultacl = Globs.defaultacl
 560         warnmessages = '\'\'\'\'\'DO NOT EDIT THIS PAGE!!\'\'\' This page is automatically generated by Page``Comment macro.\'\'\n----'
 561         newpagetext = u'%s\n%s\n%s' % (defaultacl, warnmessages, newpagetext)
 562     else:
 563         action = 'SAVE'
 564 
 565     newpagetext = pg.normalizeText( newpagetext )
 566     
 567     comment = 'New comment by "%s"' % comauthor
 568     pg._write_file(newpagetext, action, u'Modified by PageComment macro')
 569     addLogEntry(request, 'COMNEW', Globs.pagename, comment)
 570     
 571     # message(_('The comment is added'))
 572     msg = _('Thank you for your changes. Your attention to detail is appreciated.')
 573     
 574     if comautopass and comautopass == compasswd:
 575         msg2 = u'<i>You did not enter a password. A random password has been generated for you: <b>%s</b></i>' % comautopass
 576         msg = u'%s<br>%s' % (msg, msg2)
 577     
 578     message(msg)    
 579     return 1
 580 
 581 def showcomment():
 582     
 583     request = Globs.macro.request
 584     _ = request.getText
 585     
 586     commentlist = fetchcomments()
 587     
 588     if Params.newerfirst:
 589         commentlist.reverse()
 590     
 591     html = []
 592     cur_index = 0
 593     
 594     if Params.articleview:
 595         cellstyle = u'border-width: 1px; border-color: #cccccc; vertical-align: top; font-size: 9pt;'
 596         htmlcomment = [
 597             u'<tr><td colspan="5" class="commentbox" style="border-width: 0px;"><table width="99%%">',
 598             u'<tr><td colspan="5" class="commenttext" style="%(cellstyle)s">%(text)s</td></tr>',
 599             u'<tr><td colspan="5" class="commentauthor" style="text-align: right; border-width: 0px; font-size: 8pt; color: #999999">Posted by <b>%(author)s</b> %(icon)s at %(date)s %(delform)s</td></tr>',
 600             u'</table></td></tr>',
 601             ]
 602     else:
 603         cellstyle = u'border-width: 0px; border-top-width: 1px; vertical-align: top; font-size: 9pt;'
 604         htmlcomment = [
 605             u'<tr><td class="commenticon" style="%(cellstyle)s">%(icon)s</td>',
 606             u'<td class="commentauthor" style="%(cellstyle)s">%(author)s</td>',
 607             u'<td style="%(cellstyle)s width: 10px;">&nbsp;</td>',
 608             u'<td class="commenttext" style="%(cellstyle)s">%(text)s</td>',
 609             u'<td class="commentdate" style="%(cellstyle)s text-align: right; font-size: 8pt; " nowrap>%(date)s%(delform)s</td></tr>',
 610             ]
 611     
 612     htmlcommentdel_admin = [
 613         u' <font style="font-size: 8pt;">',
 614         u'<a style="color: #aa0000;" href="javascript: requesttodeleteadmin%(formid)d(document.delform%(formid)d, \'%(key)s\');" title="%(msg)s">X</a>',
 615         u'</font>',
 616         ]
 617         
 618     htmlcommentdel_guest = [
 619         u' <font style="font-size: 8pt;">',
 620         u'<a style="color: #aa0000;" href="javascript: requesttodelete%(formid)d(document.delform%(formid)d, \'%(key)s\');" title="%(msg)s">X</a>',
 621         u'</font>',
 622         ]
 623     
 624     for item in commentlist:
 625         if Globs.admin or (item['loginuser'] and request.user.valid and request.user.name == item['name']):
 626             htmlcommentdel = htmlcommentdel_admin
 627         elif item['loginuser']:
 628             htmlcommentdel = ''
 629         else:
 630             htmlcommentdel = htmlcommentdel_guest
 631         
 632         htmlcommentdel = u'\n'.join(htmlcommentdel) % {
 633             'formid': Globs.formid, 
 634             'key': item['key'],
 635             'msg': _('Delete')
 636             }
 637                 
 638         htmlcommentitem = u'\n'.join(htmlcomment) % {
 639             'cellstyle': cellstyle,
 640             'icon': getsmiley(item['icon']),
 641             'author': converttext(item['name']),
 642             'text': converttext(item['text']),
 643             'date': item['date'],
 644             'delform': htmlcommentdel
 645             }
 646         
 647         html.append(htmlcommentitem)
 648     
 649     return u'\n'.join(html)
 650 
 651 def getescapedsectionname(targettext):
 652     regex = r'\W'
 653     pattern = re.compile(regex, re.UNICODE)
 654     sectionname = pattern.sub('', targettext)
 655     
 656     return sectionname
 657 
 658 
 659 def getsmiley(markup):
 660     
 661     if markup in config.smileys.keys():
 662         formatter = Globs.macro.formatter
 663         return formatter.smiley(markup)
 664     else:
 665         return ''
 666 
 667 
 668 def converttext(targettext):
 669     # Converts some special characters of html to plain-text style
 670     # What else to handle?
 671 
 672     # targettext = targettext.strip()
 673     targettext = targettext.replace(u'&', '&amp')
 674     targettext = targettext.replace(u'>', '&gt;')
 675     targettext = targettext.replace(u'<', '&lt;')
 676     targettext = targettext.replace(u'\n', '<br>')
 677     targettext = targettext.replace(u'"', '&quot;')
 678     targettext = targettext.replace(u'\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;')
 679     targettext = targettext.replace(u'  ', '&nbsp;&nbsp;')
 680 
 681     return targettext
 682     
 683 def convertdelimiter(targettext):
 684     # Converts delimeter to other string to avoid a crash
 685     
 686     targettext = targettext.replace('{{{', '{ { {')
 687     targettext = targettext.replace('}}}', '} } }')
 688     
 689     return targettext
 690 
 691     
 692 def deleteform():
 693     # Javascript codes for deleting or restoring a comment
 694     
 695     request = Globs.macro.request
 696     _ = request.getText
 697     
 698     htmlresult = []
 699     
 700     html = [
 701         '<script language="javascript">',
 702         '<!--',
 703         ]
 704     htmlresult.append(u'\n'.join(html))
 705            
 706     html = [    
 707         '  function requesttodeleteadmin%d(delform, comkey) {' % Globs.formid,
 708         '      if (confirm("%s")) {;' % _('Really delete this page?'),
 709         '          delform.delkey.value = comkey;',
 710         '          delform.delpasswd.value = "****";',
 711         '          delform.submit();',
 712         '      }',
 713         '  }',
 714         '  function requesttodelete%d(delform, comkey) {' % Globs.formid,
 715         '      var passwd = prompt("%s:", "");' % _('Please specify a password!'),
 716         '      if(!(passwd == "" || passwd == null)) {',
 717         '          delform.delkey.value = comkey;',
 718         '          delform.delpasswd.value = passwd;',
 719         '          delform.submit();',
 720         '      }',
 721         '  }',
 722         ]
 723     
 724     htmlresult.append(u'\n'.join(html))
 725                 
 726     html = [
 727         '//-->',
 728         '</script>',
 729         '<form name="delform%d" action="%s#pagecomment%d" METHOD="post">' % (Globs.formid, Globs.cursubname, Globs.formid),
 730         '<input type="hidden" value="show" name="action">',
 731         '<input name="delpasswd" type="hidden" value="****">',
 732         '<input name="delkey" type="hidden" value="">',
 733         '<input type="hidden" name="commentaction" value="delcomment%s">' % Globs.formid,
 734         '</form>',
 735         ]
 736     htmlresult.append(u'\n'.join(html))
 737 
 738     return u'\n'.join(htmlresult)
 739 
 740 
 741 def filtercomment(index='', name='', passwd=''):
 742     
 743     # filter by index
 744     if index:
 745         filteredlist1 = fetchcomments(index, index)
 746     else:
 747         filteredlist1 = fetchcomments()
 748     
 749     # filter by name
 750     filteredlist2 = []
 751     if name:
 752         for item in filteredlist1:
 753             if name == item['name']:
 754                 filteredlist2.append(item)
 755     else:
 756         filteredlist2 = filteredlist1
 757     
 758     # filter by password
 759     filteredlist3 = []
 760     if passwd:
 761         for item in filteredlist2:
 762             if passwd == item['passwd']:
 763                 filteredlist3.append(item)
 764     else:
 765         filteredlist3 = filteredlist2
 766 
 767     return filteredlist3
 768         
 769 
 770 def fetchcomments(startindex=1, endindex=9999):
 771     
 772     commentlist = []
 773     
 774     request = Globs.macro.request
 775     formatter = Globs.macro.formatter
 776     datapagename = Globs.datapagename
 777 
 778     pg = Page( request, datapagename )
 779     pagetext = pg.get_raw_body()
 780     
 781     regex = r'^(#acl\s*.*)$'
 782     pattern = re.compile(regex, re.UNICODE + re.MULTILINE + re.IGNORECASE)
 783     pagetext = pattern.sub('', pagetext)
 784     
 785     regex = ur"""
 786 ^[\{]{3}\n
 787 ^(?P<icon>[^\n]*)\n
 788 ^(?P<name>[^\n]*)\n
 789 ^(?P<date>[^\n]*)\n\n
 790 ^(?P<text>\s*.*?[^}]*)[\}]{3}[\n]*
 791 ^[#]{2}PASSWORD[ ](?P<passwd>[^\n]*)[\n]*
 792 ^[#]{2}LOGINUSER[ ](?P<loginuser>[^\n]*)[\n]*"""
 793 
 794     pattern = re.compile(regex, re.UNICODE + re.MULTILINE + re.VERBOSE)
 795     commentitems = pattern.findall(pagetext)
 796     
 797     cur_index = 0
 798     
 799     for item in commentitems:
 800         comment = {}
 801         cur_index += 1
 802         
 803         if cur_index < startindex:
 804             continue
 805         
 806         comment['index'] = cur_index
 807         comment['icon'] = item[0]
 808         comment['name'] = item[1]
 809         comment['date'] = item[2]
 810         comment['text'] = item[3]
 811         comment['passwd'] = item[4]
 812         comment['loginuser'] = item[5]
 813         
 814         # experimental
 815         comment['key'] = comment['date'].strip()
 816         
 817         commentlist.append(comment)
 818         
 819         if cur_index >= endindex:
 820             break
 821 
 822     return commentlist
 823 
 824 def deletecomment(macro, delkey, delpasswd):
 825     # Deletes a comment with given index and password
 826     
 827     request = Globs.macro.request
 828     formatter = Globs.macro.formatter
 829     datapagename = Globs.datapagename
 830     _ = request.getText
 831 
 832     pg = PageEditor( request, datapagename )
 833     pagetext = pg.get_raw_body()
 834     
 835     regex = ur"""
 836 (?P<comblock>^[\{]{3}\n
 837 ^(?P<icon>[^\n]*)\n
 838 ^(?P<name>[^\n]*)\n
 839 ^(?P<date>[^\n]*)[\n]+
 840 ^(?P<text>\s*.*?[^}]*)[\}]{3}[\n]*
 841 ^[#]{2}PASSWORD[ ](?P<passwd>[^\n]*)[\n]*
 842 ^[#]{2}LOGINUSER[ ](?P<loginuser>[^\n]*)[\n$]*)"""
 843 
 844     pattern = re.compile(regex, re.UNICODE + re.MULTILINE + re.VERBOSE)
 845     commentitems = pattern.findall(pagetext)
 846     
 847     for item in commentitems:
 848         
 849         if delkey == item[3].strip():
 850             comauthor = item[2]
 851             if Globs.admin or (request.user.valid and request.user.name == comauthor) or delpasswd == item[5]:
 852                 newpagetext = pagetext.replace(item[0], '', 1)
 853                 
 854                 action = 'SAVE'
 855                 comment = 'comment deleted by "%s"' % comauthor
 856                 pg._write_file(newpagetext, action, u'Modified by PageComment macro')
 857                 addLogEntry(request, 'COMDEL', Globs.pagename, comment)
 858                 
 859                 message(_('The comment is deleted'))
 860                 
 861                 return
 862             else:
 863                 message(_('Sorry, wrong password.'))
 864                 return
 865                 
 866     message(_('No such comment'))
 867 
 868     
 869 def addLogEntry(request, action, pagename, msg):
 870     # Add an entry to the edit log on adding comments.
 871     from MoinMoin.logfile import editlog
 872     t = wikiutil.timestamp2version(time.time())
 873     msg = unicode(msg)
 874 
 875     # TODO: for now we simply write 2 logs, maybe better use some multilog stuff
 876     # Write to global log
 877     log = editlog.EditLog(request)
 878     log.add(request, t, 99999999, action, pagename, request.remote_addr, msg)
 879 
 880     # Write to local log
 881     log = editlog.EditLog(request, rootpagename=pagename)
 882     log.add(request, t, 99999999, action, pagename, request.remote_addr, msg)
 883     
 884 def getsmileymarkuplist(defaulticon):
 885     
 886     html = [
 887         u'Smiley: <select name="comicon">',
 888         u'  <option value=""></option>',
 889         ]
 890     
 891     for smiley in config.smileys.keys():
 892         if defaulticon.strip() == smiley:
 893             html.append(u'  <option selected>%s</option>' % wikiutil.escape(smiley))
 894         else:
 895             html.append(u'  <option>%s</option>' % wikiutil.escape(smiley))
 896 
 897     html.append(u'</select>')
 898     
 899     return u'\n'.join(html)
 900     
 901 def getsmileymarkupradio(defaulticon):
 902     
 903     smileys = Globs.smileys
 904     html = []
 905     
 906     for smiley in smileys:
 907         if defaulticon.strip() == smiley:
 908             html.append(u'<input type="radio" name="comicon" value="%s" checked>%s ' % (wikiutil.escape(smiley), getsmiley(smiley)) )
 909         else:
 910             html.append(u'<input type="radio" name="comicon" value="%s">%s ' % (wikiutil.escape(smiley), getsmiley(smiley)) )
 911 
 912     html.append(u'</select>')
 913     
 914     return u'\n'.join(html)
 915 
 916 
 917     
 918 def nicepass(alpha=2,numeric=2):
 919     """
 920     returns a human-readble password (say rol86din instead of 
 921     a difficult to remember K8Yn9muL ) 
 922     """
 923     import string
 924     import random
 925     vowels = ['a','e','i','o','u']
 926     consonants = [a for a in string.ascii_lowercase if a not in vowels]
 927     digits = string.digits
 928     
 929     ####utility functions
 930     def a_part(slen):
 931         ret = ''
 932         for i in range(slen):			
 933             if i%2 ==0:
 934                 randid = random.randint(0,20) #number of consonants
 935                 ret += consonants[randid]
 936             else:
 937                 randid = random.randint(0,4) #number of vowels
 938                 ret += vowels[randid]
 939         return ret
 940     
 941     def n_part(slen):
 942         ret = ''
 943         for i in range(slen):
 944             randid = random.randint(0,9) #number of digits
 945             ret += digits[randid]
 946         return ret
 947         
 948     #### 	
 949     fpl = alpha/2		
 950     if alpha % 2 :
 951         fpl = int(alpha/2) + 1 					
 952     lpl = alpha - fpl	
 953     
 954     start = a_part(fpl)
 955     mid = n_part(numeric)
 956     end = a_part(lpl)
 957     
 958     return "%s%s%s" % (start,mid,end)

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.