diff --git a/README.md b/README.md
index 9946aeb3d85e6c3715b57f9347d10ccdc4edb244..f09b94d050780ec31d5953b61118b417edb6c6eb 100644
--- a/README.md
+++ b/README.md
@@ -47,3 +47,20 @@ Create your own fork of the project and use
 [git-flow](https://github.com/nvie/gitflow) to create a new feature. Once
 the feature is published in your fork, send a pull request to begin the
 conversation of integrating your new feature into osTicket.
+
+License
+-------
+osTicket is released under the GPL2 license. See the included LICENSE.txt
+file for the gory details of the General Public License.
+
+osTicket is supported by several magical open source projects including:
+
+  * [HTMLawed](http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed)
+  * [PasswordHash](http://www.openwall.com/phpass/)
+  * [PEAR](http://pear.php.net/package/PEAR)
+  * [PEAR/Auth_SASL](http://pear.php.net/package/Auth_SASL)
+  * [PEAR/Mail](http://pear.php.net/package/mail)
+  * [PEAR/Net_SMTP](http://pear.php.net/package/Net_SMTP)
+  * [PEAR/Net_Socket](http://pear.php.net/package/Net_Socket)
+  * [PEAR/Serivces_JSON](http://pear.php.net/package/Services_JSON)
+  * [phplint](http://antirez.com/page/phplint.html) 
diff --git a/setup/test/lib/phplint.tcl b/setup/test/lib/phplint.tcl
new file mode 100755
index 0000000000000000000000000000000000000000..6b857c75048a26fcd136d9213ece4c5b784bbfbc
--- /dev/null
+++ b/setup/test/lib/phplint.tcl
@@ -0,0 +1,208 @@
+#!/usr/bin/tclsh
+
+# Copyright (C) 2007 Salvatore Sanfilippo <antirez at gmail dot com>
+# This software is released under the GPL license version 2
+
+proc scan file {
+    set fd [open $file]
+    set infunc 0
+    set linenr 0
+    set fnre {(^\s*)((public|private|protected|static)\s*)*function\s+([^(]+)\s*\((.*)\).*}
+    while {[gets $fd line] != -1} {
+        incr linenr
+        if {[regexp $fnre $line - ind - - - fa]} {
+            # If $infunc is true we miss the end of the last function
+            # so we analyze it now.
+            if {$infunc} {
+                analyze $file $arglist $body
+            }
+            set body {}
+            set arglist {}
+            foreach arg [split $fa ,] {
+                # remove default value
+                regsub {=.*} $arg {} arg
+                # remove optional type spec
+                regsub {^.*\s+} [string trim $arg] {} arg
+                set arg [string trim $arg " $&"]
+                lappend arglist $arg
+            }
+            set infunc 1
+        } elseif {$infunc && [regexp "^$ind\}" $line]} {
+            set infunc 0
+            analyze $file $arglist $body
+        } elseif {$infunc} {
+            lappend body $linenr [string trim $line]
+        }
+    }
+}
+
+proc analyze {file arglist body} {
+    set initialized(this) 1
+    set linton 1
+    foreach arg $arglist {
+        set initialized($arg) 1
+    }
+    # Superglobals
+    set superglobals {
+        "GLOBALS"
+        "_SESSION"
+        "_SESSION"
+        "_GET"
+        "_POST"
+        "_REQUEST"
+        "_ENV"
+        "_SERVER"
+        "_FILES"
+        "php_errormsg"
+    }
+    foreach sg $superglobals {
+        set initialized($sg) 1
+    }
+    # analyze body
+    foreach {linenr line} $body {
+        # Handle annotations
+        if {[string first {nolint} [string tolower $line]] != -1} continue
+        if {[string first {linton} [string tolower $line]] != -1} {
+            if {$linton == 1} {
+                puts "! Warning 'linton' annotation with lint already ON"
+                continue
+            }
+            set linton 1
+            puts ". $skipped lines skipped in $file from line $skipstart"
+        }
+        if {[string first {lintoff} [string tolower $line]] != -1} {
+            if {$linton == 0} {
+                puts "! Warning 'lintoff' annotation with lint already OFF"
+                continue
+            }
+            set linton 0
+            set skipped 0
+            set skipstart [expr {$linenr+1}]
+            continue
+        }
+        if {$linton == 0} {
+            incr skipped
+            continue
+        }
+        # Skip comments
+        if {[string index $line 0] eq {#}} continue
+        if {[string index $line 0] eq {/} && [string index $line 1] eq {/}} continue
+        # PHP variable regexp
+        set varre {\$[_A-Za-z]+[_A-Za-z0-9]*(\[[^\]]*\])*}
+        # Check for globals
+        set re {\s*(global|static)\s+((?:\$[^;,]+[ ,]*)+)(;|$)}
+        if {[regexp $re $line -> - g]} {
+            set g [split [string trim $g ";"] ,]
+            foreach v $g {
+                set v [string trim $v "$ "]
+                set initialized($v) 1
+            }
+        }
+        # Check for assignment via foreach ... as &$varname
+        set re {}
+        append re {foreach\s*\(.*\s+as\s+&?(} $varre {)\s*\)}
+        set l [regexp -all -inline -nocase $re $line]
+        foreach {- a -} $l {
+            set initialized([string trim $a "$ "]) 1
+        }
+        # Check for assignment via foreach ... as $key => &$val
+        set re {}
+        append re {foreach\s*\(.*\s+as\s+(} $varre {)\s*=>\s*&?(} $varre {)\s*\)}
+        set l [regexp -all -inline -nocase $re $line]
+        foreach {- a1 - a2 -} $l {
+            set initialized([string trim $a1 "$ "]) 1
+            set initialized([string trim $a2 "$ "]) 1
+        }
+        # Check for assigments in the form list($a,$b,$c) = ...
+        set re {list\s*\(([^=]*)\)\s*=}
+        set l [regexp -all -inline $re $line]
+        foreach {- vars} $l {
+            foreach v [split $vars ,] {
+                set v [string trim $v "$ "]
+                set initialized($v) 1
+            }
+        }
+        # Check for assigments via = operator
+        set re $varre
+        append re {\s*=}
+        set l [regexp -all -inline $re $line]
+        foreach {a -} $l {
+            set a [string trim $a "=$ "]
+            regsub -all {\[.*\]} $a {[]} a
+            #puts "assigmnent of $a"
+            set initialized($a) 1
+            regsub -all {\[\]} $a {} a
+            set initialized($a) 1
+        }
+        # Check for assignments via catch(Exception $e)
+        set re {}
+        append re {catch\s*\(.*\s+(} $varre {)}
+        set l [regexp -all -inline -nocase $re $line]
+        foreach {- a} $l {
+            set initialized([string trim $a "$ "]) 1
+        }
+        # Check for assignments by reference
+        #
+        # funclist format is {type funcname spos epos} where spos is the
+        # zero-based index of the first argument that can be considered
+        # an assignment, while epos is the last.
+        #
+        # name is the function name to match, and type is what
+        # to do with the args. "assignment" to consider them assigned
+        # or "ingore" to ingore them for the current line.
+        #
+        # The "ignore" is used for isset() and other functions that can
+        # deal with not initialized vars.
+        unset -nocomplain -- ignore
+        array set ignore {}
+        set funclist {
+            assignment scanf 2 100
+            assignment preg_match 2 100
+            assignment preg_match_all 2 100
+            assignment ereg 2 100
+            ignore isset 0 0
+        }
+        set cline $line
+        regsub -all {'[^']+'} $cline {''} cline
+        foreach {type name spos epos} $funclist {
+            set re {}
+            append re $name {\s*\(([^()]*)\)}
+            foreach {- fargs} [regexp -all -inline $re $cline] {
+                set argidx 0
+                foreach a [split $fargs ,] {
+                    set a [string trim $a ", $"]
+                    regsub -all {\[.*\]} $a {} a
+                    if {$argidx >= $spos && $argidx <= $epos} {
+                        if {$type eq {assignment}} {
+                            set initialized($a) 1
+                        } elseif {$type eq {ignore}} {
+                            set ignore($a) 1
+                        }
+                    }
+                    incr argidx
+                }
+            }
+        }
+
+        # Check for var accesses
+        set varsimplere {\$[_A-Za-z]+[_A-Za-z0-9]*}
+        set l [regexp -all -inline $varsimplere $line]
+        foreach a $l {
+            set a [string trim $a "=$ "]
+            regsub -all {\[.*\]} $a {} a
+            #puts "access of $a"
+            if {![info exists initialized($a)] &&
+                ![info exists ignore($a)]} {
+                puts "* In $file line $linenr: access to uninitialized var '$a'"
+            }
+        }
+    }
+}
+
+proc main argv {
+    foreach file $argv {
+        scan $file
+    }
+}
+
+main $argv
diff --git a/setup/test/lint.php b/setup/test/lint.php
new file mode 100644
index 0000000000000000000000000000000000000000..01c97df9fedf71aa6d0a416f754c0484955cc57f
--- /dev/null
+++ b/setup/test/lint.php
@@ -0,0 +1,29 @@
+#!/usr/bin/env php
+<?php
+if (php_sapi_name() != 'cli') exit();
+
+function get_osticket_root_path() {
+    # Hop up to the root folder
+    $start = dirname(__file__);
+    for (;;) {
+        if (file_exists($start . '/main.inc.php')) break;
+        $start .= '/..';
+    }
+    return $start;
+}
+
+$root = get_osticket_root_path();
+
+# Run phplint across all php files
+ob_start();
+# XXX: This won't run well on Windoze
+system("$root/setup/test/lib/phplint.tcl $root/**/*.php 2>&1");
+$lint_errors = ob_get_clean();
+$lint_errors=str_replace("$root/", '', $lint_errors);
+
+if (strlen($lint_errors)) {
+    echo "FAIL: Access to unitialized variables\n";
+    echo "-------------------------------------------------------\n";
+    echo "$lint_errors";
+}
+?>