Clok: A new way to view time

| No TrackBacks
Clok is a "very fuzzy" world-clock I built, modeled after Caskey Dickson's idea and Java Clok implementation.  Clok is not built to give you the exact time in every time zone; for that, get another, more accurate, world clock.  Instead, my version of Clok is used to help me answer basic time related questions, like:

  • Several of my co-workers are based in London; can I email them at the office, or are they at home?
  • I need to call my girlfriend, but she's in Manila visiting family.  Is it daytime there?
  • Some interesting world news just broke in Dubai; roughly what time is there?

These questions are all a slight variation of the timeless (no pun intended), "what time is it?"  The latest version of Clok can be found at http://clok.koli.ch.


1 - How Do I Read this Clok?

clok-main-snap.jpgEach column represents a single hour, in a 24-hour day.  Each hour is color coded, according to the various pieces, or periods, of a typical day.  As explained here, "sleeping is obviously the least productive and so that is represented in black. The morning is the time between sleeping and lunch, lunch is a time of recovery and planning for the rest of the day. Then there is the afternoon, which for many is the time when the majority of their work gets done. Finally comes evening, which is personal time, time spent with family, or time taking care of those responsibilities that have to do with running our lives and not earning a paycheck."  The colors of each hour in the day directly correspond to these periods.

Each row is a different time zone, modeled after this list on Wikipedia.  And finally, the red line is the approximate current time in that time zone.

Clok automatically updates itself every minute while open; no browser refresh is required.


2 - The User Interface

clok-mode-snap.jpgYou may have noticed that when you mouseover each row on the Clok, four tiny buttons appear on the far right of each time zone.  These represent the various modes: H for human, K for hacker/developer/coder, S for server, and R for raccoon (nocturnal).  When clicked, these buttons change the mode of Clok.  If you're a relatively normal individual with decent sleeping habits, you will find Human mode most useful.  If you, or a friend across the world participates in a more nocturnal lifestyle, then you might enjoy Raccoon mode.

If you find the time zone annotations annoying, and would like to hide them, click anywhere in the orange header bar and the name/UTC ID of each time zone should disappear.


3 - Technical Details

My version of Clok is pure CSS, JavaScript, and PHP (no Flash!).  When the DOM is ready, AJAX is used behind the scenes to call a PHP controller on the server, which actually does the work of computing the time in every requested time zone.  This controller returns a block of JSON that maps a time zone to the position of its red "current time" bar.  The JavaScript loops over these JSON objects in the response, and uses jQuery to move (animate) the red bars into position.  To stay current, an interval fires once every 60,000 ms (1 minute) which triggers Clok to refresh itself.


4 - Where Can I Find this Clok?

Try http://clok.koli.ch.

Enjoy.
Seeking to a line number in a text file isn't too hard to implement in Java if you use a few common and trusted API's like Apache's Commons I/O library.  Recently I needed some Java that could automatically seek to a given line in a file and then remember the line number of the last line read.  The next time I open the log reader, it should automatically seek itself to the last line read, and let me read any subsequent lines added by another user or process.  This is perfect for log file monitoring: the first invocation of the reader would read lines 1 through X and the next invocation would read lines X+1 through Y, and so on.  Using Apache's Commons I/O API, this isn't difficult at all.  You may or may not know that the Commons I/O API contains a very convenient LineIterator class, which lets the developer iterate over lines in a file using a Reader.

With that in mind, meet JumpToLine, a somewhat hackish class I wrote that wraps Apache's Commons I/O LineIterator in a way that lets you seek ahead to a specific line in a file, and is smart enough to remember the last line read (so that you don't read the same line twice).

Happy New Year's

| No TrackBacks
Thumbnail image for shanghai-fireworks-new.year.jpgLast year I wrote up a quick blog post to ring in the New Year, highlighting some of my accomplishments and failures of 2008.  In that spirit, keeping the tradition alive, here's my 2009 in a nutshell:

I kicked off 2009 figuring out how to block Trackback Spam, and wrote up an opinionated piece re: why I dislike and therefore don't use, FacebookMyCougarLand.com failed to update their DNS records, which generated a lot of traffic (not the kind you would expect) to my blog.  In late January, I discovered that I own a bottle of wine from a convicted felon.  Ala February, I joined Twitter, and heard that Network Solutions featured my WHOIS Firefox Plugin on their homepage.  I bought a new battery backup UPS for my home data center, after a little physics exercise to discover the exact type of UPS I needed.  I launched kolich.cc, but then later built and released Onyx.  With summer approaching, I made my own solar shield out of cardboard and tinfoil while thinking up ten awesome .htaccess hacks for Movable Type.  Continuing the awesomeness, I launched a mobile version of my blog at kolich.mobi for all of my readers on mobile devices.  Like any good year, a few of my systems crashed, then recovered but I had fun with HP LaserJet printers at the office.  I registered kolich.tel, went green for Iran, and figured out how to include base-64 encoded binary data in CSS.  And, of course, I released Gagawa PHP 1.2 before hiking Mount San Gorgonio in the San Bernardino National Forest, but not before I wasted several days at the office on a stupid bug.  I registered koli.ch (thank you Network Solutions!), and gave hot linkers a nice big 5000x5000px animated GIF to chew on.  And to cap it all off, I blew the whistle on Twitter (they're spying on us) and then dove into some C++ to discover how Windows UAC works, which by the way, reminded me how much I hate Windows.

2009, the end.
My somewhat narcissistic obsession with domain names involving my last name has recently driven me to purchase markkolich.com.  The saga leading up to this acquisition started when I snagged koli.ch, and saw my ranking in a few search engine results absolutely plummet.  I kicked off my own investigation and realized that Google doesn't seem to understand a custom domain hack of my last name.  For the record, Yahoo! does.  I suppose that's one thing Yahoo! actually does better than Google: properly interpreting domain hacks and other URL trickery.

In any event, I setup the markkolich.com VirtualHost to redirect to mark.koli.ch via a 302 Found.  It seems that when Google and Yahoo encounter an HTTP 302 Found, they gracefully redirect their spiders to the destination but maintain the redirector's address.  For example, this URL https://onyx.koli.ch/x2fr redirects to http://plugins.jquery.com/project/Timer using a 302 Found.  When spiders encounter https://onyx.koli.ch/x2fr they are forwarded to the destination, but add http://plugins.jquery.com/project/Timer under https://onyx.koli.ch/x2fr to their index.  In other words, the jQuery Timer plugin page will be listed under the URL https://onyx.koli.ch/x2fr in the search results!  Interestingly enough, HTTP 301 Moved Permanently does not exhibit this behavior.

For the time being, I'm going to see how the new domain stacks up against koli.ch.  My expectation is that spiders will index markkolich.com, see a 302 Found, and add it to their index as is without worrying about the destination address.

Stay tuned.
Most web-apps include a number of JavaScript and CSS files, that in most cases, need to be included/sourced on every page of the application.  Doing so can bring up a few, while trivial, often annoying problems:

  • Dependencies between scripts.  For example, if you attempt to use a jQuery plugin before the base jQuery library has loaded into the browser you'll obviously see an error.  Working out these dependencies before hand can save you a few headaches.

  • Web-browsers and web-proxies cache your JavaScript and CSS files too often.  I can't count the number of times on two hands when I made a small change to a JavaScript file, saved the change, refreshed my browser, and .... nothing.  The web-browser didn't load the changed file; instead, it loaded the JavaScript from cache.  Using a mechanism to always force the web-browser or web-proxy to reload your JavaScript and CSS can save you time.
Meet Gagawa, an open source object-oriented HTML generation engine written in Java and PHP.  You probably wouldn't build an entire site with Gagawa, but it's absolutely perfect for small HTML tasks, like solving this irritating dependency and caching problem.
javax-swing-timer-demo-screencap.jpgIn the last week or so, while working on some Java Swing code for a project at work, I hit Swing bug #4480705.  When the user clicked a button to start an "activation", I changed the ImageIcon on a JButton to an animated GIF to indicate activity (e.g., "we're doing something, please wait").  So, while the application was busy, I disabled the JButton and set its ImageIcon to an animated spinner.  Loading this animated GIF and setting it on the JButton using setIcon() caused the Java Swing EventQueue threads to deadlock, as described here, and my entire application hung.  Well technically speaking, not the entire application, but just the Swing portion of the JVM.  Clearly, Swing doesn't like animated GIF's as much as the Sun documentation claims.

The solution to this deadlock is to avoid using animated GIF's all together, and write your own animate loop using javax.swing.Timer.  That's exactly what I did, and it works great.

For your viewing pleasure, I wrote up a quick demo/example (see Beavis and Butthead screencap) which demonstrates the use of javax.swing.Timer and how you can integrate it into your Swing application.

Download just the source, or the full Eclipse project.

Rock on.
uac-prompt-sucks.jpgI just finished an absolutely monstrous project at work that involved quite a bit of Java and a little Visual C++.  The latter part of this project involved writing some VC++ that interactively upgraded a piece of Java based software installed on a PC.  This sounds relatively mundane, but frankly, it wasn't.  I ended up spending almost of week of engineering effort, writing code that gracefully understands how to deal with Window's User Account Control (UAC).  If you're not familiar with UAC, it's that incredibly annoying security mechanism in Vista, and Win7, that prompts the user for confirmation if a piece of software attempts to make any changes to a protected location on the computer.  I appreciate what Microsoft was trying to accomplish with UAC, but it couldn't be more painful for a developer to work with.  Not to mention I couldn't find any decent documentation from Microsoft that discussed how to properly integrate your software with UAC.  I found a lot of marketing type documents and other nonsense through MSDN, and eventually gave up in disgust.  All I wanted was a simple document, ideally one titled "this is how to open a UAC prompt in your application."

In the end, I figured out how to deal with UAC by studying the source code of the Mozilla Firefox Updater (knowing that Firefox is open-source, so I can look at its code, and it always seems to update itself just fine on my development Win 7 and Vista boxes).  This post is an attempt to document how I built an application that understands, and gracefully handles UAC.
delicious-vs-kolich-domain-hack-google.pngYou're reading this blog, so you may have noticed that I'm operating under mark.koli.ch; a domain hack of my name using the .ch Swiss ccTLD.  The previously retired kolich.com sits idle, serving up HTTP 410 Gone's when appropriate.  Interestingly enough, however, since making the switch to koli.ch I've noticed a significant drop-off of in traffic to my blog.  I suspect that the switch to a non-traditional ccTLD, like .ch, is to blame.  Since the switch to a dot-ch domain incoming traffic to my blog, directly from Google, has fallen off significantly.  It seems that Google's ranking algorithms consider dot-com domains "more valuable" or relevant, than sites hosted under various ccTLD's.  Equally annoying is that Google, and even Yahoo, fail to properly understand my koli.ch domain hack at all.  In other words, when someone issues a search for "kolich blog", Google and Yahoo fail to properly interpret "koli.ch" as "kolich".  Therefore, search results with "kolich" as a whole-word in the URL appear higher in the search results than others with "koli.ch".  Google must understand some domain-hacks though, given that they seem to recgonize "del.icio.us" as "delicious" in their search results.  I'm still wondering how to tell Google that "koli.ch" should be interpreted as "kolich", a whole word.

It's funny though because I've often criticized and poked fun at folks touting various SEO (search engine optimization) techniques.  My opinion has been that as long as you build a great site, with decent information on it, "they" (visitors) will come.  I still live by that mantra but it's clear to me now that Google, and other search engines, really do pay careful attention to your domain.  Even so, I have no plans to switch back to kolich.com, but if you are considering a switch to a domain hack like mark.koli.ch you should expect or at least be aware of the changes this move might bring to your page rank in various search results.
curl-reject-trace-method.pngIt's long been rumored that exposing the HTTP TRACE and TRACK methods on your web-server can open the door to a number of miscellaneous vulnerabilities, including cookie thefts and other cross-site tracing attacks.  Many resources out there claim you should configure you web-server to flat-out reject TRACE and TRACK requests, and I agree with them.  Generally speaking, there's really no good need (that I've found) that would require or make use of TRACE or TRACK.  With that said, if you're running Apache, it's fairly easy to reject TRACE and TRACK using mod_rewrite:

RewriteCond %{REQUEST_METHOD} ^TRACE [NC,OR]
RewriteCond %{REQUEST_METHOD} ^TRACK [NC]
RewriteRule ^/(.*)$ - [F,L]

You can prove to yourself that this works, by using a tool like curl to issue an HTTP TRACE and TRACK to your newly secured web-server.  Use the -X option with curl to specify the HTTP request type:

#/> curl -v -A "Curl" -X TRACE mark.koli.ch
* About to connect() to mark.koli.ch port 80 (#0)
* Trying 24.130.215.240... connected
* Connected to mark.koli.ch (24.130.215.240) port 80 (#0)
> TRACE / HTTP/1.1
> User-Agent: Curl
> Host: mark.koli.ch
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Date: Sat, 14 Nov 2009 18:53:06 GMT
< Server: Apache
< Content-Length: 202
< Connection: close
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /
on this server.</p>
</body></html>
* Closing connection #0

Yep, works nicely.  One thing that slightly annoys me though is that the HTTP OPTIONS method still reports that my server supports TRACE, even though I clearly don't anymore.  A quick Google search reports that many other folks have had the same concern, with no clear resolution.
This afternoon, I was using the HttpFox Firefox extension to analyze some web-traffic for a work related project.  With HttpFox still running in the background (I forgot I left it running), I opened another tab and navigated over to my Twitter page to check out a few things.  I clicked a few links, replied to a few folks, etc.  Switching back to my work project, I closed Twitter and re-opened HttpFox.  Well well well, what do we have here.  I discovered that Twitter silently rolled out some JavaScript that actively tracks every link I click on.  Any link, in any Tweet, that you click on is silently reported back to Twitter behind the scenes.  Looking at the output of HttpFox pretty much proves it:

twitter-abacus-tracking-clicked-links.png

Looks like twitter.com/abacus is some type of web-service used by Twitter to log what links we're all clicking on.  I'm curious why Twitter cares what links we're clicking on.

BTW, Twitter, if you're reading this, the HTTP Content-Type in your responses from /abacus are incorrect.  You're phoning home by creating a new Image() in your core JavaScript like so:

(new Image()).src="/abacus?"+$.param(A);

But your Content-Type from this request is text/html, which could cause problems in a few browsers.  If you're going to use an Image(), the returned Content-Type from your /abacus web-service should be that of an image: image/jpeg, image/png, image/gif, etc.

twitter-abacus-tracking-clicked-links-wrong-content-type.png

Cheers.