javascripthtmliframekcfinder

Uploading files to local iframe using target attribute not working in newest Chrome


I'm using kcFinder 2.54 to upload files in one of my site through CKEditor. I know that the versions of the scripts are old but they were working fine until recently.

While going through the changelog of Chrome I noticed the following:

The native file system API starts a new origin trial with added functionality

I think it may be a cause of my problems but maybe not. Here is the code:

When kcFinder is initialised, it creates a simple form:

<form enctype="multipart/form-data" method="post" target="uploadResponse" action="browse.php?type=files&amp;lng=pl&amp;opener=ckeditor&amp;act=upload">
    <input type="file" name="upload[]" onchange="_.uploadFile(this.form)" style="height:30px" multiple="multiple">
    <input type="hidden" name="dir" value="">
</form>

Notice the target="uploadResponse", which is a local iframe prepended to the body of the document:

<iframe id="uploadResponse" name="uploadResponse" src="javascript:;"></iframe>

This is what the uploadFile(this.form) function looks like :

_.uploadFile = function(form) {
    if (!_.dirWritable) {
        _.alert(_.label("Cannot write to upload folder."));
        $('#upload').detach();
        _.initUploadButton();
        return;
    }
    form.elements[1].value = _.dir;
    $('<iframe id="uploadResponse" name="uploadResponse" src="javascript:;"></iframe>').prependTo(document.body);
    $('#loading').html(_.label("Uploading file...")).show();
    form.submit();
    $('#uploadResponse').load(function() {
        var response = $(this).contents().find('body').text();
        $('#loading').hide();
        response = response.split("\n");

        var selected = [], errors = [];
        $.each(response, function(i, row) {
            if (row.substr(0, 1) == "/")
                selected[selected.length] = row.substr(1, row.length - 1);
            else
                errors[errors.length] = row;
        });
        if (errors.length) {
            errors = errors.join("\n");
            if (errors.replace(/^\s+/g, "").replace(/\s+$/g, "").length)
                _.alert(errors);
        }
        if (!selected.length)
            selected = null;
        _.refresh(selected);
        $('#upload').detach();
        setTimeout(function() {
            $('#uploadResponse').detach();
        }, 1);
        _.initUploadButton();
    });
};

I've had a go at debugging it and realised that response is completely empty. Then I realised I'm not surprised since the request has been cancelled:

enter image description here

The only thing I noticed was this header Upgrade-Insecure-Requests: 1 but not sure if that is important since the iframe is totally local.

I've been searching for information about the possible downgrade of target attribute or the way sending form using iframe works, but to no avail. If anybody experienced something similar or at least can tell me the reason why it's not working, perhaps I can figure out a workaround.

Things I have tried so far:

  1. Change javascript:; to javasript:false; in iframe source
  2. Change javascript:; to # in iframe source

Solution

  • I met the same problem. I solved it by calling form.submit in the next tick:

    // [...]
    
    $('<iframe id="uploadResponse" name="uploadResponse" src="javascript:;"></iframe>').prependTo(document.body);
    $('#loading').html(_.label("Uploading file...")).show();
    
    setTimeout(function() {
      $('#uploadResponse').load(function() {
          // [...]
      });
      form.submit();
    }, 1);