Problem trying to insert an image with CKEditor and SQLFORM

38 views
Skip to first unread message

Michael Ellis

unread,
Jun 21, 2010, 2:01:11 PM6/21/10
to web...@googlegroups.com
Not sure if this is a web2py or ckeditor problem or just some misunderstanding on my part.  Here's what's happening:

If I create a CKEditor instance in a SQLFORM, things work as expected until I try to insert an image. Clicking the Ok button in ckeditor's image dialog appears to be causing an immediate and unwanted form submission with a formkey that doesn't match the real formkey. This doesn't raise a form error. Instead it triggers the final else branch of the form.accepts logic (see below) and the image along with any other text that was entered is lost. 

I recently ran into this in a larger app, but am able to reproduce it in the following minimal model and controller. Has anyone else run into this and is there a workaround other than switching the CKEditor to Source mode and manually entering the <img> tag? I'm using web2py1.79.2 and CKEditor 3.3.1 (revision 5586) but have also seen the problem in CKEditor 3.2.


MODEL
db.define_table('page',
    Field('body', 'text'),
    )
    
def advanced_editor(field, value):
    eid = str(field).replace('.','_') 
    return TEXTAREA(_id = eid, _name=field.name
                    _class='text ckeditor', value=value, 
                    _cols=80, _rows=10)


db.page.body.widget = advanced_editor

{{extend 'layout.html'}}
<script type="text/javascript" src="{{=URL(request.application,'static','js/ckeditor/ckeditor.js')}}"></script>
{{=BEAUTIFY(response._vars)}}


CONTROLLER
def index():
    form = SQLFORM(db.page, showid=False)
    if form.accepts(request.vars,session):
        response.flash = "Form accepted"
        redirect(URL(r=request,f="show"))
    elif form.errors:
        response.flash = "Uh-oh!"
    else:
        ## Trying to insert an image lands here.
        response.flash = "Fill out the form."    
    return dict(form=form)        


def show():
    shown = dict()
    for row in db(db.page.id>0).select():
        shown[row.id] = row.body
    return dict(shown=shown)  


                                   
Thanks,
Mike

MikeEllis

unread,
Jun 29, 2010, 6:10:59 PM6/29/10
to web2py-users
This one still has me stumped so I'm taking the liberty of adding some
more info to make it current in the discussions. As I noted in the
earlier post, the problem has to to do with CKEditor's image
insertion dialog somehow triggering a form submission. This is really
puzzling, because the link insertion dialog is nearly identical but
doesn't trigger a submit. Below is a modified version of the index
function with some write statements to print the request vars and
session formkeys.

Any help much appreciated!

def index():
form = SQLFORM(db.page, showid=False,keepvalues=True)
sys.stderr.write("\n\nsession formkey:
%s"%session['_formkey[page_create]'])
sys.stderr.write("\nrequest.vars:%s"%repr(request.vars))
if form.accepts(request.vars,session):
response.flash = "Form accepted"
redirect(URL(r=request,f="show"))
elif form.errors:
response.flash = "Uh-oh!"
else:
response.flash = "Fill out the form"
sys.stderr.write("\n%s\n"%response.flash)
return dict(form=form)

So when I visit the index page and use the CKEditor to insert a link,
I see the following output in the console.

(initial display)
session formkey:bf5ec584-0ec9-4e74-90ff-ba53971ea2f5
request.vars:<Storage {}>
Fill out the form

(after inserting link, clicking ok to insert dialog, then clicking
submit)
session formkey:f95327b1-6152-4fb3-abd2-00444c9cc298
request.vars:<Storage {'body': '<p>\r\n\t<a href="http://web2py.com/
book/static/tree.jpg">link</a></p>\r\n', '_formkey':
'f95327b1-6152-4fb3-abd2-00444c9cc298', '_formname': 'page_create'}>

If I try the same thing except that this time I insert an image, I
get an extra submit and the session formkey gets out of sync with the
request.vars formkey.

(initial display)
session formkey:76e5e1fe-365c-401d-aaac-f2a751c8873e
request.vars:<Storage {}>
Fill out the form

(after inserting image and clicking ok in dialog)
session formkey:a143b2f1-bc5c-41b0-90e6-ef01fdc8e913
request.vars:<Storage {}>
Fill out the form

(after clicking Submit)
session formkey:9ee58f15-c1cd-4fa1-8766-b69b9a4478ac
request.vars:<Storage {'body': '<p>\r\n\t<img alt="" src="http://
web2py.com/book/static/tree.jpg" style="width: 401px; height: 500px;
" /></p>\r\n', '_formkey': 'a143b2f1-bc5c-41b0-90e6-ef01fdc8e913',
'_formname': 'page_create'}>
Fill out the form

The formkeys don't match, so form.accepts fails and the data never
gets into the table.

Thanks,
Mike
Message has been deleted

MikeEllis

unread,
Jun 30, 2010, 8:54:02 AM6/30/10
to web2py-users
I now have a workaround, but I don't like it very much. By checking
the length of request.vars before calling form.accepts(), I can force
the request formkey to match the session formkey, e.g.

if len(request.vars):
request.vars._formkey = session['_formkey[page_create]']
if form.accepts(request.vars,session):
... etc ...

The unwanted submit from the CKEditor image dialog is still occurring,
but forcing the keys to match when there's a real submit is avoiding
the failure in form.accepts(). I don't like it as a solution
because:
1. It relies on knowledge of web2py's internal form naming
conventions.
2. It only works if the unwanted submit has an empty request.vars
3. I suspect I may be defeating the purpose of the formkey and
possibly creating a security hole.

Is there a better way?

thanks,
Mike
Reply all
Reply to author
Forward
0 new messages