Archive for the ‘Javascript’ Category
Drag & drop Uploads with XMLHttpRequest2 and PHP
I finally had some time to read through my ever growing list must read items and play with some new software. While reading up on the new Firefox 3.6 i noticed it came with the new XMLHttpRequest [2] object based on the new file API. And according to the new specs. This would allow for easy file uploads. Now there’s been some examples [2] on the web already. But i just wanted to get my hands dirty.
The new XMLHttpRequest object makes is possible to send files in a few different formats. The most important being the binary format. The code for sending a request with XMLHttpRequest2 looks the same as the previous version. Except for sendAsBinary() in this case.
var xhr = new XMLHttpRequest();
fileUpload = xhr.upload,
fileUpload.onload = function() {
console.log("Sent!");
}
xhr.open("POST", "upload.php", true);
xhr.sendAsBinary(file.getAsBinary());
So let’s set things up for drag & drop. We need a div that will be the main drop point. And we need some event listeners to catch the drag * drop events. Let start by creating the drop zone. For this we use two simple divs. The outer div will listen for the drag & drop events. And the inner will catch the files.
Now let’s create our upload code.
var upload = {
setup : function() {},
uploadFiles : function() {event}
}
window.addEventListener("load", upload.setup, false);
The setup method will set all event listeners for drag & drop. And register the upload handler.
var container = document.getElementById('container');
var drop = document.getElementById('drop');
container.addEventListener("dragenter", function(event) {
drop.innerHTML = '';
event.stopPropagation();
event.preventDefault();
},
false
);
container.addEventListener("dragover", function(event) {
event.stopPropagation();
event.preventDefault();
},
false
);
container.addEventListener("drop", upload.uploadFiles, false);
As you could see above. the uploadFiles() method gets a event returned from the drag & drop action. This is where the new file APi comes in play. To get to the file property we access the dataTransfer object.
var files = event.dataTransfer.files;
The actual uploading is easy as cake.
for (var x = 0; x < files.length; x++) {
var file = files.item(x);
var xhr = new XMLHttpRequest();
fileUpload = xhr.upload,
fileUpload.onload = function() {
console.log("Sent!");
}
xhr.open("POST", "upload.php", true);
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.setRequestHeader("X-File-Name", file.fileName);
xhr.setRequestHeader("X-File-Size", file.fileSize);
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.sendAsBinary(file.getAsBinary());
}
That's it for the client side. There is however a small problem on the receiving side. When handling uploaded files in PHP we expect the $_FILES array to be populated. This is not the case when streaming files from the client to the server. To get the needed file information we set some headers on the client side X-File-Name and X-File-Size. And since the $_FILES are is empty. We need an other way to get the file contents. So we will use php://input streams for that.
The contents of upload.php look like this:
require_once('Streamer.php');
$ft = new File_Streamer();
$ft->setDestination('data/');
$ft->receive();
With setDestination() the destination path for the uploaded files is set. And recieve() listens for any incoming files. Most of the magic is done in the recieve() method. So here's the code.
public function receive()
{
if (!$this->isValid()) {
throw new Exception('No file uploaded!');
}
file_put_contents(
$this->_destination . $this->_fileName,
file_get_contents("php://input")
);
return true;
}
I am impressed! This promises a lot of good. And offers some interesting options. Let's hope all browsers implement this gem. I still have one issue though. I can't get this to work in firefox under linux. The drag & drop events do not seem to function properly with files being dragged from the desktop. anybody know why?
If you interested in the complete code. you can find it here
0x.vc URL shortener service
Having a hard time getting to sleep tonight. And was browsing my domain list. when i realized i still have this very short domain name that is just sitting there collecting dust. And since these URl shortener services are so hot lately i decided to roll my own.
So three hours, a bit of code and a short domain name later i present : 0x.vc (it’s shorter) It’s probably still full of holes and prone to XSS attacks. So be careful!
XSS vulnerability on Dutch bank websites
My wife just send me a link to security.nl. Pointing to an article about XSS vulnerability in Dutch banking websites. And since i am from the Netherlands. I thought to check this out a bit.
security.nl states that a “security researcher” found XSS bugs in most of Dutch websites. With a link that seems to point to the “researchers” blog. I don’t know about you. But i personally don’t trust websites that i never seen before. Let alone “researchers” that have absolutely no credibility in the scene. However the XSS bugs are real. But is this really something to write about? Showing an alert box on a screen shot seems very lame to me. I wonder if this is even exploitable at all?
One good point is that at least one bank responded in time and fixed the bug.
Animated loader on form submit
In one of our sites we load content of a third party travel organization. And some of these calls can take some time. But when the pages are loading nothing really happens to the browser state. This is confusing for the users of the website. So i decided to add some animated preloader images. Just to show the users the site is still doing stuff.
This however confronted me with a small problem. The preloader images are supposed to show up when a form is submitted. And this is exactly what’s causing the problem. In my first attempt i created the image object when the form was submitted. On submit a JavaScript function was called. This function created the image object and displayed it.
function loader() {
var loaderImg = new Image();
loaderImg.src = 'some/image/url/';
}
This however resulted in an image displayed that had no active animation. This happens i think because the image is not fully loaded when the user hits submit on the form. So to fix this i had to load the images before the page was completely rendered.
var loaderImg = new Image();
window.onload = function() {
loaderImg.src = 'some/image/url';
}







