Windows Admin Command Prompt Here and Desktop Shutdown Menu Items

Just a couple of Windows tweaks scripted into nice small nullsoft installers for convenience. This way if you want to remove them at any time in the future you just uninstall them as you would any other program, Although they were scripted on and for Windows 10, they should also work for all older versions of Windows as well.

Admin Command Prompt Here Menu Item

The Admin Command Prompt Here menu item will appear when you right click on, or inside of, any folder in Windows Explorer. It provide you with an elevated command prompt when you click on it. If you’re in the business of using command line tools often this menu item is a real time saver.

Download Installer Here

Desktop Shutdown Menu Item

You know what’s nice? Right clicking on the desktop and clicking on the Shutdown menu item to exit Windows. If you’re on a desktop system you’ll never stop using this one.

Download Installer Here

Analyze-It, Browser Extension, Internet Explorer, Javascript, Look-It-Up, Plurk-It, Share-It, Windows

Internet Explorer Context Menu Chooser Application Version 2

Analyze-it menu chooser

Analyze-it menu chooser

With this new version the Analyze-it context menus were updated to the most recent version. Analyze-it contained so many menu items that I had to add a counter to the interface to indicate when there are more than the twenty menu item visible limit. The menu counter is only active for page context (basic context menu the page provides – nothing selected in other words) menu items. I suppose when there are more than twenty selected text context menus I’ll have to add another one; this is good for now. The counter only indicates when you are over the visible limit, it doesn’t prevent you from going over, which helps you fine tune your choices.

Analyze-it context menus

Analyze-it context menus

I had to break out Analyze-it into three logical, domain based sections, making it easier to choose the menu items you would like to use.

Analyze-it-Scritch menu chooser

Analyze-it-Scritch menu chooser


Scritch menu items

Scritch menu items has its own section in the application now, making it easier to discern their tools from the rest.

ViewDNS menu chooser

ViewDNS menu chooser

ViewDNS provides a group of helpful online tools on their site that I have included menu items for in this release. The application is now up to date with my other add-ons hosted in various places. Again, if you are running a tablet exclusively, this application isn’t for you. This application is used with Internet Explorer not Microsoft Edge (the tablet browser included with Windows 10) . If you are on a Surface device and if you use Internet Explorer with your keyboard and mouse – this will give you extra context menus.

ViewDNS menu items

ViewDNS menu items

There is a newer version available – see post here

Browser Extension, Firefox, Javascript, Useful-New-Tab-Page

Firefox Useful New Tab Page Now in the Public Index at the Mozilla AMO

Firefox Useful New Tab Page

Firefox Useful New Tab Page

Firefox Useful New Tab Page addon is out of experimental hosting at Mozilla now and is available here;

I also placed the source code for it on Github here: in case anyone wants to check out the source code.


Which is darker A or B? Look to the right for an answer.


There is something to be said about how the human brain interprets everything in this picture. On its surface it’s a picture of a gray and darker gray checkerboard with a cylinder sitting upon it with a shadow being thrown upon the checkerboard. The mind perceives the two squares as different colors. It logically expects them to be different as a result of the concrete pattern established in the checkerboard itself. Because the change in color is introduced equally across all squares on the checkerboard until the color in lighter gray square is equal to that of the darker dray square with a gradient that mimics a shadow, the mind if deceived into believing that the two squares are different shades of gray. If you see a gradient (if you do they’ll be ever changing) in either of the two stripes inside the right picture, that’s just your mind trying to rationalize the illogical by reevaluating and subtly filling in what can be perceived as logical. It’s a flaw in logic, not in your eyes.

Now abstract it…



Image – Talk about a gray area in the mind – wow!

Prattsville N.Y.

This years Mudfest festival was covered by the local news stations. The finale of the fireworks show was better this year – really rocked the valley. No, I didn’t record the fireworks as I was too busy enjoying myself; maybe next year. Happy festivus and may the fall be as beautiful as the summer!

Apache, FlightPHP, Javascript, PHP

Setting up FlightPHP to work with Backbonejs

FlightPHP and Backbonejs work well together inherently by design. Even though the two frameworks are written in two different languages and are designed for different tiers in your enterprise application development design, its hard to ignore the ease of integrating the two.. Most Backbone examples you see posted on the Internet involves node.js on the server; which makes sense considering you program both in javascript. However, the most common (and cheapest) hosting on the Internet is shared host PHP hosting. As long as your load is relatively light you can get really great results out of a shared PHP host as the new PHP runs virtually as fast as C++ on the server (takes about 2x the RAM though).

How Backbone works with FlightPHP

Backbone is a REST-centric library. Basically what that means is that you have to set up four endpoints in your FlightPHP index file for every collection of models in your application. With Backbone, you will not be setting up AJAX calls – the library handles all of the traffic cop stuff for you automatically. Using a Backbone model: a save uses a POST if the model does not have an id set on it from a previous save, and uses a PUT to update the record if it does have an id; a get without and id in the path returns the array of JSON objects (used by Backbone.Collection), including an id in the path returns that record; and a model.destroy uses a DELETE verb to indicate a record delete.

Your CRUD functions will map to the GET, POST, PUT, and DELETE HTTP verbs on your server.

/* basic PHP pseudocode structure for handling backbone CRUD functionality */
// Create
Flight::route('POST /rest/somecollectionname', function($id){
    // posting a new record (saving the model)
        // return the object saved with new id created by db
// Read
Flight::route('GET /rest/somecollectionname(/@id)', function($id){
    // getting a collection or a single record if id was provided
        // return an array of javascript objects or a single
        // object if an id was provided
// Update
Flight::route('PUT /rest/somecollectionname/@id', function($id){
    // updating a record (saving a model with an id)
        // return updated object
// Delete
Flight::route('DELETE /rest/somecollectionname/@id', function($id){
    // deleting a record (destroying a model)

Flight also allows you to map these endpoints to a separate class which is probably the best way to go if you are working on an API that’s larger than a couple of endpoints.

Apache issues – something Node users never have to deal with

On some shared hosts PUT and DELETE requests are blocked by default. You’ll get a 403 Denied error on the first PUT or DELETE attempt if these HTTP verbs are blocked. Its, unfortunately, a fact of life that has to be dealt with. Apache allows PUT and DELETE by default, so its probably the way they have their virtual hosts configuration set (usually because of security issues). You can sometimes (probably) get away with a .htaccess directive to overcome this shortfall. Other than that I recommend you contact whatever host you have for a solution.

# try this in .htaccess
order deny,allow
allow from all

Even if your shared host vehemently denies you access to these verbs, a workaround is relatively easy to script. For instance: add an updateid to your model to indicate an update and handle it as a new record on the client, etc. It shouldn’t come down to that though (a paying customer is a paying customer).

If you are running your own server you should open “/etc/httpd/conf/httpd.conf” as root and look for something that looks like:

<Directory /home/*>
AllowOverride All
Options -MultiViews -Indexes FollowSymlinks IncludesNoExec +Includes
Order allow,deny
Allow from all
Order deny,allow
Deny from all

Anywhere you see “GET POST” just add put and delete : “GET POST PUT DELETE”. Then restart httpd server with “/sbin/service httpd restart” and they should work. Also, here is a link to a good how-to for Apache in case you get confused:
Apache Docs

In many cases you might not even need those two verbs. Many people use Backbonejs to display and sort data on the client without ever needing to use PUT or DELETE.

FlightPHP, Geolocation, PHP

A WhatsMyIP GeoIP Map Site with FlightPHP

IP With A Here Map

FlightPHP is a micro-framework I’ve been tinkering around with lately. Written by Mike Cao, Flight is a small framework of eleven files that offers an elegant solution to routing and JSON API development in PHP. Installation is simple and Flights’ only requirement is having PHP 5.3 or higher on your host. FlightPHP is released under the MIT license so it’s legal to use in business endeavors without having to worry about major repercussions.
I feel it’s fair to mention that I also use two bits of functionality other than the framework from external sources in this example. Firstly, I use and their PHP class for IP geolocation data. Yes, I could have either purchased or obtained a geolocation database from somewhere and pulled all the geographic information from that – I didn’t. The geoplugin site is free and easy to use. Secondly, I use a MIME class written by Robert Widdick for returning the proper headers when handling static file requests. Originally, I started with a limited associate array of file types and their associated header strings which I then used to create the response header for static file responses. I wanted to avoid the added headache of having to add header strings to an array every time I wanted to host a new filetype in the static folder. Robert Widdicks’ package works for nearly every different file type you would want to host and is released under the GNU GPL license.

IP With A Google Map

Why I chose to use the FlightPHP micro-framework

In any programming language the laconic solution is the most desirable. Thus, using any framework in your project becomes a balancing act of sorts. The bigger the framework, the larger the overhead. The more file reads a framework makes on the server, the slower the response. Too much server overhead lowers usage capacity. Using a framework that gives you desired functionality without excess becomes more and more important than in the past as the Internet grows to host single page web apps that demand more and more from the server.
The term “micro-framework” was alien to me until a few weeks ago. “How much functionality can a really small framework have and still be called a framework?” In my opinion, a framework in programming is a package of code that forms the underlying structure or interface for your application development that abstracts commonly needed functionality away to a simpler or more convenient interface. Or put another way; a bunch of code that makes programming an application a bit easier. Looking at the work “micro” prefixed to the definition made my expectations grow spartan.
I found that micro-frameworks are more task oriented and less one-size-fits-all from what would be considered a normal framework, so finding the right one for your particular project takes a bit of research. Faced with the myriad of micro-frameworks available on the Internet a programmer should choose one based on the common aspects needed in the particular project being planned. Most of the time you’ll find one that gives you almost all of the basic boilerplate functionality you desire. Depending on the feature needed, you could either fill in the gaps your own programming skills or find an external package. Either way, you’ll probably wind up with a smaller server footprint that loads faster and takes up less memory.
I came across Flight while looking for a smaller framework that I could use for an addon idea I came up with. If any, the only framework I would use for a new project is CodeIgniter. CodeIgniter is great and I really like using it, don’t misunderstand me; but its overhead seemed unnecessary for the task at hand. The addon idea I had would be creating mainly JSON traffic; entering data and retrieving it as needed. If it wasn’t for the data models, most of CodeIgniter would just be overhead. I desired a smaller framework for the backend layer that loads faster and has less overhead. I chose Flight because I like the way it ‘felt’ while coding with it. I eventually abandoned my idea, but I will most likely continue to use FlightPHP in future projects and experiments as its design naturally lends itself to single-page web application development.

IP With Wikimapia Map

Using FlightPHP

Using FlightPHP is as simple as using a global static class to call functionality. You extend Flight by mapping your global variables, functions and classes to that class. I really like the concept of the framework and its functionality here in this Flight object and plain PHP for the rest. Scripting an application using Flight just seems more intuitive and clean to me as a result.
In Flight you have no Controllers, Flight just handles the routing and response. All the routes and route handlers in your application are defined in the index.php file. Defining routing paths in your application is as simple as calling the static ‘route’ method of the global Flight object with the path string and a callback. Path strings can contain wildcards, regular expressions, named parameters, optional parameters, and HTTP verbs. Route paths defined like this in Flight are, in structure, a bit similar to the way you would code a node router in javascript. However, Flight is very flexible with regard to routing, you can map route responses to static functions and class methods.
There is also another routing feature that reminded me of node: if you return true from any route handler, execution is passed to the next matching route handler. That makes any route handler that returns true “middleware” of sorts, except that it is more explicit in functionality as it only executes for the route defined. Handling common request evaluation functionality, user agent parsing for instance, in a wildcard route defined before any of the other routes just seems more elegant and intuitive to me than calling a separate function at the beginning of every route handler.
Although FlightPHP uses the concept of views, there is no template engine included with the framework. By default, Flight uses straight PHP to render template output. However, you could use any template engine you desire by registering a class and overriding the ‘render’ function if the need arises. To render any PHP template you call the static ‘render’ function on the global Flight object passing it a path string and an associate array of data that will resolve as variables in the template during the rendering process. If you want to use partial views and a layout template that’s easy too. Just call ‘render’ on the partial views before the layout template render call with a third string representing the variable name that will hold the results to echo out during the layout render call. Really simple and elegant.
Request information is handled by Flight as well. If you need to access information about the request: request cookies, GET/POST variables etc.., they are contained in an object retrieved through the Flight::request method. Aggregate data properties of the returned request object are conveniently accessible using either object or array syntax.
Error handling, caching, redirects, JSON and JSONP responses are all handled through the FlightPHP object also. For more information on using FlightPHP its well documented here.
All in all, FlightPHP gives you a pleasant beginning to any project you may have in mind without the burden of too much overhead.

The Project Layout

The No Script Version

A Few Notes About My Code

Going over each step of the code step by step seems redundant to me. There are, however, a few notes I felt should be mentioned before gazing upon the code. Most programmers can figure out exactly what is going on in the code just by looking at the index.php file. As I stated previously, everything goes through the Flight object. There is no having to remember a bunch of different classes to extend in Flight.

About how the external resources are used

I created an includes folder to keep all of the external resources separate from the framework. As I mentioned previously, I used an external class for handling MIME types on static file requests. I didn’t register that class in the global object as not every request is a static file request. I did, however map the ‘getStaticFile’ method in the global object where I include it as necessary lazily in an effort to conserve resources. I also didn’t register the geoplugin class globally in the FlightPHP object as it is only used once per ip. All subsequent requests after the initial geoplugin service request for IP geolocation data are retrieved from the SQLite database – not the geoplugin web service.

About SQLite

I used SQLite and PDO instead of MySQL and PDO in this example for convenience. SQLite is included with PHP, so there is no need to configure a database if you want to try the code out on XAMPP. Another benefit of using SQLite is that SELECT queries are executed faster than MySQL queries; so its performant. The SQL used in the table creation in this example technically doesn’t have to be as verbose as it is. I could have just used: “CREATE TABLE(and a bunch of column name separated by commas)” and the table would have been created, SQLite would have figured the rest out. It’s fairly easy to translate the table creation SQL to MySQL the way it is now if you have to. Also, using PDO isn’t the same as using the SQLite engine; don’t count on any of the SQLite engine functions documented in the PHP documentation in other words. When using PDO you can only use PDO functions. Although not required in this instance, I find that relying totally on PHP for the grunt work that SQLite functions provide makes my code more portable. The down side of using SQLite is that it does not scale up at all. For an example on initializing MySQL with PDO and FlightPHP check out the FlightPHP documentation.

About Serving Static Files

Setting up Flight to serve up static file was simple. I first set a global variable in Flight for the static folder path using the same format as Flight uses for the views folder for convenience. I then mapped a global function in Flight to handle returning the file. I could have, technically, set up static file retrieval through the htaccess file on the server. I’ve had my share of problems, however, with htaccess files hosted on shared hosting in the past; they seem to differ in small ways from host to host. I actually like having all requests run through the index.php file better as it lends to greater flexibility in my coding.
The route used for serving static files is matched to the root folder level with a wildcard. Based on the premise that the routes are tested in order, from top to bottom, other dynamic routes can be included if needed. When adding routes with this setup you should consider at least one folder level route prefix to make route matching easier. Or, you could change the code to serve all of the static resources from a different folder route instead of root; just remember create a sub-folder structure in the static folder to match the route as the getStaticFile function operates off of the request URL path.

About The Maps

The three maps used in this example are displayed in an iframe. The google map is the only one of the three that require an API key for embedding. The way its coded, if you don’t include an embed key from google the google map will not be displayed. The maps lacks a bubble dialog on the exact IP location as a result. Considering that IP geolocation is an approximation of the users location, it really doesn’t matter. If you want to display a bubble dialog on the maps you’ll have to get a javascript API key for each of the three and do the javascript yourself.
Initially, I wanted to leave javascript out of this example, keeping the focus on using the PHP framework for HTML site development in this blog post. Since the maps displayed in the iframe require javascript to be enabled, and I had nothing but problems sizing the map iframe properly with CSS, I used javascript to accomplish the task. The noscript version of the page has no javascript and the center pane is sized and placed with CSS as its supposed to be.

About the CSS

I hacked out my own CSS for this project. Because I used the box-sizing feature of CSS3, this example only supports modern browsers. Furthermore, I didn’t use any media queries in the CSS. Horizontal scrolling starts at 700 pixels; so the outputted page is less than ideal for smaller screens. In reflection, perhaps I should have used Bootstrap and made it look like everything else on the Internet.

About setting this up and actually using this

I tried to make it easy to set this up for hosting by mapping global variable towards the top of the index.php file. Most of the variables are self explanatory. The title prefix variable is what is displayed in the upper left corner of the page (branding) and in the title. That links to whatever overrides the base URL variable. As I stated previously, if you don’t include a google embed key the google map will not be shown; its coded to show the wikimapia map instead if the default map type is still set to google (which is based on a google map). If you use google analytics, uncomment and set the UA key and the script will inject the boilerplate code at the bottom of the HTML. Every hit is recorded in the database in case you want to roll your own later.

A Birdhouse or a Townhome

Technically, this is a WhatsMyIPSite too.

<?php echo “<h1>Your IP is: “ . $_SERVER[REMOTE_ADDR] . “</h1>”; ?>


require 'flight/Flight.php';
// require 'includes/geoplugin.class.php';
// require 'includes/phpmimetypeclass-2010-10-19/class.mime.php';

//require 'includes/FirePHP.class.php';
//Flight::set('isdebug', false);
//$isdebug = Flight::get('isdebug');
//if($isdebug){$firephp = FirePHP::getInstance(true);}

// Set framework variables
// Override the base url of the request. (default: null)
Flight::set('flight.base_url', null);
// Allow Flight to handle all errors internally. (default: true)
Flight::set('flight.handle_errors', true);
// Log errors to the web server's error log file. (default: false)
Flight::set('flight.log_errors', true);
// Directory containing view template files (default: ./views)
Flight::set('flight.views.path', 'views');
// set your own variables now
Flight::set('flight.static.path', 'static');
// use js? (include maps and scripts in other words)
Flight::set('js', false);
Flight::set('title_prefix', 'WhatsMyIPSite');
Flight::set('meta_description', 'WhatsMyIPSite tells visitors what IP address they are making requests from.');
// set default maptype here (google, here, or wikimapia)
Flight::set('maptype', 'google');
// Google Maps Embed API key
// Flight::set('google_embed_key', 'your_google_map_embed_key_here');
// Google Analytics - replace UA-XXXXX-X with your site id
//Flight::set('google_analytics_site_id', 'UA-XXXXX-X');

// Now do classes
// Register db class with constructor parameters
Flight::register('db', 'PDO', array('sqlite:data/flightgeoip.sqlite3'), function($db){
    // after construct callback (with new object passed in)
    // now create tables if needed
    $db->exec('CREATE TABLE IF NOT EXISTS geo (
                    id INTEGER PRIMARY KEY,
                    ip TEXT UNIQUE,
                    geoplugin_city TEXT,
                    geoplugin_region TEXT,
                    geoplugin_areaCode TEXT,
                    geoplugin_dmaCode TEXT,
                    geoplugin_countryCode TEXT,
                    geoplugin_countryName TEXT,
                    geoplugin_continentCode TEXT,
                    geoplugin_latitude TEXT,
                    geoplugin_longitude TEXT,
                    geoplugin_regionCode TEXT,
                    geoplugin_regionName TEXT)');
    $db->exec('CREATE TABLE IF NOT EXISTS requests (
                    id INTEGER PRIMARY KEY,
                    path TEXT,
                    ip TEXT,
                    uastring TEXT,
                    time INTEGER)');
//$db = Flight::db();

// Now extend Flight with your methods
 * getStaticFile
 * Returns a static file in the static directory or 404.
 * @param [string] $filepath - path to the static file
Flight::map('getStaticFile', function($req_path){
    $filepath = Flight::get('flight.static.path') . $req_path;
	// sometimes relative to root not folder
		$server_path = realpath($_SERVER['DOCUMENT_ROOT']);
		$this_path = realpath(dirname(__FILE__));
		if (strlen($this_path) > strlen($server_path)) {
			$tmp = substr($this_path, strlen($server_path));
			$filepath = Flight::get('flight.static.path') . substr($req_path, strlen($tmp));
    if (file_exists($filepath)) {
		// we don't need MIME id until we need it
		require_once 'includes/phpmimetypeclass-2010-10-19/class.mime.php';
		$mime = new MIMETypes('includes/phpmimetypeclass-2010-10-19/class.types.php');
        $mimetype = $mime->getMimeType($filepath);
        header("Content-Type: $mimetype", true);
    } else {
        // 404 it
 * checkIP
 * Checks the ip of the request for geolocation
 * information, if none is found the information is requested.
 * @param [string] $ip - request IP
Flight::map('checkIP', function($ip){
    // query db for ip first
    $db = Flight::db();
	// If localhost set a real IP
	if($ip = '::1'){
		$ip = '';
    $dbquery ="SELECT * FROM geo WHERE ip IS '" . $ip . "'";
    $result = $db->query($dbquery);
	// does it exist in db?
    if($result->fetch(PDO::FETCH_NUM) > 0){
		$result = $db->query($dbquery);
		foreach ($result as $row) {
			// set geo information into globals
			if(strlen($row['ip']) > 0){Flight::set('ip', $row['ip']);}
			if(strlen($row['geoplugin_city']) > 0){Flight::set('city', $row['geoplugin_city']);}
			if(strlen($row['geoplugin_region']) > 0){Flight::set('region', $row['geoplugin_region']);}
			if(strlen($row['geoplugin_areaCode']) > 0){Flight::set('areaCode', $row['geoplugin_areaCode']);}
			if(strlen($row['geoplugin_dmaCode']) > 0){Flight::set('dmaCode', $row['geoplugin_dmaCode']);}
			if(strlen($row['geoplugin_countryCode']) > 0){Flight::set('countryCode', $row['geoplugin_countryCode']);}
			if(strlen($row['geoplugin_countryName']) > 0){Flight::set('countryName', $row['geoplugin_countryName']);}
			if(strlen($row['geoplugin_continentCode']) > 0){Flight::set('continentCode', $row['geoplugin_continentCode']);}
			if(strlen($row['geoplugin_latitude']) > 0){Flight::set('latitude', $row['geoplugin_latitude']);}
			if(strlen($row['geoplugin_longitude']) > 0){Flight::set('longitude', $row['geoplugin_longitude']);}
			if(strlen($row['geoplugin_regionCode']) > 0){Flight::set('regionCode', $row['geoplugin_regionCode']);}
			if(strlen($row['geoplugin_regionName']) > 0){Flight::set('regionName', $row['geoplugin_regionName']);}
		Flight::set('geoinfo', true);
		require 'includes/geoplugin.class.php';
        $geoplugin = new geoPlugin();
		// API up?
        if( strlen($geoplugin->ip ) > 0){
			$ipquery = "INSERT INTO geo (ip, geoplugin_city, geoplugin_region, geoplugin_areaCode, geoplugin_dmaCode, geoplugin_countryCode, geoplugin_countryName, geoplugin_continentCode, geoplugin_latitude, geoplugin_longitude, geoplugin_regionCode, geoplugin_regionName) VALUES(:ip, :geoplugin_city, :geoplugin_region, :geoplugin_areaCode, :geoplugin_dmaCode, :geoplugin_countryCode, :geoplugin_countryName, :geoplugin_continentCode, :geoplugin_latitude, :geoplugin_longitude, :geoplugin_regionCode, :geoplugin_regionName)";
			$stmt = $db->prepare($ipquery);
			$stmt->bindParam(':ip', $geoplugin->ip);
			$stmt->bindParam(':geoplugin_city', $geoplugin->city);
			$stmt->bindParam(':geoplugin_region', $geoplugin->region);
			$stmt->bindParam(':geoplugin_areaCode', $geoplugin->areaCode);
			$stmt->bindParam(':geoplugin_dmaCode', $geoplugin->dmaCode);
			$stmt->bindParam(':geoplugin_countryCode', $geoplugin->countryCode);
			$stmt->bindParam(':geoplugin_countryName', $geoplugin->countryName);
			$stmt->bindParam(':geoplugin_continentCode', $geoplugin->continentCode);
			$stmt->bindParam(':geoplugin_latitude', $geoplugin->latitude);
			$stmt->bindParam(':geoplugin_longitude', $geoplugin->longitude);
			$stmt->bindParam(':geoplugin_regionCode', $geoplugin->regionCode);
			$stmt->bindParam(':geoplugin_regionName', $geoplugin->regionName);
			// globals
			if(strlen($geoplugin->ip) > 0){Flight::set('ip', $geoplugin->ip);}
			if(strlen($geoplugin->city) > 0){Flight::set('city', $geoplugin->city);}
			if(strlen($geoplugin->region) > 0){Flight::set('region', $geoplugin->region);}
			if(strlen($geoplugin->areaCode) > 0){Flight::set('areaCode', $geoplugin->areaCode);}
			if(strlen($geoplugin->dmaCode) > 0){Flight::set('dmaCode', $geoplugin->dmaCode);}
			if(strlen($geoplugin->countryCode) > 0){Flight::set('countryCode', $geoplugin->countryCode);}
			if(strlen($geoplugin->countryName) > 0){Flight::set('countryName', $geoplugin->countryName);}
			if(strlen($geoplugin->continentCode) > 0){Flight::set('continentCode', $geoplugin->continentCode);}
			if(strlen($geoplugin->latitude) > 0){Flight::set('latitude', $geoplugin->latitude);}
			if(strlen($geoplugin->longitude) > 0){Flight::set('longitude', $geoplugin->longitude);}
			if(strlen($geoplugin->regionCode) > 0){Flight::set('regionCode', $geoplugin->regionCode);}
			if(strlen($geoplugin->regionName) > 0){Flight::set('regionName', $geoplugin->regionName);}
			Flight::set('geoinfo', true);
			// not responding
			Flight::set('geoinfo', false);

 * This acts as middleware of sorts
 * If your route function returns true
 * execution is passed on to the next
 * matching route function.
Flight::route('*', function(){
    $request = Flight::request();
    $db = Flight::db();
    $insert = "INSERT INTO requests (path, ip, uastring, time)
                VALUES (:path, :ip, :uastring, :time)";
    $stmt = $db->prepare($insert);
    $stmt->bindParam(':path', $request->url);
    $stmt->bindParam(':ip', $request->ip);
    $stmt->bindParam(':uastring', $request->user_agent);
    $stmt->bindParam(':time', time());
    // stuff hit into db
    // return true to pass execution
    return true;
// Now define your routes and handlers

//front page
Flight::route('GET /', function(){
	$templatedata = array();
	$request = Flight::request();
	// redundant as Flight::get is available in template too 
	$templatedata['ip'] = $request->ip;
	$templatedata['geoinfo'] = Flight::get('geoinfo');
	$templatedata['meta_description'] = Flight::get('meta_description');
	// evaluate the query string (if any)
		$templatedata['js'] = $request->query->js;
		$templatedata['js'] = Flight::get('js');
		$templatedata['maptype'] = $request->query->maptype;
		$templatedata['maptype'] = Flight::get('maptype');
	Flight::render('partials/iframe_insert.php', $templatedata,
    Flight::render('default.php', $templatedata);

// place any other dynamic routes here

// everything else (static folder)
Flight::route('GET /*', function(){
    $fpath = Flight::request()->url;
// Now Set It Off!


<!DOCTYPE html>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title><?php echo Flight::get('title_prefix'); ?> - Your IP is: <?php echo Flight::get('ip'); ?></title>
    <meta name="description" content="<?php echo $meta_description; ?>">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<link rel="icon" type="image/x-icon" href="favicon.ico" />
	<?php if($geoinfo && $js){	?>
    <script type="text/javascript">
		window.onload = function() {resizemap();}
		window.onresize = function() {resizemap();}
		function resizemap(){
			var map = document.getElementById("map");
			var container = document.getElementById("container");
			map.height = container.clientHeight - 75;
			map.width = container.clientWidth;
	<?php } ?>
	<link rel="stylesheet" href="css/main.css">
<noscript>Either enable JavaScript or click <a href="?js=0">here</a> </noscript>
<div id="container">
            <div id="toppane">
                <div class="box30">
					<div id="lefttop"><div id="brand"><a href="<?php echo Flight::get('base_url'); ?>"><?php echo Flight::get( "title_prefix"); ?></a></div></div>
                <div class="box40">
					<div id="centertop"><span id="iplbl">Your IP is: </span><br/><?php echo Flight::get('ip'); ?></div>
                <div class="box30">
					<div id="righttop">
						<?php if($geoinfo && $js){	?>
						<div class="tmbutt"><a href="?maptype=here">Here</a></div>
						<div class="tmbutt"><a href="?maptype=wikimapia">Wikimapia</a></div>
						<?php if(Flight::has('google_embed_key')){ ?>
						<div class="tmbutt"><a href="?maptype=google">Google</a></div>
						<?php } ?>
						<?php }else{ ?>
						<div class="tmbutt">
						<?php echo date('M d Y'); ?>
						<?php } ?>
				<!--<div style="clear:both;"></div>-->
			<?php echo $iframe_insert; ?>
	<div id="bottompane">
		IP <?php echo Flight::get('ip'); ?> =
		<?php echo Flight::get('latitude'); ?> ,
		<?php echo Flight::get('longitude'); ?> - 
		<?php echo Flight::get('city'); ?>, 
		<?php echo Flight::get('region'); ?>, 
		<?php echo Flight::get('countryName'); ?> - 
		Telephone Area Code: <?php echo Flight::get('areaCode'); ?>
		<a class="right" target="_blank" href=""></a>
<?php if($js && Flight::has('google_analytics_site_id')){	?>
        function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
    ga('create','<?php echo Flight::get('google_analytics_site_id'); ?>');ga('send','pageview');

<?php } ?>


<?php if($geoinfo && $js){
		switch ($maptype)
		case 'here':
			$mapurl = "" . Flight::get('latitude') . "," . Flight::get('longitude') . ",12,satellite";
		case 'google':
				$mapurl = "" . Flight::get('google_embed_key') . "&center=" . Flight::get('latitude') . "," . Flight::get('longitude') . "&zoom=12&maptype=satellite";
			} else{
				$mapurl = "" . Flight::get('latitude') . "&lon=" . Flight::get('longitude') . "&z=12&m=b";
		case 'wikimapia':
			$mapurl = "" . Flight::get('latitude') . "&lon=" . Flight::get('longitude') . "&z=12&m=b";
			$mapurl = "" . Flight::get('google_embed_key') . "&center=" . Flight::get('latitude') . "," . Flight::get('longitude') . "&zoom=12&maptype=satellite";

			<div id="mappane">
			<a href="?phpecho$mapurl;?">?phpecho$mapurl;?</a>	
<?php }elseif($geoinfo){  ?>
	$heremapurl = "" . Flight::get('latitude') . "," . Flight::get('longitude') . ",12,satellite";
	$googlemapurl = "" . Flight::get('latitude') . "," . Flight::get('longitude') . ",12z";
	$wikimapiamapurl = "" . Flight::get('latitude') . "&lon=" . Flight::get('longitude') . "&z=12&m=b";
	$openstreetmapmapurl = "" . Flight::get('latitude') . "/" . Flight::get('longitude');
	$weathermapurl = "" . Flight::get('latitude') . "&lon=" . Flight::get('longitude') . "&zoom=8&pin=" . Flight::get('city') . "%2c%20" . Flight::get('region');
	<div id="mappane">
		<div class="box50">
			<h3><?php echo Flight::get('ip'); ?></h3>
			<ul class="nsl">
				<li class="nsli"><span class="nsinfo">City: <strong><?php echo Flight::get('city'); ?></strong></span> </li>
				<li class="nsli"><span class="nsinfo">Region: <strong><?php echo Flight::get('region'); ?></strong></span> </li>
				<li class="nsli"><span class="nsinfo">Area Code: <strong><?php echo Flight::get('areaCode'); ?></strong></span> </li>
				<li class="nsli"><span class="nsinfo">DMA Code: <strong><?php echo Flight::get('dmaCode'); ?></strong></span> </li>
				<li class="nsli"><span class="nsinfo">Country Code: <strong><?php echo Flight::get('countryCode'); ?></strong></span> </li>
				<li class="nsli"><span class="nsinfo">Country Name: <strong><?php echo Flight::get('countryName'); ?></strong></span> </li>
				<li class="nsli"><span class="nsinfo">Continent Code: <strong><?php echo Flight::get('continentCode'); ?></strong></span> </li>
				<li class="nsli"><span class="nsinfo">Latitude: <strong><?php echo Flight::get('latitude'); ?></strong></span> </li>
				<li class="nsli"><span class="nsinfo">Longitude: <strong><?php echo Flight::get('longitude'); ?></strong></span> </li>
		<div class="box50">
			<h4>View location on one of these map sites:</h4>
			<ul class="nsl">
				<li class="nsli"><a class="nsinfo" href="<?php echo $googlemapurl; ?>" target="_blank">Google Map</a> </li>
				<li class="nsli"><a class="nsinfo" href="<?php echo $heremapurl; ?>" target="_blank">Here Map</a> </li>
				<li class="nsli"><a class="nsinfo" href="<?php echo $wikimapiamapurl; ?>" target="_blank">Wikimapia Map</a> </li>
				<li class="nsli"><a class="nsinfo" href="<?php echo $openstreetmapmapurl; ?>" target="_blank">Open Street Map</a> </li>
			<h4>Weather Map:</h4>
			<ul class="nsl">
				<li class="nsli"><a class="nsinfo" href="<?php echo $weathermapurl; ?>" target="_blank">
					Weather Underground Wundermap
					</a> </li>
		<!--<div style="clear:both;"></div>-->
<?php }else{  ?>
			<div id="mappane">
				<h2>Unable to retrieve Geographical information at this time. Please try again later.</h2>
				<h3>Our Geographical Information Provider May Not Be Responding</h3>
				<p>If you are connected to the Internet you can try one of the links below to view your IP address location.
				 These Internet map application providers provide a map based on your IP address by default.</p>
					<li><a href="" ></a></li>
					<li><a href="" ></a></li>
					<li><a href="" ></a></li>
<?php } ?>	

My hacked out main.css

body  {
	margin: 0px;
	padding: 0px;
	background-color: #444444;
	color: white;
	min-width: 700px;
#container {
div#toppane {
	box-sizing: border-box;
	height: 50px;
	background-color: #030303;
	color: #cccccc;
	box-sizing: border-box;
	padding-bottom: 25px;
	margin-bottom: -25px;
	height: 100vh;
	box-sizing: border-box;
	background-color: #030303;
	color: #cccccc;
	height: 25px;
	position: fixed;
	width: 100%;
	font-size: 200%;
#brand a {
	font-size: 70%;
	line-height: 100%;
	box-sizing: content-box;
	width: 30%;
	box-sizing: content-box;
	width: 40%;
	box-sizing: content-box;
	width: 50%;
	box-sizing: border-box;
	height: 100%;
	padding:15px 10px 10px 10px;
.tmbutt a {
	color: #cccccc;
	text-decoration: none;
	background-color: #444444;
	color: #eeeeee;
	font-size: 125%;
	list-style: none;
	padding: 10px;

External Resources Used:
Debugging PHP:
Articles relating to micro-frameworks:
A great listing of various PHP resources:

Source Code Package

Available on GitHub

Analyze-It, Browser Extension, Google-Music-Search, Google-Open-Storage-Search, Google-Translate-It, Internet Explorer, Javascript, Look-It-Up, Plurk-It, Share-It, Windows

IE11 Menu Addons – New Version – 1 – Happy New Year!

New Internet Explorer 11 Menus Version


This release basically fixes a few bugs and adds Google Music Search to the menu. I’ll be using whole numbers from now on on these installers (just makes things easier). I had to remove tumblr from the menu as their format changed (no more sharing with a GET request). Fixed the Fetch and Guess tools to be compliant with their new versions – so they should work properly. The spaces in query bug in Google Open Storage search was fixed – so multi word queries work properly.

Download and Install IE11 Menu Addons for Windows 7, 8, and 8.1

New Version Completed – Read and download from here.

If you’re paranoid about the download – the hash values for the file are listed on the Repo page.


This is My Take on Windows 10 Technical Preview

New Start Menu

I had the opportunity to try out the Windows 10 Technical Preview recently and I was happy to see that the Start menu has returned with a facelift of sorts. The Start menu on Windows 8, as we all know, was changed to suit a touch interface. This was really great for their premiere surface tablet line up – but for desktop users without touch functionality this left a lot to be desired.
Personally, I do far too much on my system to even be able to rely on a touch interface at this point. The keyboard and mouse will not be going away any time soon in my life. Its shameful that Microsoft made the assumption that everyone would prefer that type of, non-selectable I might add, interface. Why shameful? I learned user interface design from Microsoft and MSDN while I was learning Visual Basic 6 eons ago – they have a tremendous investment in it that was ignored in Windows 8 (unless you’re a tablet user that is).

Application Menu Scrolls – Live Tiles Never Disappear

Enough of my ranting; Microsoft is fixing the Start menu problem now. Albeit, you’ll have to pay for a new version. There are other, less spectacular improvements on the way as well.
Windows users will have the opportunity to set up multiple desktops and switch between them. Granted, most Linux users have had this feature enabled on their desktops since the dark ages – now Windows has it.

Multiple Desktops Now

Window snapping has also been improved with selectable stacking (or tiling) with more than two windows. In the preview version I was using there was gaps between the snapped windows that made it less desireable. I have to assume that this will be remedied by the release date however.
I would have really liked to put Windows 10 through a couple of months of hard usage but my Nvidea drivers refuse to install as the version number is unrecognized by the driver installer. So I shouldn’t say I had the full “user experience” when I tested it. (Everyone knows – no video drivers = poor computing experience). Still, overall, it ran as well as Windows 8 on my box.
Windows 10 is still a work in progress. In my opinion it has a long way to go before they should actually call it a new version. It’s still Windows 8 with a facelift that suits desktop users in other words.
The technical preview is requesting that you (the tester) submit your views and opinions as you use it. That’s probably the most important improvement – the user opinion factor. So if you have an extra box laying around that you use for testing – try it. Put your two cents in and try to make the OS a bit better in the end.

Google Chrome, Javascript, NodeJS, Opera

Video – Memory Management Masterclass with Addy Osmani

Really good video on managing memory using Google Chrome Dev Tools.
From YouTube:Published on Sep 2, 2014

Addy is a senior engineer on the Chrome web engineering team, focusing on tools to help improve developer productivity and satisfaction. He works on Polymer – a Web Component library, is the the lead engineer on Yeoman and Web Starter Kit and regularly writes about web application architecture and the front-end. Outside of Google, Addy enjoys both hacking on open-source projects like TodoMVC and Grunt-UnCSS. He has authored books on JavaScript design patterns and frameworks.

Efficient JavaScript webapps need to be fluid and fast. Any app with significant user interaction needs to consider how to effectively keep memory usage down because if too much is consumed, a page might be killed, forcing the user to reload it and cry in a corner. Automatic garbage collection isn’t a substitute for effective memory management, especially in large, long-running web apps. In this talk we’ll walk through how to master the Chrome DevTools for effective memory management. Learn how to tackle performance issues like memory leaks, frequent garbage collection pauses, and overall memory bloat that can really drag you down.