Attachment 'PageComment2-0993-moin193.py'

Download

   1 # -*- coding: iso-8859-1 -*-
   2 """
   3     PageComment2.py  Version 0.992  February , 2008
   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://www.silee.net/
   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 4. e.g., rows=4
  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         - notify: notifies to the subscribers of the page which includes the macro when a comment is added
  75             - notify=0: default, notification disabled
  76             - notify=1: notification enabled
  77 
  78         - encryptpass: encrypts entered password
  79             - encryptpass=0: default, the password is stored in plain text
  80             - encryptpass=1: the password is stored in encrypted format
  81             
  82         - markup: enables wiki markup in the comment text except some specified macros.
  83             - markup=0: default, use of wiki markup in the text is disabled
  84             - markup=1: use of wiki markup in the text is enabled and preview button is activated
  85 
  86     Change Log
  87         
  88         - April 17, 2006 - Version 0.98
  89             - fixed a bug on revision history
  90             - added a despam action
  91         
  92         - Jan. 05, 2006 - Version 0.97
  93             - added features:
  94                 - mail notification
  95                 - password encryption
  96                 - wiki markup support with preview
  97                 - remember author name last used
  98             - administrative actions (delete without password) are allowed to those who has WRITE acl.
  99         
 100         - Nov. 29, 2005 - Version 0.96
 101             - some format parameters are added
 102             - random password feature is added
 103 
 104         - Nov. 20, 2005 - Version 0.95
 105             - some minor bugs are fixed
 106         
 107         - Nov. 20, 2005 - Version 0.94
 108             - some parameters are added
 109             - some minor bugs are fixed
 110         
 111         - Nov. 19, 2005 - Version 0.92
 112             - some minor bugs are fixed
 113             - 'olderfirst' parameter replaced with 'newerfirst'
 114         
 115         - Nov. 19, 2005 - Version 0.91
 116             - some parameters are added
 117             - validates smiley markup
 118             - modified view
 119         
 120         - Nov. 18, 2005 - Version 0.90 (Release 2)
 121             - No text data file support any more: Comment is stored in the sub wiki page.
 122             - (does not compatible with Release 1: PageComment.py)
 123             - Custom icon (smiley) can be inserted
 124             - Pre-fill the name input field with his/her login name
 125             - Logs at add/remove comments
 126             - Added some parameters    
 127         
 128         - Oct. 08, 2005 - Version 0.82
 129             - Changed the directory the data file stored to be secured
 130         
 131         - Oct. 07, 2005 - Version 0.81 
 132             - Unicode encoding related bugs in deletecomment function are patched. 
 133             - Instruction bugs are patched. 
 134         
 135         - Oct. 06, 2005 - Version 0.80 
 136             - The initial version is released.
 137 
 138 
 139     Notes
 140         
 141         - 'Gallery.py' developed by Simon Ryan has inspired this macro.
 142         - Thanks to many of the MoinMoin users for valuable comments.
 143         - Visit http://moinmoin.wikiwikiweb.de/MacroMarket/PageComment2 for more detail
 144         - This version only works with MoinMoin version 1.6.1 and higher (until broken)
 145           No new functionality was included in the 0.99x version
 146 
 147 """
 148 
 149 from MoinMoin import config, wikiutil
 150 import StringIO, time, re
 151 from MoinMoin.Page import Page
 152 from MoinMoin.PageEditor import PageEditor
 153 from MoinMoin.parser import text_moin_wiki
 154 import MoinMoin.macro  # keep full name for scope clarity
 155 
 156 class Globs:
 157     # A quick place to plonk those shared variables
 158     
 159     adminmsg = ''
 160     datapagename = ''
 161     pagename = ''
 162     curpagename = ''
 163     cursubname = ''
 164     admin = ''
 165     macro = ''
 166     defaultacl = ''
 167     defaulticon = ''        
 168     formid = 0
 169     smileys = []
 170 
 171 class Params:
 172 
 173     rows = 0
 174     cols = 0
 175     maxlength = 0
 176     newerfirst = 0
 177     tablewidth = ''
 178     commentfirst = 0
 179     pagename = ''
 180     commentonly = 0
 181     inputonly = 0
 182     countonly = 0
 183     section = ''
 184     articleview = 0
 185     notify = 0
 186     encryptpass = 0
 187     markup = 0
 188     
 189 
 190 ##def execute(macro, args):
 191 ##    #catcher
 192 ##    try:
 193 ##        return execute2(macro,args)
 194 ##    except Exception,e:
 195 ##        print '\n\n',e,'\n\n'
 196 ##        return macro.formatter.rawHTML(e)
 197 
 198 def execute(macro, args):
 199 
 200     # INITIALIZATION ----------------------------------------
 201     getparams(args)
 202     setglobalvalues(macro)
 203     
 204     # internal variables
 205     request = macro.request
 206     _ = request.getText
 207     
 208     if not Globs.pagename == Globs.curpagename:
 209         if not macro.request.user.may.read(Globs.pagename):
 210             return macro.formatter.rawHTML(u'PageComment: %s' % _('You are not allowed to view this page.'))
 211         elif not Page(request, Globs.pagename).exists():
 212             return macro.formatter.rawHTML(u'PageComment: %s' % _('This page is already deleted or was never created!'))
 213 
 214     
 215     if Params.countonly:
 216         html = len(fetchcomments())
 217         return macro.formatter.rawHTML('%s' % html)
 218     
 219     datapagename = Globs.datapagename
 220     
 221     # form vals
 222     comicon = Globs.defaulticon
 223     comauthor = ''
 224     comtext = ''
 225     compasswd = ''
 226     comrev = 0
 227     comautopass = ''
 228     commentpreview = ''
 229     commarkup = ''
 230     
 231     addcommand = u'addcomment%d' % Globs.formid
 232     delcommand = u'delcomment%d' % Globs.formid
 233     
 234     action = macro.request.form.get('commentaction', '')
 235     
 236     if action == addcommand:
 237     
 238         # process form input for comment add
 239         form_fields = {'comicon': Globs.defaulticon, 'comauthor': '', 'comtext': '', 'compasswd': '', 'comrev': 0, 'autopasswd': '', 'button_save': '', 'button_preview': '', 'commarkup%d' % Globs.formid: '0'}
 240         required_fields = {'comauthor': _('Name'), 'comtext': _('Text'), 'compasswd': _('Password'), 'comrev': 'Rev. #'}
 241         
 242         formvals, missingfields = getforminput(macro.request.form, form_fields, required_fields)
 243         
 244         comicon = formvals['comicon']
 245         comauthor = formvals['comauthor']
 246         comtext = formvals['comtext']
 247         compasswd = formvals['compasswd']
 248         comrev = int(formvals['comrev'])
 249         comautopass = formvals['autopasswd']
 250         btnsave = formvals['button_save']
 251         btnpreview = formvals['button_preview']
 252         commarkup = formvals['commarkup%d' % Globs.formid]
 253     	
 254         if not len(missingfields) == len(required_fields):
 255             if not missingfields:
 256                 
 257                 # check input
 258                 if comicon and (not comicon in config.smileys):
 259                     message('Please use smiley markup only')
 260             
 261                 elif Params.maxlength and (len(comtext) > Params.maxlength):
 262                     message('Comment text is limited to %d characters. (%d characters now)' % (Params.maxlength, len(comtext)) )
 263                 
 264                 elif not comtext.strip() or comtext == u'Add your comment':
 265                     message('Please fill the comment text')
 266                 
 267                 ## PREVIEW
 268                 elif btnpreview:
 269                     commentpreview = previewcomment(comicon, comauthor, comtext, commarkup)
 270                 
 271                 ## ADD
 272                 elif btnsave:
 273                     flag = addcomment(macro, comicon, comauthor, comtext, compasswd, comrev, comautopass, commarkup)
 274                     
 275                     if flag:
 276                         comicon = Globs.defaulticon
 277                         comauthor = ''
 278                         comtext = ''
 279                         compasswd = ''
 280                         comrev = 0
 281                         commentpreview = ''
 282                         commarkup = ''
 283                 
 284                 ## ERROR
 285                 else:
 286                     message( 'What do you want?' )
 287                 
 288             else:
 289                 message( _('Required attribute "%(attrname)s" missing') % { 'attrname': u', '.join(missingfields) } )
 290     
 291     elif action == delcommand:
 292     
 293         # process form input for comment delete
 294         form_fields = {'delkey': '', 'delpasswd': ''}
 295         required_fields = {'delkey': 'Comment Key', 'delpasswd': 'Password'}
 296         
 297         formvals, missingfields = getforminput(macro.request.form, form_fields, required_fields)
 298         
 299         delkey = formvals['delkey']
 300         delpasswd = formvals['delpasswd']
 301         
 302         if not len(missingfields) == len(required_fields):
 303             if not missingfields:
 304                 deletecomment(macro, delkey, delpasswd)
 305             else:
 306                 message( _('Required attribute "%(attrname)s" missing') % { 'attrname': u', '.join(missingfields) } )
 307     
 308     # format output
 309     html = []
 310     
 311     html.append(u'<div id="pagecomment">')
 312     html.append(u'<a name="pagecomment%d"></a>' % Globs.formid)
 313     
 314     html.append(u'<table border="0" class="pagecomment" %s>' % Params.tablewidth)
 315     
 316     if Globs.adminmsg:
 317         html.append(u'<tr><td colspan="5" style="border-width: 0px;">')
 318         html.append(u'<font color="#aa0000">%s</font>' % Globs.adminmsg)
 319         html.append(u'</td></tr>')
 320 
 321     commentlisthtml = showcommentsection()
 322     commentformhtml = commentformsection(comauthor, comtext, compasswd, comicon, comrev, comautopass, commarkup)
 323 
 324     if Params.commentfirst:
 325         if commentpreview:
 326             html.append(commentpreview)
 327             
 328         html.append(commentlisthtml)
 329         html.append(u'<tr><td colspan="5" class="commentblankline" style="border-width: 0px; height: 20px;"></td></tr>')
 330         html.append(commentformhtml)
 331     else:
 332         html.append(commentformhtml)
 333         html.append(u'<tr><td colspan="5" class="commentblankline" style="border-width: 0px; height: 20px;"></td></tr>')
 334         if commentpreview:
 335             html.append(commentpreview)
 336 
 337         html.append(commentlisthtml)
 338 
 339     if Globs.debugmsg:
 340         html.append(u'<tr><td colspan="5" style="border-width: 0px;">')
 341         html.append(u'<font color="#aa0000">%s</font>' % Globs.debugmsg)
 342         html.append(u'</td></tr>')
 343     
 344     html.append(u'</table>')
 345 
 346     if Globs.customscript:
 347         html.append(u'%s' % Globs.customscript)
 348 
 349     html.append(u'</div>')
 350     
 351     return macro.formatter.rawHTML(u'\n'.join(html))
 352 
 353 
 354 def commentformsection(comauthor, comtext, compasswd, comicon, comrev, autopass, commarkup):
 355     html = []
 356     
 357     if not Params.commentonly:
 358         html.append(u'<tr><td style="border-width: 1px; margin: 10px 0 10px 0;" colspan="5">')
 359         #html.append(u'<table class="commentform"><tr><td style="border-width: 1px;">')
 360         html.append(commentform(comauthor, comtext, compasswd, comicon, comrev, autopass, commarkup))
 361         #html.append(u'</td></tr></table>')
 362         html.append(u'</td></tr>')
 363     
 364     return u'\n'.join(html)
 365 
 366 
 367 def showcommentsection():
 368     html = []
 369     if (not Params.inputonly) or Globs.admin:
 370         html.append(deleteform())
 371         html.append(showcomment())
 372     else:
 373         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>')
 374 
 375     return u'\n'.join(html)
 376 
 377 def getforminput(form, inputfields, requiredfields):
 378     
 379     formvals = {}
 380     missingfields = []
 381     
 382     for item in inputfields.keys():
 383         formvals[item] = form.get(item, inputfields[item])
 384         if (not formvals[item]) and (item in requiredfields):
 385             missingfields.append(requiredfields[item])
 386         
 387     return formvals, missingfields
 388 
 389 def getparams(args):
 390     # process arguments
 391     
 392     params = {}
 393     if args:
 394         # Arguments are comma delimited key=value pairs
 395         sargs = args.split(',')
 396     
 397         for item in sargs:
 398             sitem = item.split('=')
 399         
 400             if len(sitem) == 2:
 401                 key, value = sitem[0], sitem[1]
 402                 params[key.strip()] = value.strip()
 403 
 404     Params.pagename = params.get('pagename', '')
 405     
 406     Params.section = params.get('section', '')
 407     if Params.section:
 408         Params.section = getescapedsectionname(Params.section)
 409 
 410     try:
 411         Params.inputonly = int(params.get('inputonly', 0))
 412     except ValueError:
 413         Params.inputonly = 0
 414 
 415     try:
 416         Params.commentonly = int(params.get('commentonly', 0))
 417     except ValueError:
 418         Params.commentonly = 0
 419 
 420     try:
 421         Params.countonly = int(params.get('countonly', 0))
 422     except ValueError:
 423         Params.countonly = 0
 424 
 425     try:
 426         Params.newerfirst = int(params.get('newerfirst', 1))
 427     except ValueError:
 428         Params.newerfirst = 1
 429         
 430     try:
 431         Params.commentfirst = int(params.get('commentfirst', 0))
 432     except ValueError:
 433         Params.commentfirst = 0
 434 
 435     try:
 436         Params.articleview = int(params.get('articleview', 0))
 437     except ValueError:
 438         Params.articleview = 0
 439         
 440     try:
 441         Params.smileylist = int(params.get('smileylist', 0))
 442     except ValueError:
 443         Params.smileylist = 0
 444         
 445     try:
 446         Params.nosmiley = int(params.get('nosmiley', 1))
 447     except ValueError:
 448         Params.nosmiley = 1
 449 
 450     try:
 451         Params.rows = int(params.get('rows', 8))
 452     except ValueError:
 453         Params.rows = 8
 454 
 455     try:
 456         Params.cols = int(params.get('cols', 80))
 457     except ValueError:
 458         Params.cols = 80
 459 
 460     try:
 461         Params.maxlength = int(params.get('maxlength', 0))
 462     except ValueError:
 463         Params.maxlength = 0
 464 
 465     try:
 466         Params.notify = int(params.get('notify', 1))
 467     except ValueError:
 468         Params.notify = 1
 469         
 470     try:
 471         Params.encryptpass = int(params.get('encryptpass', 0))
 472     except ValueError:
 473         Params.encryptpass = 0
 474         
 475     try:
 476         Params.markup = int(params.get('markup', 1))
 477     except ValueError:
 478         Params.markup = 1
 479 
 480     Params.tablewidth = params.get('tablewidth', '')
 481     if Params.tablewidth:
 482         Params.tablewidth = ' width="%s" ' % Params.tablewidth
 483 
 484 def setglobalvalues(macro):
 485     
 486     # Global variables
 487     Globs.macro = macro
 488     Globs.defaultacl = u'#acl All:'
 489     Globs.adminmsg = ''
 490     Globs.debugmsg = ''
 491     Globs.customscript = ''
 492     Globs.defaulticon = ''
 493     request = macro.request
 494     
 495     # ADD SMILEYS HERE TO BE USED:
 496     Globs.smileys = [':)', ':))', ':(', ';)', ':\\', '|)', 'X-(', 'B)']
 497     
 498     if Params.markup:
 499         
 500         # ADD MACROS HERE TO ALLOW TO BE USED IN THE TEXT:
 501         Globs.macroallowed = [ 'BR', 'Date', 'DateTime', 'MailTo', 'Icon' ]
 502         
 503         macronames = [name for name in MoinMoin.macro.getNames(request.cfg)\
 504                            if name not in Globs.macroallowed]
 505         
 506         # ADD REGEX PATTERN HERE TO MAKE IT FORBIDDEN TO USE IN MARKUP:
 507         Globs.markupforbidden = { 
 508             #ur'(^\s*)((?P<hmarker>=+)\s.*\s(?P=hmarker))( $)': r'\1`\2`\4',
 509             #ur'(?P<rule>-{4,})': r'`\1`',
 510             ur'(?P<macro>\<\<(%(macronames)s)(?:\(.*?\))?\>\>)' % { 'macronames': u'|'.join(macronames) } : r'`\1`'
 511             }
 512         
 513     Globs.curpagename = macro.formatter.page.page_name
 514     
 515     if Params.pagename:
 516         Globs.pagename = Params.pagename
 517     else:
 518         Globs.pagename = Globs.curpagename
 519         
 520     Globs.cursubname = Globs.curpagename.split('/')[-1]
 521     Globs.datapagename = u'%s/%s%s' % (Globs.pagename, 'PageCommentData', Params.section)
 522 
 523     try:
 524         #if request.user.may.delete(Globs.pagename):
 525         if request.user.may.write(Globs.pagename):
 526             Globs.admin = 'true'
 527         else:
 528             Globs.admin = ''
 529     except AttributeError:
 530         Globs.admin = ''
 531         pass
 532 
 533     # set form id
 534     
 535     if not hasattr(request, 'pgformid'):
 536         request.pgformid = 0
 537     
 538     request.pgformid += 1
 539     Globs.formid = request.pgformid
 540     
 541 
 542 def message(astring):
 543     Globs.adminmsg = u'PageComment: %s\n' % astring
 544 
 545 def debug(astring):
 546     Globs.debugmsg += u'%s\n<br>' % astring
 547 
 548 
 549 def commentform(tmpauthor, tmptext, tmppasswd, tmpicon, comrev, tmpautopass, tmpmarkup):
 550     # A form for posting a new comment
 551     request = Globs.macro.request
 552     datapagename = Globs.datapagename
 553     _ = request.getText
 554     
 555     cellstyle = u'border-width: 0px; vertical-align: middle; font-size: 0.9em;'
 556     
 557     pg = Page( request, datapagename )
 558     
 559     if pg.exists():
 560         comrev = pg.current_rev()
 561     else:
 562         comrev = 0
 563     
 564     if not Params.nosmiley:
 565         if not Params.smileylist:
 566             iconlist = getsmileymarkupradio(tmpicon)
 567         else:
 568             iconlist = getsmileymarkuplist(tmpicon)
 569     else:
 570         iconlist = ''
 571     
 572     initName = ''
 573     initPass = ''
 574     initText = ''
 575 
 576     if not (request.user.valid or tmpauthor):
 577         
 578         tmpauthor = getAuthorFromCookie()
 579         
 580         if not tmpauthor:
 581         
 582             import socket
 583             host = request.remote_addr
 584     
 585             try:
 586                 hostname = socket.gethostbyaddr(host)[0]
 587             except socket.error:
 588                 hostname = host
 589     
 590             tmpauthor = hostname.split('.')[0]
 591             
 592         initName = tmpauthor
 593     
 594     if not tmppasswd:
 595         tmppasswd = nicepass()
 596         initPass = tmppasswd
 597     elif tmpautopass and tmpautopass == tmppasswd:
 598         tmppasswd = nicepass()
 599         initPass = tmppasswd
 600     
 601     if not tmptext:
 602         tmptext = u'Add your comment'
 603         initText = tmptext
 604     elif tmptext and tmptext == u'Add your comment':
 605         initText = tmptext
 606     
 607     previewbutton = ''
 608     markupcheckbox = ''
 609     
 610     if Params.markup:
 611         if not (tmpmarkup == '0'):
 612             markupchecked = "checked"
 613         else:
 614             markupchecked = ''
 615             
 616         previewbutton = '<br><input type="submit" name="button_preview" value="%s" style="color: #ff7777; font-size: 9pt; width: 6em; ">' % _('Preview')
 617         markupcheckbox = '<input type="checkbox" name="commarkup%d" value="1" %s> Markup' % (Globs.formid, markupchecked)
 618         
 619         
 620     if request.user.valid:
 621         html1 = [
 622             u'<input type="hidden" value="%s" name="comauthor">' % request.user.name,
 623 		    u'<input type="hidden" value="*" name="compasswd">',
 624     		]
 625         authorJavascriptCode = ''
 626         onSubmitCode = ''
 627     else:
 628         html1 = [
 629             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': wikiutil.escape(initName), 'cellstyle': cellstyle, 'author': wikiutil.escape(tmpauthor) },
 630     		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': wikiutil.escape(initPass), 'passwd': wikiutil.escape(tmppasswd)  },
 631     		u'<input type="hidden" value="%s" name="autopasswd">' % wikiutil.escape(initPass),
 632     		]
 633     		
 634         authorJavascriptCode = """
 635 <script language="javascript">
 636 <!--
 637 function setCookie(name, value) {
 638     var today = new Date();
 639     var expire = new Date(today.getTime() + 60*60*24*365*1000);
 640     document.cookie = name + "=" + encodeURIComponent(value) + "; expires=" + expire.toGMTString() + "; path=%s";
 641 }
 642 //-->
 643 </script>""" % request.script_root
 644         
 645         onSubmitCode = 'onSubmit="setCookie(\'PG2AUTHOR\', this.comauthor.value);"'
 646     
 647     html1 = u'\n'.join(html1)
 648     scripthtml = u'onfocus="if (this.value==\'%(msg)s\') {this.value=\'\';};" onblur="if (this.value==\'\') {this.value=\'%(msg)s\';};"' % {'msg': wikiutil.escape(initText) }
 649     
 650     page_url = wikiutil.quoteWikinameURL(Globs.cursubname)
 651     
 652     html2 = [
 653         u'%s' % authorJavascriptCode,
 654         u'<form action="%s#pagecomment%d" name="comment" METHOD="POST" %s>' % (page_url, Globs.formid, onSubmitCode),
 655         u'<table class="addcommentform">',
 656 		u'<tr>',
 657 		u'<td style="%s"><textarea name="comtext" rows="%d" cols="%d" style="font-size: 9pt;" ' % (cellstyle, Params.rows, Params.cols),
 658         u'%s>%s</textarea></td>' % (scripthtml, wikiutil.escape(tmptext)),
 659         u'<td style="%s vertical-align: bottom;"><input type="submit" name="button_save" value="%s" style="font-size: 9pt; width: 6em; height:3em; ">%s</td>' % (cellstyle, _('Save'), previewbutton),
 660         u'</tr>',
 661         u'<tr><td style="%s">' % cellstyle,
 662         u'%s' % html1,
 663         u'%s' % iconlist,
 664         u'</td>',
 665         u'<td style="%s text-align: right; font-size: 9pt;">%s</td>' % (cellstyle, markupcheckbox),
 666         u'</tr>',
 667 		u'</table>',
 668 		u'<input type="hidden" name="action" value="show" >',
 669 		u'<input type="hidden" name="comrev" value="%s">' % comrev,
 670 		u'<input type="hidden" name="commentaction" value="addcomment%d">' % Globs.formid,
 671 		u'</form>',
 672         ]
 673     
 674     
 675     return u'\n'.join(html2)
 676       
 677 def addcomment(macro, comicon, comauthor, comtext, compasswd, comrev, comautopass, commarkup):
 678     # Add a comment with inputs
 679     
 680     request = Globs.macro.request
 681     cfg = request.cfg
 682     _ = request.getText
 683     
 684     datapagename = Globs.datapagename
 685     
 686     pg = PageEditor( request, datapagename )
 687     pagetext = pg.get_raw_body()
 688     
 689     # HACK for despam
 690     try:
 691         if not request.user.may.save( pg, comtext, pg.current_rev()):
 692             #message("No permission to save this text.")
 693             #return 0
 694             pass
 695             
 696     except pg.SaveError, msg:
 697         message(msg)
 698         return 0
 699     
 700     comtext = convertdelimeter(comtext)
 701     
 702     if request.user.valid:
 703         comloginuser = 'TRUE'
 704         comauthor = request.user.name
 705     else:
 706         comloginuser = ''
 707         comauthor = convertdelimeter(comauthor)
 708     
 709     orgcompasswd = compasswd
 710     
 711     if Params.encryptpass:
 712         from MoinMoin import user
 713         compasswd = user.encodePassword(compasswd)
 714     
 715     newcomment = [
 716         u'{{{',
 717         u'%s,%s' % (comicon, commarkup),
 718         u'%s' % comauthor,
 719         u'%s' % time.strftime(cfg.datetime_fmt, time.localtime(time.time())),
 720         u'',
 721         u'%s' % comtext,
 722         u'}}}',
 723         u'##PASSWORD %s' % compasswd,
 724         u'##LOGINUSER %s' % comloginuser,
 725         ]
 726         
 727     newpagetext = u'%s\n\n%s' % (pagetext, u'\n'.join(newcomment))
 728 
 729     parent_acl_string = Page(request, Globs.pagename).parse_processing_instructions()['acl'].getString()
 730     if not pg.exists():
 731         action = 'SAVENEW'
 732         # default acl was Globs.defaultacl
 733         defaultacl = parent_acl_string 
 734         warnmessages = '\'\'\'\'\'DO NOT EDIT THIS PAGE!!\'\'\' This page is automatically generated by Page``Comment macro.\'\'\n----'
 735         # redirect to the client's orignal page, not the comment only page (helps the user when this page shows up as a page-hit)
 736         redirect = '#redirect %s' % Globs.pagename
 737         newpagetext = u'%s%s\n%s\n%s' % (defaultacl, redirect,warnmessages, newpagetext)
 738     else:
 739         action = 'SAVE'
 740     
 741     newpagetext = pg.normalizeText( newpagetext )
 742     
 743     comment = u'PageComment modification at %s' % Globs.curpagename
 744     pg._write_file(newpagetext, action, comment)
 745     
 746     comment = u'New comment by "%s"' % comauthor
 747     
 748     trivial = 0
 749     addLogEntry(request, 'COMNEW', Globs.curpagename, comment)
 750     
 751     #msg = _('Thank you for your changes. Your attention to detail is appreciated.')
 752     msg = _('The comment is added.')
 753     
 754     # send notification mails
 755     if Params.notify:
 756         msg = msg + commentNotify(comment, trivial, comtext)
 757         
 758     if comautopass and comautopass == orgcompasswd:
 759         msg2 = u'<i>You did not enter a password. A random password has been generated for you: <b>%s</b></i>' % comautopass
 760         msg = u'%s%s' % (msg, msg2)
 761     
 762     message(msg)    
 763     return 1
 764 
 765 
 766 def patch_acl(parent_acl_string):
 767     "Patch the ACL line of the datapage with the acl line of the viewing page (current page)" 
 768     request = Globs.macro.request
 769     cfg = request.cfg
 770     _ = request.getText
 771     
 772     datapagename = Globs.datapagename
 773     
 774     pg = PageEditor( request, datapagename )
 775     pagetext = pg.get_raw_body()
 776     lines = pagetext.split('\n')
 777     if not lines[0].upper().startswith('#ACL '):
 778         lines.insert(0,'dummy line')
 779     lines[0] = parent_acl_string[:-1] # no newline!
 780     if not lines[1].upper().startswith('#REDIRECT '):
 781         lines.insert(1,'dummy line')
 782     lines[1] = "#redirect " + Globs.pagename + '\n'
 783     newpagetext = '\n'.join(lines)
 784     while newpagetext[0] == '\n':
 785         newpagetext = newpagetext[1:]
 786     newpagetext = pg.normalizeText( newpagetext )
 787     comment = u'Acl modification at %s' % Globs.curpagename
 788     pg._write_file(newpagetext, 'SAVE', comment)
 789     return 1
 790 
 791 def previewcomment(comicon, comauthor, comtext, commarkup):
 792     request = Globs.macro.request
 793     _ = request.getText
 794     cfg = request.cfg
 795     
 796     # normalize text
 797     lines = comtext.splitlines()
 798     if not lines[-1] == u'':
 799         # '' will make newline after join
 800         lines.append(u'')
 801     
 802     comtext = u'\n'.join(lines)
 803     
 804     #comtext = convertdelimeter(comtext)
 805     #comauthor = convertdelimeter(comauthor)
 806     
 807     if Params.articleview:
 808         cellstyle = u'border-width: 1px; border-bottom-width: 0px; border-color: #ff7777; background-color: #eeeeee; vertical-align: top; font-size: 9pt;'
 809         htmlcomment = [
 810             u'<tr><td colspan="5" class="commenttext" style="%(cellstyle)s">%(text)s</td></tr>',
 811             u'<tr><td colspan="5" class="commentauthor" style="border-color: #ff7777; border-width: 1px; border-top-width: 0px; text-align: right; font-size: 8pt; color: #999999;">Posted by <b>%(author)s</b> %(icon)s at %(date)s %(delform)s</td></tr>',
 812             u'<tr><td colspan="5" class="commentblankline" style="border-width: 0px; height: 20px;"></td></tr>',
 813             ]
 814             
 815     else:
 816         cellstyle = u'border-width: 0px; background-color: #ffeeee; border-top-width: 1px; vertical-align: top; font-size: 9pt;'
 817         htmlcomment = [
 818             u'<tr><td class="commenticon" style="%(cellstyle)s">%(icon)s</td>',
 819             u'<td class="commentauthor" style="%(cellstyle)s">%(author)s</td>',
 820             u'<td style="%(cellstyle)s width: 10px;">&nbsp;</td>',
 821             u'<td class="commenttext" style="%(cellstyle)s">%(text)s</td>',
 822             u'<td class="commentdate" style="%(cellstyle)s text-align: right; font-size: 8pt; " nowrap>%(date)s%(delform)s</td></tr>',
 823             ]
 824     
 825     htmlcommentitem = u'\n'.join(htmlcomment) % {
 826         'cellstyle': cellstyle,
 827         'icon': getsmiley(comicon),
 828         'author': converttext(comauthor),
 829         'text': converttext(comtext, commarkup),
 830         'date': time.strftime(cfg.datetime_fmt, time.localtime(time.time())),
 831         'delform': ''
 832         }
 833         
 834     return htmlcommentitem
 835     
 836 def showcomment():
 837     
 838     request = Globs.macro.request
 839     _ = request.getText
 840     
 841     commentlist = fetchcomments()
 842 
 843     # controleer of de acls'van de data pagina en de view pagina verschillen
 844     parent_acl_string = Page(request, Globs.pagename).parse_processing_instructions()['acl'].getString()
 845     datapage_acl_string = Page(request, Globs.datapagename).parse_processing_instructions()['acl'].getString()
 846     if parent_acl_string != datapage_acl_string:
 847         # indien dat het geval is: patch de datapagina's acl regel met de acl 's van de view pagina
 848         patch_acl(parent_acl_string)
 849     
 850     if Params.newerfirst:
 851         commentlist.reverse()
 852     
 853     html = []
 854     cur_index = 0
 855     
 856     if Params.articleview:
 857         cellstyle = u'border-width: 0px; background-color: #eeeeee; vertical-align: top; font-size: 9pt;'
 858         htmlcomment = [
 859             u'<tr><td colspan="5" class="commenttext" style="%(cellstyle)s">%(text)s</td></tr>',
 860             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>',
 861             u'<tr><td colspan="5" class="commentblankline" style="border-width: 0px; height: 20px;"></td></tr>',
 862             ]
 863             
 864     else:
 865         cellstyle = u'border-width: 0px; border-top-width: 1px; vertical-align: top; font-size: 9pt;'
 866         htmlcomment = [
 867             u'<tr><td class="commenticon" style="%(cellstyle)s">%(icon)s</td>',
 868             u'<td class="commentauthor" style="%(cellstyle)s">%(author)s</td>',
 869             u'<td style="%(cellstyle)s width: 10px;">&nbsp;</td>',
 870             u'<td class="commenttext" style="%(cellstyle)s">%(text)s</td>',
 871             u'<td class="commentdate" style="%(cellstyle)s text-align: right; font-size: 8pt; " nowrap>%(date)s%(delform)s</td></tr>',
 872             ]
 873     
 874     htmlcommentdel_admin = [
 875         u' <font style="font-size: 8pt;">',
 876         u'<a style="color: #aa0000;" href="javascript: requesttodeleteadmin%(formid)d(document.delform%(formid)d, \'%(key)s\');" title="%(msg)s">X</a>',
 877         u'</font>',
 878         ]
 879         
 880     htmlcommentdel_guest = [
 881         u' <font style="font-size: 8pt;">',
 882         u'<a style="color: #aa0000;" href="javascript: requesttodelete%(formid)d(document.delform%(formid)d, \'%(key)s\');" title="%(msg)s">X</a>',
 883         u'</font>',
 884         ]
 885     
 886     for item in commentlist:
 887         if Globs.admin or (item['loginuser'] and request.user.valid and request.user.name == item['name']):
 888             htmlcommentdel = htmlcommentdel_admin
 889         elif item['loginuser']:
 890             htmlcommentdel = ''
 891         else:
 892             htmlcommentdel = htmlcommentdel_guest
 893         
 894         htmlcommentdel = u'\n'.join(htmlcommentdel) % {
 895             'formid': Globs.formid, 
 896             'key': item['key'],
 897             'msg': _('Delete')
 898             }
 899                 
 900         htmlcommentitem = u'\n'.join(htmlcomment) % {
 901             'cellstyle': cellstyle,
 902             'icon': getsmiley(item['icon']),
 903             'author': converttext(item['name']),
 904             'text': converttext(item['text'], item['markup']),
 905             'date': item['date'],
 906             'delform': htmlcommentdel
 907             }
 908         
 909         html.append(htmlcommentitem)
 910     
 911     return u'\n'.join(html)
 912 
 913 def getescapedsectionname(targettext):
 914     regex = r'\W'
 915     pattern = re.compile(regex, re.UNICODE)
 916     sectionname = pattern.sub('', targettext)
 917     
 918     return sectionname
 919 
 920 
 921 def getsmiley(markup):
 922     
 923     if markup in config.smileys:
 924         formatter = Globs.macro.formatter
 925         return formatter.smiley(markup)
 926     else:
 927         return ''
 928 
 929 
 930 def converttext(targettext, markup='0'):
 931     # Converts some special characters of html to plain-text style
 932     # What else to handle?
 933     
 934     if Params.markup and markup == '1':
 935         targettext = getMarkupText(targettext)
 936     else:
 937         # targettext = targettext.strip()
 938         targettext = targettext.replace(u'&', '&amp')
 939         targettext = targettext.replace(u'>', '&gt;')
 940         targettext = targettext.replace(u'<', '&lt;')
 941         targettext = targettext.replace(u'\n', '<br>')
 942         targettext = targettext.replace(u'"', '&quot;')
 943         targettext = targettext.replace(u'\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;')
 944         targettext = targettext.replace(u'  ', '&nbsp;&nbsp;')
 945 
 946     return targettext
 947     
 948 def convertdelimeter(targettext, reverse=0):
 949     # Converts delimeter to other string to avoid a crash
 950     
 951     if reverse:
 952         targettext = targettext.replace(u'{_{_{', u'{{{')
 953         targettext = targettext.replace(u'}_}_}', u'}}}')
 954     
 955     else:
 956         targettext = targettext.replace(u'{{{', u'{_{_{')
 957         targettext = targettext.replace(u'}}}', u'}_}_}')
 958     
 959     return targettext
 960 
 961 
 962 def deleteform():
 963     # Javascript codes for deleting or restoring a comment
 964     
 965     request = Globs.macro.request
 966     _ = request.getText
 967     
 968     htmlresult = []
 969     
 970     html = [
 971         '<script language="javascript">',
 972         '<!--',
 973         ]
 974     htmlresult.append(u'\n'.join(html))
 975            
 976     html = [    
 977         '  function requesttodeleteadmin%d(delform, comkey) {' % Globs.formid,
 978         '      if (confirm("%s")) {;' % _('Really delete this comment?'),
 979         '          delform.delkey.value = comkey;',
 980         '          delform.delpasswd.value = "****";',
 981         '          delform.submit();',
 982         '      }',
 983         '  }',
 984         '  function requesttodelete%d(delform, comkey) {' % Globs.formid,
 985         '      var passwd = prompt("%s:", "");' % _('Please specify a password!'),
 986         '      if(!(passwd == "" || passwd == null)) {',
 987         '          delform.delkey.value = comkey;',
 988         '          delform.delpasswd.value = passwd;',
 989         '          delform.submit();',
 990         '      }',
 991         '  }',
 992         ]
 993     
 994     htmlresult.append(u'\n'.join(html))
 995 
 996     page_url = wikiutil.quoteWikinameURL(Globs.cursubname)
 997 
 998     html = [
 999         '//-->',
1000         '</script>',
1001         '<form name="delform%d" action="%s#pagecomment%d" METHOD="post">' % (Globs.formid, page_url, Globs.formid),
1002         '<input type="hidden" value="show" name="action">',
1003         '<input name="delpasswd" type="hidden" value="****">',
1004         '<input name="delkey" type="hidden" value="">',
1005         '<input type="hidden" name="commentaction" value="delcomment%s">' % Globs.formid,
1006         '</form>',
1007         ]
1008     htmlresult.append(u'\n'.join(html))
1009 
1010     return u'\n'.join(htmlresult)
1011 
1012 
1013 def filtercomment(index='', name='', passwd=''):
1014     
1015     # filter by index
1016     if index:
1017         filteredlist1 = fetchcomments(index, index)
1018     else:
1019         filteredlist1 = fetchcomments()
1020     
1021     # filter by name
1022     filteredlist2 = []
1023     if name:
1024         for item in filteredlist1:
1025             if name == item['name']:
1026                 filteredlist2.append(item)
1027     else:
1028         filteredlist2 = filteredlist1
1029     
1030     # filter by password
1031     filteredlist3 = []
1032     if passwd:
1033         for item in filteredlist2:
1034             if passwd == item['passwd']:
1035                 filteredlist3.append(item)
1036     else:
1037         filteredlist3 = filteredlist2
1038 
1039     return filteredlist3
1040         
1041 
1042 def fetchcomments(startindex=1, endindex=9999):
1043     
1044     commentlist = []
1045     
1046     request = Globs.macro.request
1047     formatter = Globs.macro.formatter
1048     datapagename = Globs.datapagename
1049 
1050     pg = Page( request, datapagename )
1051     pagetext = pg.get_raw_body()
1052     
1053     regex = ur"""
1054 ^[\{]{3}\n
1055 ^(?P<icon>[^\n]*)\n
1056 ^(?P<name>[^\n]*)\n
1057 ^(?P<date>[^\n]*)\n\n
1058 ^(?P<text>
1059     \s*.*?
1060     (?=[\}]{3})
1061 )[\}]{3}[\n]*
1062 ^[#]{2}PASSWORD[ ](?P<passwd>[^\n]*)[\n]*
1063 ^[#]{2}LOGINUSER[ ](?P<loginuser>[^\n]*)[\n]*"""
1064 
1065     pattern = re.compile(regex, re.UNICODE + re.MULTILINE + re.VERBOSE + re.DOTALL)
1066     commentitems = pattern.findall(pagetext)
1067     
1068     cur_index = 0
1069     
1070     for item in commentitems:
1071         comment = {}
1072         cur_index += 1
1073         
1074         if cur_index < startindex:
1075             continue
1076         
1077         comment['index'] = cur_index
1078         
1079         custom_fields = item[0].split(',')
1080         
1081         comment['icon'] = custom_fields[0]
1082         
1083         if len(custom_fields) > 1:
1084             comment['markup'] = custom_fields[1].strip()
1085         else:
1086             comment['markup'] = ''
1087         
1088         comment['name'] = convertdelimeter(item[1], 1)
1089         comment['date'] = item[2]
1090         comment['text'] = convertdelimeter(item[3], 1)
1091         comment['passwd'] = item[4]
1092         comment['loginuser'] = item[5]
1093         
1094         # experimental
1095         comment['key'] = comment['date'].strip()
1096         
1097         commentlist.append(comment)
1098         
1099         if cur_index >= endindex:
1100             break
1101 
1102     return commentlist
1103 
1104 def deletecomment(macro, delkey, delpasswd):
1105     # Deletes a comment with given index and password
1106     
1107     request = Globs.macro.request
1108     formatter = Globs.macro.formatter
1109     datapagename = Globs.datapagename
1110     _ = request.getText
1111     
1112     if Params.encryptpass:
1113         from MoinMoin import user
1114         delpasswd = user.encodePassword(delpasswd)
1115     
1116     pg = PageEditor( request, datapagename )
1117     pagetext = pg.get_raw_body()
1118     
1119     regex = ur"""
1120 (?P<comblock>
1121     ^[\{]{3}\n
1122     ^(?P<icon>[^\n]*)\n
1123     ^(?P<name>[^\n]*)\n
1124     ^(?P<date>[^\n]*)[\n]+
1125     ^(?P<text>
1126         \s*.*?
1127         (?=[\}]{3})
1128     )[\}]{3}[\n]*
1129     ^[#]{2}PASSWORD[ ](?P<passwd>[^\n]*)[\n]*
1130     ^[#]{2}LOGINUSER[ ](?P<loginuser>[^\n]*)[\n$]*
1131 )"""
1132 
1133     pattern = re.compile(regex, re.UNICODE + re.MULTILINE + re.VERBOSE + re.DOTALL)
1134     commentitems = pattern.findall(pagetext)
1135     
1136     for item in commentitems:
1137         
1138         if delkey == item[3].strip():
1139             comauthor = item[2]
1140             if Globs.admin or (request.user.valid and request.user.name == comauthor) or delpasswd == item[5]:
1141                 newpagetext = pagetext.replace(item[0], '', 1)
1142                 
1143                 action = 'SAVE'
1144                 comment = 'Deleted comment by "%s"' % comauthor
1145                 trivial = 1
1146                 pg._write_file(newpagetext, action, u'PageComment modification at %s' % Globs.curpagename)
1147                 addLogEntry(request, 'COMDEL', Globs.curpagename, comment)
1148                 
1149                 msg = _('The comment is deleted.')
1150                 
1151                 # send notification mails
1152                 if Params.notify:
1153                     msg = msg + commentNotify(comment, trivial)
1154                 
1155                 message(msg)
1156                 
1157                 return
1158             else:
1159                 message(_('Sorry, wrong password.'))
1160                 return
1161                 
1162     message(_('No such comment'))
1163 
1164 
1165 def getAuthorFromCookie():
1166 
1167     import Cookie
1168     request = Globs.macro.request
1169     cookieauthor = ''
1170     
1171     try:
1172         cookie = Cookie.SimpleCookie(request.cookies)
1173     except Cookie.CookieError:
1174         # ignore invalid cookies
1175         cookie = None
1176     
1177     if cookie and cookie.has_key('PG2AUTHOR'):
1178         cookieauthor = cookie['PG2AUTHOR']
1179     
1180     cookieauthor = decodeURI(cookieauthor)
1181     
1182     return cookieauthor
1183 
1184 
1185 def commentNotify(comment, trivial, comtext=''):
1186     
1187     request = Globs.macro.request
1188     
1189     if hasattr(request.cfg, 'mail_enabled'):
1190         mail_enabled = request.cfg.mail_enabled
1191     elif hasattr(request.cfg, 'mail_smarthost'):
1192         mail_enabled = request.cfg.mail_smarthost
1193     else:
1194         mail_enabled = ''
1195 
1196     if not mail_enabled:
1197         return ''
1198         
1199     _ = request.getText
1200     pg = PageEditor( request, Globs.curpagename )
1201     
1202     subscribers = pg.getSubscribers(request, return_users=1, trivial=trivial)
1203     if subscribers:
1204         # get a list of old revisions, and append a diff
1205 
1206         # send email to all subscribers
1207         results = [_('Status of sending notification mails:')]
1208         for lang in subscribers.keys():
1209             emails = map(lambda u: u.email, subscribers[lang])
1210             names  = map(lambda u: u.name,  subscribers[lang])
1211             mailok, status = sendNotification(pg, comtext, comment, emails, lang, trivial)
1212             recipients = ", ".join(names)
1213             results.append(_('[%(lang)s] %(recipients)s: %(status)s') % {
1214                 'lang': lang, 'recipients': recipients, 'status': status})
1215 
1216         # Return mail sent results. Ignore trivial - we don't have
1217         # to lie. If mail was sent, just tell about it.
1218         return '<p>\n%s\n</p> ' % '<br>'.join(results) 
1219 
1220     # No mail sent, no message.
1221     return ''
1222 
1223 def sendNotification(pg, comtext, comment, emails, email_lang, trivial):
1224 ##    return pg._sendNotification(\
1225 ##            comment+'\n\n'+('-'*70)+'\n'+comtext+'\n', \
1226 ##            emails, email_lang, [], trivial)
1227     
1228     from MoinMoin import util, user, mail
1229     request = Globs.macro.request
1230     
1231     _ = lambda s, formatted=True, r=request, l=email_lang: r.getText(s, formatted=formatted, lang=l)
1232 
1233     mailBody = _("Dear Wiki user,\n\n"
1234         'You have subscribed to a wiki page or wiki category on "%(sitename)s" for change notification.\n\n'
1235         "The following page has been changed by %(editor)s:\n"
1236         "%(pagelink)s\n\n", formatted=False) % {
1237             'editor': pg.uid_override or user.getUserIdentification(request),
1238             'pagelink': pg.request.getQualifiedURL(pg.url(request,relative=False)),
1239             'sitename': pg.cfg.sitename or request.getBaseURL(),
1240     }
1241 
1242     if comment:
1243         mailBody = mailBody + \
1244             _("The comment on the change is:\n%(comment)s\n\n", formatted=False) % {'comment': comment}
1245 
1246     # append comment text
1247     if comtext:
1248         mailBody = mailBody + "%s\n%s\n" % (("-" * 78), comtext)
1249     
1250     return mail.sendmail.sendmail(request, emails,
1251         _('[%(sitename)s] %(trivial)sUpdate of "%(pagename)s" by %(username)s', formatted=False) % {
1252             'trivial' : (trivial and _("Trivial ", formatted=False)) or "",
1253             'sitename': pg.cfg.sitename or "Wiki",
1254             'pagename': pg.page_name,
1255             'username': pg.uid_override or user.getUserIdentification(request),
1256         },
1257         mailBody, mail_from=pg.cfg.mail_from)
1258 
1259 
1260 
1261 def decodeURI(quotedstring):
1262 
1263     try:
1264         unquotedstring = wikiutil.url_unquote(quotedstring)
1265     except AttributeError:
1266         # for compatibility with old versions
1267         unquotedstring = url_unquote(quotedstring)
1268         
1269     return unquotedstring
1270 
1271 
1272 def url_unquote(s, want_unicode=True):
1273     """
1274     From moinmoin 1.5
1275     
1276     Wrapper around urllib.unquote doing the encoding/decoding as usually wanted:
1277     
1278     @param s: the string to unquote (can be str or unicode, if it is unicode,
1279               config.charset is used to encode it before calling urllib)
1280     @param want_unicode: for the less usual case that you want to get back
1281                          str and not unicode, set this to False.
1282                          Default is True.
1283     """
1284     import urllib
1285     
1286     if isinstance(s, unicode):
1287         s = s.encode(config.charset) # ascii would also work
1288     s = urllib.unquote(s)
1289     if want_unicode:
1290         s = s.decode(config.charset)
1291     return s
1292     
1293     
1294 def addLogEntry(request, action, pagename, msg):
1295     # Add an entry to the edit log on adding comments.
1296     from MoinMoin.logfile import editlog
1297     t = wikiutil.timestamp2version(time.time())
1298     msg = unicode(msg)
1299 
1300     pg = Page( request, pagename )
1301     #rev = pg.current_rev()
1302     rev = 99999999
1303 
1304     # TODO: for now we simply write 2 logs, maybe better use some multilog stuff
1305     # Write to global log
1306     log = editlog.EditLog(request)
1307     log.add(request, t, rev, action, pagename, request.remote_addr, '', msg)
1308 
1309     # Write to local log
1310     log = editlog.EditLog(request, rootpagename=pagename)
1311     log.add(request, t, rev, action, pagename, request.remote_addr, '', msg)
1312     
1313 def getsmileymarkuplist(defaulticon):
1314     
1315     html = [
1316         u'Smiley: <select name="comicon">',
1317         u'  <option value=""></option>',
1318         ]
1319     
1320     for smiley in config.smileys:
1321         if defaulticon.strip() == smiley:
1322             html.append(u'  <option selected>%s</option>' % wikiutil.escape(smiley))
1323         else:
1324             html.append(u'  <option>%s</option>' % wikiutil.escape(smiley))
1325 
1326     html.append(u'</select>')
1327     
1328     return u'\n'.join(html)
1329     
1330 def getsmileymarkupradio(defaulticon):
1331     
1332     smileys = Globs.smileys
1333     html = []
1334     
1335     for smiley in smileys:
1336         if defaulticon.strip() == smiley:
1337             html.append(u'<input type="radio" name="comicon" value="%s" checked>%s ' % (wikiutil.escape(smiley), getsmiley(smiley)) )
1338         else:
1339             html.append(u'<input type="radio" name="comicon" value="%s">%s ' % (wikiutil.escape(smiley), getsmiley(smiley)) )
1340 
1341     html.append(u'</select>')
1342     
1343     return u'\n'.join(html)
1344 
1345 
1346 def getMarkupText(lines):
1347     request = Globs.macro.request
1348     formatter = Globs.macro.formatter
1349     
1350     markup = Globs.markupforbidden
1351     
1352     for regex in markup.keys():
1353         pattern = re.compile(regex, re.UNICODE + re.VERBOSE + re.MULTILINE)
1354         lines, nchanges = pattern.subn(markup[regex], lines)
1355         
1356         #if nchanges:
1357         #    debug(regex)
1358         
1359     out = StringIO.StringIO()
1360     request.redirect(out)
1361     wikiizer = text_moin_wiki.Parser(lines, request)
1362     wikiizer.format(formatter)
1363     targettext = out.getvalue()
1364     request.redirect()
1365     del out
1366     
1367     return targettext    
1368     
1369     
1370 def nicepass(alpha=3,numeric=1):
1371     """
1372     returns a human-readble password (say rol86din instead of 
1373     a difficult to remember K8Yn9muL ) 
1374     """
1375     import string
1376     import random
1377     vowels = ['a','e','i','o','u']
1378     consonants = [a for a in string.ascii_lowercase if a not in vowels]
1379     digits = string.digits
1380     
1381     ####utility functions
1382     def a_part(slen):
1383         ret = ''
1384         for i in range(slen):			
1385             if i%2 ==0:
1386                 randid = random.randint(0,20) #number of consonants
1387                 ret += consonants[randid]
1388             else:
1389                 randid = random.randint(0,4) #number of vowels
1390                 ret += vowels[randid]
1391         return ret
1392     
1393     def n_part(slen):
1394         ret = ''
1395         for i in range(slen):
1396             randid = random.randint(0,9) #number of digits
1397             ret += digits[randid]
1398         return ret
1399         
1400     #### 	
1401     fpl = alpha/2		
1402     if alpha % 2 :
1403         fpl = int(alpha/2) + 1 					
1404     lpl = alpha - fpl	
1405     
1406     start = a_part(fpl)
1407     mid = n_part(numeric)
1408     end = a_part(lpl)
1409     
1410     # return "%s%s%s" % (start,mid,end)
1411     return "%s%s%s" % (start,end,mid)

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.