It’s been a while since I wrote anything here, and probably longer since I actually made any real progress on Nuubz. As was the case in 2017, life has been kind of hectic thanks to my day job. (Example, I spent roughly 2 months out of town for work out of the last 3.5 months of the year.) Well, over the last 10 days or so, I’ve made some pretty good progress.

First and foremost, I got back to work on the OAuth2 system, and I’ve managed to actually receive usable account data from both Google and Facebook with it. I have received some limited user account data from Twitch, which may just be an issue of expectations, but I’m also reconsidering Twitter support. (Up until now, I’ve thought that the lack of email or real user information in their responses made supporting Twitter pointless, but as long as an account ID is supplied, I guess it’s enough to identify a particular Twitter account.) I have updated the publicly available open source versions of these OAuth classes I implemented over at GitHub.

What I’m working on at this precise moment is encryption support. Up until now, I’ve been using mcrypt to encrypt email addresses and other important tidbits, but as of PHP 7.2, that’s deprecated. Yes, you can fight to get it installed as a PECL extension, but if you’re using the IUS version of PHP, that is exceptionally difficult to do since they don’t include a PECL binary. (I’ve done it on this server, but I can’t remember precisely how I accomplished it to tell anyone else or repeat it for my own development server.) So, I’m switching over to use Sodium, the [current] new wave of the future. In general, there are fewer commands to use to accomplish good encryption, however, it’s also more tedious because if you actually want to decrypt something you encrypted with it, you not only have to have the key, but you also have to have the nonce that was used. Which means you need to store both somewhere. There’s a trade off between security and practicality that has to be made as a result. A site I read while implementing this literally said “never use the same key and nonce twice” but how can you encrypt important data on a website without using them twice or more? That I haven’t figured out yet.

Once I get the new encryption working, I can officially implement the OAuth2 registration and login paths; I am hesitant to store the OAuth2 provider’s access key, client ID, and client secret in the database unencrypted. While I could do that on disk in the configuration file, I’m trying to minimize the important data that’s present there for fear of misconfigured web servers or clever exploits of the code I’m writing. I’m trying to be as mindful as possible of potential exploits as I write Nuubz, but there’s always something that you overlook as a programmer, and always potential and actual bugs in the software that yours depends on. Of course, once an attacker has access to the database, it’s all over. That could come from SQL injection (hopefully a path eliminated by proper use of PHP’s PDO database abstraction which I’ve used for years), some sort of cross site exploit that might elevate privileges, or a shell script of some sort that gives them access to the files on the server as if the user running the server. (Usually “apache”, “httpd”, or “www”.) Nonetheless, security is on my mind as I code.

Finally, for this update at least, I’m looking for some comic strips to post as a demo once I get that far. I really wanted to steal… ahem, borrow some strips from comics I read (Grrl Power Comic, Least I Could Do, LFG, TMI Comic, Megatokyo) to for the demo, but I think it’s better if I get some creator/writer/artist to volunteer some of their work or at least give me permission to go through their stuff. It doesn’t even have to be a real comic or part of a regular series, I just need something to showcase for Nuubz. Eventually. I’m hoping this will be the year that I have something usable to demonstrate, and not just a bunch of code tests. If you’d like to help out, drop me a line with the form below.

Beyond that, happy New Year!

So… you want to know how to upload a file via AJAX using jQuery and HTML5? Well, here’s how I’m doing it. This is not polished code, but something I cobbled together after visiting a number of sites and reading documentation in two books I have. I’m not going to provide the complete example or the PHP/server side of things, but this should be useful nonetheless.

Starting with HTML, I used the standard file input type with an onchange handler like so:

<input type="file" onchange="uploadIt(this.files);" name="uploadfile" id="uploadfile">
<div id="progressbox" >
<div id="progressbar"></div >
<div id="statustxt">0%</div>
</div>
<div id="output"</div>

The name of the field is completely arbitrary, and ultimately doesn’t matter because this field will not be submitted with your form, if you even have a form. If you do have a form, use an onsubmit() handler or your validation check to disable this field so the file isn’t uploaded a second time. By using the onchange handler, as soon as a file is chosen with the file dialog box, the upload process begins. No extra clicks are necessary. The progressbar and statustxt divisions (div) are used to indicate the upload progress, and the output division can be used for whatever output you want; while developing this code, I used it to report error messages and final status from the server.

The uploadIt function looks like this:

function uploadIt(files)
{
var file = files[0];
 switch(file.type)
 {
 case 'image/png': 
 case 'image/gif': 
 case 'image/jpeg': 
 case 'image/pjpeg':
 case 'image/webp':
 {
 $('#statustxt').html('0%');
 var fd = new FormData();
 fd.append('uploadFile',file,file.name);
 $.ajax({
 url: '/upload-handler',
 type: 'POST',
 cache: false,
 contentType: false,
 processData: false,
 data: fd,
 success: function(data, textStatus, jqXHR)
 {
 if( typeof data.error == 'undefined')
 {
 $('#output').html('<b>success!:</b> ' +data);
 }
 },
 error: function(jqXHR,textStatus,errorThrown)
 {
 $('#output').html('<b>error:</b> ' + errorThrown);
 },
 xhr: function() {
 var myXhr = $.ajaxSettings.xhr();
 if(myXhr.upload) {
 myXhr.upload.addEventListener('progress',function(event){
 var percentComplete = (event.loaded / event.total) * 100.0;
 $('#progressbox').show();
 $('#progressbar').width(percentComplete.toFixed(2) + '%') //update progressbar percent complete
 $('#statustxt').html(percentComplete.toFixed(2) + '%'); //update status text
 if(percentComplete>50)
 {
 $('#statustxt').css('color','#000'); //change status text to white after 50%
 }
 },false);
 }
 return myXhr;
 }
 });
 }
 }}

In my particular implementation, I only wanted certain file types (png, gif, jpeg, and webp as determined by the browser) to be uploaded to the server. You could also check to make sure the file is greater than 0 bytes and less than an arbitrary limit here, but I don’t have that implemented here.

Every time we have a file of the corresponding type selected, the statustxt content is set to “0%”, then we create the FormData object that will do the important job of properly formatting the file for upload. In the fd.append() call, the first parameter is the field name as it will be received on the server; this is the reason why it’s not important to have the field name set in the input tag itself. Naturally, you could copy that or use the same one, but you could just as easily set it here or make this a variable set by jQuery through another AJAX call. In PHP, this is the field name that will appear in your $_FILES variable, so you will need to know what to look for.

Next we have the file variable. While the function received an argument called “files“, and you can handle multiple files through this functionality, I wanted to maintain clarity here, and only took the first file in the files array to process and upload. Looping through the contents of files would be trivial to get this to work for multiple uploads.

The last field in fd.append() is the file name as it existed on disk at the time the file was chosen. Using this field triggers FormData to use the Content-Disposition header which, from my experience, makes the upload possible.

Next, we use jQuery to initiate the upload via the ajax function. This is where things get ugly fast, but the bottom line is you can pretty much copy and paste what I have here. But for clarity’s sake, here’s what’s what:

url is the URL to which the file will be uploaded.

type is going to be POST, though you could also use PUT in theory. There’s no reason to use PUT, but you theoretically could.

cache just as a precaution, lets make sure the browser doesn’t cache anything.

contentType is going to get set by FormData a little bit lower, so don’t manually set it. Do not confuse this with the file’s actual type or MIME type! This will get set to something akin to “multipart/form-data”.

processData we’re not going to process the data locally, so move on.

data is the FormData object, fd, that contains our file.

Next up we have 3 anonymous functions that override the success, error, and xhr handlers in the jQuery ajax call. If you don’t care about displaying progress information as the file gets uploaded, you can omit the xhr handler, though you should keep success and error so your application will know if the upload succeeded or not.

The success and error handlers here are fairly simple, they really just give you an idea of what’s happened. The success function is called if there were no errors uploading the file on the client/browser side. I repeat, the success function is called if there were no errors uploading the file on the client/browser side of things. This means that as far as the browser knows, everything went smoothly, but it’s still entirely possible that there was some error on the server, such as the server being out of space, a virus scanner might have decided the file was malware, or even just a configuration problem. Personally, I beat my head against a server side problem for a couple of hours when I couldn’t figure out why files larger than 2 MB were failing even though I had PHP configured to accept files as large as 50 MB. (Spoiler: there was a typo in a different setting in my php.ini file, which caused PHP’s ini parser to stop and use default values..)

The error function is called if there was a javascript or browser error. As stated above, this does not handle errors on the server.

The xhr handler, as presented here, is responsible for updating the progress divisions, and thus the user. xhr is shorthand for XMLHttpRequest, and we need to send jQuery a lightly prepared version of the object prior to letting it do its thing, so we’re overriding its internal instantiator for the XMLHttpRequest object. First things first, we get the copy of XMLHttpRequest this particular call is going to use through the $.ajaxSettings.xhr() call. After making sure it has the upload member, we add an event listener with another anonymous function to handle the “progress” events. With the event argument, we calculate the completion percentage percentComplete, and use that to update the status indicators.

Assuming nothing has fundamentally changed by the time you read this, your script should be able to upload a file via AJAX using jQuery and HTML5 without submitting the whole form. (Assuming you bother with one at all.)

Over the last few months, I’ve been [albeit slowly] working on a new piece of software. Instead of something for Android or a particular operating system, this one is for the web. While browsing my favorite webcomics, I came to realize that many were using WordPress which seemed like a problem to me. While WordPress is a hugely popular and flexible piece of software, it’s really overkill for webcomics. So, I started developing my own dedicated piece of software that I’m calling Nuubz.

It’s still relatively early in development, but if you want to watch on progress, you can visit http://dev.nuubz.com to take a look. Be sure to check back regularly as I make progress.