Made of Everything You're Not

No, not the flute playing Eric Lamb; the guitar playing, PHP programmer Eric Lamb. The better Eric Lamb.
  • Home
  • Projects
  • Portfolio
  • Resume

Category: Brain Dump

Practical PHP Reflection

Posted in Brain Dump, Code, Programming on March 1st, 2011 by Eric Lamb – 8 Comments

The Reflection API in PHP is one of those language features that can kind of creep up on you; it’s just not needed for a vast majority of projects. In fact, I’d wager there are a bunch of professional developers who have never had to make use of the Reflection API. Hell, I spent 8 years writing code professionally before I ever had to use it (though, because of some unrelated .NET research I was peripherally aware of it). It’s just not something that really comes up all that often in the day to day coding tasks.

Then, one day, out of nowhere, it comes up. The perfect problem where the Reflection API appears to be the perfect solution. For me this came up a couple months ago while I was working on a European zip code radius project that had to be built using one of those obfuscated and ill documented 3rd party commercial programs (nothing worse than when the platform is forced on you). So, I had to use this program that was intentionally encoded to prevent me from doing what I wanted to do. I couldn’t even look at the code; it was completely obfuscated.

Before getting into things it should be noted that the Reflection API is capable above and beyond what I’m outlining; usually for the kind of high level stuff like core Zend Framework components and anything you’d want way abstracted.

So, yeah, weird problem.

This is where reflection comes in for me. It was made for problems like the above; according to the manual:

PHP 5 comes with a complete reflection API that adds the ability to reverse-engineer classes, interfaces, functions, methods and extensions. Additionally, the reflection API offers ways to retrieve doc comments for functions, classes and methods.

So, the theory was that I could use the Reflection API to look into the obfuscated code and get some insight into what was going on and what I had to work with. I figured that, at the least, if I could see what methods, properties and comments the code had; maybe I’d get some clue about what the code was about. Using, for example, the internal PHP class “SimpleXMLElement” it’s real simple to get a nice map of the class by calling the class ReflectionClass and passing the name of the class you want to get details on as a parameter like the below:

1
2
3
4
<?php
$reflector = new ReflectionClass("SimpleXMLElement"); 
echo $reflector;
?>

The above outputs an eye gouging but verbose class map:

Class [ <internal:SimpleXML> <iterateable> class SimpleXMLElement implements Traversable ] {
 
  - Constants [0] {
  }
 
  - Static properties [0] {
  }
 
  - Static methods [0] {
  }
 
  - Properties [0] {
  }
 
  - Methods [14] {
    Method [ <internal:SimpleXML, ctor> final public method __construct ] {
    }
 
    Method [ <internal:SimpleXML> public method asXML ] {
    }
 
    Method [ <internal:SimpleXML> public method saveXML ] {
    }
 
    Method [ <internal:SimpleXML> public method xpath ] {
    }
 
    Method [ <internal:SimpleXML> public method registerXPathNamespace ] {
    }
 
    Method [ <internal:SimpleXML> public method attributes ] {
    }
 
    Method [ <internal:SimpleXML> public method children ] {
    }
 
    Method [ <internal:SimpleXML> public method getNamespaces ] {
    }
 
    Method [ <internal:SimpleXML> public method getDocNamespaces ] {
    }
 
    Method [ <internal:SimpleXML> public method getName ] {
    }
 
    Method [ <internal:SimpleXML> public method addChild ] {
    }
 
    Method [ <internal:SimpleXML> public method addAttribute ] {
    }
 
    Method [ <internal:SimpleXML> public method __toString ] {
    }
 
    Method [ <internal:SimpleXML> public method count ] {
    }
  }
}

As you can see, the above lists every property, method and constant about a class along with any parent classes and interfaces. If there were any variables the methods accepted it would also list those as well but SimpleXMLElement doesn’t have any.

It’s also possible to get the individual elements on a one by one basis while using the ReflectionClass object; for example the below methods returns the class name, any comments (if they’re in docblock format), the constants, parent class, constructor and default properties for the class DateTime.

<?php
$reflector = new ReflectionClass("DateTime");
echo "Class name: ".$reflector->getName()."\n";
echo "Doc Comment:".var_dump($reflector->getDocComment())."\n";
echo "Contants: ".var_dump($reflector->getConstants())."\n";
echo "Parent Class: ".var_dump($reflector->getParentClass())."\n";
echo "Constructor: ".var_dump($reflector->getConstructor())."\n";
echo "Default Properties: ".var_dump($reflector->getDefaultProperties())."\n";
?>

Outputs

Class name: DateTime
Doc Comment: bool(false)
Contants: array(11) {
  ["ATOM"]=>
  string(13) "Y-m-d\TH:i:sP"
  ["COOKIE"]=>
  string(16) "l, d-M-y H:i:s T"
  ["ISO8601"]=>
  string(13) "Y-m-d\TH:i:sO"
  ["RFC822"]=>
  string(16) "D, d M y H:i:s O"
  ["RFC850"]=>
  string(16) "l, d-M-y H:i:s T"
  ["RFC1036"]=>
  string(16) "D, d M y H:i:s O"
  ["RFC1123"]=>
  string(16) "D, d M Y H:i:s O"
  ["RFC2822"]=>
  string(16) "D, d M Y H:i:s O"
  ["RFC3339"]=>
  string(13) "Y-m-d\TH:i:sP"
  ["RSS"]=>
  string(16) "D, d M Y H:i:s O"
  ["W3C"]=>
  string(13) "Y-m-d\TH:i:sP"
}
 
Parent Class: bool(false)
Constructor: object(ReflectionMethod)#2 (2) {
  ["name"]=>
  string(11) "__construct"
  ["class"]=>
  string(8) "DateTime"
}
Default Properties: array(0) {
}

Check out the documentation; there are a bunch of other details you can get from other methods.

This is really just the tip of the iceberg though. There are other classes that allow even deeper insight into functions, methods, extensions and much more. Definitely worth checking out.

Bookmark and Share

My Xbox Live Fraud Experience

Posted in Brain Dump, Rant on February 14th, 2011 by Eric Lamb – 26 Comments

This Sunday I had one of those moments I’ve heard about but never experienced: my Xbox Live account was compromised and someone had purchased a crap load of points and transferred them to someone else. Since I default to the outlook that corporations don’t give a crap anymore (have they ever?) I was thinking I was screwed and was out of the money unless I contact my bank. Not the case though; turns out Micro$soft actually seemed to care and everything turned out better than expected.

On Sunday, I woke up to a series of 4 emails confirming the purchase of 10,000 points from Xbox Live Marketplace, a renewal of my Xbox Live Family account (dude actually changed my plan to include his account) and an email confirming the transfer of those points to another Xbox Live account. Now, my first thought was that I had really tied one on the night before and had just blacked out while doing some shopping on Xbox Live.  Then I remembered that I didn’t drink (just smoked) and, after checking the email timestamps, the purchases were made while I was sleeping. Fuck me.

Now, I’m not a stranger to the odd charge on my credit cards and know exactly what to do; call the bank and contest the charges. Because I actually use my Xbox though, and I do purchase a lot of content through Zune and Xbox both, I thought it would be a good idea to contact Microsoft and let them know about what was going on. God forbid I contest the charges and Microsoft thinks I’m the one ripping them off, right? So, I call them up and, after waiting on hold for a good 10 minutes, I get on the phone with Regina.

Regina was very pleasant and, after she confirmed I was who I said I was, she was actually pretty sympathetic and understanding as well. I honestly didn’t expect actual sympathy though and was pretty taken back by it; going through the motions and patronizing wouldn’t have surprised me in the least but Regina was very accommodating, knowledgeable and helpful. Regina explained that while this isn’t what she would call a common issue it does happen from time to time and, to me at least, she came across as having dealt with similar issues in the past personally. This really put me at ease when dealing with her which was good because I was in fight mode, expecting to be screwed at any moment.

One key part that struck me about this whole thing was the paper trail; because the system emailed me confirmations about each transaction it was obvious who was responsible and Regina made it clear that this a good thing. I had the username of the person the points were transferred to so, apparently, it’s pretty trivial for them to respond though I find the idea that the account wasn’t temporary ridiculous. I don’t want to underestimate the stupidity of criminals but surely the jackass who ripped me off must know the username they sent the points to would be flagged and investigated. Right?

Anyway, Regina gave me some details about what Microsoft were going to do on their side (which I’ll post once the investigation is completed lest I tip someone off in the event I know the asshole) and what my expectations should be as far as resolution (pretty good since it was caught within hours of the purchases). She also made sure to make a point of contacting my bank and letting them know as well which, while I was going to do regardless, I definitely appreciated.

It should be about a week until I hear something about the investigation and, hopefully, the resolution. All told the process took only 34 minutes and left me feeling a lot better about Xbox and Microsoft as companies to, if not completely respect, not worry about screwing me given half a chance.

That said, I’m not an idiot (well, about this stuff anyway); I still contacted my bank and contested the charges so my money is back safely where it should be. The bank, as a matter of policy, invalidated my credit card and is going to send me a new one but it’s a small price to pay I think. Well, that and now there’s no way I’m ever going to let a service keep my credit card on file ever again.

Bookmark and Share

Buh Bye Blackberry

Posted in Brain Dump, IT on November 28th, 2010 by Eric Lamb – Be the first to comment

It’s a strange day when an opinion piece condemning a device for not a few inadequacies actually sells someone else on the supposedly flawed device; but that’s exactly what happened while reading Omar Shahine’s recent rant against the iPhone. In a nutshell, he’s been using the iPhone for the last couple years and, while he initially loved the iPhone, he’s grown tired of all the problems he has (which are mostly due to his work situation because of Windows tech).

However, I have grown tired of you. As an enterprise device, you have completely failed. Each update of iOS brings more problems with Exchange support. You fundamentally don’t understand what it means to talk to an Exchange server since your programmers don’t use Exchange for their jobs. I put up with months of email hangs, years of poorly formated emails, calendar appointments went missing from my calendar, and you still don’t understand that it’s important when you look someone up in the corporate directory that you show their office location. After 2 years of this, I’m convinced you’ll never figure this out. I put up with it though because you were the best lifestyle phone around.

All good points and the above is almost picture perfect for why I’ve been sticking with the Blackberry for the last 4 years. I always looked at the iPhone (and I hate to say it but pretty much anything Apple) as just a toy used by amateurs. Yeah, I’m a snob about computers (Surprise!). But it was true; once upon a time Blackberry had the better reputation for email and, with email being as important to me as it is, Blackberry wins. It was really that simple.

Blackberry really took care of me and most of my needs for a LONG time. I’ve used the Blackberry Enterprise Server (BES), IMAP and POP with the Blackberry for email and it’s always been pretty cool (POP less so but what do you expect from POP?). There’s a pretty nice App ecosystem too, not as good as the iPhone (obviously), but I never really felt like I was missing anything. I had Google Maps, a great RSS reader with Viigo, a couple cool games, an SSH client and a pretty nice phone to boot. Along with the email, which, seriously, I thought couldn’t be beat, I was a pretty happy man.

And then, about a year and a half ago things started to get a little… crappy with the Blackberry. I’ve been using a Blackberry Bold, once a really good device, but there was a constant issue with the trackball not working. For days at a time I couldn’t scroll down. That probably doesn’t sound so bad at first glance but when you consider that the Blackberry doesn’t have keyboard shortcuts for navigation and moving the trackball to the extreme of any direction doesn’t loop to the opposite side the device in the interface this made my Blackberry pretty much useless for anything except email (painful, but usable anyway) because of a keyboard shortcut for opening that application.

I couldn’t use Google Maps and I couldn’t read any articles. I couldn’t use the web browser (unless I clicked a link in an email). Hell, a couple times I couldn’t even turn the ringer back on once I’d turned it off. Oddly though, the trackball would miraculously start working after about a week though I could never figure out what happened.

And that’s where I found myself last week as I was reading Omar’s post; I’d been ham fisting my way through using my Blackberry for basic, email only, stuff and I was fucking sick of it. Hearing all of Omar’s reasons for dropping the iPhone were reasons that don’t apply to me anymore. I don’t work in a corporate job so no more Exchange or IT policies to comply with that aren’t of my making. This was a revelation; I don’t need a Blackberry just a good smart phone that does email alright. Enter the iPhone.

So I took the plunge. I dropped a couple hundred, signed a 2 year contract with AT&T (sigh…) and after playing with the iPhone for the last 24 hours I really think I made the right choice. The whole tapping thing is pretty nice though typing is challenging right now (makes me feel like I have fat fingers…) but I’m told it gets easier.

The weird thing is just how much I love the email management. It. Is. Slick!! The iPhone really makes the Blackberry look like shit; it’s like comparing Windows 3 to Windows 7. It’s that good. Animations, smooth interface, decent search and really thorough Google Apps integration; wow was I impressed. It’s that good.

Still, the juries out on whether or not this is a good move; it’s entirely possible I’m going to regret moving to the iPhone but for now at least everything’s nice. I still have my old Blackberry Bold, ready to use at a moments notice (sans trackball moving down of course), so I should be cool but as of right now I’m happy.

Bookmark and Share

ExpressionEngine White Screen Fix

Posted in Brain Dump, Code, Programming on July 29th, 2010 by Eric Lamb – Be the first to comment

The more I work with ExpressionEngine the more I keep running into the same issues. ExpressionEngine hides most error messages, especially those related to configuration, probably for security, but this doesn’t make debugging any easier. To be fair, I don’t know if this is how ExpressionEngine works out of the box or if this is a configuration setup done by the projects original developers but it does make fixing the issue that much harder.

ExpressionEngine White Screen

ExpressionEngine White Screen

Admin White Screen

I’ve only come across the administration area throwing a white screen when using ExpressionEngine 1.67 on a PHP 5.3 server and only if extensions are enabled. I’m not sure if the newer versions of the 1.x branch have this fixed so this might not work for you.

The issue has to do with how the variables are being passed and called; PHP 5.3 changed how references were handled so the method ExpressionEngine 1.67 uses no longer works. To fix you have to modify “/system/core/core.extensions.php” with the below changes that are on the ExpressionEngine forums:

<?php
//system/core/core.extensions.php around line 115 modify:
if (sizeof($args) == 1)
{
    $args = array($which, '');
}
 
if (version_compare(PHP_VERSION, '5.3') >= 0)
{
    foreach ($args as $k => $v)
    {
        $args[$k] =& $args[$k];
    }            
}  
?>
 
<?php
//and likewise around line 174 modify:
{
    $php4_object = FALSE;
    $args = array_slice(func_get_args(), 1);
}
 
if (version_compare(PHP_VERSION, '5.3') >= 0)
{
    foreach ($args as $k => $v)
    {
        $args[$k] =& $args[$k];
    }            
}  
?>

Front End White Screen

Then there’s the front end white screen; so far I’ve encountered this type of white screen in both the 1.6 and 2.0 branches of ExpressionEngine. Luckily, whenever I’ve ran into a white screen on the front site it’s always due to various path configurations which is easily fixed by over riding the configuration file.

Expression Engine is one of those programs that stores as much as possible in the database including file and path directory paths. To get around this permanently I’ve gotten in the habit of using a default config.php file for all any Expression Engine site I work on; it’s the first thing I do before anything else.

This new configuration file uses the $_SERVER super global to dynamically determine the paths and makes allowances for development, staging and production environments.

<?php
if ( ! defined('EXT')){
	exit('Invalid file request');
}
 
$conf['app_version'] = "167";
$conf['license_number'] = "";
$conf['debug'] = "0";
$conf['install_lock'] = "1";
$conf['db_hostname'] = "";
$conf['db_username'] = "";
$conf['db_password'] = "";
$conf['db_name'] = "";
 
if('dev.site.com' == $_SERVER['HTTP_HOST'])
{
	$conf['db_hostname'] = "";
	$conf['db_username'] = "";
	$conf['db_password'] = "";
	$conf['db_name'] = "";
}
elseif('stage.site.com' == $_SERVER['HTTP_HOST'])
{
	$conf['db_hostname'] = "";
	$conf['db_username'] = "";
	$conf['db_password'] = "";
	$conf['db_name'] = "";	
}
 
$conf['avatar_url'] = "http://".$_SERVER['HTTP_HOST']."/images/avatars/";
$conf['avatar_path'] = $_SERVER['DOCUMENT_ROOT']."/images/avatars/";
$conf['photo_url'] = "http://".$_SERVER['HTTP_HOST']."/images/member_photos/";
$conf['photo_path'] = $_SERVER['DOCUMENT_ROOT']."/images/member_photos/";
$conf['sig_img_url'] = "http://".$_SERVER['HTTP_HOST']."/images/signature_attachments/";
$conf['sig_img_path'] = $_SERVER['DOCUMENT_ROOT']."/images/signature_attachments/";
$conf['prv_msg_upload_path'] = $_SERVER['DOCUMENT_ROOT']."/images/pm_attachments/";
$conf['theme_folder_url'] = "http://".$_SERVER['HTTP_HOST']."/themes/";
$conf['site_url'] = "http://".$_SERVER['HTTP_HOST'];
$conf['captcha_url'] = "http://".$_SERVER['HTTP_HOST']."/images/captchas/";
$conf['captcha_path'] = $_SERVER['DOCUMENT_ROOT']."/images/captchas/";
$conf['emoticon_path'] = "http://".$_SERVER['HTTP_HOST']."/images/smileys/";
$conf['theme_folder_path'] = $_SERVER['DOCUMENT_ROOT']."/themes/";	
$conf['db_type'] = "mysql";
$conf['db_prefix'] = "exp";
$conf['db_conntype'] = "0";
$conf['system_folder'] = "system";
$conf['cp_url'] = "http://".$_SERVER['HTTP_HOST']."/".$conf['system_folder']."/index.php";
$conf['doc_url'] = "http://expressionengine.com/docs/";
$conf['cookie_prefix'] = "";
$conf['is_system_on'] = "y";
$conf['allow_extensions'] = "y";
$conf['multiple_sites_enabled'] = "n";
?>

The above config is for the 1.x branch though most values should work for the 2.x branch with the addition of $config['tmpl_file_basepath'].

Hopefully, this should take care of those white screens.

Bookmark and Share

Portability Is A Good Goal

Posted in Brain Dump, Code, Programming on July 27th, 2010 by Eric Lamb – 2 Comments

For most web developers that I’ve met and worked with, at least, the concept of “hard coding” variable values, especially environment variables, is a definite “I will kill you and your first born if you do this” offense. Through a combination of painful moments, especially in the push to live phase, we all learned just how fucked up hard coding could make a day.

padlock

Portability Is A Good Goal

I’m telling you, it’s a special kind of pain when you’re frantically trying to fix a site you broke through poor planning and execution.

So, we do the most logical thing and abstract out all the system variables into a single point; either a config file or a database usually. For some reason we then go about our task feeling proud that we’ve stopped hard coding, oblivious to the fact that all we’ve done is just minimized the amount of hard coding. And that’s not enough.

According to WikiPedia hard coding

…refers to the software development practice of embedding input or configuration data directly into the source code of a program or other executable object, or fixed formatting of the data, instead of obtaining that data from external sources or generating data or formatting in the program itself with the given input.

Now, while that explanation is appropriate for good old fashioned native development, to be sure, I don’t think it’s applicable to web development because for most sites the database is as much a part of the application as the code is (especially when doing maintenance work). By which I mean that, in my experience, storing environment values inside a database isn’t a good idea unless there’s no other way (sometimes a project requires the rules be broken).

Anywho, for most of us who don’t have the natural, innate, knowledge, learning not to hard code was a tough lesson because when we first started developing web sites it was natural to connect the idea of the web site with the code and server it was running on. Hell, I personally remember being shocked to find out it was actually bad to develop a site on the live/production server; just didn’t make sense at the time (stupid, I know). In hindsight it was an obviously silly and short sighted mindset to adopt but changing that was probably the most important choice I’ve made to improve the quality of my projects.

I was reminded of this with painful clarity when a whole slew of issues came up from a client I’m working with. During the course of transitioning dozens of their legacy sites to a new server, some of which hadn’t been updated since the projects were completed some years ago by coders long since forgotten, quite a few started having weird and, not a little insidious, bugs in the new environment. Looking deeper into the issues revealed a nasty amount of hard coding in not only the custom projects, which I would expect actually, but also from various third party commercial and open source projects that were used for the base of the sites.

Here’s an example of what I’m talking about in terms of your everyday configuration file hard coding along with an example of what I’ve learned to do:

<?php
//bad
$path = '/var/www/mysite.com/html/';
$url = 'http://www.mysite.com';
$cache = '/var/www/mysite.com/cache/';
 
//good
$path = $_SERVER['DOCUMENT_ROOT'];
$url = 'http://'.$_SERVER['HTTP_HOST'];
$cache = $url.'/../cache/';
?>

All thanks to the $_SERVER variable, in PHP (though most languages have some way to get that info), you shouldn’t have to ever hard code the paths to pretty much anything within your site. Note though that when executing PHP through CLI scripts or using the exec() function all bets are off (though there are ways to get around that too like using variations on __FILE__ and dirname()). And, yes, there are circumstances that demand hard coding, I know, but those cases are few and far between and usually have people capable of making those changes.

It was the third party programs that really annoyed me though. I find it a little easier to accept an individual inexperienced coder’s exuberance in coming up with a base solution at zero hour. I’ve been there; an issue comes up and the quickest, and less painful, solution is to just throw the path in place with a perosnal promise to come back later and make it elegant. Then… well, life takes over and the promise is forgotten. Happens all the time.

On the other hand though, when dealing with third party projects, both open source and commercial, this type of hard coding, well, that just bugs the crap out of me. It seems like such an obvious design decision yet Expression Engine, Zen Cart and WordPress (for example) all hard code environment variables into the configuration files.

This is especially irritating to me because it’s been my experience that most websites move to a different server at one time or another, so it’s a given that configuration is going to be changed at some point. Keeping the pain of moving the site to a minimum rates a higher priority to me. And, unless I’m missing something, it seems that there’s very little difference between having your installation/configuration script write $_SERVER['DOCUMENT_ROOT'] versus “/var/www/html” to a configuration file.

Something like (as a base example with no sanitization):

<?php
if($_POST['path'] == $_SERVER['DOCUMENT_ROOT'])
{
    $path = '$_SERVER[\'DOCUMENT_ROOT\']';
}
else
{
    $path = $_POST['path'];
}
 
//write it to the config file
?>

As I mentioned above there are definitely times when $_SERVER['DOCUMENT_ROOT'] isn’t appropriate per the requirements or spec but for most projects that I’ve worked with replacing hard paths with the variable has been effective 99% of the time.

Bookmark and Share

Create Expression Engine Plugin

Posted in Brain Dump, Code, Programming on June 8th, 2010 by Eric Lamb – 1 Comment

In Expression Engine Escaping Madness I laid out an issue I was experiencing with a client site. The issue was that there didn’t appear to be a method available to escape Expression Engine markup when it is mixed with php so there is a definite risk of parse errors using that technique (it’s not a security issue or anything; I want to be clear on that). This made me nervous enough that I couldn’t let it go and kept thinking about how to get around the issue. The answer: write an Expression Engine plugin. Of course this meant I had to actually learn how to write an Expression Engine plugin first. Here are my notes :)

Create Expression Engine Plugin

Create Expression Engine Plugin

First though credit where it’s due: for this example I used the number_format plugin as a base so a lot of credit goes to Robert Wallis for the nicely written plugin I’m basically leaching from:)

An Expression Engine plugin is essentially a php class with at least one method that translates into an Expression Engine tag and used inside of Expression Engine templates (I don’t think they can be used inside of entries directly though I haven’t confirmed this). They are best left for small tasks though because they can’t have an administrative backend or integration with the Expression Engine l10n stuff or form processing or any manageable settings. No fun stuff for plugins…

Like most platforms there’s a few conventions that have to be followed but, also like most platforms, they aren’t too troublesome to work with. It should be noted that the syntax for the class uses the php4 syntax so dumb yourself down accordingly.

For example our plugin class will look like:

<?php
class Add_Slashes
{
	function Add_Slashes()
	{
 
        }
}

And the plugin will be executed with the below Expression Engine template tag:

{exp:add_slashes}O'Reilly{/exp:add_slashes}

Now, it’s possible to create template tags that aren’t done in pairs but for this example I’m going to stick with pairs. In case it wasn’t obvious, if you wanted to have a plugin that has more than a single method you would call that method like:

{exp:add_slashes:somethingelse}O'Reilly{/exp:add_slashes:somethingelse}

So that’s the basic syntax. The next thing that needs to be done is that a file has to be created inside the “/system/plugin/” folder. Note that I’m using the default name for that folder (system) so if you renamed it during the installation process use that instead. The file name must be lower case the same as the class name and it must have pi. as the prefix, and begin with the second segment of the tag. So, with our example plugin, the plugin name would be: pi.add_slashes.php. Simple enough. Once the file is saved to the location the plugin is installed. That’s how Expression Engine rolls.

Now we have a working plugin in theory but if you go into the plugin manager you’ll see an error about a missing variable as well as a distorted view of the page. We’re missing something; the $plugin_info array.

Every Expression Engine plugin should have a variable outside of the class called $plugin_info. For our example it should look like the below:

<?php
$plugin_info = array(
	'pi_name'        => 'Add Slashes',
	'pi_version'      => '1.0',
	'pi_author'       => 'Eric Lamb',
	'pi_author_url'  => 'http://blog.ericlamb.net/',
	'pi_description' => 'Exposes PHP\'s <a href="http://php.net/manual/en/function.addslashes.php">addslashes()</a> function via EE tags.',
	'pi_usage'        => Add_Slashes::usage()
);
?>

Obviously, the above lists all the details about the plugin for display in the plugin administration module:

Expression Engine Plugin Manager

Expression Engine Plugin Manager

You may have noticed the pi_usage key in the array; this method is recommended by the Expression Engine Developer Center for describing the usage of a plugin. Inside the plugin create a method called usage() and just return the instructions. Those instructions will be used on the plugin description page:

Expression Engine Plugin Information

Expression Engine Plugin Information

Using all of the above the completed plugin is below:

<?php
$plugin_info = array(
	'pi_name'        => 'Add Slashes',
	'pi_version'      => '1.0',
	'pi_author'       => 'Eric Lamb',
	'pi_author_url'  => 'http://blog.ericlamb.net/',
	'pi_description' => 'Exposes PHP\'s <a href="http://php.net/manual/en/function.addslashes.php">addslashes()</a> function via EE tags.',
	'pi_usage'        => Add_Slashes::usage()
);
 
class Add_Slashes
{
	function Add_Slashes()
	{
		global $TMPL;
		$this->return_data = addslashes($TMPL->tagdata);
        } 
 
	function usage()
	{
		return "This is really just a wrapper for PHP's add_slashes function:
http://php.net/manual/en/function.addslashes.php
 
{exp:add_slashes}
O'Reilly
{/exp:add_slashes}
returns: O\'Reilly
 
";
	} 
 
}

Now, this example was used using Expression Engine 1.6.9 so the process might not work for the upcoming 2.0 (I haven’t looked into that version just yet). It also doesn’t look like EllisLabs is accepting any new submissions to their plugin library so if you’re hoping to distribute your plugin prepare to do it solo and without any help from them.

Still, an easy enough process that any custom functionality you may need for an Expression Engine site should be trivial to achieve.

UPDATE February 21, 2011
I completely forgot to include any info on customization through passing parameters. Note: this is totally cribbed from the ExpressionEngine forums.

{exp:add_slashes return="FALSE"}
O'Reilly
{/exp:add_slashes}

Doing the above will create a variable within the plugin called “return” which can be accessed like:

<?php
global $TMPL;
$return = $TMPL->fetch_param('return');  
?>
Bookmark and Share

A Closer Look At Avactis

Posted in Brain Dump, Code, Programming, Rant on May 31st, 2010 by Eric Lamb – 8 Comments

Avactis is another in a long line of e-commerce web applications written in php (similar to OpenCart and PrestaCart), this one a little different in that Avactis has different versions, each with different features, depending on how much you’re willing to spend. Avactis is a full featured product with all the bells and whistles any ambitious store would need (and then some more features stacked on top for good measure) combined with a very php like integration methodology. Unfortunately, the dated administration interface combined with a lack of a plugin architecture and theme community really holds it back from the awesome bar.

Avactis

Avactis

For the uninitiated, Avactis is created and maintained by Pentasoft Corp; oddly, there’s no website for the parent company so take that for what you will. As mentioned, Avactis is based on a pay model though it’s way more upfront about it than PrestaCart and, while the free version is missing some features, the source is available for modifications. Not too bad in my opinion; at least the more cash strapped shops can still play if they want to.

The different versions of Avactis are Free, Owned ($199), Monthly Leased ($19.95 a month) and White Label ($299) each with their own features and options. Most notably the Free version doesn’t include any (useful) payment modules (Authorize.net anyone?), coupon module, data export and import, quantity discounts or search engine friendly URLs out of the box. They do offer discounts for web developers though (at least 50% and they say up to 100%), and the complete source is available without obfuscation, so at least those functions that are needed can be added which can really ease the pain of paying for the thing in my opinion.

As expected, Avactis has the ability for custom themes though I’m disappointed to see that there doesn’t appear to be any theme community in existence (compared to other cart software packages). The reasoning behind this is probably because Avactis bills itself as being “easy integration with an existing website thanks to unique Avactis tag technology”. And by unique they mean including a php file and calling php function snippets. I’m all for marketing hype but wtf is that?!? Here’s an example:

<?php include('init.php'); ?>
<?php NavigationBar(); ?>
<?php Breadcrumb(); ?>
<?php ProductList(); ?>

It’s called php and EVERY php site does this Avactis not just you. Essentially though, this isn’t a bad strategy and, in fact, is definitely a strength especially without all the hyperbole. Obviously, Avactis can stand alone and doesn’t need to be integrated into a separate site but it’s a good idea to allow easy integration into existing sites.

Avactis PHP shopping cart software

Avactis PHP shopping cart software

Avactis is packed with all the features any online store would want; content management system, coupon and discount mechanisms, order and customer management, packing slip builder to name a few. Each feature is also highly customizable and usually includes a plethora of options and settings; nice if you build complex product build outs or specific functionality. On the other hand though, this amount of features and customization comes at a cost in terms of ease of use, work flow and a lacking user friendly experience.

The administration interface for Avactis is a nightmare mess of pop-up windows, tabs and accordion widgets. Slick is not a word I would use to describe the experience. Functional or crappy or painful or eyebleedingworstinterfaceeverpleasekillmefortheloveofgod!; those are better words to describe it.

There’s inconsistencies all over the place; for example while editing a product the help widgets will open another pop-up window (sigh…) yet in the main menu hovering over a link will display a tool tip and in the installation process the help widgets are all inline divs.

Avactis Admin Popups

Avactis Admin Popups

Going through the code yields such codesod qualifiers as the below:

<?php
    /**
     * Defines the possibility of uploading images by file type.
     *
     * @param $file The array consists of the $_FILES variable, for
     * the current file.
     * @return boolean
     */
    function isAllowedImageType($file)
    {
/*        $type = _ml_strtolower($file['type']);
        switch ($type)
        {
            case 'image/gif':
            case 'image/jpeg':
            case 'image/jpg':
            case 'image/jpe':
            case 'image/jfif':
            case 'image/pjpeg':
            case 'image/pjp':
            case 'image/png':
            case 'image/x-png':
                return true;
            default:
                return false;
        }
*/
        return true;
    }
?>

If that doesn’t make any sense to you suffice it to say that the above function is supposed to verify that an image’s mime type matches the list; unfortunately though, the function is, what we call “commented out” and will not be executed. All files sent to the function will validate as true so, essentially, any file type can be uploaded. While it’s entirely possible this is an old function that was replaced with something useful, and it should be noted that I never found any calls to that function (but I really didn’t look too hard), the fact that it’s still in the code-base speaks volumes, to me, about the project maintenance at the very least.

On top of that Avactis has one of the most wasteful and useless installation processes I’ve ever seen. Initially, Avactis ships with a very minimal file set that includes a 15 mega byte (MB) file whose sole purpose is to contain all additional files in a gzipped and base64 encoded string. The sole purpose of this is to allow Avactis to programmatically write all source files to the file system during installation. For the life of me I can’t imagine what functional requirement precipitated this design decision. Considering the complexity added to the development cycle this would cause it makes no sense to me; I’m at a loss. I could be missing something though; you never know it may have a really sick benefit that I’m just not privy to.

Are any of those “issues” at all relevant? Not the function and not the installation process. Those are subjective issues that may only matter to me; it’s armchair quarterbacking at it’s finest (if I do say so myself). For everything else, well, that obviously depends on the specific needs of the project. For my needs it’s a pass simply because my clients care about the interface and Avactis looks like it hasn’t been updated since 2002 (at least).

So, while Avactis is a nice program with all of the features any store would ever need I personally feel that it’s not ready for my project.

Bookmark and Share

Should We Use OpenCart?

Posted in Brain Dump, Programming on May 25th, 2010 by Eric Lamb – 39 Comments

As a continuation of my research into choosing an appropriate shopping cart application for an upcoming project I’m working on I chose to review OpenCart this time. To be honest, I hadn’t even heard of OpenCart until one of the comments from the last post turned me onto it but after reviewing it I am glad I did.

opencart-logo

opencart-logo

As mentioned above, OpenCart is another e-commerce platform useful for setting up an online storefront. OpenCart is released under the GNU General Public License version 3 (GPLv3) which means it’s freely available for anyone to use and since OpenCart is written in php it’s right in my wheel house. The main developer of OpenCart is Daniel Kerr who, from what I can gather, is over in Great Britain but not the Australian rules footballer (in case there was some confusion from any Aussies).

Anywho, OpenCart has lot of good features available out of the box with my favorites being the Backup Manager, User Groups, really nice localization (l18n) and internationalization (i18n) options, support for multiple stores and a slick reporting overview. OpenCart also has the one feature I personally love from any and all e-commerce packages; Guest Checkouts. Personally, when I’m buying something from an online store that’s not a 500 pound gorilla like Amazon or Best Buy I hate signing up for an account. Guest checkout is the shit.

The code is really well structured and thought out; it uses a nice implementation of the MVC pattern which made things ridiculously easy to walk through and find out what was going on under the hood. OpenCart appears to be using a home grown MVC framework, which, while, in my opinion a little unnecessary,  isn’t at all a big deal. Unfortunately, the code appears to be open to Cross Site Request Forgery (CSRF) attacks and other security issues. More on this in a minute.

The OpenCart administration module is attractive and laid out logically. Everything is ready and available in such a way that most people with experience working with administration panels would feel right at home. It should be noted though that the administration panel will NOT work in Internet Explorer 6.

OpenCart Dashboard

OpenCart Dashboard

Naturally, OpenCart also ships with the ability to have custom themes and the default theme that ships with OpenCart is quite attractive too. After reviewing the procedure for creating themes though I have to say that I’m not even a little impressed in how themes are supposed to be created; they appear, in my opinion, to be overly complicated, a little convoluted and deviates from the traditional manner used with countless other open source projects.

OpenCart Store

OpenCart Store

OpenCart has a basic module system though it isn’t what, in my experience, should be considered a module system; in OpenCart a module is more of a sidebar widget. A small distinction to be sure and not really an issue; more of an inconvenience of nomenclature than anything else but something that drives me nuts (can’t we all agree on what these terms mean already?).

There’s also a lot of manual intervention needed when configuring the system. Want to add a module? FTP the module, go to the module section of the admin, click install, click edit and fill out the form (be sure to enable the module too). Want to turn on search engine friendly URLs? Rename the file .htaccess.txt to .htaccess (through FTP or similar) then go to the administration panel, then to the settings area to enable. Very anti user friendly in my opinion.

There are other issues with OpenCart, like the flow for adding images to a product being pretty convoluted, but those are all small in the grand scheme (pretty much all my gripes can be, rightfully, dismissed as design decisions I don’t agree with). Fair enough. What isn’t acceptable is the complete lack of respect the developer has for security in OpenCart or the developers who try to help out in general. This, I’m afraid, is a deal breaker.

May 2010 was actually a pretty fortuitous time for me to research OpenCart; as soon as I began looking into the program I started seeing some discussion on OpenCart which lead me to a forum post on the official OpenCart forums. Another developer had some suggestions on how to improve the style and conventions of OpenCart and, well, Daniel really showed his ass.

Then, not a week later, I see on that there’s another war going on between Daniel and a developer who found some pretty nasty CSRF issues. Again, Daniel showed his ass (along with a good helping of ignorance mixed with arrogance this time) with nothing being resolved.

This was truly the breaking point for me. Why in the world would I ever use software written by someone who, when confronted with the issues, acts like nothing’s wrong? Nope. I have people relying on me to make choices that won’t, you know, ruin their business and OpenCart, for all it’s bells and whistles and nice code and pretty administration panel, is a horrible platform because the developer refuses to do anything about issues when presented with them.

Bookmark and Share

The Horrors of C99.php

Posted in Brain Dump, Code, IT on February 22nd, 2010 by Eric Lamb – 17 Comments

If you were a sysadmin a few years ago, and you had php on your servers, you’re probably already familiar with c99. In case you haven’t had the personal pleasure, c99, or specifically c99.php (hint: check the source), is the name of a script used by hackers to gain access to a web server running php using an exploit technique called Remote File Inclusion.

The Horrors of C99.php

The Horrors of C99.php

A Little History

See, back in the day some php developers were pretty stupid. (Admit it; you were stupid once too.) What other explanation could there be for writing code that allowed the injection of arbitrary routines into a program. Trivially easy too.

To be fair, PHP was to blame a little for this as well. Given PHP’s high adoption, and design, by, and for, newbie programmers allowing such a technique by default was just ill conceived, and maybe even a little negligent. I understand the desire, and sometime need, for a technique that could be dangerous but to enable the feature by default…. damn man…

So, the risk was known, yet code was still being written (like the below example) that allowed remote file inclusion to be possible. Mostly because of the aforementioned default setting.

<?php
$color = 'blue';
if (isset( $_GET['COLOR'] ) )
{
	$color = $_GET['COLOR'];
}
require( $color . '.php' );
?>

BTW, if you currently write code that does anything like the above, frankly, you’re an idiot. You aren’t nearly as smart and clever as you think you are. I promise you this will bite you. Bad too.

About C99.php

So, using a technique like the above opens you up to learning first hand about c99.php. Finding information about the program itself is a little tricky but there are a couple examples that highlight just how devastating it can be.

When malicious intruders compromise a web server, there’s an excellent chance a famous Russian PHP script, r57shell, will follow. The r57shell PHP script gives the intruder a number of capabilities, including, but not limited to: downloading files, uploading files, creating backdoors, setting up a spam relay, forging email, bouncing a connection to decrease the risk of being caught, and even taking control of SQL databases. All these functions become readily available through an easy to use web interface, but now you can fight back.

Using the above explanation, which I agree with, c99.php acts as an interface to control your server. Once it’s on your server an attacker has easy access to view all the files and their contents, make changes to the system, upload new files, manipulate the database(s) and more.

Quite the nasty little script but pretty elegant in how it’s implemented. c99 is a completely standalone script; even the images are embedded inside using base64!

Until a month ago I would have thought the risk of encountering c99.php in the wild would have been small these days. Then, SMACK!!, a client had a site get hacked (quick CYA; that I didn’t’ work on :) ) using c99. So be warned. It’s out there and if you’re not smart, or if you’re a lazy, lazy, coder, c99 will get you.

Bookmark and Share

Google Didn’t Fuck You; You Did

Posted in Brain Dump, Rant on February 15th, 2010 by Eric Lamb – 1 Comment

With the release of Google Buzz last week a lot of people have been screaming bloody murder over some privacy concerns they have and Google’s perceived lack of forethought on the matter.

Google Didn't Fuck You; You Did

Google Didn't Fuck You; You Did

First, Google Buzz appears to be a FriendFeed clone that Google just launched about a week (or 2) ago. Initially, it was enabled inside of all gmail accounts by default without any authorization to the contrary. I haven’t had the opportunity to try it though. Not because I don’t use gmail (I do; sorta) but because I use Google Apps gmail which wasn’t a part of the rollout.

From what I can glean; Google Buzz works by parsing your contact list and then making connections between everyone in it and displaying their social network activity info publicly for all to see (seriously, just like FriendFeed). Make sense? No? Here’s the Crunchgear explanation of Google Buzz:

Google Buzz is a social network and sharing product built by Google. Based within Google Profiles, Buzz offers a stream of status updates, pictures, links, and videos from your friends. You can “like” these items and you can comment on them. Updates from Flickr, Picasa, Google Reader, or Twitter can also be automatically imported into a Buzz stream. Buzz will recommend items you might like based on your friends’ activity.

So, apparently, one of the “features” of Google Buzz is that when it was initially released it displayed your contact list publicly which raised all sorts of hell from people who can’t afford for this to happen (think lawyers, journalists, etc).

This smacks of a high level of naivete on most of the users. Under what delusion are people living in to think that they have any expectation of privacy from a publicly traded company. Yes, I know they claim to care about your privacy, and I’m sure on a personal level the people working for Google do, in fact, care about your privacy. But the organization itself? Not a fucking chance.

Let’s get serious here; as stated above, Google is a publicly traded company which means their priorities start and end with cash ($$$). Frankly, it’s naive to think otherwise. Ask any corporate officer and they’ll tell you they have a responsibility to their shareholders. This is a notorious lose for consumers but it’s the reality nonetheless. Cry all you want but Google fucking their users in this way did ensure they launched a new social network with millions of users. From a fiscal standpoint, this was a HUGE win even with all the bitching and moaning. Even taking into account any users who would leave Google (along with any ill will this may have created) this was still a winning strategy for launch.

If privacy is an issue then, it seems to me, that you really should have taken greater measures to protect yourself. Relying on Google to protect something like this screams of escapism and finger pointing. Guess what? It’s your fault. Deal with that instead of crying that a publicly traded company that provides a service you use for free does something in a way that you don’t like.

Do I think that Google was right in any way for doing what they did? Not for a second. That said, people need to take responsibility for their own needs instead of blindly trusting a for profit company to do it for them. Yes, even when that company claims to “do no evil”.

Bookmark and Share
« Older Entries
Newer Entries »
  • Subscribe: Entries | Comments
  • About Me

    Email Email
    Twitter Twitter
    310.739.3322
  • Categories

    • Brain Dump
    • Business
    • Code
    • IT
    • Programming
    • Rant
    • Servers
  • Archives

    • February 2012
    • October 2011
    • August 2011
    • July 2011
    • June 2011
    • May 2011
    • April 2011
    • March 2011
    • February 2011
    • January 2011
    • December 2010
    • November 2010
    • October 2010
    • September 2010
    • August 2010
    • July 2010
    • June 2010
    • May 2010
    • April 2010
    • March 2010
    • February 2010
    • January 2010
    • December 2009
    • November 2009
    • October 2009
    • September 2009
    • August 2009
    • July 2009
    • June 2009
    • May 2009
    • April 2009
    • March 2009
    • February 2009
    • January 2009
    • December 2008
    • November 2008
    • October 2008

Copyright © 2008 - 2012 Eric Lamb - All rights reserved