Attachment 'PageComment-082.py'

Download

   1 # -*- coding: iso-8859-1 -*-
   2 """
   3     PageComment.py  Version 0.82  2005. 10. 08.
   4                                                                                                            
   5     This macro gives a form to post a new comment to the page and a list of the posted comments.
   6                                                                                                            
   7     @copyright: 2005 by Seungik Lee <seungiklee<at>gmail.com>  http://cds.icu.ac.kr/~silee/
   8     @license: GPL
   9 
  10     Usage: [[PageComment]]
  11 
  12     Features:
  13         
  14         Simple usage, just put [[PageComment]] 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             - to restore a deleted comment
  21             - to show the host IP address where a comment is posted
  22             
  23 
  24     Change Log
  25 
  26         Oct. 08, 2005 - Version 0.82
  27             - Changed the directory the data file stored to be secured
  28         Oct. 07, 2005 - Version 0.81 
  29             - Unicode encoding related bugs in deletecomment function are patched. 
  30             - Instruction bugs are patched. 
  31         Oct. 06, 2005 - Version 0.80 
  32             - The initial version is released.
  33 
  34 
  35     Notes
  36         
  37         'Gallery.py' developed by Simon Ryan has inspired this macro.
  38    
  39 
  40 """
  41 
  42 from MoinMoin import config, wikiutil
  43 import string, os, StringIO, time
  44 import codecs
  45 
  46 class Globs:
  47     # A quick place to plonk those shared variables
  48     adminmsg=''
  49     datafiledir=''
  50     pagename=''
  51     admin=''
  52     baseurl=''
  53     welcome_msg='Please leave your comment for this page.'
  54 
  55 def message(astring):
  56     Globs.adminmsg='<font style="color: #aa0000; font-size: 0.9em;">PageComment: '+astring+'</font>\n'
  57 
  58 
  59 def commentform(tmpauthor, tmptext, tmppasswd):
  60     # A form for posting a new comment
  61     
  62     html = [
  63         u'<div id="commentform">',
  64         u'<table id=commentform>',
  65         u'<form action='+Globs.subname+' name=comment METHOD=POST>',
  66 		u'<tr><td>Name</td><td>Comment Text</td><td>Password</td><td></td></tr>',
  67 		u'<tr><td><input type=text size=10 maxlength=20 name=comauthor value="' + tmpauthor + '"></td>',
  68 		#u'<td><textarea name="comtext" rows="3" size="40">content</textarea></td>',
  69 		u'<td><input type=text size=50 maxlength=255 name=comtext value="' + tmptext + '"></td>',
  70 		u'<td><input type=password size=6 maxlength=10 name=compasswd value="' + tmppasswd + '"></td>',
  71         u'<td><input type=submit value="POST"></td></tr>',
  72 		u'<input type=hidden value="show" name="action">',
  73 		u'</form>',
  74 		u'</table>',
  75 		u'</div>',
  76         ]
  77 
  78     return u'\n'.join(html) + u'\n'
  79       
  80 def addcomment(macro, comauthor, comtext, compasswd):
  81     # Add a comment with inputs
  82     
  83     com_delimeter = Globs.com_delimeter
  84     cfg = macro.request.cfg
  85     
  86     try:
  87         # If the data file exists
  88         inx_file = codecs.open(Globs.datafiledir+'/pagecommentsindex.txt','r+',encoding='utf-8')
  89     except:
  90         try:
  91             # If the directory does not exist
  92             if not os.path.isdir(Globs.datafiledir):
  93                 # Create a attachments directory first
  94                 # Is conflict with moinmoin?
  95                 os.mkdir(Globs.datafiledir)
  96             
  97             inx_file = codecs.open(Globs.datafiledir+'/pagecommentsindex.txt','w',encoding='utf-8')
  98 
  99         except:
 100             message('Failed to add the comment (unable to create an index file)')
 101             return
 102     
 103     try:
 104         cur_index = inx_file.readline()
 105         cur_index = int(cur_index)
 106     except:
 107         cur_index = 0
 108 
 109     cur_index = cur_index + 1
 110     cur_index = str(cur_index)
 111     
 112     try:
 113         out_file = codecs.open(Globs.datafiledir+'/pagecomments.txt','a+',encoding='utf-8')
 114     except:
 115         message('Failed to add the comment (unable to create a data file)')
 116         return
 117     
 118     commentitem = [
 119         'o', 
 120         com_delimeter,
 121         cur_index,
 122         com_delimeter,
 123         convertdelimiter(comauthor),
 124         com_delimeter,
 125         convertdelimiter(comtext),
 126         com_delimeter,
 127         compasswd,
 128         com_delimeter,
 129         macro.request.user.host(),
 130         com_delimeter,
 131         time.strftime(cfg.datetime_fmt, time.localtime(time.time())),
 132         #str('%s  %s/%s  %s:%s' % (cur_year, cur_month, cur_day, cur_time, cur_min)),
 133         ]
 134     
 135     commentitem = u''.join(commentitem)
 136     
 137     out_file.write(commentitem + u'\r\n')
 138     out_file.close()
 139     
 140     inx_file.seek(0)
 141     inx_file.write(cur_index)
 142     inx_file.close()
 143     
 144     message('The comment is added')
 145     
 146 def showcomment():
 147 
 148     html = ''
 149     com_delimeter = Globs.com_delimeter
 150     
 151     if not os.path.isfile(Globs.datafiledir+'/pagecomments.txt'):
 152         return ''
 153     
 154     try:
 155         com_file = codecs.open(Globs.datafiledir+'/pagecomments.txt','r', encoding='utf-8')
 156     except:
 157         #return u'<div=commentlist><table><tr><td style="border: 0px;">no comments</td></tr></td></table></div>'
 158         return ''
 159     
 160     html = u'<div=commentlist><table width=100%>'
 161     
 162     #cur_pos = 0
 163     
 164     while 1:
 165         in_line = com_file.readline()
 166         #cur_pos = cur_pos + len(in_line.encode('utf-8'))
 167         
 168         if in_line == "":
 169             break
 170         
 171         if in_line[0] == 'x':
 172             if Globs.admin == 'true':
 173                 text_style = 'color: #d0d0d0;'
 174                 signature_style = text_style
 175             else:
 176                 continue
 177         else:
 178             text_style = ''
 179             signature_style = 'color: #999999;'
 180         
 181         try:
 182             in_line = in_line[:-2]
 183             [flg_active, cur_index,comauthor,comtext,compasswd,comhost,comtime] = string.split(in_line,com_delimeter)
 184         except:
 185             message('Failed to show the comment (the data file may be corrupt)')
 186             return ''
 187         
 188         if Globs.admin == 'true':
 189             signature = comhost + ' | ' + comtime
 190         else:
 191             signature = comtime
 192         
 193         htmlcomment = [
 194             u'<tr><td colspan=2 style="border: 0px; height:0.2px; background-color: #c0c0c0;"></td></tr>',
 195             u'<tr><td style="border: 0px; width: 9em; vertical-align: top; ' + text_style + '">',
 196             #u'(' + str(cur_pos) + ')',
 197             converttext(comauthor),
 198             u'</td><td style="border: 0px; ' + text_style + '">',
 199             converttext(comtext),
 200             u' <font style="font-size: 0.8em; ' + signature_style + '">(',
 201             signature,        
 202             u')</font>',
 203             ]
 204 
 205         htmlcomment = u'\n'.join(htmlcomment)
 206             
 207         if Globs.admin == 'true' and flg_active == 'x':
 208             
 209             htmlcomment2 = [
 210                 u'<font style="font-size: 0.9em;">',
 211                 u'<a style="color: #aa0000;" href="javascript: requesttorestore(\'' + cur_index + u'\');" alt="Restore">o</a>',
 212                 u'</font></td></tr>'
 213                 ]
 214             
 215         else:
 216         
 217             htmlcomment2 = [
 218                 u'<font style="font-size: 0.9em;">',
 219                 u'<a style="color: #aa0000;" href="javascript: requesttodelete(\'' + cur_index + u'\');" alt="Delete">x</a>',
 220                 u'</font></td></tr>'
 221                 ]
 222         
 223         htmlcomment2 = u'\n'.join(htmlcomment2)
 224         html =  html + htmlcomment + htmlcomment2 + '\n'
 225     
 226     com_file.close()
 227     
 228     html = html + u'</table></div>'
 229     
 230     return html
 231 
 232 
 233 def execute(macro, args):
 234 
 235     # Containers
 236     formvals={}
 237     try:
 238         import wikiconfig
 239     except:
 240         wikiconfig=''
 241 
 242     # Class variables need to be specifically set 
 243     Globs.datafiledir=''
 244     Globs.admin=''
 245     Globs.adminmsg=''
 246     Globs.pagename=''
 247     Globs.com_delimeter = ' {||} '
 248 
 249     # process arguments
 250     if args:
 251 	sargs=string.split(args,',')
 252 	for item in sargs:
 253 	    sitem=string.split(item,'=')
 254 	    if len(sitem)==2:
 255     		key,value=sitem[0],sitem[1]
 256 
 257     # Useful variables
 258     Globs.baseurl=macro.request.getBaseURL()+'/'
 259     if not Globs.pagename:
 260 	#Globs.pagename = string.replace(macro.formatter.page.page_name,'/','_2f')
 261 	Globs.pagename = macro.formatter.page.page_name
 262 	# This fixes the subpages bug. subname is now used instead of pagename when creating certain urls
 263 	Globs.subname = string.split(Globs.pagename,'/')[-1]
 264     # Hmmm. A bug in moinmoin? underscores are getting escaped. These doubly escaped pagenames are even appearing in data/pages
 265     try:
 266         # Try the old MoinMoin-1.2.x way first
 267         textdir=config.text_dir
 268         pagepath = string.replace(wikiutil.getPagePath(Globs.pagename),'_5f','_')
 269     except:
 270         pagepath = macro.formatter.page.getPagePath()
 271     Globs.datafiledir = pagepath+'/pagecommentdata'
 272     
 273     if args:
 274         args=macro.request.getText(args)
 275 
 276     for item in macro.form.items():
 277         if not formvals.has_key(item[0]):
 278 	    try:
 279 		    formvals[item[0]]=item[1][0]
 280 	    except AttributeError:
 281 	        pass
 282 
 283     # Figure out if we have delete privs
 284     try:
 285         # If a user can delete the page containing the PageComment, then they are considered a PageComment administrator
 286         if macro.request.user.may.delete(macro.formatter.page.page_name):
 287             Globs.admin='true'
 288     except AttributeError:
 289         pass
 290     
 291     out=StringIO.StringIO()
 292 
 293     comauthor = ''
 294     comtext = ''
 295     compasswd = ''
 296     
 297     tmpauthor = ''
 298     tmptext = ''
 299     tmppasswd = ''
 300     
 301     message(Globs.welcome_msg)
 302     
 303     if formvals.has_key('comauthor') or formvals.has_key('comtext') or formvals.has_key('compasswd'):
 304         
 305         all_input = 1
 306         
 307         try:
 308             comauthor = formvals['comauthor']
 309         except:
 310             comauthor = ''
 311             all_input = 0
 312         
 313         try:
 314             comtext = formvals['comtext']
 315         except:
 316             comtext = ''
 317             all_input = 0
 318             
 319         try:
 320             compasswd = formvals['compasswd']
 321         except:
 322             compasswd = ''
 323             all_input = 0
 324         
 325         try:
 326             if all_input == 1:
 327                 addcomment(macro, comauthor, comtext, compasswd)
 328             else:
 329                 message('Failed to add the comment (insufficient input)')
 330                 
 331                 tmpauthor = comauthor
 332                 tmptext = comtext
 333                 tmppasswd = compasswd
 334 
 335         except:
 336             message('Failed to add the comment (internal error)')
 337             
 338             tmpauthor = comauthor
 339             tmptext = comtext
 340             tmppasswd = compasswd
 341 
 342     if formvals.has_key('delindex'):
 343         
 344         try:
 345             delindex = formvals['delindex']
 346             delpasswd = formvals['delpasswd']
 347             delaction = formvals['delaction']
 348             
 349             deletecomment(macro, delindex, delpasswd, delaction)
 350         except:
 351             message('Failed to delete the comment (internal error or insufficient input)')
 352     
 353     out.write(deleteform())
 354     out.write(u'<table><tr><td style="border: 0px;">')
 355     out.write(Globs.adminmsg)
 356     out.write(commentform(tmpauthor, tmptext, tmppasswd))
 357     out.write(u'</td></tr><tr><td style="border: 0px; height: 0.5em;"></td></tr><tr><td style="border: 0px;">')
 358     out.write(showcomment())
 359     out.write(u'</td></tr></table>')
 360     
 361 	
 362     out.seek(0)
 363     # Finally output any administrative messages at the top followed by any generated content
 364     return macro.formatter.rawHTML(
 365         out.read()	
 366     )
 367 
 368 def converttext(targettext):
 369     # Converts some special characters of html to plain-text style
 370     # What else to handle?
 371 
 372     targettext = targettext.replace(u'&', '&amp')
 373     targettext = targettext.replace(u'>', '&gt;')
 374     targettext = targettext.replace(u'<', '&lt;')
 375     targettext = targettext.replace(u'\n', '<br>')
 376     targettext = targettext.replace(u'\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;')
 377     targettext = targettext.replace(u'  ', '&nbsp;&nbsp;')
 378         
 379     return targettext
 380     
 381 def convertdelimiter(targettext):
 382     # Converts delimeter to other string to avoid a crash
 383     
 384     targettext = targettext.replace(Globs.com_delimeter, '(del)')
 385     
 386     return targettext
 387 
 388     
 389 def deleteform():
 390     # Javascript codes for deleting or restoring a comment
 391 
 392     html = [
 393         '<script language=javascript>',
 394         '<!--',
 395         ]
 396     html = '\n'.join(html)
 397            
 398     if Globs.admin == 'true':
 399         html2 = [    
 400             '  function requesttodelete(comindex) {',
 401             '      document.delform.delindex.value = comindex;',
 402             '      document.delform.delpasswd.value = "****";',
 403             '      document.delform.delaction.value = "delete";',
 404             '      document.delform.submit();',
 405             '  }',
 406             '  function requesttorestore(comindex) {',
 407             '      document.delform.delindex.value = comindex;',
 408             '      document.delform.delpasswd.value = "****";',
 409             '      document.delform.delaction.value = "restore";',
 410             '      document.delform.submit();',
 411             '  }',
 412             ]
 413         html2 = '\n'.join(html2)
 414     else:
 415         html2 = [    
 416             '  function requesttodelete(comindex) {',
 417             '      var passwd = prompt("Enter password:", "");',
 418             '      if(!(passwd == "" || passwd == null)) {',
 419             '          document.delform.delindex.value = comindex;',
 420             '          document.delform.delpasswd.value = passwd;',
 421             '          document.delform.delaction.value = "delete";',
 422             '          document.delform.submit();',
 423             '      }',
 424             '  }',
 425             ]
 426         html2 = '\n'.join(html2)
 427                 
 428     html3 = [
 429         '//-->',
 430         '</script>',
 431         '<form name="delform" action="'+Globs.subname+'" METHOD="post"> <input type=hidden value="show" name="action">',
 432         '<input name="delpasswd" type="hidden" value="****"><input name="delindex" type="hidden" value=""><input name="delaction" type="hidden" value=""> </form>',
 433         ]
 434     html3 = '\n'.join(html3)
 435 
 436     return '\n' + html + '\n' + html2 + '\n' + html3
 437         
 438 def deletecomment(macro, delindex, delpasswd, delaction):
 439     # Deletes or restores a comment with give index and password
 440 
 441     html = ''
 442     com_delimeter = Globs.com_delimeter
 443     
 444     try:
 445         com_file = codecs.open(Globs.datafiledir+'/pagecomments.txt','r+',encoding='utf-8')
 446     except:
 447         message('No such comment')
 448         return
 449     
 450     delindex = int(delindex)
 451     
 452     if delindex < 1:
 453         message('No such comment')
 454         return
 455     
 456     cur_byte = 0
 457     selectedcomment = ''
 458     
 459     for x in range(delindex):
 460         cur_byte = cur_byte + len(selectedcomment.encode('utf-8'))
 461         selectedcomment = com_file.readline()
 462         
 463     if selectedcomment == "":
 464         message('No such comment')
 465         return
 466     
 467     if selectedcomment[0] == 'x' and delaction == 'delete':
 468         message('The comment is already deleted')
 469         return
 470         
 471     if Globs.admin == 'true' and selectedcomment[0] == 'o' and delaction == 'restore':
 472         message('The comment is already restored')
 473         return
 474     
 475     selectedcomment = selectedcomment[:-2]
 476     [flg_active, cur_index,comauthor,comtext,compasswd,comhost,comtime] = string.split(selectedcomment,com_delimeter)
 477     
 478     if Globs.admin != 'true' and compasswd != delpasswd:
 479         message('Failed to delete the comment (incorrect password)')
 480         return
 481         
 482     com_file.seek(cur_byte)
 483     if Globs.admin == 'true' and delaction == 'restore':
 484         com_file.write(u'o')
 485         message('The comment is restored')
 486     else:
 487         com_file.write(u'x')
 488         message('The comment is deleted')
 489     
 490     com_file.close()
 491     
 492     return
 493     

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] (2005-10-07 01:55:46, 15.6 KB) [[attachment:PageComment-080.py]]
  • [get | view] (2005-10-07 01:56:31, 15.7 KB) [[attachment:PageComment-081.py]]
  • [get | view] (2005-10-28 10:35:49, 16.4 KB) [[attachment:PageComment-082-tw.py]]
  • [get | view] (2005-10-07 22:55:29, 15.5 KB) [[attachment:PageComment-082.py]]
  • [get | view] (2005-10-06 11:34:45, 13.7 KB) [[attachment:snap-pagecomment.jpg]]
 All files | Selected Files: delete move to page copy to page

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