Attachment 'PageComment-080.py'

Download

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

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.