Attachment 'PageComment2-099-rg.py'

Download

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

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