Adobe Air Log File Watcher

August 9th, 2008 by Aaron

One of the biggest pet-peaves I have is when errors are generated on PHP files between redirects using the header() function. Especially if they’re not a fatal error, you never get to see them! Also, missing files that hit the apache logs usually are not found later until you review the logs as well. I thought: wouldn’t it be great if there was a tool that would watch these log files for me? (yes, a while ago, I talked about the perl “tail” script that I used in my eclipse to watch these… but… this is even better). Well there is a solution! My first Adobe Air application: Log File Watcher!

This was my first attempt at using Adobe Air - and I’d have to say I like it. This application is very ugly - I didn’t really use any CSS or anything. I used JS and HTML - no action script (well besides AIR’s built in stuff…).

Basically, I found some examples online and pieced them all together - and it worked! So yay. (Also, a good portion of this was done while working at SuperDev - sooo… shhhh)

Anyway, when you first start out the application, you can choose 1 or more files for it to watch. Then, when you click to start the watching, the application minimizes to the tray. (at least in windows…). Then, it will generate a popup whenever there is a change in any of the files that you’re watching.

Yeh, not great, but it was a start.

I’ve attached the AIR application - and a zip with the source in it. If I find time later, I might come back and rewrite it to be 1) prettier and 2) more useful. hah!

Adobe Air Application: logfilewatcher.air

Adobe Air Source files: logfilewatcher.zip


Programming without E_Notice

July 17th, 2008 by Aaron

Well, my boss at #superdev - who can only be compared to a more energetic version of the squirrel from hoodwinked

#superdev boss

#superdev boss

asked me to start putting together some thoughts here and there on some proper PHP coding. I thought I’d start out the series with this article, Programming without E_NOTICE.

Ok.

How does it happen?

E_NOTICE errors are generally generated when variables that haven’t been declared are read. But Aaron - why is this an error? I thought PHP did not require you to define your variables a head of time? Well, buddy, thanks for asking! PHP does not require you to define your variables ahead of time - when you write to them. However, it does suggest that you define them with some value before you read them. One of the main reasons why this is important is the registered globals feature… “feature”… that PHP had prior to PHP6.

Image this code:

1
2
3
4
5
<?php
if ($admin) {
 print "super secret stuff";
}
?>

Well, every time you run this script, no super secret stuff will be printed. However, if you have registered globals on, and then pass in a get variable, such as:
http://localhost/test.php?admin=TRUE
you’ll find that you just accessed a variable that was set to something you didn’t really expect.

Anyways, that’s the history of why this notice was generated.

Now, lets move on to the real meat:

Uninstantiated Variables

Lets take a common decision tree:

If my variable has been set to something, print something else. If my admin variable has been set, print the admin menu.

I’ve seen code do this like this:

1
2
3
4
5
<?php
if ($isAdmin) {
 print "<div id='menu'>blahb lah blah</div>";
}
?>

Also, other times I’ve seen this:

1
2
3
4
5
<?php
if (!$normalUser) {
 print "<div id='menu'>blah blalhickity blah</div>";
}
?>

Both of these are bound to generate E_NOTICE errors if not used properly. We’ll use the first example. Think about this:
Is there ever a case where $isAdmin won’t be set? You know that an unset variable will evaluate to false - but php will generate that E_NOTICE on you.

How to fix this?

There are two ways that you can fix this type of error:

First, predefine every variable to a blank or null before you could even use it. This is especially good for those who still have registered globals on.

1
2
3
4
5
6
7
8
9
10
<?php
/** top of script **/
$isAdmin = FALSE;
 
/** some function that may or may not actually define $isAdmin to true or false **/
areTheyAdmin();
 
if ($isAdmin) {
/** continues **/
?>

Other suitable predefined values include: ”, NULL, 0, array().

One Caveat: Be careful with predefining your values, however, so that you don’t use a legitimate value when not expecting it. For example, if you assigned $locationOfString = 0 and then did a stristr(), you could legitimately get a 0 returned. This might cause issues with your code that might be difficult to track down-such as false positives.

If you’re really lazy and don’t like spending all those extra lines, here’s a tip:

1
2
3
4
5
<?php
$a = '';
$b = '';
$c = '';
?>

OR


The second style: using isset().

Isset will return whether the variable is set to any value or not. If it is not, it returns false, and then your if statement exits right away. No calculation is done on an unset variable. Example:

1
2
3
4
5
6
7
<?php
 
areTheyAdmin();
 
if (isset($isAdmin) && $isAdmin) {
 /** continue some stuff here for admin dude **/
?>

What else does this affect?

This also affects array keys that are unset. You can view array keys the exact same as variables - you shouldn’t read from an unset one - but you can write to one that doesn’t exist yet.

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
 
$myArray = array('something'=>"another");
 
/** bad boy **/
if ($myArray['kakaw']) {
 print "word";
}
 
/** good to go boy **/
$myArray['chunky'] = 'soup';
 
?>

As with variables, you should use isset(). I would caution against using array_key_exists(). Isset is a language construct whereas array_key_exists() is not - so isset is immensely faster. The only time you might want to use array_key_exists is when you have an array of keys. Otherwise, isset() supports everything you need.

Bonus! In that previous example, to write to the chunky key, you don’t even have to define $myArray. In this example, $arrayKaBob is defined into an array automatically, and then the key is set:

1
2
3
<?php
$arrayKaBob['key master'] = 'gate keeper';
?>

Well what if I just use the @?

Don’t. Seriously. Look here.

Wrapping it Up

Ok - so that about wraps it up - any comments are welcome. :)


JEMGames Launched

June 6th, 2008 by Aaron

JEMGames has finally joined the 102 Degrees network. JEMGames is an experiment comparing the successfulness of a custom programed websites versus off the shelf open source PHP scripts.


No More “The Triangle”

June 6th, 2008 by Aaron

Well, I’ve officially resigned from “The Triangle.” Don’t worry, I’ve got a new place to keep bring experience to this blog. I look forward to my new opportunities.


Prototype JS - form elements need names, not just IDs

June 6th, 2008 by Aaron

So, I got stuck on this bug for an hour - so I thought I’d write it down.

I was using prototype js’s serialize command on a form. I was also using a strict xhtml doctype. My form elements had IDs only - and did not have names. Well, serialize kept coming back empty. Turns out that prototype requires there to be names on each of the elements.

UPDATE: Der - according to W3C, the ‘name’ attribute of the ‘form’ tag is deprecated, not the name attribute of the form elements…
*hits head with hand*


Finally - PHP has NoIndex on phpinfo output

June 4th, 2008 by Aaron

Security Issue?

A big issue with PHP security had been the developers creating a php info page and not removing it from a production site. As you may know, phpinfo() will dump a ton of useful information (for the developer - as well as the cracker) to the screen:

1
phpinfo();

I can’t imagine how many versions of that are out on various servers…

Actually, let’s take a look with this google query

More than a million returns (granted they’re not all phpinfo() calls… but it gives you a good idea…)

There is Hope

With the release of 5.2.1 of PHP, phpinfo() now outputs the following meta tag:

1
<meta name="ROBOTS" content="NOINDEX,NOFOLLOW,NOARCHIVE" />

This will slowly but surely stop compliant robots (see: google, yahoo… not crackerMcCrackenstein.com) from archiving these… yes!


PHP Script Configuration Class with Logic built in

June 2nd, 2008 by Aaron

Sometimes we have static configuration options, such as the name of the company or the location of a particular partner’s website. Other times, there are more dynamic configuration options - such as the current location’s URL or database connection credentials.

For this article, I wanted to build on my previous article here, and make a config class that could still get all of this information from a static method, while making decisions to create accurate config options.

Continue reading PHP Script Configuration Class with Logic built in


PHP Script Configuration Options - Class Constants or MySQL

May 31st, 2008 by Aaron

I’m trying to figure out the best way to do configuration options for my newest PHP scripts that I’m working on. My requirements are simple:
1) You cannot change the config option once it is loaded
2) The options are easy to modify quickly
3) Must call a method to get values, no matter if they’re available globally or not (this is just in case I want to change the logic in the future)

Non-Requirements:
1) Does not need to make dynamic configuration options or choose configuration options based on logic (IE, one mysql credential for LIVE vs another for development)

with this in mind, lets figure out what may work best:

Continue reading PHP Script Configuration Options - Class Constants or MySQL


Dig for Windows

May 30th, 2008 by Aaron

For those of us who develop on windows, we can sometimes feel linux tool envy. One particular tool is the ‘dig’ command. Well, luckily, you can get this to run on windows easily:

Download Bind from ISC

Visit the www.isc.org/sw/bind/index.php download page to download the Windows binary version.

Create folder and Extract necessary Files

Create a folder called ‘dig’ - or just push all the dlls and exe’s into your windows/system32 folder. Extract the following:

dig.exe
libbind9.dll
libdns.dll
libisc.dll
libisccfg.dll
liblwres.dll

Run Dig

c:\>dig

; <<>> DiG 9.4.2 <<>>
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 752
;; flags: qr rd ra; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 12

;; QUESTION SECTION:
;.                              IN      NS

;; ANSWER SECTION:
.                       4060    IN      NS      e.root-servers.net.
.                       4060    IN      NS      b.root-servers.net.
.                       4060    IN      NS      f.root-servers.net.
.                       4060    IN      NS      a.root-servers.net.
.                       4060    IN      NS      c.root-servers.net.
.                       4060    IN      NS      i.root-servers.net.
.                       4060    IN      NS      g.root-servers.net.
.                       4060    IN      NS      h.root-servers.net.
.                       4060    IN      NS      m.root-servers.net.
.                       4060    IN      NS      d.root-servers.net.
.                       4060    IN      NS      k.root-servers.net.
.                       4060    IN      NS      l.root-servers.net.
.                       4060    IN      NS      j.root-servers.net.

;; ADDITIONAL SECTION:
e.root-servers.net.     71529   IN      A       192.203.230.10
b.root-servers.net.     71529   IN      A       192.228.79.201
f.root-servers.net.     85723   IN      A       192.5.5.241
a.root-servers.net.     85723   IN      A       198.41.0.4
c.root-servers.net.     71529   IN      A       192.33.4.12
i.root-servers.net.     71529   IN      A       192.36.148.17
g.root-servers.net.     71529   IN      A       192.112.36.4
h.root-servers.net.     71529   IN      A       128.63.2.53
m.root-servers.net.     25212   IN      A       202.12.27.33
d.root-servers.net.     71529   IN      A       128.8.10.90
k.root-servers.net.     85723   IN      A       193.0.14.129
j.root-servers.net.     85723   IN      A       192.58.128.30

;; Query time: 15 msec
;; SERVER: 10.30.12.26#53(10.30.12.26)
;; WHEN: Tue May 27 10:49:05 2008
;; MSG SIZE  rcvd: 433

Yay!

Thanks to Todd Keup @ magnifisites for this tip.


PHP application plugins - force the interface

May 27th, 2008 by Aaron

The other day I was experimenting with some PHP plugin scripts and trying to develop my own robust plugin system. I started thinking: how can I guarantee that a 3rd party developer sticks to my plugin standards?

Well the obvious answer is an interface. But, I wanted to make sure that their plugin actually implemented it.

Enter instanceof

I had previously only thought of instanceof as a way to verify if an object was of a specific type of class - but this can be extended to interfaces. let’s check out my test code here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
interface pluginInterface
{
    public function update();
}
 
class thirdPartyPlugin implements pluginInterface
{
    public function __construct()
    {
        print 'constructed';
    }
 
    public function update()
    {
        print 'update ran';
    }
}
 
$a = new thirdPartyPlugin();
 
if ($a instanceof pluginInterface) {
    print 'is good';
}
else {
    print 'discard me.';
}

The first section is the plugin interface. For our example, I’m making a very simple interface: all plugins must have a method called update().

Next, we have the third party plugin which implements pluginInterface. It has the update method - as well as any other methods.

Finally, our plugin loader will make a new instance of the plugin, and then verify its of the type of pluginInterface. This makes sure that we’ve loaded this interface with our third party plugin. In this code, if you were to remove ‘implements pluginInterface’ from thirdPartyPlugin, the ‘instanceof’ will fail and print ‘discard me’.

Make the parameters in the Interface more exacting

So, let’s say that every single update() method should do something to the object ‘testObject’. With this modified code, I make sure that the update() method of the 3rd party plugin expects its first parameter to be testObject. If you do not match up the exact type of object in the declaration as the interface, it will fail. (note: the object’s variable name does NOT need to match)

see code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
interface pluginInterface
{
    public function update(testObject $tO);
}
 
class thirdPartyPlugin implements pluginInterface
{
    public function __construct()
    {
        print 'constructed';
    }
 
    public function update(testObject $object)
    {
        print 'update ran';
    }
}
 
class testObject
{}

Can this help with security?

Sure! Think about this: you install a 3rd party plugin, but you don’t have time to review all of its code line by line. Ok - so this malicious 3rd party plugin now wants to access your database connection and drop all of your records. It expects to pass in the database connection to its update function… so it defines the function as this:

1
public function update(testObject $object, $dbConnection)

Well, sure enough, this will fail as well - you must match EXACTLY to the interface.

Note: I’m not advocating that this is your only security measure in your application. There are other ways for 3rd party plugins to take advantage of your system - but as a responsible developer, you should make multiple layers of security.


©2008 102 Degrees LLC - All Rights Reserved Home Services Products Network Blog Open Source Learning Contact