Author: sjan

Development

iPhone icons for your site

Adding a shortcut to a favorite site on an iPhone (or iPod Touch) is as easy as tapping the “+” sign at the bottom of the Safari browser on the phone and selecting “Add to Homepage” – but the icon is not so appealing. In fact, the iPhone defaults to a tiny, cropped screenshot of the site unless it finds a 57×57 pixel png file in the site root. This is similar to the concept of the favicon.ico for web browsers. The file needs to be named apple-touch-icon.png.

The iPhone (or iPod Touch) will round the corners and overlay the glass look to make it blend in to the overall look and feel of the “Springboard” (their name for the desktop on these devices.)

Mine looks like this (before the modifications which take place on the device itself):

And this is what it looks like on the iPhone:

WordPress

Time for a new look

After looking at the same design since January of 2007, I felt it was time for a new look. So, a little tweaking to the theme Hope by Fatma Hassan and here it is, Evardsson 2.0. I love the look of the theme as it is, but I have to have my reindeer or I feel like it isn’t my site.

I like having a fluid layout, and this one seems to work reliably well while still looking good. I now return you to your regularly scheduled browsing …

Community

Repurposing Social Software

Social software has had an enormous impact on the workplace, but how much bigger can we go? Already chat is a major communication tool (usually within a business, but sometimes with customers as well.) Businesses are finding justification for setting up blogs and wikis both internally and externally. I work at a company where a large portion of the developers work remotely (there is a joke internally that the hiring manager is trying to get a developer in every state) and keeping in touch is done through a combination of chat, wiki, GoogleDocs and phone conferences. The issue we are discovering with phone conferences is one of bandwidth. While the old style of everyone in the office sitting around a conference phone while everyone remote dials in isn’t a major strain on the VoIP server, many of our conferences lately have involved everyone who is taking part in the conference dialing in via soft-phone from their workstation. The load on the poor server! So the idea was brought up – why not set up an account on a hosted Ventrilo server. That way our VoIP server stays available for our customers (as it should).

This got me thinking – what other social software might be re-purposed for business use? The one that immediately sprang to mind was Twitter. A business could set up a twitter server with a few little modifications which could make it extremely handy. First, set up the server to log all the tweets. Next, set it up so that when logging the tweet it checks the message. If the message starts with @log it could do some magic with it and then either silently discard it (not passing it on to the network), pass it on without changing it, or pass on a customized message based on that tweet.

As a for instance, here are some @log actions I thought up this afternoon. (Most of these require that the twitter server also has access to things like the primary db server, etc):

  • @login <message> – the server puts a clock in message in the time clock table of the database for the user sending the tweet, and puts the optional message in the ‘notes’ column of the table (if there is one). The server then sends the message username has clocked in
  • @logout <message> – same as for login, but clocks the user out.
  • @log [task_message] – the server puts the userid, message and time in the tasks table and sends the tweet username is working on [task message]
  • @logend <message> – same as above, but puts an end time in the row and sends the tweet username is no longer working on [task_message] <message>

Ok, so it’s not a lot, but it is simple, and simple things are more easily adopted. And this ties into electronic time cards, and electronic task time tracking. Hmmm. So what others are there that could be adapted? how about adding a “social tagging” site (something like Spock) to enhance your intranet and internal wiki? You could easily see who is tagged with which project or team and quickly find the right person to answer your question.

I’m sure there are plenty more things that could be incorporated. I just haven’t thought of them yet.

Technorati Tags: , ,

WordPress

WordPress as a psuedo-CMS

I just finished moving my wife’s art site completely to WordPress. She recently asked if I could add a blog to her site, and since I knew that she also wanted the ability to modify someof her content from time to time, I decided to completely move her site to WordPress. It is not as full-featured as a full Content Management System (CMS), but it is also much more light-weight and supports all the things she wants to do (with a few plugins, of course).

The plugins I chose to meet her needs are:

  • Akismet (of course): Spam Filter (now a default with WP installs)
  • Flexible Upload: Picture Uploader which auto-creates thumbnails and supports Light-box like plugins.
  • Google XML Sitemaps: if you don’t know what that is check out Google’s Web Master tools.
  • WP-PostViews Plus: Not the most straight-forward plugin, but she did want some counter tracking.
  • Lightbox 2: Provides Lightbox functionality for WordPress. And with the Flexible Upload plugin she doesn’t have to hand code any of it or write any image links with rel tags.

Technorati Tags:

Development

Problems arising from PHP type casting in ==

While trying to work through the issues I mentioned in the last post I started doing some serious digging and testing. Here is what I have found.

PHP seems to use == for determining equivalance when performing array_search, in_array and switch, while using either === or strcmp when doing array_key_exists.

The result of this is that array_search and in_array will return improper results when used on an array with mixed string and integer values. (Another thing I found, that may or may not be related, is that array keys will be cast from strings to integers when those strings are valid integer values.)

array_search() with mixed types

$one = array (
  'abc',
  'abc1',
  111,
  '111b',
  2,
  '2xyz',
  '123a',
  123
);
$two = $one;
for ($i = 0; $i < count($one); $i++) {
  $xkey = array_search($one[$i], $two);
  if(strcmp(strval($one[$i]), strval($two[$xkey])) != 0) {
    // This should NEVER be reached, but it is, often!
    $eq = 'FALSE';
  } else {
    $eq = 'true';
  }
}
Row $one $two Correct? Found Notes
0 abc abc true 0 abc == abc : array_search($one[0], $two) where $one[0] = string(3) “abc”
1 abc1 abc1 true 1 abc1 == abc1 : array_search($one[1], $two) where $one[1] = string(4) “abc1”
2 111 111 true 2 111 == 111 : array_search($one[2], $two) where $one[2] = int(111)
3 111b 111b FALSE 2 111b == 111 : array_search($one[3], $two) where $one[3] = string(4) “111b”
4 2 2 true 4 2 == 2 : array_search($one[4], $two) where $one[4] = int(2)
5 2xyz 2xyz FALSE 4 2xyz == 2 : array_search($one[5], $two) where $one[5] = string(4) “2xyz”
6 123a 123a true 6 123a == 123a : array_search($one[6], $two) where $one[6] = string(4) “123a”
7 123 123 FALSE 6 123 == 123a : array_search($one[7], $two) where $one[7] = int(123)

array_search() with all strings

$one = array (
  'abc',
  'abc1',
  '111',
  '111b',
  '2',
  '2xyz',
  '123a',
  '123'
);
$two = $one;
for ($i = 0; $i < count($one); $i++) {
  $xkey = array_search($one[$i], $two);
  if(strcmp(strval($one[$i]), strval($two[$xkey])) != 0) {
    // This should NEVER be reached, and with all strings it isn't.
    $eq = 'FALSE';
  } else {
    $eq = 'true';
  }
}
Row $one $two Correct? Found Notes
0 abc abc true 0 abc == abc : array_search($one[0], $two) where $one[0] = string(3) “abc”
1 abc1 abc1 true 1 abc1 == abc1 : array_search($one[1], $two) where $one[1] = string(4) “abc1”
2 111 111 true 2 111 == 111 : array_search($one[2], $two) where $one[2] = string(3) “111”
3 111b 111b true 3 111b == 111b : array_search($one[3], $two) where $one[3] = string(4) “111b”
4 2 2 true 4 2 == 2 : array_search($one[4], $two) where $one[4] = string(1) “2”
5 2xyz 2xyz true 5 2xyz == 2xyz : array_search($one[5], $two) where $one[5] = string(4) “2xyz”
6 123a 123a true 6 123a == 123a : array_search($one[6], $two) where $one[6] = string(4) “123a”
7 123 123 true 7 123 == 123 : array_search($one[7], $two) where $one[7] = string(3) “123”

in_array() and array_key_exists()

$array = array('111'=>'111', '11b'=>'11b', '222b'=>'222b','2x22'=>'2x22');
$keys = array_keys($array);
$searches = array('111b',222,11,'222b',2);
foreach ($searches as $search) {
  $ia = (in_array($search, $array))?'true':'false';
  $ake = (array_key_exists($search, $array))?'true':'false';
  if ($search === '222b') {
    // This is the only place where either should return true
    $iaf = ($ia == 'true')?" class=\"$true\"":" class=\"$false\"";
    $akef = ($ake == 'true')?" class=\"$true\"":" class=\"$false\"";
    $notes = "** Both should be true **";
  } else {
    $iaf = ($ia == 'false')?" class=\"$true\"":" class=\"$false\"";
    $akef = ($ake == 'false')?" class=\"$true\"":" class=\"$false\"";
    $notes = "Both should be false";
  }
}

Notice how the array keys are cast to type int in both the original array and in array_keys.

$array $keys
array(4) {
  [111]=>
  string(3) "111"
  ["11b"]=>
  string(3) "11b"
  ["222b"]=>
  string(4) "222b"
  ["2x22"]=>
  string(4) "2x22"
}
array(4) {
  [0]=>
  int(111)
  [1]=>
  string(3) "11b"
  [2]=>
  string(4) "222b"
  [3]=>
  string(4) "2x22"
}
Search Item in_array array_key_exists Notes
111b false false Both should be false
222 true false Both should be false
11 true false Both should be false
222b true true ** Both should be true **
2 true false Both should be false

So, it appears that array_key_exists() uses either or === strcmp() while in_array() uses ==

NOTE: Calling array_key_exists() with a string value ‘111’ will return true for an item with a key of int 111. This is not the same behavior as ===, but is the same behavior as strcmp() which must be what is used internally for array_key_exists().

The difference between the 3 operations is clear:

$a $b $a == $b $a === $b strcmp(strval($a),strval($b))
int(123) string(4) “123b” bool(true) bool(false) int(-1)

Another area where this becomes an issue is in switch statements. Take the following, for example:

switch()

$array = array(111,'222b');
foreach($array as $val)
{
  $row = ($row == 'row')?'offset_row':'row';
  $false = ($false == 'false')?'offset_false':'false';
  $true = ($true == 'true')?'offset_true':'true';
  switch($val)
  {
    case '111b': // this displays
      $match = '111b';
      $f = " class=\"$false\"";
      $notes = "Incorrect: should have fallen through to next case";
      break;
    case 111: // never makes it here even tho this is correct
      $match = 111;
      $f = " class=\"$true\"";
      $notes = "** Correct **";
      break;
    case 222: // this displays
      $match = 222;
      $f = " class=\"$false\"";
      $notes = "Incorrect: should have fallen through to next case";
      break;
    case '222b': // never makes it here even tho this is correct
      $match = '222b';
      $f = " class=\"$true\"";
      $notes = "** Correct **";
      break;
    default:
      $match = 'no match';
      $f = " class=\"$false\"";
      $notes = "Incorrect: should have matched";
      break;
  }
}
Search Item Match Notes
111 111b Incorrect: should have fallen through to next case
222b 222 Incorrect: should have fallen through to next case
Development

PHP array_search implicit cast of search term

There is an error in the values that array_search returns when searching on an array that has a mix of numeric values (123) and alpha-numeric mixed strings that start with the same and follow with alpha characters (‘123a’).

The results are actually kind of bizarre, but explainable by a bug in PHP’s equivalence test. When testing for equivalence (using ==) PHP determines that 123 == ‘123xyz’. PHP casts the string to an integer when doing the comparison (so ‘123xyz’ becomes 123). This is documented in bugs.php.net (http://bugs.php.net/bug.php?id=23110) – but this leads to problems: both switch and array_search use == for comparison.

So, using:

$one = array (
  'abc',
  'abc1',
  111,
  '111b',
  2,
  '2xyz',
  '123a',
  123
);
$two = $one;

foreach($one as $val)
{
  $key = array_search($val, $two);
  if ($key !== false) {
    echo "$val == {$two[$key]} \n";
    if (strcmp(strval($val), strval($two[$key])) == 0) {
      echo "strcmp returns true";
    } else {
      echo "strcmp returns false";
    }
  } else {
    echo "$val not found \n";
  }
}

results in:

abc == abc -- strcmp returns true
abc1 == abc1 -- strcmp returns true
111 == 111 -- strcmp returns true
111b == 111 -- strcmp returns false
2 == 2 -- strcmp returns true
2xyz == 2 -- strcmp returns false
123a == 123a -- strcmp returns true
123 == 123a -- strcmp returns false

This becomes a real problem when you can’t be sure that the values in an array are all of the same type. However, if you are sure that all the values in the array are of type string then array_search works flawlessly.

I am still unsure how to work around this, however, I think having a version of array_search that doesn’t do an implicit cast on the search value would be of great use.

OS X

Mail.app – Making the switch

It has been 10 days now that I have been using Mail.app rather than Thunderbird and I am ready to uninstall Thunderbird entirely. While I am still waiting for GPGMail for 10.5 to advance beyond the beta stage I can use it as is. I didn’t really notice any difference in startup times between Mail.app and Thunderbird, but I did notice that it was faster at sorting incoming mail by rules and especially at putting the junk mail where it belongs. Thunderbird first loads all the incoming into the inbox and then sorts out junk mail and applies the other sorting rules. With Mail.app I don’t end up waiting for the rules to run before I can start weeding through my mail. I think the biggest thing, though, is that using Mail.app gets me into a position where I can more easily use other tools like the address book and it will, no doubt, facilitate syncing with the iPhone (if I ever get around to taking it out of the box and activating it – but that’s another story for another time.)

OS X

Solved: Mail.app folder headaches

Well, I finally worked through the issues with Mail.app and mapping the Junk folder. I found the fix for it entirely accidentally – I was going through all the settings and found that changing the setting under Mail > Preferences > Junk Mail > When junk mail arrives from “Mark as junk mail, but leave it in the Inbox” to “Move to the Junk mail folder” was enough to restore the mapping for the Junk mail folder.

I also found that the Drafts folder didn’t exactly disappear, it just doesn’t show up when there are no drafts saved.

While GPGMail for 10.5 still incorrectly reports signatures as not being valid, it is still in beta and sure to improve. So, I guess the week of trying it on has begun.

Technorati Tags: ,

OS X

Trying Mail.app again (it’s so very trying)

I am trying out Mail.app again – to see if some the issues I had in the past have been corrected in Leopard. Somehow, it just doesn’t seem to work right. I installed GPGMail (which is still beta for Leopard) and mostly got that working, except that for every key in my GPGKeyring it says that the key is invalid and there is no signing date (they all work fine in Enigmail…). Also, I set Mail.app to use the Trash folder for trash and the Sent folder for sent items, the Drafts folder for drafts and the Junk folder for junk mail. Seemed straightforward. Until I shut down Mail.app and reopened it. The trash and sent mail were still correctly mapped, but the Drafts folder was gone and no matter what I tried the Junk folder would not map to junk mail. Thankfully I didn’t have anything in the Drafts folder at the time! What a pain! So any junk mail I get is marked as junk (but I mostly have to do it myself – I am used to Thunderbird catching the majority of the stuff that spamassassin didn’t mark) but it stays in the inbox. That’s because Mail.app doesn’t know that the Junk folder is the junk folder. Even after I tried again (and again, and again) with the Mailbox > Use Folder As > Junk.

If I can get Mail.app to properly map the Drafts and Junk folders again I will likely try it on for a full week or two and see how I feel about it. If I can’t get it over that hurdle, however, forget it.

Technorati Tags: , ,

Read More

HTML5

HTML 5 First Public Draft

I realize I am a bit late to the party on this one, but things like work take place while these things are happening. Such is life. Anyhow, on to the content …

The W3C released the first public draft of HTML 5 today. If you want to see the announcement it is a great document for playing buzzword bingo. Aside from links (and buzzword bingo), however, the press release doesn’t have much value to me. The links on the other hand …

The release links to the draft itself, a comprehensive list of differences between HTML 4 and HTML 5, and several process and working-group related informational pages. I say it is worth it just to peruse the links.

There are several new elements listed in HTML 5, many of them structural, (such as section, article, header, nav, footer) and many of them to extend the capabilities of HTML (such as audio, video, canvas [for drawing an image], datagrid, progress). What really stuck out was one element that was never an actual HTML element but was treated as one ‘back in the day’: embed. I find it interesting that it finally made it into the (working draft of) the standard.

There are several new input types like number, datetime and email and a long list of new attributes. A few elements have changed in meaning, while several more elements (and attributes) have been removed entirely. Hooray for CSS doing what CSS does, and double hooray for the end of frameset, frame and noframes!

Technorati Tags: ,