Attachment 'PageComment2-0992-moin16.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.form.get('commentaction', [''])[0]
 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.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.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]])[0]
 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', 0))
 427     except ValueError:
 428         Params.newerfirst = 0
 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', 0))
 447     except ValueError:
 448         Params.nosmiley = 0
 449 
 450     try:
 451         Params.rows = int(params.get('rows', 4))
 452     except ValueError:
 453         Params.rows = 4
 454 
 455     try:
 456         Params.cols = int(params.get('cols', 60))
 457     except ValueError:
 458         Params.cols = 60
 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', 0))
 467     except ValueError:
 468         Params.notify = 0
 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', 0))
 477     except ValueError:
 478         Params.markup = 0
 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.getScriptname()
 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     if not pg.exists():
 730         action = 'SAVENEW'
 731         defaultacl = Globs.defaultacl
 732         warnmessages = '\'\'\'\'\'DO NOT EDIT THIS PAGE!!\'\'\' This page is automatically generated by Page``Comment macro.\'\'\n----'
 733         newpagetext = u'%s\n%s\n%s' % (defaultacl, warnmessages, newpagetext)
 734     else:
 735         action = 'SAVE'
 736     
 737     newpagetext = pg.normalizeText( newpagetext )
 738     
 739     comment = u'PageComment modification at %s' % Globs.curpagename
 740     pg._write_file(newpagetext, action, comment)
 741     
 742     comment = u'New comment by "%s"' % comauthor
 743     
 744     trivial = 0
 745     addLogEntry(request, 'COMNEW', Globs.curpagename, comment)
 746     
 747     #msg = _('Thank you for your changes. Your attention to detail is appreciated.')
 748     msg = _('The comment is added.')
 749     
 750     # send notification mails
 751     if Params.notify:
 752         msg = msg + commentNotify(comment, trivial, comtext)
 753         
 754     if comautopass and comautopass == orgcompasswd:
 755         msg2 = u'<i>You did not enter a password. A random password has been generated for you: <b>%s</b></i>' % comautopass
 756         msg = u'%s%s' % (msg, msg2)
 757     
 758     message(msg)    
 759     return 1
 760 
 761 
 762 def previewcomment(comicon, comauthor, comtext, commarkup):
 763     request = Globs.macro.request
 764     _ = request.getText
 765     cfg = request.cfg
 766     
 767     # normalize text
 768     lines = comtext.splitlines()
 769     if not lines[-1] == u'':
 770         # '' will make newline after join
 771         lines.append(u'')
 772     
 773     comtext = u'\n'.join(lines)
 774     
 775     #comtext = convertdelimeter(comtext)
 776     #comauthor = convertdelimeter(comauthor)
 777     
 778     if Params.articleview:
 779         cellstyle = u'border-width: 1px; border-bottom-width: 0px; border-color: #ff7777; background-color: #eeeeee; vertical-align: top; font-size: 9pt;'
 780         htmlcomment = [
 781             u'<tr><td colspan="5" class="commenttext" style="%(cellstyle)s">%(text)s</td></tr>',
 782             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>',
 783             u'<tr><td colspan="5" class="commentblankline" style="border-width: 0px; height: 20px;"></td></tr>',
 784             ]
 785             
 786     else:
 787         cellstyle = u'border-width: 0px; background-color: #ffeeee; border-top-width: 1px; vertical-align: top; font-size: 9pt;'
 788         htmlcomment = [
 789             u'<tr><td class="commenticon" style="%(cellstyle)s">%(icon)s</td>',
 790             u'<td class="commentauthor" style="%(cellstyle)s">%(author)s</td>',
 791             u'<td style="%(cellstyle)s width: 10px;">&nbsp;</td>',
 792             u'<td class="commenttext" style="%(cellstyle)s">%(text)s</td>',
 793             u'<td class="commentdate" style="%(cellstyle)s text-align: right; font-size: 8pt; " nowrap>%(date)s%(delform)s</td></tr>',
 794             ]
 795     
 796     htmlcommentitem = u'\n'.join(htmlcomment) % {
 797         'cellstyle': cellstyle,
 798         'icon': getsmiley(comicon),
 799         'author': converttext(comauthor),
 800         'text': converttext(comtext, commarkup),
 801         'date': time.strftime(cfg.datetime_fmt, time.localtime(time.time())),
 802         'delform': ''
 803         }
 804         
 805     return htmlcommentitem
 806     
 807 def showcomment():
 808     
 809     request = Globs.macro.request
 810     _ = request.getText
 811     
 812     commentlist = fetchcomments()
 813     
 814     if Params.newerfirst:
 815         commentlist.reverse()
 816     
 817     html = []
 818     cur_index = 0
 819     
 820     if Params.articleview:
 821         cellstyle = u'border-width: 0px; background-color: #eeeeee; vertical-align: top; font-size: 9pt;'
 822         htmlcomment = [
 823             u'<tr><td colspan="5" class="commenttext" style="%(cellstyle)s">%(text)s</td></tr>',
 824             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>',
 825             u'<tr><td colspan="5" class="commentblankline" style="border-width: 0px; height: 20px;"></td></tr>',
 826             ]
 827             
 828     else:
 829         cellstyle = u'border-width: 0px; border-top-width: 1px; vertical-align: top; font-size: 9pt;'
 830         htmlcomment = [
 831             u'<tr><td class="commenticon" style="%(cellstyle)s">%(icon)s</td>',
 832             u'<td class="commentauthor" style="%(cellstyle)s">%(author)s</td>',
 833             u'<td style="%(cellstyle)s width: 10px;">&nbsp;</td>',
 834             u'<td class="commenttext" style="%(cellstyle)s">%(text)s</td>',
 835             u'<td class="commentdate" style="%(cellstyle)s text-align: right; font-size: 8pt; " nowrap>%(date)s%(delform)s</td></tr>',
 836             ]
 837     
 838     htmlcommentdel_admin = [
 839         u' <font style="font-size: 8pt;">',
 840         u'<a style="color: #aa0000;" href="javascript: requesttodeleteadmin%(formid)d(document.delform%(formid)d, \'%(key)s\');" title="%(msg)s">X</a>',
 841         u'</font>',
 842         ]
 843         
 844     htmlcommentdel_guest = [
 845         u' <font style="font-size: 8pt;">',
 846         u'<a style="color: #aa0000;" href="javascript: requesttodelete%(formid)d(document.delform%(formid)d, \'%(key)s\');" title="%(msg)s">X</a>',
 847         u'</font>',
 848         ]
 849     
 850     for item in commentlist:
 851         if Globs.admin or (item['loginuser'] and request.user.valid and request.user.name == item['name']):
 852             htmlcommentdel = htmlcommentdel_admin
 853         elif item['loginuser']:
 854             htmlcommentdel = ''
 855         else:
 856             htmlcommentdel = htmlcommentdel_guest
 857         
 858         htmlcommentdel = u'\n'.join(htmlcommentdel) % {
 859             'formid': Globs.formid, 
 860             'key': item['key'],
 861             'msg': _('Delete')
 862             }
 863                 
 864         htmlcommentitem = u'\n'.join(htmlcomment) % {
 865             'cellstyle': cellstyle,
 866             'icon': getsmiley(item['icon']),
 867             'author': converttext(item['name']),
 868             'text': converttext(item['text'], item['markup']),
 869             'date': item['date'],
 870             'delform': htmlcommentdel
 871             }
 872         
 873         html.append(htmlcommentitem)
 874     
 875     return u'\n'.join(html)
 876 
 877 def getescapedsectionname(targettext):
 878     regex = r'\W'
 879     pattern = re.compile(regex, re.UNICODE)
 880     sectionname = pattern.sub('', targettext)
 881     
 882     return sectionname
 883 
 884 
 885 def getsmiley(markup):
 886     
 887     if markup in config.smileys:
 888         formatter = Globs.macro.formatter
 889         return formatter.smiley(markup)
 890     else:
 891         return ''
 892 
 893 
 894 def converttext(targettext, markup='0'):
 895     # Converts some special characters of html to plain-text style
 896     # What else to handle?
 897     
 898     if Params.markup and markup == '1':
 899         targettext = getMarkupText(targettext)
 900     else:
 901         # targettext = targettext.strip()
 902         targettext = targettext.replace(u'&', '&amp')
 903         targettext = targettext.replace(u'>', '&gt;')
 904         targettext = targettext.replace(u'<', '&lt;')
 905         targettext = targettext.replace(u'\n', '<br>')
 906         targettext = targettext.replace(u'"', '&quot;')
 907         targettext = targettext.replace(u'\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;')
 908         targettext = targettext.replace(u'  ', '&nbsp;&nbsp;')
 909 
 910     return targettext
 911     
 912 def convertdelimeter(targettext, reverse=0):
 913     # Converts delimeter to other string to avoid a crash
 914     
 915     if reverse:
 916         targettext = targettext.replace(u'{_{_{', u'{{{')
 917         targettext = targettext.replace(u'}_}_}', u'}}}')
 918     
 919     else:
 920         targettext = targettext.replace(u'{{{', u'{_{_{')
 921         targettext = targettext.replace(u'}}}', u'}_}_}')
 922     
 923     return targettext
 924 
 925 
 926 def deleteform():
 927     # Javascript codes for deleting or restoring a comment
 928     
 929     request = Globs.macro.request
 930     _ = request.getText
 931     
 932     htmlresult = []
 933     
 934     html = [
 935         '<script language="javascript">',
 936         '<!--',
 937         ]
 938     htmlresult.append(u'\n'.join(html))
 939            
 940     html = [    
 941         '  function requesttodeleteadmin%d(delform, comkey) {' % Globs.formid,
 942         '      if (confirm("%s")) {;' % _('Really delete this comment?'),
 943         '          delform.delkey.value = comkey;',
 944         '          delform.delpasswd.value = "****";',
 945         '          delform.submit();',
 946         '      }',
 947         '  }',
 948         '  function requesttodelete%d(delform, comkey) {' % Globs.formid,
 949         '      var passwd = prompt("%s:", "");' % _('Please specify a password!'),
 950         '      if(!(passwd == "" || passwd == null)) {',
 951         '          delform.delkey.value = comkey;',
 952         '          delform.delpasswd.value = passwd;',
 953         '          delform.submit();',
 954         '      }',
 955         '  }',
 956         ]
 957     
 958     htmlresult.append(u'\n'.join(html))
 959 
 960     page_url = wikiutil.quoteWikinameURL(Globs.cursubname)
 961 
 962     html = [
 963         '//-->',
 964         '</script>',
 965         '<form name="delform%d" action="%s#pagecomment%d" METHOD="post">' % (Globs.formid, page_url, Globs.formid),
 966         '<input type="hidden" value="show" name="action">',
 967         '<input name="delpasswd" type="hidden" value="****">',
 968         '<input name="delkey" type="hidden" value="">',
 969         '<input type="hidden" name="commentaction" value="delcomment%s">' % Globs.formid,
 970         '</form>',
 971         ]
 972     htmlresult.append(u'\n'.join(html))
 973 
 974     return u'\n'.join(htmlresult)
 975 
 976 
 977 def filtercomment(index='', name='', passwd=''):
 978     
 979     # filter by index
 980     if index:
 981         filteredlist1 = fetchcomments(index, index)
 982     else:
 983         filteredlist1 = fetchcomments()
 984     
 985     # filter by name
 986     filteredlist2 = []
 987     if name:
 988         for item in filteredlist1:
 989             if name == item['name']:
 990                 filteredlist2.append(item)
 991     else:
 992         filteredlist2 = filteredlist1
 993     
 994     # filter by password
 995     filteredlist3 = []
 996     if passwd:
 997         for item in filteredlist2:
 998             if passwd == item['passwd']:
 999                 filteredlist3.append(item)
1000     else:
1001         filteredlist3 = filteredlist2
1002 
1003     return filteredlist3
1004         
1005 
1006 def fetchcomments(startindex=1, endindex=9999):
1007     
1008     commentlist = []
1009     
1010     request = Globs.macro.request
1011     formatter = Globs.macro.formatter
1012     datapagename = Globs.datapagename
1013 
1014     pg = Page( request, datapagename )
1015     pagetext = pg.get_raw_body()
1016     
1017     regex = ur"""
1018 ^[\{]{3}\n
1019 ^(?P<icon>[^\n]*)\n
1020 ^(?P<name>[^\n]*)\n
1021 ^(?P<date>[^\n]*)\n\n
1022 ^(?P<text>
1023     \s*.*?
1024     (?=[\}]{3})
1025 )[\}]{3}[\n]*
1026 ^[#]{2}PASSWORD[ ](?P<passwd>[^\n]*)[\n]*
1027 ^[#]{2}LOGINUSER[ ](?P<loginuser>[^\n]*)[\n]*"""
1028 
1029     pattern = re.compile(regex, re.UNICODE + re.MULTILINE + re.VERBOSE + re.DOTALL)
1030     commentitems = pattern.findall(pagetext)
1031     
1032     cur_index = 0
1033     
1034     for item in commentitems:
1035         comment = {}
1036         cur_index += 1
1037         
1038         if cur_index < startindex:
1039             continue
1040         
1041         comment['index'] = cur_index
1042         
1043         custom_fields = item[0].split(',')
1044         
1045         comment['icon'] = custom_fields[0]
1046         
1047         if len(custom_fields) > 1:
1048             comment['markup'] = custom_fields[1].strip()
1049         else:
1050             comment['markup'] = ''
1051         
1052         comment['name'] = convertdelimeter(item[1], 1)
1053         comment['date'] = item[2]
1054         comment['text'] = convertdelimeter(item[3], 1)
1055         comment['passwd'] = item[4]
1056         comment['loginuser'] = item[5]
1057         
1058         # experimental
1059         comment['key'] = comment['date'].strip()
1060         
1061         commentlist.append(comment)
1062         
1063         if cur_index >= endindex:
1064             break
1065 
1066     return commentlist
1067 
1068 def deletecomment(macro, delkey, delpasswd):
1069     # Deletes a comment with given index and password
1070     
1071     request = Globs.macro.request
1072     formatter = Globs.macro.formatter
1073     datapagename = Globs.datapagename
1074     _ = request.getText
1075     
1076     if Params.encryptpass:
1077         from MoinMoin import user
1078         delpasswd = user.encodePassword(delpasswd)
1079     
1080     pg = PageEditor( request, datapagename )
1081     pagetext = pg.get_raw_body()
1082     
1083     regex = ur"""
1084 (?P<comblock>
1085     ^[\{]{3}\n
1086     ^(?P<icon>[^\n]*)\n
1087     ^(?P<name>[^\n]*)\n
1088     ^(?P<date>[^\n]*)[\n]+
1089     ^(?P<text>
1090         \s*.*?
1091         (?=[\}]{3})
1092     )[\}]{3}[\n]*
1093     ^[#]{2}PASSWORD[ ](?P<passwd>[^\n]*)[\n]*
1094     ^[#]{2}LOGINUSER[ ](?P<loginuser>[^\n]*)[\n$]*
1095 )"""
1096 
1097     pattern = re.compile(regex, re.UNICODE + re.MULTILINE + re.VERBOSE + re.DOTALL)
1098     commentitems = pattern.findall(pagetext)
1099     
1100     for item in commentitems:
1101         
1102         if delkey == item[3].strip():
1103             comauthor = item[2]
1104             if Globs.admin or (request.user.valid and request.user.name == comauthor) or delpasswd == item[5]:
1105                 newpagetext = pagetext.replace(item[0], '', 1)
1106                 
1107                 action = 'SAVE'
1108                 comment = 'Deleted comment by "%s"' % comauthor
1109                 trivial = 1
1110                 pg._write_file(newpagetext, action, u'PageComment modification at %s' % Globs.curpagename)
1111                 addLogEntry(request, 'COMDEL', Globs.curpagename, comment)
1112                 
1113                 msg = _('The comment is deleted.')
1114                 
1115                 # send notification mails
1116                 if Params.notify:
1117                     msg = msg + commentNotify(comment, trivial)
1118                 
1119                 message(msg)
1120                 
1121                 return
1122             else:
1123                 message(_('Sorry, wrong password.'))
1124                 return
1125                 
1126     message(_('No such comment'))
1127 
1128 
1129 def getAuthorFromCookie():
1130 
1131     import Cookie
1132     request = Globs.macro.request
1133     cookieauthor = ''
1134     
1135     try:
1136         cookie = Cookie.SimpleCookie(request.saved_cookie)
1137     except Cookie.CookieError:
1138         # ignore invalid cookies
1139         cookie = None
1140     
1141     if cookie and cookie.has_key('PG2AUTHOR'):
1142         cookieauthor = cookie['PG2AUTHOR'].value
1143     
1144     cookieauthor = decodeURI(cookieauthor)
1145     
1146     return cookieauthor
1147 
1148 
1149 def commentNotify(comment, trivial, comtext=''):
1150     
1151     request = Globs.macro.request
1152     
1153     if hasattr(request.cfg, 'mail_enabled'):
1154         mail_enabled = request.cfg.mail_enabled
1155     elif hasattr(request.cfg, 'mail_smarthost'):
1156         mail_enabled = request.cfg.mail_smarthost
1157     else:
1158         mail_enabled = ''
1159 
1160     if not mail_enabled:
1161         return ''
1162         
1163     _ = request.getText
1164     pg = PageEditor( request, Globs.curpagename )
1165     
1166     subscribers = pg.getSubscribers(request, return_users=1, trivial=trivial)
1167     if subscribers:
1168         # get a list of old revisions, and append a diff
1169 
1170         # send email to all subscribers
1171         results = [_('Status of sending notification mails:')]
1172         for lang in subscribers.keys():
1173             emails = map(lambda u: u.email, subscribers[lang])
1174             names  = map(lambda u: u.name,  subscribers[lang])
1175             mailok, status = sendNotification(pg, comtext, comment, emails, lang, trivial)
1176             recipients = ", ".join(names)
1177             results.append(_('[%(lang)s] %(recipients)s: %(status)s') % {
1178                 'lang': lang, 'recipients': recipients, 'status': status})
1179 
1180         # Return mail sent results. Ignore trivial - we don't have
1181         # to lie. If mail was sent, just tell about it.
1182         return '<p>\n%s\n</p> ' % '<br>'.join(results) 
1183 
1184     # No mail sent, no message.
1185     return ''
1186 
1187 def sendNotification(pg, comtext, comment, emails, email_lang, trivial):
1188     
1189     from MoinMoin import util, user, mail
1190     request = Globs.macro.request
1191     
1192     _ = lambda s, formatted=True, r=request, l=email_lang: r.getText(s, formatted=formatted, lang=l)
1193 
1194     mailBody = _("Dear Wiki user,\n\n"
1195         'You have subscribed to a wiki page or wiki category on "%(sitename)s" for change notification.\n\n'
1196         "The following page has been changed by %(editor)s:\n"
1197         "%(pagelink)s\n\n", formatted=False) % {
1198             'editor': pg.uid_override or user.getUserIdentification(request),
1199             'pagelink': pg.request.getQualifiedURL(pg.url(request)),
1200             'sitename': pg.cfg.sitename or request.getBaseURL(),
1201     }
1202 
1203     if comment:
1204         mailBody = mailBody + \
1205             _("The comment on the change is:\n%(comment)s\n\n", formatted=False) % {'comment': comment}
1206 
1207     # append comment text
1208     if comtext:
1209         mailBody = mailBody + "%s\n%s\n" % (("-" * 78), comtext)
1210     
1211     return mail.sendmail.sendmail(request, emails,
1212         _('[%(sitename)s] %(trivial)sUpdate of "%(pagename)s" by %(username)s', formatted=False) % {
1213             'trivial' : (trivial and _("Trivial ", formatted=False)) or "",
1214             'sitename': pg.cfg.sitename or "Wiki",
1215             'pagename': pg.page_name,
1216             'username': pg.uid_override or user.getUserIdentification(request),
1217         },
1218         mailBody, mail_from=pg.cfg.mail_from)
1219 
1220 
1221 
1222 def decodeURI(quotedstring):
1223 
1224     try:
1225         unquotedstring = wikiutil.url_unquote(quotedstring)
1226     except AttributeError:
1227         # for compatibility with old versions
1228         unquotedstring = url_unquote(quotedstring)
1229         
1230     return unquotedstring
1231 
1232 
1233 def url_unquote(s, want_unicode=True):
1234     """
1235     From moinmoin 1.5
1236     
1237     Wrapper around urllib.unquote doing the encoding/decoding as usually wanted:
1238     
1239     @param s: the string to unquote (can be str or unicode, if it is unicode,
1240               config.charset is used to encode it before calling urllib)
1241     @param want_unicode: for the less usual case that you want to get back
1242                          str and not unicode, set this to False.
1243                          Default is True.
1244     """
1245     import urllib
1246     
1247     if isinstance(s, unicode):
1248         s = s.encode(config.charset) # ascii would also work
1249     s = urllib.unquote(s)
1250     if want_unicode:
1251         s = s.decode(config.charset)
1252     return s
1253     
1254     
1255 def addLogEntry(request, action, pagename, msg):
1256     # Add an entry to the edit log on adding comments.
1257     from MoinMoin.logfile import editlog
1258     t = wikiutil.timestamp2version(time.time())
1259     msg = unicode(msg)
1260 
1261     pg = Page( request, pagename )
1262     #rev = pg.current_rev()
1263     rev = 99999999
1264 
1265     # TODO: for now we simply write 2 logs, maybe better use some multilog stuff
1266     # Write to global log
1267     log = editlog.EditLog(request)
1268     log.add(request, t, rev, action, pagename, request.remote_addr, '', msg)
1269 
1270     # Write to local log
1271     log = editlog.EditLog(request, rootpagename=pagename)
1272     log.add(request, t, rev, action, pagename, request.remote_addr, '', msg)
1273     
1274 def getsmileymarkuplist(defaulticon):
1275     
1276     html = [
1277         u'Smiley: <select name="comicon">',
1278         u'  <option value=""></option>',
1279         ]
1280     
1281     for smiley in config.smileys:
1282         if defaulticon.strip() == smiley:
1283             html.append(u'  <option selected>%s</option>' % wikiutil.escape(smiley))
1284         else:
1285             html.append(u'  <option>%s</option>' % wikiutil.escape(smiley))
1286 
1287     html.append(u'</select>')
1288     
1289     return u'\n'.join(html)
1290     
1291 def getsmileymarkupradio(defaulticon):
1292     
1293     smileys = Globs.smileys
1294     html = []
1295     
1296     for smiley in smileys:
1297         if defaulticon.strip() == smiley:
1298             html.append(u'<input type="radio" name="comicon" value="%s" checked>%s ' % (wikiutil.escape(smiley), getsmiley(smiley)) )
1299         else:
1300             html.append(u'<input type="radio" name="comicon" value="%s">%s ' % (wikiutil.escape(smiley), getsmiley(smiley)) )
1301 
1302     html.append(u'</select>')
1303     
1304     return u'\n'.join(html)
1305 
1306 
1307 def getMarkupText(lines):
1308     request = Globs.macro.request
1309     formatter = Globs.macro.formatter
1310     
1311     markup = Globs.markupforbidden
1312     
1313     for regex in markup.keys():
1314         pattern = re.compile(regex, re.UNICODE + re.VERBOSE + re.MULTILINE)
1315         lines, nchanges = pattern.subn(markup[regex], lines)
1316         
1317         #if nchanges:
1318         #    debug(regex)
1319         
1320     out = StringIO.StringIO()
1321     request.redirect(out)
1322     wikiizer = text_moin_wiki.Parser(lines, request)
1323     wikiizer.format(formatter)
1324     targettext = out.getvalue()
1325     request.redirect()
1326     del out
1327     
1328     return targettext    
1329     
1330     
1331 def nicepass(alpha=3,numeric=1):
1332     """
1333     returns a human-readble password (say rol86din instead of 
1334     a difficult to remember K8Yn9muL ) 
1335     """
1336     import string
1337     import random
1338     vowels = ['a','e','i','o','u']
1339     consonants = [a for a in string.ascii_lowercase if a not in vowels]
1340     digits = string.digits
1341     
1342     ####utility functions
1343     def a_part(slen):
1344         ret = ''
1345         for i in range(slen):			
1346             if i%2 ==0:
1347                 randid = random.randint(0,20) #number of consonants
1348                 ret += consonants[randid]
1349             else:
1350                 randid = random.randint(0,4) #number of vowels
1351                 ret += vowels[randid]
1352         return ret
1353     
1354     def n_part(slen):
1355         ret = ''
1356         for i in range(slen):
1357             randid = random.randint(0,9) #number of digits
1358             ret += digits[randid]
1359         return ret
1360         
1361     #### 	
1362     fpl = alpha/2		
1363     if alpha % 2 :
1364         fpl = int(alpha/2) + 1 					
1365     lpl = alpha - fpl	
1366     
1367     start = a_part(fpl)
1368     mid = n_part(numeric)
1369     end = a_part(lpl)
1370     
1371     # return "%s%s%s" % (start,mid,end)
1372     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.