00001
00002 """
00003 PageComment2.py Version 0.98.1 April 25, 2006
00004
00005 This macro gives a form to post a new comment to the page and shows a list of the posted comments.
00006
00007 @copyright: 2005 by Seungik Lee <seungiklee<at>gmail.com> http://www.silee.net/
00008 @license: GPL
00009
00010 Usage: [[PageComment2]]
00011
00012 Features:
00013
00014 - Simple usage, just put [[PageComment2]] on any page.
00015 - Lets anonymous users post a new comment with an input form.
00016 - Shows a list of the posted comments.
00017 - Support for comment deletion by given password.
00018 - Support for administrative action, e.g.,
00019 - to delete a comment without entering a given password
00020
00021 Parameters:
00022
00023 - pagename: the page name which the comments are retrieved for. by default the page itself.
00024 If the user has no 'read' ACL for that page, it does not allow to insert/view comments.
00025 e.g., pagename=AnotherPage
00026
00027 - section: the section name of the page. The comments in different sections are managed in separated sub pages.
00028 Section name should be alphanumeric format ([a-zA-Z0-9] in regular expression).
00029 If not, all the non-alphanumric characters are removed.
00030 e.g., section=1, section=News, section=Opinion
00031
00032 - inputonly: shows input form only. list of the comments are shown to admin users only.
00033 - inputonly=0; default, all list is shown to all users including anonymous users
00034 - inputonly=1; shown to admin users only (who has the page delete privilege)
00035
00036 - commentonly: shows the list of comments only.
00037 - commentonly=0; default, both of the list and input form will be shown
00038 - commentonly=1; only the list of comments will be shown
00039
00040 - countonly: returns the number of the comments posted to this page
00041 - countonly=0; default, normal form (input form; list of comments)
00042 - countonly=1; just return the number of comments.
00043 e.g., 'There are [[PageComments(countonly=1)]] comments here'
00044
00045 - rows: the # of rows of the textarea. default 4. e.g., rows=4
00046
00047 - cols: the # of columns of the textarea. default 60. e.g., cols=60
00048
00049 - maxlength: limitation on # of characters for comment text. default 0 (no limit). e.g., maxlength=500
00050
00051 - newerfirst: order of the list of comments.
00052 - newerfirst=0: default, newer ones are listed at the end
00053 - newerfirst=1: newer ones are listed at the top
00054
00055 - commentfirst: shows comment list before the input form.
00056 - commentfirst=0: default, the input form first
00057 - commentfirst=1: comment list first
00058
00059 - articleview: shows comment list in an article view.
00060 - articleview=0: default, list in table view
00061 - articleview=1: list in article view
00062
00063 - tablewidth: the width of the table format for PageComment2, default '' (none).
00064 e.g., tablewidth=600, tablewidth=100%
00065
00066 - smileylist: shows smiley options with drop-down list box
00067 - smileylist=0: default, a part of the smiley in radio button
00068 - smileylist=1: smiley in drop-down list box
00069
00070 - nosmiley: shows no smiley
00071 - nosmiley=0: default, shows smiley selection
00072 - nosmiley=1: no smiley selection
00073
00074 - notify: notifies to the subscribers of the page which includes the macro when a comment is added
00075 - notify=0: default, notification disabled
00076 - notify=1: notification enabled
00077
00078 - encryptpass: encrypts entered password
00079 - encryptpass=0: default, the password is stored in plain text
00080 - encryptpass=1: the password is stored in encrypted format
00081
00082 - markup: enables wiki markup in the comment text except some specified macros.
00083 - markup=0: default, use of wiki markup in the text is disabled
00084 - markup=1: use of wiki markup in the text is enabled and preview button is activated
00085
00086 Change Log
00087
00088 - April 17, 2006 - Version 0.98
00089 - fixed a bug on revision history
00090 - added a despam action
00091
00092 - Jan. 05, 2006 - Version 0.97
00093 - added features:
00094 - mail notification
00095 - password encryption
00096 - wiki markup support with preview
00097 - remember author name last used
00098 - administrative actions (delete without password) are allowed to those who has WRITE acl.
00099
00100 - Nov. 29, 2005 - Version 0.96
00101 - some format parameters are added
00102 - random password feature is added
00103
00104 - Nov. 20, 2005 - Version 0.95
00105 - some minor bugs are fixed
00106
00107 - Nov. 20, 2005 - Version 0.94
00108 - some parameters are added
00109 - some minor bugs are fixed
00110
00111 - Nov. 19, 2005 - Version 0.92
00112 - some minor bugs are fixed
00113 - 'olderfirst' parameter replaced with 'newerfirst'
00114
00115 - Nov. 19, 2005 - Version 0.91
00116 - some parameters are added
00117 - validates smiley markup
00118 - modified view
00119
00120 - Nov. 18, 2005 - Version 0.90 (Release 2)
00121 - No text data file support any more: Comment is stored in the sub wiki page.
00122 - (does not compatible with Release 1: PageComment.py)
00123 - Custom icon (smiley) can be inserted
00124 - Pre-fill the name input field with his/her login name
00125 - Logs at add/remove comments
00126 - Added some parameters
00127
00128 - Oct. 08, 2005 - Version 0.82
00129 - Changed the directory the data file stored to be secured
00130
00131 - Oct. 07, 2005 - Version 0.81
00132 - Unicode encoding related bugs in deletecomment function are patched.
00133 - Instruction bugs are patched.
00134
00135 - Oct. 06, 2005 - Version 0.80
00136 - The initial version is released.
00137
00138
00139 Notes
00140
00141 - 'Gallery.py' developed by Simon Ryan has inspired this macro.
00142 - Thanks to many of the MoinMoin users for valuable comments.
00143 - Visit http://moinmoin.wikiwikiweb.de/MacroMarket/PageComment2 for more detail
00144
00145 """
00146
00147 from MoinMoin import config, wikiutil
00148 import StringIO, time, re
00149 from MoinMoin.Page import Page
00150 from MoinMoin.PageEditor import PageEditor
00151
00152
00153
00154 class Globs:
00155
00156
00157 adminmsg = ''
00158 datapagename = ''
00159 pagename = ''
00160 curpagename = ''
00161 cursubname = ''
00162 admin = ''
00163 macro = ''
00164 defaultacl = ''
00165 defaulticon = ''
00166 formid = 0
00167 smileys = []
00168
00169 class Params:
00170
00171 rows = 0
00172 cols = 0
00173 maxlength = 0
00174 newerfirst = 0
00175 tablewidth = ''
00176 commentfirst = 0
00177 pagename = ''
00178 commentonly = 0
00179 inputonly = 0
00180 countonly = 0
00181 section = ''
00182 articleview = 0
00183 notify = 0
00184 encryptpass = 0
00185 markup = 0
00186
00187
00188 def execute(macro, args):
00189
00190
00191 getparams(args)
00192 setglobalvalues(macro)
00193
00194
00195 request = macro.request
00196 _ = request.getText
00197
00198 if not Globs.pagename == Globs.curpagename:
00199 if not macro.request.user.may.read(Globs.pagename):
00200 return macro.formatter.rawHTML(u'PageComment: %s' % _('You are not allowed to view this page.'))
00201 elif not Page(request, Globs.pagename).exists():
00202 return macro.formatter.rawHTML(u'PageComment: %s' % _('This page is already deleted or was never created!'))
00203
00204
00205 if Params.countonly:
00206 html = len(fetchcomments())
00207 return macro.formatter.rawHTML('%s' % html)
00208
00209 datapagename = Globs.datapagename
00210
00211
00212 comicon = Globs.defaulticon
00213 comauthor = ''
00214 comtext = ''
00215 rating = ''
00216 compasswd = ''
00217 comrev = 0
00218 comautopass = ''
00219 commentpreview = ''
00220 commarkup = ''
00221
00222 addcommand = u'addcomment%d' % Globs.formid
00223 delcommand = u'delcomment%d' % Globs.formid
00224
00225 action = macro.form.get('commentaction', [''])[0]
00226
00227 if action == addcommand:
00228
00229
00230 form_fields = {'comicon': Globs.defaulticon, 'comauthor': '', 'comtext': '', 'compasswd': '', 'rating': '', 'comrev': 0, 'autopasswd': '', 'button_save': '', 'button_preview': '', 'commarkup%d' % Globs.formid: '0'}
00231 required_fields = {'comauthor': _('Name'), 'comtext': _('Text'), 'rating': _('Text'), 'compasswd': _('Password'), 'comrev': 'Rev. #'}
00232
00233 formvals, missingfields = getforminput(macro.form, form_fields, required_fields)
00234
00235 comicon = formvals['comicon']
00236 comauthor = formvals['comauthor']
00237 comtext = formvals['comtext']
00238 rating = formvals['rating']
00239 compasswd = formvals['compasswd']
00240 comrev = int(formvals['comrev'])
00241 comautopass = formvals['autopasswd']
00242 btnsave = formvals['button_save']
00243 btnpreview = formvals['button_preview']
00244 commarkup = formvals['commarkup%d' % Globs.formid]
00245
00246 if not len(missingfields) == len(required_fields):
00247 if not missingfields:
00248
00249
00250 if comicon and (not comicon in config.smileys.keys()):
00251 message('Please use smiley markup only')
00252
00253 elif Params.maxlength and (len(comtext) > Params.maxlength):
00254 message('Comment text is limited to %d characters. (%d characters now)' % (Params.maxlength, len(comtext)) )
00255
00256 elif not comtext.strip() or comtext == u'Add your comment':
00257 message('Please fill the comment text')
00258
00259
00260 elif btnpreview:
00261 commentpreview = previewcomment(comicon, comauthor, comtext, commarkup, rating)
00262
00263
00264 elif btnsave:
00265 flag = addcomment(macro, comicon, comauthor, comtext, compasswd, comrev, comautopass, commarkup, rating)
00266
00267 if flag:
00268 comicon = Globs.defaulticon
00269 comauthor = ''
00270 comtext = ''
00271 rating = ''
00272 compasswd = ''
00273 comrev = 0
00274 commentpreview = ''
00275 commarkup = ''
00276
00277
00278 else:
00279 message( 'What do you want?' )
00280
00281 else:
00282 message( _('Required attribute "%(attrname)s" missing') % { 'attrname': u', '.join(missingfields) } )
00283
00284 elif action == delcommand:
00285
00286
00287 form_fields = {'delkey': '', 'delpasswd': ''}
00288 required_fields = {'delkey': 'Comment Key', 'delpasswd': 'Password'}
00289
00290 formvals, missingfields = getforminput(macro.form, form_fields, required_fields)
00291
00292 delkey = formvals['delkey']
00293 delpasswd = formvals['delpasswd']
00294
00295 if not len(missingfields) == len(required_fields):
00296 if not missingfields:
00297 deletecomment(macro, delkey, delpasswd)
00298 else:
00299 message( _('Required attribute "%(attrname)s" missing') % { 'attrname': u', '.join(missingfields) } )
00300
00301
00302 html = []
00303
00304 html.append(u'<div id="pagecomment">')
00305 html.append(u'<a name="pagecomment%d"></a>' % Globs.formid)
00306
00307 html.append(u'<table border="0" class="pagecomment" %s>' % Params.tablewidth)
00308
00309 if Globs.adminmsg:
00310 html.append(u'<tr><td colspan="5" style="border-width: 0px;">')
00311 html.append(u'<font color="#aa0000">%s</font>' % Globs.adminmsg)
00312 html.append(u'</td></tr>')
00313
00314 commentlisthtml = showcommentsection()
00315 commentformhtml = commentformsection(comauthor, comtext, compasswd, comicon, comrev, comautopass, commarkup, rating)
00316
00317 if Params.commentfirst:
00318 if commentpreview:
00319 html.append(commentpreview)
00320
00321 html.append(commentlisthtml)
00322 html.append(u'<tr><td colspan="5" class="commentblankline" style="border-width: 0px; height: 20px;"></td></tr>')
00323 html.append(commentformhtml)
00324 else:
00325 html.append(commentformhtml)
00326 html.append(u'<tr><td colspan="5" class="commentblankline" style="border-width: 0px; height: 20px;"></td></tr>')
00327 if commentpreview:
00328 html.append(commentpreview)
00329
00330 html.append(commentlisthtml)
00331
00332 if Globs.debugmsg:
00333 html.append(u'<tr><td colspan="5" style="border-width: 0px;">')
00334 html.append(u'<font color="#aa0000">%s</font>' % Globs.debugmsg)
00335 html.append(u'</td></tr>')
00336
00337 html.append(u'</table>')
00338
00339 if Globs.customscript:
00340 html.append(u'%s' % Globs.customscript)
00341
00342 html.append(u'</div>')
00343
00344 return macro.formatter.rawHTML(u'\n'.join(html))
00345
00346
00347 def commentformsection(comauthor, comtext, compasswd, comicon, comrev, autopass, commarkup, rating):
00348 html = []
00349
00350 if not Params.commentonly:
00351 html.append(u'<tr><td style="border-width: 1px; margin: 10px 0 10px 0;" colspan="5">')
00352
00353 html.append(commentform(comauthor, comtext, compasswd, comicon, comrev, autopass, commarkup, rating))
00354
00355 html.append(u'</td></tr>')
00356
00357 return u'\n'.join(html)
00358
00359
00360 def showcommentsection():
00361 html = []
00362 if (not Params.inputonly) or Globs.admin:
00363 html.append(deleteform())
00364 html.append(showcomment())
00365 else:
00366 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>')
00367
00368 return u'\n'.join(html)
00369
00370 def getforminput(form, inputfields, requiredfields):
00371
00372 formvals = {}
00373 missingfields = []
00374
00375 for item in inputfields.keys():
00376 formvals[item] = form.get(item, [inputfields[item]])[0]
00377 if (not formvals[item]) and (item in requiredfields):
00378 missingfields.append(requiredfields[item])
00379
00380 return formvals, missingfields
00381
00382 def getparams(args):
00383
00384
00385 params = {}
00386 if args:
00387
00388 sargs = args.split(',')
00389
00390 for item in sargs:
00391 sitem = item.split('=')
00392
00393 if len(sitem) == 2:
00394 key, value = sitem[0], sitem[1]
00395 params[key.strip()] = value.strip()
00396
00397 Params.pagename = params.get('pagename', '')
00398
00399 Params.section = params.get('section', '')
00400 if Params.section:
00401 Params.section = getescapedsectionname(Params.section)
00402
00403 try:
00404 Params.inputonly = int(params.get('inputonly', 0))
00405 except ValueError:
00406 Params.inputonly = 0
00407
00408 try:
00409 Params.commentonly = int(params.get('commentonly', 0))
00410 except ValueError:
00411 Params.commentonly = 0
00412
00413 try:
00414 Params.countonly = int(params.get('countonly', 0))
00415 except ValueError:
00416 Params.countonly = 0
00417
00418 try:
00419 Params.newerfirst = int(params.get('newerfirst', 0))
00420 except ValueError:
00421 Params.newerfirst = 0
00422
00423 try:
00424 Params.commentfirst = int(params.get('commentfirst', 1))
00425 except ValueError:
00426 Params.commentfirst = 1
00427
00428 try:
00429 Params.articleview = int(params.get('articleview', 0))
00430 except ValueError:
00431 Params.articleview = 0
00432
00433 try:
00434 Params.smileylist = int(params.get('smileylist', 0))
00435 except ValueError:
00436 Params.smileylist = 0
00437
00438 try:
00439 Params.nosmiley = int(params.get('nosmiley', 1))
00440 except ValueError:
00441 Params.nosmiley = 1
00442
00443 try:
00444 Params.rows = int(params.get('rows', 8))
00445 except ValueError:
00446 Params.rows = 8
00447
00448 try:
00449 Params.cols = int(params.get('cols', 80))
00450 except ValueError:
00451 Params.cols = 80
00452
00453 try:
00454 Params.maxlength = int(params.get('maxlength', 0))
00455 except ValueError:
00456 Params.maxlength = 0
00457
00458 try:
00459 Params.notify = int(params.get('notify', 0))
00460 except ValueError:
00461 Params.notify = 0
00462
00463 try:
00464 Params.encryptpass = int(params.get('encryptpass', 0))
00465 except ValueError:
00466 Params.encryptpass = 0
00467
00468 try:
00469 Params.markup = int(params.get('markup', 0))
00470 except ValueError:
00471 Params.markup = 0
00472
00473 Params.tablewidth = params.get('tablewidth', '')
00474 if Params.tablewidth:
00475 Params.tablewidth = ' width="%s" ' % Params.tablewidth
00476
00477 def setglobalvalues(macro):
00478
00479
00480 Globs.macro = macro
00481 Globs.defaultacl = u'#acl All:'
00482 Globs.adminmsg = ''
00483 Globs.debugmsg = ''
00484 Globs.customscript = ''
00485 Globs.defaulticon = ''
00486 request = macro.request
00487
00488
00489 Globs.smileys = [':)', ':))', ':(', ';)', ':\\', '|)', 'X-(', 'B)']
00490
00491 if Params.markup:
00492
00493
00494 Globs.macroallowed = [ 'BR', 'Date', 'DateTime', 'MailTo', 'Icon' ]
00495
00496 from MoinMoin import wikimacro
00497 macronames = wikimacro.getNames(request.cfg)
00498
00499 for names in Globs.macroallowed:
00500 macronames.remove(names)
00501
00502
00503 Globs.markupforbidden = {
00504
00505
00506 ur'(?P<macro>\[\[(%(macronames)s)(?:\(.*?\))?\]\])' % { 'macronames': u'|'.join(macronames) } : r'`\1`'
00507 }
00508
00509 Globs.curpagename = macro.formatter.page.page_name
00510
00511 if Params.pagename:
00512 Globs.pagename = Params.pagename
00513 else:
00514 Globs.pagename = Globs.curpagename
00515
00516 Globs.cursubname = Globs.curpagename.split('/')[-1]
00517 Globs.datapagename = u'%s/%s%s' % (Globs.pagename, 'PageCommentData', Params.section)
00518
00519 try:
00520 if request.user.may.delete(Globs.pagename):
00521
00522 Globs.admin = 'true'
00523 else:
00524 Globs.admin = ''
00525 except AttributeError:
00526 Globs.admin = ''
00527 pass
00528
00529
00530
00531 if not hasattr(request, 'pgformid'):
00532 request.pgformid = 0
00533
00534 request.pgformid += 1
00535 Globs.formid = request.pgformid
00536
00537
00538 def message(astring):
00539 Globs.adminmsg = u'PageComment: %s\n' % astring
00540
00541 def debug(astring):
00542 Globs.debugmsg += u'%s\n<br>' % astring
00543
00544
00545 def commentform(tmpauthor, tmptext, tmppasswd, tmpicon, comrev, tmpautopass, tmpmarkup, rating):
00546
00547 request = Globs.macro.request
00548 datapagename = Globs.datapagename
00549 _ = request.getText
00550
00551 cellstyle = u'border-width: 0px; vertical-align: middle; font-size: 0.9em;'
00552
00553 pg = Page( request, datapagename )
00554
00555 if pg.exists():
00556 comrev = pg.current_rev()
00557 else:
00558 comrev = 0
00559
00560 if not Params.nosmiley:
00561 if not Params.smileylist:
00562 iconlist = getsmileymarkupradio(tmpicon)
00563 else:
00564 iconlist = getsmileymarkuplist(tmpicon)
00565 else:
00566 iconlist = ''
00567
00568 initName = ''
00569 initPass = ''
00570 initText = ''
00571
00572 if not (request.user.valid or tmpauthor):
00573
00574 tmpauthor = getAuthorFromCookie()
00575
00576 if not tmpauthor:
00577
00578 import socket
00579 host = request.remote_addr
00580
00581 try:
00582 hostname = socket.gethostbyaddr(host)[0]
00583 except socket.error:
00584 hostname = host
00585
00586 tmpauthor = hostname.split('.')[0]
00587
00588 initName = tmpauthor
00589
00590 if not tmppasswd:
00591 tmppasswd = nicepass()
00592 initPass = tmppasswd
00593 elif tmpautopass and tmpautopass == tmppasswd:
00594 tmppasswd = nicepass()
00595 initPass = tmppasswd
00596
00597 if not tmptext:
00598 tmptext = u'Add your comment'
00599 initText = tmptext
00600 elif tmptext and tmptext == u'Add your comment':
00601 initText = tmptext
00602
00603 previewbutton = ''
00604 markupcheckbox = ''
00605
00606 if Params.markup:
00607 if not (tmpmarkup == '0'):
00608 markupchecked = "checked"
00609 else:
00610 markupchecked = ''
00611
00612 previewbutton = '<br><input type="submit" name="button_preview" value="%s" style="color: #ff7777; font-size: 9pt; width: 6em; ">' % _('Preview')
00613 markupcheckbox = '<input type="checkbox" name="commarkup%d" value="1" %s> Markup' % (Globs.formid, markupchecked)
00614
00615
00616 if request.user.valid:
00617 html1 = [
00618 u'<input type="hidden" value="%s" name="comauthor">' % request.user.name,
00619 u'<input type="hidden" value="*" name="compasswd">',
00620 ]
00621 authorJavascriptCode = ''
00622 onSubmitCode = ''
00623 else:
00624 html1 = [
00625 u'Username: <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) },
00626 u'Password: <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) },
00627 u'<input type="hidden" value="%s" name="autopasswd">' % wikiutil.escape(initPass),
00628 ]
00629
00630 authorJavascriptCode = """
00631 <script language="javascript">
00632 <!--
00633 function setCookie(name, value) {
00634 var today = new Date();
00635 var expire = new Date(today.getTime() + 60*60*24*365*1000);
00636 document.cookie = name + "=" + encodeURIComponent(value) + "; expires=" + expire.toGMTString() + "; path=%s";
00637 }
00638 function validateForm() {
00639 if (document.getElementById('comment').checked && document.getElementById('comment').value == '') {
00640 alert("You must select a rating.");
00641 return false;
00642 }
00643 return true;
00644 }
00645 //-->
00646 </script>""" % request.getScriptname()
00647
00648 onSubmitCode = 'onSubmit="setCookie(\'PG2AUTHOR\', this.comauthor.value);"'
00649
00650 validateJavascriptCode = """
00651 <script language='javascript'>
00652 <!--
00653 function validateForm() {
00654 rating = document.getElementById('rating');
00655 if (rating.selectedIndex == 0) {
00656 alert('You must select a rating.');
00657 return false;
00658 }
00659 return true;
00660 }
00661 //-->
00662 </script>"""
00663
00664 html1 = u'\n'.join(html1)
00665 scripthtml = u'onfocus="if (this.value==\'%(msg)s\') {this.value=\'\';};" onblur="if (this.value==\'\') {this.value=\'%(msg)s\';};"' % {'msg': wikiutil.escape(initText) }
00666
00667 page_url = wikiutil.quoteWikinameURL(Globs.cursubname)
00668
00669 html2 = [
00670 u'%s' % validateJavascriptCode,
00671 u'%s' % authorJavascriptCode,
00672 u'<form action="%s#pagecomment%d" id="comment" name="comment" METHOD="POST" %s onsubmit="return validateForm();">' % (page_url, Globs.formid, onSubmitCode),
00673 u'<table class="addcommentform">',
00674 u'<tr>',
00675 u'<td style="%s">Rating: <select id="rating" name="rating"><option value="">Please choose a rating...<option value=1.0>1.0 - Completely useless!<option value=2.0>2.0 - Not very useful.<option value=2.5>2.5 - Neutral.<option value=3.0>3.0 - Useful.<option value=4.0>4.0 - Definately useful!<option value="Comment">Additional comments<option value="helpful">Helpful but not what I was looking for.</option></select> ' % (cellstyle, ),
00676 u'</tr>',
00677 u'<tr>',
00678 u'<td style="%s"><textarea name="comtext" rows="%d" cols="%d" style="font-size: 9pt;" ' % (cellstyle, Params.rows, Params.cols),
00679 u'%s>%s</textarea></td></tr>' % (scripthtml, wikiutil.escape(tmptext)),
00680 u'<tr><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),
00681 u'</tr>',
00682 u'<tr><td style="%s">' % cellstyle,
00683 u'%s' % html1,
00684 u'%s' % iconlist,
00685 u'</td>',
00686 u'<td style="%s text-align: right; font-size: 9pt;">%s</td>' % (cellstyle, markupcheckbox),
00687 u'</tr>',
00688 u'</table>',
00689 u'<input type="hidden" name="action" value="show" >',
00690 u'<input type="hidden" name="comrev" value="%s">' % comrev,
00691 u'<input type="hidden" name="commentaction" value="addcomment%d">' % Globs.formid,
00692 u'</form>',
00693 ]
00694
00695
00696 return u'\n'.join(html2)
00697
00698 def addcomment(macro, comicon, comauthor, comtext, compasswd, comrev, comautopass, commarkup, rating):
00699
00700
00701 request = Globs.macro.request
00702 cfg = request.cfg
00703 _ = request.getText
00704
00705 datapagename = Globs.datapagename
00706
00707 pg = PageEditor( request, datapagename )
00708 pagetext = pg.get_raw_body()
00709
00710
00711 try:
00712 if not request.user.may.save( pg, comtext, pg.current_rev()):
00713
00714
00715 pass
00716
00717 except pg.SaveError, msg:
00718 message(msg)
00719 return 0
00720
00721 comtext = convertdelimeter(comtext)
00722
00723 if request.user.valid:
00724 comloginuser = 'TRUE'
00725 comauthor = request.user.name
00726 else:
00727 comloginuser = ''
00728 comauthor = convertdelimeter(comauthor)
00729
00730 orgcompasswd = compasswd
00731
00732 if Params.encryptpass:
00733 from MoinMoin import user
00734 compasswd = user.encodePassword(compasswd)
00735
00736 newcomment = [
00737 u'{{{',
00738 u'%s,%s' % (comicon, commarkup),
00739 u'%s' % comauthor,
00740 u'%s' % time.time(),
00741 u'%s' % rating,
00742 u'',
00743 u'%s' % comtext,
00744 u'}}}',
00745 u'##PASSWORD %s' % compasswd,
00746 u'##LOGINUSER %s' % comloginuser,
00747 ]
00748
00749 newpagetext = u'%s\n\n%s' % (pagetext, u'\n'.join(newcomment))
00750
00751 if not pg.exists():
00752 action = 'SAVENEW'
00753 defaultacl = Globs.defaultacl
00754 warnmessages = '\'\'\'\'\'DO NOT EDIT THIS PAGE!!\'\'\' This page is automatically generated by Page``Comment macro.\'\'\n----'
00755 newpagetext = u'%s\n%s\n%s' % (defaultacl, warnmessages, newpagetext)
00756 else:
00757 action = 'SAVE'
00758
00759 newpagetext = pg.normalizeText( newpagetext )
00760
00761 comment = u'PageComment modification at %s' % Globs.curpagename
00762 pg._write_file(newpagetext, action, comment)
00763
00764 comment = u'New comment by "%s"' % comauthor
00765
00766 trivial = 0
00767
00768
00769
00770 msg = _('The comment is added.')
00771
00772
00773 if Params.notify:
00774 msg = msg + commentNotify(comment, trivial, comtext)
00775
00776 if comautopass and comautopass == orgcompasswd:
00777 msg2 = u'<i>You did not enter a password. A random password has been generated for you: <b>%s</b></i>' % comautopass
00778 msg = u'%s%s' % (msg, msg2)
00779
00780 message(msg)
00781 return 1
00782
00783
00784 def previewcomment(comicon, comauthor, comtext, commarkup, rating):
00785 request = Globs.macro.request
00786 _ = request.getText
00787 cfg = request.cfg
00788
00789
00790 lines = comtext.splitlines()
00791 if not lines[-1] == u'':
00792
00793 lines.append(u'')
00794
00795 comtext = u'\n'.join(lines)
00796
00797
00798
00799
00800 if Params.articleview:
00801 cellstyle = u'border-width: 1px; border-bottom-width: 0px; border-color: #ff7777; background-color: #eeeeee; vertical-align: top; font-size: 9pt;'
00802 htmlcomment = [
00803 u'<tr><td colspan="5" class="commenttext" style="%(cellstyle)s">%(text)s</td></tr>',
00804 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>',
00805 u'<tr><td colspan="5" class="commentblankline" style="border-width: 0px; height: 20px;"></td></tr>',
00806 ]
00807
00808 else:
00809 cellstyle = u'border-width: 0px; background-color: #ffeeee; border-top-width: 1px; vertical-align: top; font-size: 9pt;'
00810 htmlcomment = [
00811 u'<tr><td class="commenticon" style="%(cellstyle)s">%(icon)s</td>',
00812 u'<td class="commentauthor" style="%(cellstyle)s">%(author)s</td>',
00813 u'<td style="%(cellstyle)s width: 10px;"> </td>',
00814 u'<td class="commenttext" style="%(cellstyle)s">%(text)s</td>',
00815 u'<td class="commentdate" style="%(cellstyle)s text-align: right; font-size: 8pt; " nowrap>%(date)s%(delform)s</td></tr>',
00816 ]
00817
00818
00819 date = time.time()
00820
00821 htmlcommentitem = u'\n'.join(htmlcomment) % {
00822 'cellstyle': cellstyle,
00823 'icon': getsmiley(comicon),
00824 'author': converttext(comauthor),
00825 'text': converttext(comtext, commarkup),
00826 'rating': converttext(comtext, rating),
00827 'date': date,
00828 'delform': ''
00829 }
00830
00831 return htmlcommentitem
00832
00833 def showcomment():
00834
00835 request = Globs.macro.request
00836 _ = request.getText
00837
00838 from MoinMoin import user
00839
00840 commentlist = fetchcomments()
00841 showCommentsFlag = False
00842 showCommentsFlag = True
00843
00844 for item in commentlist:
00845 if item['name'] == user.getUserIdentification(request):
00846 showCommentsFlag = True
00847
00848 if Params.newerfirst:
00849 commentlist.reverse()
00850
00851 html = []
00852 cur_index = 0
00853
00854 if Params.articleview:
00855 cellstyle = u'border-width: 0px; background-color: #eeeeee; vertical-align: top; font-size: 9pt;'
00856 htmlcomment = [
00857 u'<tr><td colspan="5" class="commenttext" style="%(cellstyle)s">%(text)s</td></tr>',
00858 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>',
00859 u'<tr><td colspan="5" class="commentblankline" style="border-width: 0px; height: 20px;"></td></tr>',
00860 ]
00861
00862 else:
00863 cellstyle = u'border-width: 0px; border-top-width: 1px; vertical-align: top; font-size: 9pt;'
00864 htmlcomment = [
00865 u'<tr><td class="commenticon" style="%(cellstyle)s">%(icon)s</td>',
00866 u'<td class="commentauthor" style="%(cellstyle)s">%(author)s</td>',
00867 u'<td style="%(cellstyle)s width: 10px;"> </td>',
00868 u'<td class="commenttext" style="%(cellstyle)s">%(rating)s</td>',
00869 u'<td class="commenttext" style="%(cellstyle)s">%(text)s</td>',
00870 u'<td class="commentdate" style="%(cellstyle)s text-align: right; font-size: 8pt; " nowrap>%(date)s%(delform)s</td></tr>',
00871 ]
00872
00873 htmlcommentdel_admin = [
00874 u' <font style="font-size: 8pt;">',
00875 u'<a style="color: #aa0000;" href="javascript: requesttodeleteadmin%(formid)d(document.delform%(formid)d, \'%(key)s\');" title="%(msg)s">X</a>',
00876 u'</font>',
00877 ]
00878 htmlcommentdel_guest = [
00879 u' <font style="font-size: 8pt;">',
00880 u'<a style="color: #aa0000;" href="javascript: requesttodelete%(formid)d(document.delform%(formid)d, \'%(key)s\');" title="%(msg)s">X</a>',
00881 u'</font>',
00882 ]
00883
00884 for item in commentlist:
00885
00886 if Globs.admin:
00887 htmlcommentdel = htmlcommentdel_admin
00888 elif item['loginuser']:
00889 htmlcommentdel = ''
00890 else:
00891 htmlcommentdel = ''
00892
00893
00894 if htmlcommentdel:
00895 htmlcommentdel = u'\n'.join(htmlcommentdel) % {
00896 'formid': Globs.formid,
00897 'key': item['key'],
00898 'msg': _('Delete')
00899 }
00900
00901 rating = converttext(item['rating'])
00902 text = converttext(item['text'], item['markup'])
00903 if not showCommentsFlag:
00904 text = "<div id=commentp_%(key)s onclick='javascript:document.getElementById(\"comment_%(key)s\").style.display=\"inline\";javascript:document.getElementById(\"commentr_%(key)s\").style.display=\"inline\";document.getElementById(\"commentp_%(key)s\").style.display=\"none\";'><nobr><font color=green>comment suppressed</font> Click here to show</nobr></div><div id=comment_%(key)s style='display:none'>%(text)s</div>" % {'text' : text, 'key' : item['key']}
00905 rating = "<div id=commentr_%(key)s style='display:none'>%(rating)s</div>" % {'rating' : rating, 'key' : item['key']}
00906
00907
00908 htmlcommentitem = u'\n'.join(htmlcomment) % {
00909 'cellstyle': cellstyle,
00910 'icon': getsmiley(item['icon']),
00911 'author': converttext(item['name']),
00912 'rating': rating,
00913 'text': text,
00914 'date': item['date'],
00915 'delform': htmlcommentdel
00916 }
00917
00918 html.append(htmlcommentitem)
00919
00920 return u'\n'.join(html)
00921
00922 def getescapedsectionname(targettext):
00923 regex = r'\W'
00924 pattern = re.compile(regex, re.UNICODE)
00925 sectionname = pattern.sub('', targettext)
00926
00927 return sectionname
00928
00929
00930 def getsmiley(markup):
00931 return ''
00932
00933
00934 def converttext(targettext, markup='0'):
00935
00936
00937
00938 if Params.markup and markup == '1':
00939 targettext = getMarkupText(targettext)
00940 else:
00941
00942 targettext = targettext.replace(u'&', '&')
00943 targettext = targettext.replace(u'>', '>')
00944 targettext = targettext.replace(u'<', '<')
00945 targettext = targettext.replace(u'\n', '<br>')
00946 targettext = targettext.replace(u'"', '"')
00947 targettext = targettext.replace(u'\t', ' ')
00948 targettext = targettext.replace(u' ', ' ')
00949
00950 return targettext
00951
00952 def convertdelimeter(targettext, reverse=0):
00953
00954
00955 if reverse:
00956 targettext = targettext.replace(u'{_{_{', u'{{{')
00957 targettext = targettext.replace(u'}_}_}', u'}}}')
00958
00959 else:
00960 targettext = targettext.replace(u'{{{', u'{_{_{')
00961 targettext = targettext.replace(u'}}}', u'}_}_}')
00962
00963 return targettext
00964
00965
00966 def deleteform():
00967
00968
00969 request = Globs.macro.request
00970 _ = request.getText
00971
00972 htmlresult = []
00973
00974 html = [
00975 '<script language="javascript">',
00976 '<!--',
00977 ]
00978 htmlresult.append(u'\n'.join(html))
00979
00980 html = [
00981 ' function requesttodeleteadmin%d(delform, comkey) {' % Globs.formid,
00982 ' if (confirm("%s")) {;' % _('Really delete this comment?'),
00983 ' delform.delkey.value = comkey;',
00984 ' delform.delpasswd.value = "****";',
00985 ' delform.submit();',
00986 ' }',
00987 ' }',
00988 ' function requesttodelete%d(delform, comkey) {' % Globs.formid,
00989 ' var passwd = prompt("%s:", "");' % _('Please specify a password!'),
00990 ' if(!(passwd == "" || passwd == null)) {',
00991 ' delform.delkey.value = comkey;',
00992 ' delform.delpasswd.value = passwd;',
00993 ' delform.submit();',
00994 ' }',
00995 ' }',
00996 ]
00997
00998 htmlresult.append(u'\n'.join(html))
00999
01000 page_url = wikiutil.quoteWikinameURL(Globs.cursubname)
01001
01002 html = [
01003 '//-->',
01004 '</script>',
01005 '<form name="delform%d" action="%s#pagecomment%d" METHOD="post">' % (Globs.formid, page_url, Globs.formid),
01006 '<input type="hidden" value="show" name="action">',
01007 '<input name="delpasswd" type="hidden" value="****">',
01008 '<input name="delkey" type="hidden" value="">',
01009 '<input type="hidden" name="commentaction" value="delcomment%s">' % Globs.formid,
01010 '</form>',
01011 ]
01012 htmlresult.append(u'\n'.join(html))
01013
01014 return u'\n'.join(htmlresult)
01015
01016
01017 def filtercomment(index='', name='', passwd=''):
01018
01019
01020 if index:
01021 filteredlist1 = fetchcomments(index, index)
01022 else:
01023 filteredlist1 = fetchcomments()
01024
01025
01026 filteredlist2 = []
01027 if name:
01028 for item in filteredlist1:
01029 if name == item['name']:
01030 filteredlist2.append(item)
01031 else:
01032 filteredlist2 = filteredlist1
01033
01034
01035 filteredlist3 = []
01036 if passwd:
01037 for item in filteredlist2:
01038 if passwd == item['passwd']:
01039 filteredlist3.append(item)
01040 else:
01041 filteredlist3 = filteredlist2
01042
01043 return filteredlist3
01044
01045
01046 def fetchcomments(startindex=1, endindex=9999):
01047
01048 commentlist = []
01049
01050 request = Globs.macro.request
01051 formatter = Globs.macro.formatter
01052 datapagename = Globs.datapagename
01053
01054 pg = Page( request, datapagename )
01055 pagetext = pg.get_raw_body()
01056
01057 regex = ur"""
01058 ^[\{]{3}\n
01059 ^(?P<icon>[^\n]*)\n
01060 ^(?P<name>[^\n]*)\n
01061 ^(?P<date>[^\n]*)\n
01062 ^(?P<rating>[^\n]*)\n\n
01063 ^(?P<text>
01064 \s*.*?
01065 (?=[\}]{3})
01066 )[\}]{3}[\n]*
01067 ^[#]{2}PASSWORD[ ](?P<passwd>[^\n]*)[\n]*
01068 ^[#]{2}LOGINUSER[ ](?P<loginuser>[^\n]*)[\n]*"""
01069
01070 pattern = re.compile(regex, re.UNICODE + re.MULTILINE + re.VERBOSE + re.DOTALL)
01071 commentitems = pattern.findall(pagetext)
01072
01073 cur_index = 0
01074
01075
01076 for item in commentitems:
01077 comment = {}
01078 cur_index += 1
01079
01080 if cur_index < startindex:
01081 continue
01082
01083 comment['index'] = cur_index
01084
01085 custom_fields = item[0].split(',')
01086
01087 comment['icon'] = custom_fields[0]
01088
01089 if len(custom_fields) > 1:
01090 comment['markup'] = custom_fields[1].strip()
01091 else:
01092 comment['markup'] = ''
01093
01094 now = time.time()
01095 t = float(item[2])
01096 date = time.strftime(request.cfg.datetime_fmt, time.localtime(t))
01097
01098 dt = now-t
01099 datestr = ""
01100
01101 years = int(dt / (86400*365))
01102 months = int(dt / (86400*30))
01103 days = int(dt / 86400)
01104 hours = int(dt / 3600)
01105 minutes = int(dt / 60)
01106
01107 if years > 1: datestr = " (%d years ago)" % years
01108 if years == 1: datestr = " (%d year ago)" % years
01109 elif months > 1: datestr = " (%d months ago)" % months
01110 elif days > 1: datestr = " (%d days ago)" % days
01111 elif days == 1: datestr = " (%d day ago)" % days
01112 elif hours > 1: datestr = " (%d hours ago)" % hours
01113 elif hours == 1: datestr = " (%d hour ago)" % hours
01114 elif minutes > 1: datestr = " (%d minutes ago)" % minutes
01115 elif minutes == 1: datestr = " (%d minute ago)" % minutes
01116 else:
01117 datestr = " (%d seconds ago)" % int(dt)
01118
01119 comment['name'] = convertdelimeter(item[1], 1)
01120 comment['date'] = date + datestr
01121 comment['rating'] = convertdelimeter(item[3], 1)
01122 comment['text'] = convertdelimeter(item[4], 1)
01123 comment['passwd'] = item[5]
01124 comment['loginuser'] = item[6]
01125
01126
01127 comment['key'] = item[2]
01128
01129 commentlist.append(comment)
01130
01131 if cur_index >= endindex:
01132 break
01133
01134 return commentlist
01135
01136 def deletecomment(macro, delkey, delpasswd):
01137
01138
01139 request = Globs.macro.request
01140 formatter = Globs.macro.formatter
01141 datapagename = Globs.datapagename
01142 _ = request.getText
01143
01144 if Params.encryptpass:
01145 from MoinMoin import user
01146 delpasswd = user.encodePassword(delpasswd)
01147
01148 pg = PageEditor( request, datapagename )
01149 pagetext = pg.get_raw_body()
01150
01151 regex = ur"""
01152 (?P<comblock>
01153 ^[\{]{3}\n
01154 ^(?P<icon>[^\n]*)\n
01155 ^(?P<name>[^\n]*)\n
01156 ^(?P<date>[^\n]*)[\n]+
01157 ^(?P<text>
01158 \s*.*?
01159 (?=[\}]{3})
01160 )[\}]{3}[\n]*
01161 ^[#]{2}PASSWORD[ ](?P<passwd>[^\n]*)[\n]*
01162 ^[#]{2}LOGINUSER[ ](?P<loginuser>[^\n]*)[\n$]*
01163 )"""
01164
01165 pattern = re.compile(regex, re.UNICODE + re.MULTILINE + re.VERBOSE + re.DOTALL)
01166 commentitems = pattern.findall(pagetext)
01167
01168 for item in commentitems:
01169
01170 if delkey == item[3].strip():
01171 comauthor = item[2]
01172 if Globs.admin or (request.user.valid and request.user.name == comauthor) or delpasswd == item[5]:
01173 newpagetext = pagetext.replace(item[0], '', 1)
01174
01175 action = 'SAVE'
01176 comment = 'Deleted comment by "%s"' % comauthor
01177 trivial = 1
01178 pg._write_file(newpagetext, action, u'PageComment modification at %s' % Globs.curpagename)
01179 addLogEntry(request, 'COMDEL', Globs.curpagename, comment)
01180
01181 msg = _('The comment is deleted.')
01182
01183
01184 if Params.notify:
01185 msg = msg + commentNotify(comment, trivial)
01186
01187 message(msg)
01188
01189 return
01190 else:
01191 message(_('Sorry, wrong password.'))
01192 return
01193
01194 message(_('No such comment'))
01195
01196
01197 def getAuthorFromCookie():
01198
01199 import Cookie
01200 request = Globs.macro.request
01201 cookieauthor = ''
01202
01203 try:
01204 cookie = Cookie.SimpleCookie(request.saved_cookie)
01205 except Cookie.CookieError:
01206
01207 cookie = None
01208
01209 if cookie and cookie.has_key('PG2AUTHOR'):
01210 cookieauthor = cookie['PG2AUTHOR'].value
01211
01212 cookieauthor = decodeURI(cookieauthor)
01213
01214 return cookieauthor
01215
01216
01217 def commentNotify(comment, trivial, comtext=''):
01218
01219 request = Globs.macro.request
01220
01221 if hasattr(request.cfg, 'mail_enabled'):
01222 mail_enabled = request.cfg.mail_enabled
01223 elif hasattr(request.cfg, 'mail_smarthost'):
01224 mail_enabled = request.cfg.mail_smarthost
01225 else:
01226 mail_enabled = ''
01227
01228 if not mail_enabled:
01229 return ''
01230
01231 _ = request.getText
01232 pg = PageEditor( request, Globs.curpagename )
01233
01234 subscribers = pg.getSubscribers(request, return_users=1, trivial=trivial)
01235 if subscribers:
01236
01237
01238
01239 results = [_('Status of sending notification mails:')]
01240 for lang in subscribers.keys():
01241 emails = map(lambda u: u.email, subscribers[lang])
01242 names = map(lambda u: u.name, subscribers[lang])
01243 mailok, status = sendNotification(pg, comtext, comment, emails, lang, trivial)
01244 recipients = ", ".join(names)
01245 results.append(_('[%(lang)s] %(recipients)s: %(status)s') % {
01246 'lang': lang, 'recipients': recipients, 'status': status})
01247
01248
01249
01250 return '<p>\n%s\n</p> ' % '<br>'.join(results)
01251
01252
01253 return ''
01254
01255 def sendNotification(pg, comtext, comment, emails, email_lang, trivial):
01256
01257 from MoinMoin import util, user
01258 request = Globs.macro.request
01259
01260 _ = lambda s, formatted=True, r=request, l=email_lang: r.getText(s, formatted=formatted, lang=l)
01261
01262 mailBody = _("Dear Wiki user,\n\n"
01263 'You have subscribed to a wiki page or wiki category on "%(sitename)s" for change notification.\n\n'
01264 "The following page has been changed by %(editor)s:\n"
01265 "%(pagelink)s\n\n", formatted=False) % {
01266 'editor': pg.uid_override or user.getUserIdentification(request),
01267 'pagelink': pg.request.getQualifiedURL(pg.url(request)),
01268 'sitename': pg.cfg.sitename or request.getBaseURL(),
01269 }
01270
01271 if comment:
01272 mailBody = mailBody + \
01273 _("The comment on the change is:\n%(comment)s\n\n", formatted=False) % {'comment': comment}
01274
01275
01276 if comtext:
01277 mailBody = mailBody + "%s\n%s\n" % (("-" * 78), comtext)
01278
01279 return util.mail.sendmail(request, emails,
01280 _('[%(sitename)s] %(trivial)sUpdate of "%(pagename)s" by %(username)s', formatted=False) % {
01281 'trivial' : (trivial and _("Trivial ", formatted=False)) or "",
01282 'sitename': pg.cfg.sitename or "Wiki",
01283 'pagename': pg.page_name,
01284 'username': pg.uid_override or user.getUserIdentification(request),
01285 },
01286 mailBody, mail_from=pg.cfg.mail_from)
01287
01288
01289
01290 def decodeURI(quotedstring):
01291
01292 try:
01293 unquotedstring = wikiutil.url_unquote(quotedstring)
01294 except AttributeError:
01295
01296 unquotedstring = url_unquote(quotedstring)
01297
01298 return unquotedstring
01299
01300
01301 def url_unquote(s, want_unicode=True):
01302 """
01303 From moinmoin 1.5
01304
01305 Wrapper around urllib.unquote doing the encoding/decoding as usually wanted:
01306
01307 @param s: the string to unquote (can be str or unicode, if it is unicode,
01308 config.charset is used to encode it before calling urllib)
01309 @param want_unicode: for the less usual case that you want to get back
01310 str and not unicode, set this to False.
01311 Default is True.
01312 """
01313 import urllib
01314
01315 if isinstance(s, unicode):
01316 s = s.encode(config.charset)
01317 s = urllib.unquote(s)
01318 if want_unicode:
01319 s = s.decode(config.charset)
01320 return s
01321
01322
01323 def addLogEntry(request, action, pagename, msg):
01324
01325 from MoinMoin.logfile import editlog
01326 t = wikiutil.timestamp2version(time.time())
01327 msg = unicode(msg)
01328
01329 pg = Page( request, pagename )
01330
01331 rev = 99999999
01332
01333
01334
01335 if 0:
01336 log = editlog.EditLog(request)
01337 log.add(request, t, rev, action, pagename, request.remote_addr, '', msg)
01338
01339
01340 log = editlog.EditLog(request, rootpagename=pagename)
01341 log.add(request, t, rev, action, pagename, request.remote_addr, '', msg)
01342
01343 def getsmileymarkuplist(defaulticon):
01344
01345 html = [
01346 u'Smiley: <select name="comicon">',
01347 u' <option value=""></option>',
01348 ]
01349
01350 for smiley in config.smileys.keys():
01351 if defaulticon.strip() == smiley:
01352 html.append(u' <option selected>%s</option>' % wikiutil.escape(smiley))
01353 else:
01354 html.append(u' <option>%s</option>' % wikiutil.escape(smiley))
01355
01356 html.append(u'</select>')
01357
01358 return u'\n'.join(html)
01359
01360 def getsmileymarkupradio(defaulticon):
01361
01362 smileys = Globs.smileys
01363 html = []
01364
01365 for smiley in smileys:
01366 if defaulticon.strip() == smiley:
01367 html.append(u'<input type="radio" name="comicon" value="%s" checked>%s ' % (wikiutil.escape(smiley), getsmiley(smiley)) )
01368 else:
01369 html.append(u'<input type="radio" name="comicon" value="%s">%s ' % (wikiutil.escape(smiley), getsmiley(smiley)) )
01370
01371 html.append(u'</select>')
01372
01373 return u'\n'.join(html)
01374
01375
01376 def getMarkupText(lines):
01377 request = Globs.macro.request
01378 formatter = Globs.macro.formatter
01379
01380 markup = Globs.markupforbidden
01381
01382 for regex in markup.keys():
01383 pattern = re.compile(regex, re.UNICODE + re.VERBOSE + re.MULTILINE)
01384 lines, nchanges = pattern.subn(markup[regex], lines)
01385
01386
01387
01388
01389 out = StringIO.StringIO()
01390 request.redirect(out)
01391 wikiizer = wiki.Parser(lines, request)
01392 wikiizer.format(formatter)
01393 targettext = out.getvalue()
01394 request.redirect()
01395 del out
01396
01397 return targettext
01398
01399
01400 def nicepass(alpha=3,numeric=1):
01401 """
01402 returns a human-readble password (say rol86din instead of
01403 a difficult to remember K8Yn9muL )
01404 """
01405 import string
01406 import random
01407 vowels = ['a','e','i','o','u']
01408 consonants = [a for a in string.ascii_lowercase if a not in vowels]
01409 digits = string.digits
01410
01411
01412 def a_part(slen):
01413 ret = ''
01414 for i in range(slen):
01415 if i%2 ==0:
01416 randid = random.randint(0,20)
01417 ret += consonants[randid]
01418 else:
01419 randid = random.randint(0,4)
01420 ret += vowels[randid]
01421 return ret
01422
01423 def n_part(slen):
01424 ret = ''
01425 for i in range(slen):
01426 randid = random.randint(0,9)
01427 ret += digits[randid]
01428 return ret
01429
01430
01431 fpl = alpha/2
01432 if alpha % 2 :
01433 fpl = int(alpha/2) + 1
01434 lpl = alpha - fpl
01435
01436 start = a_part(fpl)
01437 mid = n_part(numeric)
01438 end = a_part(lpl)
01439
01440
01441 return "%s%s%s" % (start,end,mid)