Multiprotocol IM clients on OS X - a list I have tried so far

IM is one of the PIM applications I often rely to. I still use ICQ for that matter (and AIM, Yahoo! MSN, Skype). For anyone who needs a multiprotocol IM client on Mac OS X. I won't go into details and what I like/dislike about these clients as it is a personal thing. Some are more developed than others. Some are more native than others. Some ore more opensource than others. And some are easier to set up than others.

 


Taps 11: The Ripples tap

Ok, a tap I actually haven't used, but it looks weird enough to think about the fun and toil moments with it.

"... On top of the frosted ripple surface sits a metal ball. An array of electromagnetic sensors detects that ball’s position. Moving the ball in or out from the center controls water pressure. Moving it around [left hot - right cold] controls temperature.

The surface glows red or blue to denote how hot or cold it is. The two separate channels combine the hot and cold water to get the perfect mix... " Yanko Design - From beyond function, Water Ball Ripples, 27.2.2008

This tap is really nice looking, probably funny to play with and a piece of equipment to show to visitors. But it has some flaws (or disadvantages) as well, so I think not everyone would adopt it:

  • the ball seems easy to lose (think of kids ... ok and the rest of us) or drop down the drain (look at one on the photo)
  • it would be hard to clean water stone from the water canals and also the canals where the ball moves
  • handling it with wet (and soapy) hands would leave a mess (not to say this doesn't happen with every tap, but with the regular tap pouring some water over it would do; with this one the water stays in the canals)
  • it cannot fit on an ordinary sink
  • not sure if mixing really works as with every tap without an aerator I used so far I had a feeling that water was scolding and freezing my hands at the same time (my own peculiarity)
  • it needs electricity as well - so aside a plumber, fitting would need to be done also by an electrician
  • it is probably more prone to faults as more complex parts are used

Designer: Smith Newnam & Touch360 Studio"

Suggestions on PIM applications design

PIM research produced a significant amount of work. Many researchers gave guidelines on how future PIM applications should be designed or what should be taken into account when designing them. These guidelines are based on observations during the PIM studies. Let's look at some of them.

Henderson [1] argues that there are three groups of users: pilers, filers and structurers. PIM tools should accommodate the following:

  • Piling strategy
    Do not require containment
    Support a time based interface
       Provide optional tagging
  • Filing strategy
        Support containment
        Provide a cleanup interface
        Support reminders
  • Structuring strategy
        Support containment with multiple classification/dynamic containers
        Provide optional relationships between items
        Provide optional tagging and colour coding
        Provide optional custom metadata

Ravasio et. al. [2] looked at the problems users encounter when managing files on computers. She and her colleagues addressed several issues that need to be addressed quickly

(1) ‘Annotations’ as a new type of information. Suitable handling—in programs, storage and retrieval facilities, and so forth—are subsequent requirements.
(2) Store documents in publicly available default formats in order to avoid difficulties when exchanging documents.
(3) Provide a ‘search for content’ feature that includes all file formats that exist in a system.
(4) Simplify the UI of the existing built-in search tools. Do not require users to specify more information than they can possibly know.

In general, She claims that PIM systems should accommodate 3 aspects of file management:

(1) Task oriented—focused on the task to be accomplished,
(2) context oriented—focused on other documents, programs and tasks at hand con- currently, and
(3) content oriented—focusing on the actual information encapsulated in a specific document.

Bergman [3] identified 3 subjective principles that should be taken into account in PIM

  • The subjective classification principle: information items related to the same subjective topic should classified together despite technological format.
  • The subjective importance principle: this should provide a degree of visibility or salience and accessibility. When exposed to new information users determine how important that information is and systems should take in to account the this importance as perceived by the user.
    - High subjective importance: what was dealt with most recently and what was frequently dealt with in last xy time is the most important.
    - Low subjective importance: a cognitive problem or irrelevant information being in a way while searching for important information, users do not archive old information, graphically change items not being accessed for a long time specified by user.

  • The subjective context principle: information should be retrieved and viewed in the same context in which it was previously used. Context should be captured and added to information. - External context: items that users dealt with (activated) while interacting with a specific item: like coping and pasting text should create a link.
    - Internal context: relates to users thoughts while interacting with information item, users might write annotations of what they read and search these.
    - Temporal context: this pertains the state in which the user left information item when last interacting with it and working plans regarding that information. Similar happens with unread email that are in bold and web links (change color when visited) so the user knows what has been already done - trace past activities. Users could mark information they plan to work on in the future.

Boardman [4] highlights two perspectives that need to be taken into account (he also defends the idea of separated information by type):

  • From a tool-specific perspective, each PIM-tool is a distinct sub-system to be optimized independently.
    - consider how that tool is employed along with other tools in supporting cross-tool production activities
    - be aware that anything new is added to a set of existing PIM sub-systems
    - careful attention should be paid to potential side-effects in other tool contexts
  • On the other hand, a cross-tool perspective emphasises the need to optimize the combined sub-systems. In other words, the designer is more concerned about how well the PIM sub-systems work together.
    - when investigating user needs, designers should pay attention to current user behaviour across all the tools that will be affected
    - a key implementation challenge is dealing with the sheer range of PIM-tools in use

Voit et. al. [5] addressed different aspects that need to be taken into account when designing PIM tools. They claim that PIM tools should comply with this set of requirements:

  • Be Compatible with Current User Habits: Users are comfortable with their application environment and want to keep it that way. Any new software solution has to integrate into the current environment as smoothly as possible.
  • Minimal Interference: Any new software solution requires some kind of additional user interface. It is essential to keep the learning effort as small as possible. Any interaction step which the users have to make should be absolutely necessary to the process.
  • Support Multiple Contexts: Studies show that over the years users still prefer browsing over teleporting. When browsing a classification hierarchy, users can see the choices available at each level and choose the most promising.
  • No Unnecessary Limitations: Since large numbers of computer files define our everyday lives, any PIM software solution should scale well to a large number of files and should not affect the efficiency of the browsing process.
  • Transparency: User have built up knowledge of their software environment: a set of experiences, expectations, and standard processes concerning file storage and retrieval. For example, an existing backup process should not be affected by a new PIM system. Users should know where their files are located and what happens to them.
  • Provide for Expiry Dates: Providing an expiry date offers the user to explicitly define information as ephemeral, which is an important need as user studies suggest.
  • Add Metadata While Storing: When a file is stored the user should be given the option to manually add metadata and contextual information to the file. Manual and semi-manual tagging can offer an effective solution for a better retrieval method.

[1] Henderson, Sarah, Personal document management strategies, CHINZ '09
[2] Pamela Ravasio and Sissel Guttormsen Schr and Helmut Krueger, In pursuit of desktop evolution: User problems and practices with modern desktop systems, TOCHI, 2004
[3] Bergman, Ofer and Beyth-Marom, Ruth and Nachmias, Rafi, The user-subjective approach to personal information management systems design: Evidence and implementations, JASIST, 2008
[4] Richard Boardman, Improving tool support for personal information management, PhD thesis, mperial college London, University of London, 2004
[5] Voit, K. and Andrews, K. and Slany, W., Why Personal Information Management (PIM) Technologies Are Not Widespread, ASIST '09: Personal Information Management (PIM) Workshop

PHP - get favicon from an URL

I recently commented on Alan's blog about getting favicon from and URL. The simplest way is getting a domain of an URL and adding "favicon.ico" at the end. The problem arises if:

  • the favicon is not on the root on the host name
  • it has an uncommon name
  • it is not in MS ICO format which (nowadays PNG is very common).

Finding the <link rel="icon"> or <link rel="shortcut icon"> in the DOM of an external URL is hardly possible in Javascript for security reasons (look at the XMLHttpRequest for possibilities). One way of doing it is to access external URLs through proxy.

The simpler way is using some server side scripting language such us PHP and a DOM (HTML) parser. I just finished the script and it worked on a few given URLs (with keeping in mind that it could be improved). I deliberately first look at the DOM of a document (see the first bullet above) as for example a personal web page  http://osebje.famnit.upr.si/~mkljun/ might have a different favicon as the main http://osebje.famnit.upr.si/ server page. Here's the code:

<?php
function getFavicon ($url) {
    $file_headers = @get_headers($url);
    $found = FALSE;
    // 1. CHECK THE DOM FOR THE <link> TAG
    // check if the url exists - if the header returned is not 404
    if($file_headers[0] != 'HTTP/1.1 404 Not Found') {
        $dom = new DOMDocument();
        $dom->strictErrorChecking = FALSE;
        @$dom->loadHTMLfile($url);  //@ to discard all the warnings of malformed htmls
        if (!$dom) {
            $error[]='Error parsing the DOM of the file';
        } else {
            $domxml = simplexml_import_dom($dom);
            //check for the historical rel="shortcut icon"
            if ($domxml->xpath('//link[@rel="shortcut icon"]')) {
                $path = $domxml->xpath('//link[@rel="shortcut icon"]');
                $faviconURL = $path[0]['href'];
                $found == TRUE;
                return $faviconURL;
            //check for the HTML5 rel="icon"
            } else if ($domxml->xpath('//link[@rel="icon"]')) {
                $path = $domxml->xpath('//link[@rel="icon"]');
                $faviconURL = $path[0]['href'];
                $found == TRUE;
                return $faviconURL;
            } else {
                $error[]="The URL does not contain a favicon <link> tag.";
            }
        }

        // 2. CHECK DIRECTLY FOR favicon.ico OR favicon.png FILE
        // the two seem to be most common
        if ($found == FALSE) {
            $parse = parse_url($url);
            $favicon_headers = @get_headers("http://".$parse['host']."/favicon.ico");
            if($favicon_headers[0] != 'HTTP/1.1 404 Not Found') {
                $faviconURL = "/favicon.ico";
                $found == TRUE;
                return $faviconURL;
            }
            $favicon_headers = @get_headers("http://".$parse['host']."/favicon.png");
            if($favicon_headers[0] != 'HTTP/1.1 404 Not Found') {
                $faviconURL = "/favicon.png";
                $found == TRUE;
                return $faviconURL;
            }
            if ($found == FALSE) {
                $error[]= "Files favicon.ico and .png do not exist on the server's root."
            }
        }
    // if the URL does not exists ...
    } else {
        $error[]="URL does not exist";
    }

    if ($found == FALSE && isset($error) ) {
        return $error;
    }
}

// URL in one line 
$tempurl = 'http://stackoverflow.com/questions/1732348/regex-match-open-tags
-except-xhtml-self-contained-tags/1732454#1732454';
$result = getFavicon ($tempurl);
echo $result;
?>

However, the script is very slow and parsing badly structured DOMs returns a bucketful of warnings. Hence the @ before $dom->loadHTMLfile($url).

Although the slowness of the script can be accounted to waiting for server to respond, I wondered if computing times could be improved (see the measured times below).

Another way of finding the appropriate <link> tag is to read the file line by line (assuming the link tag is in one line). I know, I know ... but the <link rel="icon"> is at the beginning of the file and we could exit the loop when we find it. Here's the solution echoing the result (note that here is just the changed if sentence from the above function):

    //check if the url exists
    if($file_headers[0] != 'HTTP/1.1 404 Not Found') {
        //open the pointer to the file 
        $handle = @fopen($url, "r");
        //while the file is not end of file
        while (!feof($handle)) {
            //read next line
            $buffer = fgets($handle, 4096);
            if (strstr($buffer, '<link')) {
                if (strstr($buffer, 'icon')) {
                    $doc=new DOMDocument();
                    $doc->loadHTML('<html><head>'.$buffer.'</head><body></body></html>');
                    $domxml=simplexml_import_dom($doc); 
                    $path=$domxml->xpath('//link');
                    $faviconURL = $path[0]['href'];
                    $found == TRUE;
                    echo $faviconURL;
                    //exit the loop
                    break;
                }
            }
        }
    } 

This version was a bit faster (see user and system times below). I also thought why not giving the regular expressions a try. I know, I know ... regular expression are not meant to parse HTML. But as we know what we are looking for ...

    //check if the url exists
    if($file_headers[0] != 'HTTP/1.1 404 Not Found') {
        $handle = @fopen($url, "r");
        while (!feof($handle)) {
            $buffer = fgets($handle, 4096);
            if (strstr($buffer, '<link')) {
                if (strstr($buffer, 'icon')) {
                    preg_match_all('/href=["\']([^"\']*)["\']/i',$buffer, $array);
                    echo print_r($array);
                    break;
                }
            }
        }
    }

The third solution is comparable to the second. However, the response time from the server was quicker?!? Albeit still slow ... maybe I'm missing something ... but have no time at the moment ... Also, the # of tries I tested each script (around 20) is low to draw any conclusion.

Here are some measured times of running these scripts:

mkljun@pim:~$ time php getFavicon.php 
http://cdn.sstatic.net/stackoverflow/img/favicon.ico
real    0m26.881s
user    0m0.048s
sys    0m0.036s
mkljun@pim:~$ time php getFavicon.php 
http://cdn.sstatic.net/stackoverflow/img/favicon.ico
real    0m21.531s
user    0m0.052s
sys    0m0.028s
mkljun@pim:~$ time php getFavicon.php 
http://cdn.sstatic.net/stackoverflow/img/favicon.ico
real    0m31.562s
user    0m0.052s
sys    0m0.024s
mkljun@pim:~$ time php getFavicon2.php 
http://cdn.sstatic.net/stackoverflow/img/favicon.ico
real    0m26.080s
user    0m0.044s
sys    0m0.008s
mkljun@pim:~$ time php getFavicon2.php 
http://cdn.sstatic.net/stackoverflow/img/favicon.ico
real    0m25.918s
user    0m0.024s
sys    0m0.028s
mkljun@pim:~$ time php getFavicon2.php 
http://cdn.sstatic.net/stackoverflow/img/favicon.ico
real    0m25.984s
user    0m0.032s
sys    0m0.020s
mkljun@pim:~$ time php getFavicon3.php 
            [0] => http://cdn.sstatic.net/stackoverflow/img/favicon.ico
real    0m20.954s
user    0m0.028s
sys    0m0.024s
mkljun@pim:~$ time php getFavicon3.php 
            [0] => http://cdn.sstatic.net/stackoverflow/img/favicon.ico
real    0m26.077s
user    0m0.032s
sys    0m0.020s
mkljun@pim:~$ time php getFavicon3.php 
            [0] => http://cdn.sstatic.net/stackoverflow/img/favicon.ico
real    0m20.884s
user    0m0.028s
sys    0m0.028s


Javascript (Mootools) random date generator

I've needed a random date generator between two dates. This has been easy with Mootools. Both dates are first converted to unix timestamp format (# of seconds after 1.1.1970), then a random number between the two unix times is generated and converted back to date.



function randomDate(date1, date2) {
   var minD = new Date().parse(date1).format('%s');
   var maxD = new Date().parse(date2).format('%s');
   var random = Number.random(parseInt(minD), parseInt(maxD));
   var randomDate = new Date().parse(random+"000").format('db'); 
}

Which can be called

var randomDateTmp = randomDate('1999-06-08 16:34:52', new Date()); 

Set the format accordingly to http://mootools.net/docs/more/Types/Date#Date:format

This can be easily accomplished in other programming languages.