# -*- coding: iso-8859-1 -*-
"""
    PageComment.py  Version 0.82  2005. 10. 08.
                                                                                                           
    This macro gives a form to post a new comment to the page and a list of the posted comments.
                                                                                                           
    @copyright: 2005 by Seungik Lee <seungiklee<at>gmail.com>  http://cds.icu.ac.kr/~silee/
    @license: GPL

    Usage: [[PageComment]]

    Features:
        
        Simple usage, just put [[PageComment]] on any page.
        Lets anonymous users post a new comment with an input form.
        Shows a list of the posted comments.
        Support for comment deletion by given password.
        Support for administrative action, e.g., 
            - to delete a comment without entering a given password
            - to restore a deleted comment
            - to show the host IP address where a comment is posted
            

    Change Log

        Oct. 08, 2005 - Version 0.82
            - Changed the directory the data file stored to be secured
        Oct. 07, 2005 - Version 0.81 
            - Unicode encoding related bugs in deletecomment function are patched. 
            - Instruction bugs are patched. 
        Oct. 06, 2005 - Version 0.80 
            - The initial version is released.


    Notes
        
        'Gallery.py' developed by Simon Ryan has inspired this macro.
   

"""

from MoinMoin import config, wikiutil
import string, os, StringIO, time
import codecs

class Globs:
    # A quick place to plonk those shared variables
    adminmsg=''
    datafiledir=''
    pagename=''
    admin=''
    baseurl=''
    welcome_msg='Please leave your comment for this page.'

def message(astring):
    Globs.adminmsg='<font style="color: #aa0000; font-size: 0.9em;">PageComment: '+astring+'</font>\n'


def commentform(tmpauthor, tmptext, tmppasswd):
    # A form for posting a new comment
    
    html = [
        u'<div id="commentform">',
        u'<table id=commentform>',
        u'<form action='+Globs.subname+' name=comment METHOD=POST>',
		u'<tr><td>Name</td><td>Comment Text</td><td>Password</td><td></td></tr>',
		u'<tr><td><input type=text size=10 maxlength=20 name=comauthor value="' + tmpauthor + '"></td>',
		#u'<td><textarea name="comtext" rows="3" size="40">content</textarea></td>',
		u'<td><input type=text size=50 maxlength=255 name=comtext value="' + tmptext + '"></td>',
		u'<td><input type=password size=6 maxlength=10 name=compasswd value="' + tmppasswd + '"></td>',
        u'<td><input type=submit value="POST"></td></tr>',
		u'<input type=hidden value="show" name="action">',
		u'</form>',
		u'</table>',
		u'</div>',
        ]

    return u'\n'.join(html) + u'\n'
      
def addcomment(macro, comauthor, comtext, compasswd):
    # Add a comment with inputs
    
    com_delimeter = Globs.com_delimeter
    cfg = macro.request.cfg
    
    try:
        # If the data file exists
        inx_file = codecs.open(Globs.datafiledir+'/pagecommentsindex.txt','r+',encoding='utf-8')
    except:
        try:
            # If the directory does not exist
            if not os.path.isdir(Globs.datafiledir):
                # Create a attachments directory first
                # Is conflict with moinmoin?
                os.mkdir(Globs.datafiledir)
            
            inx_file = codecs.open(Globs.datafiledir+'/pagecommentsindex.txt','w',encoding='utf-8')

        except:
            message('Failed to add the comment (unable to create an index file)')
            return
    
    try:
        cur_index = inx_file.readline()
        cur_index = int(cur_index)
    except:
        cur_index = 0

    cur_index = cur_index + 1
    cur_index = str(cur_index)
    
    try:
        out_file = codecs.open(Globs.datafiledir+'/pagecomments.txt','a+',encoding='utf-8')
    except:
        message('Failed to add the comment (unable to create a data file)')
        return
    
    commentitem = [
        'o', 
        com_delimeter,
        cur_index,
        com_delimeter,
        convertdelimiter(comauthor),
        com_delimeter,
        convertdelimiter(comtext),
        com_delimeter,
        compasswd,
        com_delimeter,
        macro.request.user.host(),
        com_delimeter,
        time.strftime(cfg.datetime_fmt, time.localtime(time.time())),
        #str('%s  %s/%s  %s:%s' % (cur_year, cur_month, cur_day, cur_time, cur_min)),
        ]
    
    commentitem = u''.join(commentitem)
    
    out_file.write(commentitem + u'\r\n')
    out_file.close()
    
    inx_file.seek(0)
    inx_file.write(cur_index)
    inx_file.close()
    
    message('The comment is added')
    
def showcomment():

    html = ''
    com_delimeter = Globs.com_delimeter
    
    if not os.path.isfile(Globs.datafiledir+'/pagecomments.txt'):
        return ''
    
    try:
        com_file = codecs.open(Globs.datafiledir+'/pagecomments.txt','r', encoding='utf-8')
    except:
        #return u'<div=commentlist><table><tr><td style="border: 0px;">no comments</td></tr></td></table></div>'
        return ''
    
    html = u'<div=commentlist><table width=100%>'
    
    #cur_pos = 0
    
    while 1:
        in_line = com_file.readline()
        #cur_pos = cur_pos + len(in_line.encode('utf-8'))
        
        if in_line == "":
            break
        
        if in_line[0] == 'x':
            if Globs.admin == 'true':
                text_style = 'color: #d0d0d0;'
                signature_style = text_style
            else:
                continue
        else:
            text_style = ''
            signature_style = 'color: #999999;'
        
        try:
            in_line = in_line[:-2]
            [flg_active, cur_index,comauthor,comtext,compasswd,comhost,comtime] = string.split(in_line,com_delimeter)
        except:
            message('Failed to show the comment (the data file may be corrupt)')
            return ''
        
        if Globs.admin == 'true':
            signature = comhost + ' | ' + comtime
        else:
            signature = comtime
        
        htmlcomment = [
            u'<tr><td colspan=2 style="border: 0px; height:0.2px; background-color: #c0c0c0;"></td></tr>',
            u'<tr><td style="border: 0px; width: 9em; vertical-align: top; ' + text_style + '">',
            #u'(' + str(cur_pos) + ')',
            converttext(comauthor),
            u'</td><td style="border: 0px; ' + text_style + '">',
            converttext(comtext),
            u' <font style="font-size: 0.8em; ' + signature_style + '">(',
            signature,        
            u')</font>',
            ]

        htmlcomment = u'\n'.join(htmlcomment)
            
        if Globs.admin == 'true' and flg_active == 'x':
            
            htmlcomment2 = [
                u'<font style="font-size: 0.9em;">',
                u'<a style="color: #aa0000;" href="javascript: requesttorestore(\'' + cur_index + u'\');" alt="Restore">o</a>',
                u'</font></td></tr>'
                ]
            
        else:
        
            htmlcomment2 = [
                u'<font style="font-size: 0.9em;">',
                u'<a style="color: #aa0000;" href="javascript: requesttodelete(\'' + cur_index + u'\');" alt="Delete">x</a>',
                u'</font></td></tr>'
                ]
        
        htmlcomment2 = u'\n'.join(htmlcomment2)
        html =  html + htmlcomment + htmlcomment2 + '\n'
    
    com_file.close()
    
    html = html + u'</table></div>'
    
    return html


def execute(macro, args):

    # Containers
    formvals={}
    try:
        import wikiconfig
    except:
        wikiconfig=''

    # Class variables need to be specifically set 
    Globs.datafiledir=''
    Globs.admin=''
    Globs.adminmsg=''
    Globs.pagename=''
    Globs.com_delimeter = ' {||} '

    # process arguments
    if args:
	sargs=string.split(args,',')
	for item in sargs:
	    sitem=string.split(item,'=')
	    if len(sitem)==2:
    		key,value=sitem[0],sitem[1]

    # Useful variables
    Globs.baseurl=macro.request.getBaseURL()+'/'
    if not Globs.pagename:
	#Globs.pagename = string.replace(macro.formatter.page.page_name,'/','_2f')
	Globs.pagename = macro.formatter.page.page_name
	# This fixes the subpages bug. subname is now used instead of pagename when creating certain urls
	Globs.subname = string.split(Globs.pagename,'/')[-1]
    # Hmmm. A bug in moinmoin? underscores are getting escaped. These doubly escaped pagenames are even appearing in data/pages
    try:
        # Try the old MoinMoin-1.2.x way first
        textdir=config.text_dir
        pagepath = string.replace(wikiutil.getPagePath(Globs.pagename),'_5f','_')
    except:
        pagepath = macro.formatter.page.getPagePath()
    Globs.datafiledir = pagepath+'/pagecommentdata'
    
    if args:
        args=macro.request.getText(args)

    for item in macro.form.items():
        if not formvals.has_key(item[0]):
	    try:
		    formvals[item[0]]=item[1][0]
	    except AttributeError:
	        pass

    # Figure out if we have delete privs
    try:
        # If a user can delete the page containing the PageComment, then they are considered a PageComment administrator
        if macro.request.user.may.delete(macro.formatter.page.page_name):
            Globs.admin='true'
    except AttributeError:
        pass
    
    out=StringIO.StringIO()

    comauthor = ''
    comtext = ''
    compasswd = ''
    
    tmpauthor = ''
    tmptext = ''
    tmppasswd = ''
    
    message(Globs.welcome_msg)
    
    if formvals.has_key('comauthor') or formvals.has_key('comtext') or formvals.has_key('compasswd'):
        
        all_input = 1
        
        try:
            comauthor = formvals['comauthor']
        except:
            comauthor = ''
            all_input = 0
        
        try:
            comtext = formvals['comtext']
        except:
            comtext = ''
            all_input = 0
            
        try:
            compasswd = formvals['compasswd']
        except:
            compasswd = ''
            all_input = 0
        
        try:
            if all_input == 1:
                addcomment(macro, comauthor, comtext, compasswd)
            else:
                message('Failed to add the comment (insufficient input)')
                
                tmpauthor = comauthor
                tmptext = comtext
                tmppasswd = compasswd

        except:
            message('Failed to add the comment (internal error)')
            
            tmpauthor = comauthor
            tmptext = comtext
            tmppasswd = compasswd

    if formvals.has_key('delindex'):
        
        try:
            delindex = formvals['delindex']
            delpasswd = formvals['delpasswd']
            delaction = formvals['delaction']
            
            deletecomment(macro, delindex, delpasswd, delaction)
        except:
            message('Failed to delete the comment (internal error or insufficient input)')
    
    out.write(deleteform())
    out.write(u'<table><tr><td style="border: 0px;">')
    out.write(Globs.adminmsg)
    out.write(commentform(tmpauthor, tmptext, tmppasswd))
    out.write(u'</td></tr><tr><td style="border: 0px; height: 0.5em;"></td></tr><tr><td style="border: 0px;">')
    out.write(showcomment())
    out.write(u'</td></tr></table>')
    
	
    out.seek(0)
    # Finally output any administrative messages at the top followed by any generated content
    return macro.formatter.rawHTML(
        out.read()	
    )

def converttext(targettext):
    # Converts some special characters of html to plain-text style
    # What else to handle?

    targettext = targettext.replace(u'&', '&amp')
    targettext = targettext.replace(u'>', '&gt;')
    targettext = targettext.replace(u'<', '&lt;')
    targettext = targettext.replace(u'\n', '<br>')
    targettext = targettext.replace(u'\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;')
    targettext = targettext.replace(u'  ', '&nbsp;&nbsp;')
        
    return targettext
    
def convertdelimiter(targettext):
    # Converts delimeter to other string to avoid a crash
    
    targettext = targettext.replace(Globs.com_delimeter, '(del)')
    
    return targettext

    
def deleteform():
    # Javascript codes for deleting or restoring a comment

    html = [
        '<script language=javascript>',
        '<!--',
        ]
    html = '\n'.join(html)
           
    if Globs.admin == 'true':
        html2 = [    
            '  function requesttodelete(comindex) {',
            '      document.delform.delindex.value = comindex;',
            '      document.delform.delpasswd.value = "****";',
            '      document.delform.delaction.value = "delete";',
            '      document.delform.submit();',
            '  }',
            '  function requesttorestore(comindex) {',
            '      document.delform.delindex.value = comindex;',
            '      document.delform.delpasswd.value = "****";',
            '      document.delform.delaction.value = "restore";',
            '      document.delform.submit();',
            '  }',
            ]
        html2 = '\n'.join(html2)
    else:
        html2 = [    
            '  function requesttodelete(comindex) {',
            '      var passwd = prompt("Enter password:", "");',
            '      if(!(passwd == "" || passwd == null)) {',
            '          document.delform.delindex.value = comindex;',
            '          document.delform.delpasswd.value = passwd;',
            '          document.delform.delaction.value = "delete";',
            '          document.delform.submit();',
            '      }',
            '  }',
            ]
        html2 = '\n'.join(html2)
                
    html3 = [
        '//-->',
        '</script>',
        '<form name="delform" action="'+Globs.subname+'" METHOD="post"> <input type=hidden value="show" name="action">',
        '<input name="delpasswd" type="hidden" value="****"><input name="delindex" type="hidden" value=""><input name="delaction" type="hidden" value=""> </form>',
        ]
    html3 = '\n'.join(html3)

    return '\n' + html + '\n' + html2 + '\n' + html3
        
def deletecomment(macro, delindex, delpasswd, delaction):
    # Deletes or restores a comment with give index and password

    html = ''
    com_delimeter = Globs.com_delimeter
    
    try:
        com_file = codecs.open(Globs.datafiledir+'/pagecomments.txt','r+',encoding='utf-8')
    except:
        message('No such comment')
        return
    
    delindex = int(delindex)
    
    if delindex < 1:
        message('No such comment')
        return
    
    cur_byte = 0
    selectedcomment = ''
    
    for x in range(delindex):
        cur_byte = cur_byte + len(selectedcomment.encode('utf-8'))
        selectedcomment = com_file.readline()
        
    if selectedcomment == "":
        message('No such comment')
        return
    
    if selectedcomment[0] == 'x' and delaction == 'delete':
        message('The comment is already deleted')
        return
        
    if Globs.admin == 'true' and selectedcomment[0] == 'o' and delaction == 'restore':
        message('The comment is already restored')
        return
    
    selectedcomment = selectedcomment[:-2]
    [flg_active, cur_index,comauthor,comtext,compasswd,comhost,comtime] = string.split(selectedcomment,com_delimeter)
    
    if Globs.admin != 'true' and compasswd != delpasswd:
        message('Failed to delete the comment (incorrect password)')
        return
        
    com_file.seek(cur_byte)
    if Globs.admin == 'true' and delaction == 'restore':
        com_file.write(u'o')
        message('The comment is restored')
    else:
        com_file.write(u'x')
        message('The comment is deleted')
    
    com_file.close()
    
    return
    