Attachment 'PageComment-081.py'

Download

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

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.