Changeset 419

Show
Ignore:
Timestamp:
07/24/06 09:03:12
Author:
crchemist
Message:

Added compatibility for Plone-2.5 in captchas for qPloneComments.
Added dynamic captcha generation.
Added configlet for switching between modes of generate engine.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • qPloneCaptchas/trunk/Extensions/Install.py

    r418 r419  
    66from App.Common import package_home 
    77from os.path import exists as path_exists, join as path_join 
     8from Products.CMFCore.CMFCorePermissions import ManagePortal 
    89 
    910 
    1011def install(self): 
    1112    out=StringIO() 
     13    updateqPloneCaptchasPropertySheet(self, out) 
    1214    Layers = LAYERS 
    1315    mtool = getToolByName(self, 'portal_migration') 
     
    1719    elif plone_version.startswith('2.0'): 
    1820        plone_version = '2.0.5' 
     21    elif plone_version.startswith('2.5'): 
     22        plone_version = '2.5' 
    1923    else: 
    20         raise Exception("Error - Unsupported version. Suported versions: Plone 2.0.5-2.1.2") 
     24        raise Exception("Error - Unsupported version. Suported versions: Plone 2.0.5-2.5") 
    2125    DiscussionLayer = LAYER_DISCUSSION 
    2226    try: 
     
    3236    out.write('Call setupSkin... \n') 
    3337    setupSkin(self, out, Layers) 
     38    addConfiglet(self, CONFIGLET_ID, CONFIGLET_NAME) 
    3439 
    3540def setupSkin(self, out, layers): 
     
    5863def uninstall(self): 
    5964    skinstool = getToolByName(self, 'portal_skins') 
     65 
     66    # Unregister configlet 
     67    controlpanel_tool = getToolByName(self, 'portal_controlpanel') 
     68    controlpanel_tool.unregisterConfiglet(CONFIGLET_ID) 
     69 
    6070    # Remove skin 
    6171    for skinName in skinstool.getSkinSelections(): 
     
    6777                    path.remove(l) 
    6878        skinstool.addSkinSelection(skinName, ','.join(path)) 
     79 
     80def updateProperty(pp_ps, id, value,out, property_type = None): 
     81    if not pp_ps.hasProperty(id): 
     82        pp_ps.manage_addProperty(id, value, property_type) 
     83        out.write("Adding %s property to %s property sheet\n" % (id, 'qPloneCapthas') ) 
     84    else: 
     85        pp_ps._updateProperty(id, value) 
     86 
     87def updateqPloneCaptchasPropertySheet(self, out): 
     88    pp = getToolByName(self, 'portal_properties') 
     89    if not 'qPloneCaptchas' in pp.objectIds(): 
     90        pp.addPropertySheet(id='qPloneCaptchas', title= '%s Properties' % 'qPloneCaptchas') 
     91        out.write("Adding %s property sheet to portal_properies\n" % 'qPloneCaptchas' ) 
     92    props_sheet = pp['qPloneCaptchas'] 
     93 
     94    updateProperty(props_sheet, id="captcha_bg", value='white', property_type='string', out=out) 
     95    updateProperty(props_sheet, id="captcha_textcolor", value='black', property_type='string', out=out) 
     96 
     97    avaliable_libs = [] 
     98    avaliable_libs.append('Static') 
     99    if havePIL: avaliable_libs.append('PIL') 
     100    if havePyCaptchas: avaliable_libs.append('PyCaptchas') 
     101    updateProperty(props_sheet, id="avaliable_libs", value=avaliable_libs, property_type='lines', out=out) 
     102    updateProperty(props_sheet, id="current_lib", value='avaliable_libs', property_type='selection', out=out) 
     103 
     104def addConfiglet(self, configlet_id, configlet_name): 
     105    """ Add Configlet. Delete old version before adding, if exist one. 
     106    """ 
     107 
     108    controlpanel_tool = getToolByName(self, 'portal_controlpanel') 
     109    controlpanel_tool.unregisterConfiglet(configlet_id) 
     110    controlpanel_tool.registerConfiglet(id=configlet_id, name=configlet_name, category='Products', 
     111                                        action='string:${portal_url}/%s' % configlet_id, 
     112                                        appId=PRODUCT_NAME, permission=ManagePortal, 
     113                                        imageUrl='logoIcon.gif') 
  • qPloneCaptchas/trunk/README.txt

    r418 r419  
    44    2.0.5 
    55    2.1.2 
     6    2.5 
    67 
    78Plugs to: 
     
    1516If qPloneCaptchas is expected to be used with qPloneComments or PloneFormMailer please make sure that qPloneCaptchas installed only after these products. 
    1617 
    17 Author
     18Authors
    1819 
    1920Volodymyr Cherepanyak - chervol@quintagroup.com 
    20  
     21Mykola Kharechko - crchemist@quintagroup.com 
    2122 
    2223Future: 
  • qPloneCaptchas/trunk/__init__.py

    r418 r419  
    11from Products.CMFCore.DirectoryView import registerDirectory 
    2 from config import GLOBALS 
    32from AccessControl import allow_module 
     3from config import * 
    44 
    55allow_module('Products.qPloneCaptchas.utils') 
    66allow_module('Products.qPloneCaptchas.config') 
     7try: 
     8    import Captcha 
     9    havePyCaptchas = True 
     10except: 
     11    havePyCaptchas = False 
     12 
     13try: 
     14    import PIL 
     15    havePIL = True 
     16except: 
     17    havePIL = False 
    718 
    819registerDirectory('skins', GLOBALS) 
  • qPloneCaptchas/trunk/skins/plone_captchas/captcha_validator.vpy

    r418 r419  
    22    return  state 
    33request = context.REQUEST 
     4 
     5cprops = context.portal_properties['qPloneCaptchas'] 
     6curr_lib = cprops.getProperty('current_lib', 'Static') 
     7 
    48key = request.get('hashkey', '') 
    59evalkey = request.get('evalkey', '') 
     
    913 
    1014from Products.qPloneCaptchas.config import CAPTCHAS_COUNT 
    11 from Products.qPloneCaptchas.utils import encrypt 
    12 index = int(key[:4],16)%CAPTCHAS_COUNT 
    13 if index == 0: 
    14     index = CAPTCHAS_COUNT 
    15 img = getattr(context, '%s.jpg' % index) 
    16 solution = img.title 
    17 enc = encrypt(test_key) 
     15from Products.qPloneCaptchas.utils import encrypt, getIndex 
     16 
     17if curr_lib == 'Static': 
     18    index = int(key[:4],16)%CAPTCHAS_COUNT 
     19    if index == 0: 
     20        index = CAPTCHAS_COUNT 
     21    img = getattr(context, '%s.jpg' % index) 
     22    solution = img.title 
     23    enc = encrypt(test_key) 
     24 
     25elif curr_lib == 'PIL': 
     26    index = getIndex(test_key) 
     27    enc = encrypt('pAss'+evalkey+str(index)) 
     28    solution = key 
    1829 
    1930if enc != solution: 
    2031   state.setError('key', 'Please submit the validation code.', 'key_required') 
    21    return  state.set(status="failure", portal_status_message="Please re enter validation code") 
     32   return  state.set(status="failure", portal_status_message = "Please re enter validation code") 
    2233return  state.set(status="success") 
  • qPloneCaptchas/trunk/skins/plone_captchas/captcha_widget.pt

    r418 r419  
    11<div metal:define-macro="captcha" tal:omit-tag=""> 
    2   <div class="field" tal:define="captcha here/getCaptcha; 
    3                                  error errors/key|nothing;" 
     2  <div class="field" 
     3       tal:define="captcha here/getCaptcha; 
     4                   error errors/key|nothing" 
    45       tal:attributes="class python:test(error, 'field error', 'field')"> 
     6 
    57     <input type="hidden" name="hashkey" 
    68            tal:attributes="value captcha/key"> 
    79     <input type="hidden" name="evalkey" 
    810            tal:attributes="value captcha/evalkey"> 
     11 
    912     <label for="key">Please enter the validataion code</label> 
    1013     <span class="fieldRequired" title="Required">(Required)</span><br /> 
    1114     <input type="text" name="key" size="10" value=""> 
    12      <img tal:attributes="src string:${portal_url}/getCaptchaImage/${captcha/key}"/> 
     15<!--      <h1 tal:content="captcha/key" /> --> 
     16     <span tal:condition="python:context.portal_properties['qPloneCaptchas'].current_lib=='Static'" 
     17           tal:replace="structure captcha/src"/> 
     18     <img tal:condition="python:context.portal_properties['qPloneCaptchas'].current_lib=='PIL'" 
     19          tal:attributes="src string:${portal_url}/getCaptchaImage/${captcha/evalkey}"/> 
    1320  </div> 
    1421</div> 
  • qPloneCaptchas/trunk/skins/plone_captchas/getCaptcha.py

    r418 r419  
    88##title= 
    99from DateTime import DateTime 
    10 from Products.qPloneCaptchas.utils import encrypt 
    11 purl = context.portal_url() 
     10from Products.qPloneCaptchas.utils import encrypt, getLen 
     11from Products.qPloneCaptchas.config import CAPTCHAS_COUNT 
     12cprops = context.portal_properties['qPloneCaptchas'] 
     13curr_lib = cprops.getProperty('current_lib', 'Static') 
     14 
     15res = {} 
    1216date = str(DateTime().timeTime()) 
    13 key = encrypt('pAss'+date) 
    14 return {'key':key, 'evalkey':date} 
     17res['evalkey'] = date 
     18 
     19if curr_lib == 'Static': 
     20    key = encrypt('pAss'+date) 
     21    res['key'] = key 
     22    index = int(key[:4],16)%CAPTCHAS_COUNT 
     23    if index == 0: 
     24        index = CAPTCHAS_COUNT 
     25    img = getattr(context, '%s.jpg' % index) 
     26    res['src'] = img.tag() 
     27 
     28elif curr_lib == 'PyCaptchas': 
     29    """ 
     30    c = getPyCaptchaImage() 
     31    context.REQUEST.RESPONSE.setHeader('Content-Type', 'image/gif') 
     32    context.REQUEST.RESPONSE.setHeader('Content-Length', c[2]) 
     33    context.REQUEST.RESPONSE.setHeader('Accept-Ranges', 'bytes') 
     34    context.REQUEST.form['hashkey'] = c[1] 
     35    context.REQUEST.form['evalkey'] = date 
     36    return c[0] 
     37    """ 
     38    pass 
     39 
     40elif curr_lib == 'PIL': 
     41    length = getLen() 
     42    index = int(float(date) % length) 
     43    key = encrypt('pAss'+date+str(index)) 
     44    res['key'] = key 
     45 
     46return res 
  • qPloneCaptchas/trunk/skins/plone_captchas/getCaptchaImage.py

    r418 r419  
    77##parameters= 
    88##title= 
    9 from Products.qPloneCaptchas.config import CAPTCHAS_COUNT 
     9from Products.qPloneCaptchas.utils import gen_captcha, getLen, getWord 
    1010request = context.REQUEST 
    11 key = request.traverse_subpath[0] 
    12 index = int(key[:4],16)%CAPTCHAS_COUNT 
    13 if index == 0: 
    14     index = CAPTCHAS_COUNT 
    15 img = getattr(context, '%s.jpg' % index) 
    16 return img.index_html(request, request.RESPONSE) 
     11date = request.traverse_subpath[0] 
     12length = getLen() 
     13index = int(float(date) % length) 
     14 
     15im = gen_captcha(getWord(index), 50) 
     16context.REQUEST.RESPONSE.setHeader('Content-Type', 'image/jpeg') 
     17context.REQUEST.RESPONSE.setHeader('Content-Length', im['size']) 
     18context.REQUEST.RESPONSE.setHeader('Accept-Ranges', 'bytes') 
     19 
     20return im['src'] 
  • qPloneCaptchas/trunk/utils.py

    r418 r419  
    11import md5 
    2  
     2import random 
     3from Products.qPloneCaptchas.data import basic_english 
    34def encrypt(s): 
    45    return md5.new(s).hexdigest().upper() 
     6 
     7""" 
     8def getPyCaptchaImage(): 
     9    import ImageFile 
     10    from PIL import ImageFile as pyImageFile 
     11    import sys 
     12    sys.modules['ImageFile'] = pyImageFile 
     13    from Captcha.Visual.Tests import PseudoGimpy 
     14    from cStringIO import StringIO 
     15    g = PseudoGimpy() 
     16    image = g.render() 
     17    sol = g.solutions[0] 
     18    outFile = StringIO() 
     19    image.save(outFile, "GIF") 
     20    outFile.seek(0) 
     21    src = outFile.read() 
     22    size = len(src) 
     23    sys.modules['ImageFile'] = ImageFile 
     24    return (src, sol, size) 
     25""" 
     26 
     27def gen_captcha(text, fnt_sz, fmt='JPEG'): 
     28    """Generate a captcha image""" 
     29    import ImageFile 
     30    import Image 
     31    import ImageFont 
     32    import ImageDraw 
     33    import ImageFilter 
     34    from PIL import ImageFile as pyImageFile 
     35    import sys 
     36    sys.modules['ImageFile'] = pyImageFile 
     37    from Captcha.Visual.Tests import PseudoGimpy 
     38    from cStringIO import StringIO 
     39    outFile = StringIO() 
     40 
     41    font = ImageFont.load_default() 
     42    dim = font.getsize(text) 
     43    im = Image.new('RGB', (dim[0]+5,dim[1]+5), 0xffffff) 
     44    draw = ImageDraw.Draw(im) 
     45    draw.textsize(text) 
     46    draw.text((3,3), text, font=font, fill=0x0b) 
     47    """ 
     48    # randomly select the foreground color 
     49    fgcolor = random.randint(0,0xffff00) 
     50    # make the background color the opposite of fgcolor 
     51    bgcolor = fgcolor ^ 0xffffff 
     52    # create a font object 
     53    import sys 
     54    #font = ImageFont.truetype('data/fonts/vera/Vera.ttf',fnt_sz) 
     55    font = ImageFont.load_default() 
     56    # determine dimensions of the text 
     57    dim = font.getsize(text) 
     58    # create a new image slightly larger that the text 
     59    im = Image.new('RGB', (dim[0]+5,dim[1]+5), bgcolor) 
     60    d = ImageDraw.Draw(im) 
     61    x, y = im.size 
     62    r = random.randint 
     63    # draw 100 random colored boxes on the background 
     64    for num in range(100): 
     65            d.rectangle((r(0,x),r(0,y),r(0,x),r(0,y)),fill=r(0,0xffffff)) 
     66    # add the text to the image 
     67    d.text((3,3), text, font=font, fill=fgcolor) 
     68    im = im.filter(ImageFilter.EDGE_ENHANCE_MORE) 
     69    """ 
     70    # save the image to a file 
     71    im.save(outFile, format=fmt) 
     72    outFile.seek(0) 
     73    src = outFile.read() 
     74    size = len(src) 
     75    sys.modules['ImageFile'] = ImageFile 
     76    return {'src':src, 'size':size} 
     77 
     78def getLen(): 
     79    words = basic_english.words.split() 
     80    return len(words) 
     81 
     82def getWord(index): 
     83    words = basic_english.words.split() 
     84    return words[index] 
     85 
     86def getIndex(word): 
     87    words = basic_english.words.split() 
     88    try: 
     89        res = words.index(word) 
     90    except ValueError: 
     91        res = getLen()+1 
     92    return res 
  • qPloneCaptchas/trunk/version.txt

    r418 r419  
    1 0.8 
     10.8.3