Terrible PHP hacks: making PHP/FI style file uploads work in PHP5.5 and newer

Mar 22, 2014 18:15


One of my past consulting customers, came to me with a problem. He'd been relatively diligent in upgrading his servers since last I spoke (it had been some years), and now the admin panel on one of his client's very old PHP websites was no longer working.

I knew the code had some roots back to at least PHP3, at the file headers I'd previously seen had copyright dates back to 1999. Little did I know, I was in for a treat today.

When last I visited this codebase, due to it's terrible nature with hundreds of globals, I had to put some hacks in for PHP 5.4, since register_globals were no longer an option. The hack for this is quite simple:

foreach($_POST as $__k => $__v) { $$__k = $__v; } foreach($_GET as $__k => $__v) { $$__k = $__v; }
Well it seems since the last upgrade, they had also changed the register_long_arrays setting by demand of another project, and the login on the old site was broken. Quite simple this, just need to s/HTTP_SERVER_VARS/_SERVER/ (and similarly for POST/GET/COOKIE depending on your site).

Almost all was well now, except that the next complain was file uploads didn't work for several forms. I naively duplicated the _POST/_GET block above to $_FILES. No luck. Thus, my memory not remembering how file uploads used to work in early PHP, I set out to fix this.

I picked a good one to test with, and noticed that it used some of the very old PHP variables for file uploads (again globals). These files dated back to 1997 and PHP/FI!. The initial solution was to map $_FILES[x]['tmp_name'] to $x, and the rest of $_FILES[x][y] to $x_y. Great it seems to work now.

Except... one file upload form was still broken; it had multiple files allowed in a single form. Time for a more advanced hack:

# PHP/FI used this structure for files: http://www.php.net/manual/phpfi2.php#upload foreach($_FILES as $__k => $__v) { if(!is_array($__v['tmp_name'])) { $s = $__k; $$s = $__v['tmp_name']; $keys = array('name','size','type'); foreach($keys as $k) { $s = $__k.'_'.$k; $$s = $__v[$k]; } } else { for($i = 0; $i <= count($__v['tmp_name']); $i++) { if(defined($__v['tmp_name']) && defined($__v['tmp_name'][$i])) { $s = $__k.'['.$i.']'; $$s = $__v['tmp_name'][$i]; $keys = array('name','size','type'); foreach($keys as $k) { $s = $__k.'_'.$k.'['.$i.']'; $$s = $__v[$k][$i]; } } } } }
Thus I solved the problem, and had to relearn back how it used to be done with PHP/FI.

php, old code

Previous post Next post
Up