2009/12/12

Uploading .app files

Developing an extension for an application like CKEditor means that you have to be aware of the environment. CKEditor tries to cover the differences between the browsers and even adds workarounds for the bugs that are known in each one (as long as it's possible of course)

So when you are writting your code and something doesn't work as expected you have to start searching for bugs in your own code (the usual culprit), then you have to review how you are using the CKEditor API, verify that you have understood the explanation and that it matches the actual code that you have written. Then you escalate up the problem to the CKEditor source code, maybe there's some bug there that it's causing your problems. And sometimes you have to get even higher in the chain...

One of these situations is an issue that I've talked about in the post about uploads in CKEditor, I did try to apply an onChange listener for an uiElement with type="file", but it didn't work. After debugging the issue I found that despite the huge differences in DOM (this element was created as an iframe with a form and the <input type="file">), the event listeners aren't aware of this difference, so they apply the listeners to the container <div>.

This week I've been writing the code to fix this problem (that's the beauty of open source, when a problem is spotted it's possible to really check what's going on under the hood and create the patch without waiting for a company to include it in their plans), and after some tests it seemed to work: as soon as the user picks an image from their computer it is uploaded to the server and they just have to review the Alt attribute, the Class or the Title.

I had to review that the events are being reapplied correctly when the iframe recreates, so the tests (somewhat random) also included uploading non image files to verify that they are handled properly and everything still works.

Then I started to find that something was wrong, I selected an application, the file picker showed the name but there was no message. I debugged it further and the onChange event was being correctly fired (well, at first it was fired too many times due to a bug in the logic to append the listeners, but this is what these tests were about).

Maybe not CKEditor?

I had this form inside an iframe in a lot of nested code with lots of javascript, custom events and God knows what else. The next step was to create a simple testcase to focus on the problem:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
    <head>
    <title>Upload test</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <script type="text/javascript">
            function fileChanged(e)
            {
                var input = document.getElementById("upload");
                console.log("Selected file: " + input.value);
                //input.form.submit();
            }
        </script>
    </head>
<body>
    <form method="POST" enctype="multipart/form-data">
        <input type="file" name="upload" id="upload" onchange="fileChanged(event)">
        <input type="submit">
    </form>
</body>
</html>

This showed that I could select any file and it showed the name correctly and the form was posted by pressing the submit button or with the js call. But if I selected an application (I'm using currently a MacBook) then it showed the name and the form wasn't submitted. No error message, no warning, nothing.

The simple test removed CKEditor out of the equation and avoided long hours trying to find a non-existing problem in that code, and instead it pointed to some other basic issue with the browser and the upload of Applications (.app)

The current browser was Firefox 3.5, so I searched bugzilla but I wasn't able to find any report about this, the only bug that reported some strange problem was one about sending sometimes files with 0 size to the server.

So I added

                console.log("File size: " + input.files[0].fileSize);

and it showed the .app to be files of 0 size.

Something is quite wrong here!. I tested Safari and it seemed to allow the upload the .app but it showed the size as 102 bytes instead of several Mb.

Then I finally realized that an Application in Mac OS X is really a folder with subfolders and files, so this is the reason why it fails. Firefox accepts the .app in the filepicker but at the upload time it somehow sees that it is a folder (or that it isn't a real file) and rejects to send the form, but as I said, there's no warning about the problem. Testing with Opera did provide a message stating that the path pointed to some file that it couldn't find.

The most interesting situation was Safari, I changed the form to point to a real script that would handle the file and the result was that the application has been compressed on the fly and sent to the server as a .zip

How does each browser behave?

This is a live test with some code similar to the above:

So on one hand we have Firefox, it doesn't allow to upload the .app and doesn't provide any hint that there's a problem with the selected file. Also shows the size as 0.

Opera does its job much better and shows a tooltip on the <input type="file"> explaining that there's a problem there. Better but still not good enough as people might get confused about the reason of the problem. It hasn't implemented the API to get the size of a selected file.

Safari is quite different, if you select an .app then it will compress it and send it as a .zip so even if the user might find it a little strange that it has bothered to compress the data he finds that he was able to upload the file that he wanted. The only issue is that it shows the size as 102 instead of showing the same data that it's in the Finder.

The final test was the new beta of Google Chrome. Like Safari it showed the size of an .app as 102 bytes, but when I tried to upload it to the server (localhost) it just hanged. It showed a warning about a non responding page and no matter if I selected to close the page or ignore the warning. Chrome was dead and the only solution was to force quit it, even if the tab can be closed, something remains working there that didn't allow a clean exit.

So this can lead to one bug report for each browser (well Opera is almost OK, so it should be just a feature request), so much fun and job for a little test trying to find a bug in my code or CKEditor.

2 comments:

Florin said...

Method Not Allowed
Error 405

Alfonso said...

Yes, if you send the file here you'll get a 405 because I didn't point the form to a valid server script.

Testing now it seems that Chrome 5 doesn't allow to select .app files, there's no change in Safari 5, Firefox 4b2 or Opera 10.60