Misc

[UPDATE]This post has been featured at Sky News. Check out more information here.

[UPDATE]As events occur, I will do my best to add them to the map. It seems that Russia is no longer focusing on South Ossetia, but instead has started attacking all areas of the country of Georgia. The attacks are marked on the map and it can be seen that they are spread throughout the country.

[UPDATE]Cyberattacks have been commencing against various governmental and news organizations for the country of Georgia. The website for the Georgian Ministry of Foreign Affairs (mfa.gov.ge) has been defaced, for example. Instead of a website, you are treated to an image of Hitler and Saakashvili. More details (including the image) can be found in this post.

Though the conflict has been going on for some years, today the region of South Ossetia has fallen victim to levels of violence not seen for quite some time.

Russia has decided to attack Georgia for their response against the South Ossetians. Many of whom, Russians say, are still Russian citizens.

It seems a bit too convenient that just a month ago, thousands of troops were meeting with other countries in the region for training exercises called “Immediate Response 2008.” You can see some photos of the event here. In addition, Russia has recently been critical of Georgia for wanting to join up with NATO.

I thought I might be able to get a decent view of the area with Google maps. However, there is very little data for the region. So, as I have done before, I created my own map to further my understanding of what is going on in the region. The map was created through research and the use of a map that was uploaded to Wikipedia detailing the region.

I tried my best to locate the various towns and villages that are scattered throughout the area. In addition, if you click on the View Larger Map link, then you can see the list of conflicts in the order they occurred along the left. I hope that others will be able to use this map to further their understanding of the region and what is really taking place.

In this map, you can find small towns and villages marked with a small green indicator, larger towns with a yellow indicator and capitals marked with reddish indicators. The area known as South Ossetia is highlighted in orange. In addition, if you zoom in, you can see the approximate route that the refugees are most likely taking to flee the area to Russia. The exclamation points mark where conflicts/attacks occurred and the tent-looking images represent military bases that have been attacked:

Now that I have completed the map I feel like I have a much better idea of what is going on over there. I hope that this map will help provide others with the same kind of knowledge.

Please let me know if there are any corrections that need to be made and I would be glad to make them. Also, if you liked this post, please be sure to subscribe to my feed.

Geekery

If you’ve ever had to deal with time and PHP before, chances are you’ve had to deal with time zones. Dealing with time is difficult enough, but once the time becomes variable based on the preferences of the user of your application, it becomes even more confusing.

Why so confusing? I mean, it seems simple enough doesn’t it?

Well, there’s a lot to consider:

  • How do you store the dates?
  • How do you store the time zones?
  • How do you do the math for adjustments?
  • etc.

Through enough research and googling, you can answer most of these questions. However, there came a time to decide how the time zone was going to be displayed to the user. In PHP you have some built in options that are fairly handy. However, we wanted to show the user the time zone abbreviation. In addition, we had to match up what PHP does with the time zone options that we give our users. The time zone options are stored in our database like so:

 timezone_id |                   name              | gmt_offset
-------------+-------------------------------------+------------
           1 | -12:00 International Date Line W.   |       -720
           2 | -11:00 Midway Island, Samoa         |       -660
           3 | -10:00 Hawaii                       |       -600
...

Pretty straightforward list of time zones with their IDs along with the offset in minutes. This does not include every single time zone under the sun mind you.

The PHP functionality provides a fairly easy way to find the different time zone codes in the country/area format such as America/Los_Angeles or Europe/Berlin. You can use functions such as timezone_abbreviations_list to get the offset along with the time zone code or you can use timezone_identifiers_list to get a list of just the time zone codes.

However, PHP does not have any simple means of gathering the time zone abbreviations for each time zone such as MDT or BST. This is the format that we wanted to use to display to our client.

So, here's a simple function to list them all out for you:

$time_zones = timezone_identifiers_list();
$time_to_use = 'now'; # just a dummy time
$time_zone_abbreviations = array();
foreach ($time_zones as $time_zone_id) {
    $dateTime = new DateTime($time_to_use);
    $dateTime->setTimeZone(new DateTimeZone($time_zone_id));
    $abbreviation = $dateTime->format('T');
    if (!in_array($abbreviation, $time_zone_abbreviations)) {
        echo $time_zone_id . ' - ' . $abbreviation . "\n";
        $time_zone_abbreviations[] = $abbreviation;
    }
}

This will give you a wonderful list of unique time zone codes that you can use now:

Africa/Abidjan - GMT
Africa/Addis_Ababa - EAT
Africa/Algiers - CET
Africa/Bangui - WAT
etc.

Eventually you may come to an unexpected result in the list:

Factory - Local time zone must be set--se

But, for the most part, this is a useful list.

Now, this list is okay, but what if you need to know the offsets that go with this? Well, PHP provides another function called timezone_abbreviations_list. This gives us the time zone code and the offsets. Cool: let's modify our previous function and make our list that way.

This is where some unexpected results start to occur. The timezone_abbreviations_list function returns an array of time zones that are sorted by their abbreviation like so:

["mst"]=>
  array(32) {
    [0]=>
    array(3) {
      ["dst"]=>
      bool(false)
      ["offset"]=>
      int(-25200)
      ["timezone_id"]=>
      string(14) "America/Denver"
    }
    [1]=>
    array(3) {
      ["dst"]=>
      bool(false)
      ["offset"]=>
      int(-25200)
      ["timezone_id"]=>
      string(13) "America/Boise"
    
    etc...

Our previous function extracted the abbreviation by using the long description, such as America/Boise, to create a date. We are going to do the same thing, only we are going to use the timezone_ids that are given to us from the timezone_abbreviations_list function. It seems like this would be the correct route since we can have access to the offsets from that function. For now, we just want to produce the same list as we did before with this function:

$time_zones = timezone_abbreviations_list();
$time_to_use = 'now'; # just a dummy time
$time_zone_abbreviations = array();
foreach ($time_zones as $key => $time_zone_array) {
    foreach ($time_zone_array as $key => $info) {
        $time_zone_id = $info['timezone_id'];
        $dateTime = new DateTime($time_to_use);
        $dateTime->setTimeZone(new DateTimeZone($time_zone_id));
        $abbreviation = $dateTime->format('T');
        if (!in_array($abbreviation, $time_zone_abbreviations)) {
            echo $time_zone_id . ' - ' . $abbreviation . "\n";
            $time_zone_abbreviations[] = $abbreviation;
        }
    }
}

It all goes fine and dandy until it gets to the end of the list:

...
Antarctica/Vostok - VOST
Pacific/Efate - VUT
America/Godthab - WGST
Asia/Yakutsk - YAKST

Fatal error: Uncaught exception 'Exception' with message 'DateTimeZone::__construct() [function.DateTimeZone---construct]: Unknown or bad timezone ()'

Uh-oh, that doesn't seem good. It looks like it is trying to construct the time with no time zone information. A bit of code will show us where the problem lies:

$time_zones = timezone_abbreviations_list();
foreach ($time_zones as $key => $time_zone_array) {
    var_dump($key, $time_zone_array);
}

We can go through the list of arrays and look to see where the problem is occurring. Eventually we come to listings that look like this:

string(1) "a"
array(1) {
  [0]=>
  array(3) {
    ["dst"]=>
    bool(false)
    ["offset"]=>
    int(3600)
    ["timezone_id"]=>
    NULL
  }
}
string(1) "b"
array(1) {
  [0]=>
  array(3) {
    ["dst"]=>
    bool(false)
    ["offset"]=>
    int(7200)
    ["timezone_id"]=>
    NULL
  }
}

Yes, the entire alphabet is at the end of the list. There are a bunch of arrays with keys of a-z that have null timezone_ids associated with them. What are they there for? I can't find any rhyme or reason to the entries, but they are there, and they mess up our function.

A quick change to our code to check for empty timezone_ids will make our function work properly:

$time_zones = timezone_abbreviations_list();
$time_to_use = 'now'; # just a dummy time
$time_zone_abbreviations = array();
foreach ($time_zones as $key => $time_zone_array) {
    foreach ($time_zone_array as $key => $info) {
        $time_zone_id = $info['timezone_id'];		
        if (!empty($time_zone_id) {
            $dateTime = new DateTime($time_to_use);
            $dateTime->setTimeZone(new DateTimeZone($time_zone_id));
            $abbreviation = $dateTime->format('T');
            if (!in_array($abbreviation, $time_zone_abbreviations)) {
                echo $time_zone_id . ' - ' . $abbreviation . "\n";
                $time_zone_abbreviations[] = $abbreviation;
            }
        }
    }
}

Now we should have the same list we did before. But, we don't. The first script, using the timezone_identifiers_list function gave us 175 results. Our other script? 136. So, what are the time zones that exist in the timezone_identifiers_list function that don't show up in the timezone_abbreviations_list function? Here's the list:

Indian/Cocos - CCT
Indian/Christmas - CXT
Pacific/Tarawa - GILT
Etc/GMT+1 - GMT+1
Etc/GMT+10 - GMT+10
Etc/GMT+11 - GMT+11
Etc/GMT+12 - GMT+12
Etc/GMT+2 - GMT+2
Etc/GMT+3 - GMT+3
Etc/GMT+4 - GMT+4
Etc/GMT+5 - GMT+5
Etc/GMT+6 - GMT+6
Etc/GMT+7 - GMT+7
Etc/GMT+8 - GMT+8
Etc/GMT+9 - GMT+9
Etc/GMT-1 - GMT-1
Etc/GMT-10 - GMT-10
Etc/GMT-11 - GMT-11
Etc/GMT-12 - GMT-12
Etc/GMT-13 - GMT-13
Etc/GMT-14 - GMT-14
Etc/GMT-2 - GMT-2
Etc/GMT-3 - GMT-3
Etc/GMT-4 - GMT-4
Etc/GMT-5 - GMT-5
Etc/GMT-6 - GMT-6
Etc/GMT-7 - GMT-7
Etc/GMT-8 - GMT-8
Etc/GMT-9 - GMT-9
Factory - Local time zone must be set--se
Pacific/Port_Moresby - PGT
Pacific/Ponape - PONT
Pacific/Palau - PWT
Pacific/Fakaofo - TKT
Pacific/Truk - TRUT
Pacific/Funafuti - TVT
Etc/UCT - UCT
Pacific/Wake - WAKT
Pacific/Wallis - WFT

So now we know that we can get a more complete list of the PHP abbreviated time zones by just using the timezone_identifiers_list function. We are going to use that list and instead of relying on the offset given to us by the timezone_abbreviations_list, we are going to use the built-in getOffset function to get the offset from GMT:

$time_zones = timezone_identifiers_list();
$time_to_use = 'now'; # just a dummy time
$time_zone_abbreviations = array();
foreach ($time_zones as $time_zone_id) {
    $dateTime = new DateTime($time_to_use);
    $dateTime->setTimeZone(new DateTimeZone($time_zone_id));
    $abbreviation = $dateTime->format('T');
    $offset = $dateTime->getOffset() / 60;
    echo $offset . ' - ' . $abbreviation . ' (' . $time_zone_id . ')' . "\n";
}

This looks like the useful list that we were looking for in the beginning:

0 - GMT (Africa/Abidjan)
0 - GMT (Africa/Accra)
180 - EAT (Africa/Addis_Ababa)
60 - CET (Africa/Algiers)
...

Now you know all the acceptable time zone abbreviations to use for PHP! But wait, there's a catch (isn't there always?):

Some time zone abbreviations refer to more than one time offset!

Do'h!

Let's modify our function so that we know which ones to be careful for:

$time_zones = timezone_identifiers_list();
$time_to_use = 'now'; # just a dummy time
$time_zone_abbreviations = array();
foreach ($time_zones as $time_zone_id) {
    $dateTime = new DateTime($time_to_use);
    $dateTime->setTimeZone(new DateTimeZone($time_zone_id));
    $abbreviation = $dateTime->format('T');
    $offset = $dateTime->getOffset() / 60;
    if (!array_key_exists($abbreviation, $time_zone_abbreviations)) {
        $time_zone_abbreviations[$abbreviation] = $offset;
    } else {
        if ($time_zone_abbreviations[$abbreviation] != $offset) {
            // We have two offsets for the same abbreviation
            $previous_offset = $time_zone_abbreviations[$abbreviation];
            $same_abb_diff_o[$abbreviation] = $previous_offset . ' and ' . $offset;
        }
    }
    $time_zone_ids[$abbreviation] = $time_zone_id;
}
foreach ($time_zone_abbreviations as $abbreviation => $offset) {
    echo $offset . ' - ' . $abbreviation . ' (' . $time_zone_ids[$abbreviation] . ')' . "\n";
}
echo "Watch out for:\n";
foreach ($same_abb_diff_o as $abbreviation => $info) {
    echo $abbreviation . ' same abbreviation used for ' . $info . "\n";
}

This gives us our same list before, but it lets us know that there are a few to watch our for at the end:

CDT same abbreviation used for -300 and -240
AST same abbreviation used for -240 and 180
ADT same abbreviation used for -180 and 240
CST same abbreviation used for -360 and 480
GST same abbreviation used for 240 and -120
EST same abbreviation used for -300 and 600
IST same abbreviation used for 330 and 60
WST same abbreviation used for 480 and -660

So what did we learn here today?:

  • There are helpful time zone functions available in PHP.
  • When speaking of time zone abbreviations, you may get unexpected results between the timezone_identifiers_list function and the timezone_abbreviations_list functions.
  • The timezone_abbreviations_list function returns an array that (for some odd reason) has time zone entries for each letter of the alphabet, a-z, that have no valid timezone_id.
  • Using the time zone abbreviation when setting time zones is not always safe.

I hope this post was helpful to those struggling to understand the time zone functions or to others who are trying to utilize time zone abbreviations within PHP. Once you understand how the time zone functions work, and how you can get access to the abbreviations, it becomes a bit easier to understand how to shape your code for your application.

If you enjoyed this post, then please be sure to subscribe to my feed.

Geekery

Applying for new jobs can be a tough thing to do. This can be especially true in the high tech world.

Most jobs require that you have certification ahead of time. Once you have the magical piece of paper (or pieces of paper), you will probably have to prove your abilities in some way before you even get to talk to the person who may be able to refer you to the person that might be able to hire you. Usually this “proof of competence” comes in the way of a verbal or written quiz.

Depending on the business, you may have to answer the questions in the interview, or you may be able to take the quiz home and use reasonable resources to answer the questions to the best of your abilities.

This particular applicant apparently didn’t understand that you should, at the very least, do your own work. He got pwnd for it.

The original post was from a user named bradcarr in the Ubuntu linux forums. It was entitled “Calling All Linux Experts”:

“If I could ever so kindly ask the Linux world for some help.

I have applied for a job that is in a heavy Linux environment and I have been sent a questionnaire about my knowledge. I know my way around pretty good and just want double check my answers. Some of the questions and a gim-me, some take some thinking and some are just down right hard. Any and all help will be greatly appreciated.

Here are the questions:

1. Give an example of set of shell commands that will give you the number of files in a directory
2. How do you tell what process has a TCP port open in Linux
3. On a Red Hat Linux Variant how do you control whether a service starts when the system boots
4. How do you tell the amount of free disk space left on a volume
5. Give an example of a set of shell commands to tell how many times “bob” has logged on to the system this month
6. Give an example of a recursively copying a directory from one location to another.
7. How do you modify the IP and Net mask of a system running a Red Hat Variant of Linux
8. Give an example of a set of shell commands that will give you the number of “httpd” processes running on a Linux box.
9. On CentOS or Fedora based system using the package management application, how do you tell what package provided the file “libnss_ldap.so”
10. What is the difference between VTP client, server, and transparent
11. What is the maximum length of CAT6
12. How does one set up a layer two link to share VLANs
13. How does one implement redundant links at Layer 2
14. What is the difference between a hub, switch, and a router
a. What are the security advantages of switch vs. hub
15. Show an example of using telnet to learn the headers of an http server.
16. In what OSI layer does PPP exist
17. What’s the difference between TCP and UDP
18. Given a DNS server that has just started (with an empty cache) and host contacting this DNS server (using it’s OS setting) to learn an address for google.com, list the steps the DNS server will take to learn it with IP addresses (each step will have multiple possible IP addresses – you need choose only one per step).
19. Why are layer 2 loops bad, and what protocol was designed to prevent them
20. Given a radius server at 10.0.0.2 and a shared key of ‘abc123’ show the IOS commands necessary to authenticate switch users against the radius server, while still allowing the use of local username / password pairs

THANKS FOR THE HELP!!!!!!!!!!”

Users were quick to respond with reasonable answers to his post like this one from dcstar:

“How about you supply the answers so we “experts” can tell you if they are correct or not, because I for one will not be taking the risk of aiding and abetting someone to get a job they may not be qualified for by potentially helping them cheat (and possibly prevent someone that is qualified from succeeding).

If you don’t answer then those others on this forum who may not be as cynical as me may have learned a valuable lesson themselves…..”

However, the real kicker was the response on page two of the post from a user named ptinsley:

“For those who have commented, it is indeed an entry level network administration position with some Linux skills required as most of our network management tools run on Linux. I would also like to say thank you for the very sensible comments you all have made about the call for answers. And “bradcarr” while you haven’t broken the rules of my questionnaire you have definitely broken the spirit of the exercise. I did indeed say you could use any resource available to you, but didn’t it cross your mind that this might be the wrong thing to do? I want to see the “real world” ability of a potential employee, not what they can recite in an interview but what they can come up with using their normal information sources to solve a problem or research a subject.

This has shown me that you won’t take the initiative to research a problem, even when it might land you a job. I “googled” most of these questions before making the list and most of them are very easily discovered. It didn’t seem to me that I was asking too much for people to use mailing lists, forums, IRC whatever to compile the answers themselves. I actually expected to see some questions show up on forums but I didn’t expect someone to paste the entire thing and expect the forum users to do all the work that would qualify you for an interview. I think at this point you could save us all some time and not turn the answers back in, I already have the information I need on your answers.

As far as the rest of you, if there are any of you reading this thread that live in the Nashville area that want a network administration job with some Linux work feel free to shoot me your resume at [please check original post for email address]. Oh, while you are at it, go ahead and send me the answers to the questions :)”

Yup, I think pwnd would definitely be the correct word here.

If you liked this post, then please consider subscribing to my feed.