Last updated: 21 December 2000
By 12 April, we had lots of interesting guesses, but not a single one that came anywhere near the correct solution. (It was quite amusing to see the suggestions that were made. One person suggested that the picture on the cover contains a hidden image of an Easter egg; another person suggested that the Easter eggs were two of the ovals in Figure 11.1 on page 431. Naturally, we wouldn't do anything either so devious or so obvious :-)
After we didn't get any correct entries for nearly two weeks, we decided to drop a hint and let people know that one egg could be found in Chapter 3 and the other one in Chapter 7. That got the ball rolling.
Darrell Brunsch, Chris Cleeland, Kevin Curley, Donnacha Forde, Krishna Kunchithapadam, Sacha Laborey, Bill Lloyd, David McCann, Loren Rittle, Mark Sheppard, and Nanbor Wang.
Congratulations to all of you!
A few people had problems caused by byte swapping on little-endian machines and sent scrambled eggs instead of Easter eggs ;-), or they introduced typos when they entered an IOR and only sent one correct image. However, we gave everyone who made at least a serious effort the benefit of the doubt. We figured that anyone who was determined enough to type in the two IORs from the printed text in the book deserved a spot in the draw :-) We also apologize for the collective loss of productivity we apparently caused around various companies :-)
Well, when you think about it, there aren't all that many places in a book where one could hide something. We thought that telling people that there are two eggs would clue them off as to where they are: there are two stringified IORs shown in the book (apart from two nil IORs, which obviously have no interesting content). Stringified IORs are a pile of hexadecimal gibberish, which makes them ideal places in which to hide something. (Unfortunately, no-one thought that this was as obvious as we did. Only after we provided the hint did the penny drop and solutions started to come in.)
So, the eggs are contained in the IORs shown on page 44 and page 249. The IORs are:
IOR:000000000000000d49444c3a54696d653a312e300000000000000001000000 00000000f000010100000000066d6572676500060b000000d7030231310c000016 7e0000175d360aed118143582d466163653a20457348795e426e5851664e527333 3d4d7268787b72643b4b4c4e59295a526a4c3a39564628296e4345633637533d6a 2c77245879727c7b6371752b7434567d61383b3422535e514a2b48322e772f354f 245e573e69512b6b24717a412f7822265c2172772d577d303927537d5e715c5757 70784a2734385832694f3e7433483753276f4825305a2858382e4a30667577487b 3647343e3e7e5b554b21643d67613c6d367a4e784d414f7a7658606d214a45677e 272f737756642420000000000000
IOR:000000000000000d49444c3a54696d653a312e300000000000000001000000 00000000d800010100000000066d6572676500060b000000bd030231310c000016 7e0000175d360aed118129582d466163653a20267a682e2a4e394d4f77724d7152 73352a5d443948434b446a702c347634527250722f7d3f5b2b554c74644726485a 3c4d3259797c62325e642b65447a37442b21684f473c2a39795521302723373f69 633f5e7e7c7d73647b52235c722c7230694f32535d577e644f2d21455035216a64 562d2b33437362317029554d4e57627c3f303a364f67776b613c6d354b2227443c 577a215a5d234b484a517175465a200000000000000000
Chapters 2, 13, and 14 explain quite a bit about the internal structure of IORs. In particular, each IOR contains an object key that is provided by the application. Naturally, the object keys of the above two IORs are where we hid the Easter eggs.
To find the eggs, you had to type the IORs into a file (which was the hardest part of the contest :-) and decode them. The correct way to do this is detailed in the CDR encoding rules for IORs in the CORBA specification. However, most ORBs ship with a tool that decodes an IOR and shows the information contained in it, so that's a much easier way to extract the IOR contents. (There are several freeware and open source versions of such tools available.) Most of these tools display the value of the object key as a string. The object keys are:
..11....~...]6....CX-Face: EsHy^BnXQfNRs3=Mrhx{rd;KLNY)ZRjL:9VF()n CEc67S=j,w$Xyr|{cqu+t4V}a8;4"S^QJ+H2.w/5O$^W>iQ+k$qzA/x"&\!rw-W}09 'S}^q\WWpxJ'48X2iO>t3H7S'oH%0Z(X8.J0fuwH{6G4>>~[UK!d=ga<m6zNxMAOzv X`m!JEg~'/swVd$ .
..11....~...]6....)X-Face: &zh.*N9MOwrMqRs5*]D9HCKDjp,4v4RrPr/}?[+ ULtdG&HZ<M2Yy|b2^d+eDz7D+!hOG<*9yU!0'#7?ic?^~|}sd{R#\r,r0iO2S]W~dO -!EP5!jdV-+3Csb1p)UMNWb|?0:6Ogwka<m5K"'D<Wz!Z]#KHJQquFZ .
Looking through these strings, we find that both of them contain
the substring "X-Face:
". This provides
a clue that we are on the right track. An X-Face (for those of you who
have been on the net less than ten years or so) is a mail header that
contains a 48x48 black and white compressed bitmap. (People used to add
an X-Face: header to their e-mail; various mail readers can be configured
to automatically display the bitmap when the e-mail is read.)
Now the problem is nearly solved. The remaining piece of the puzzle is how
to decode the X-Faces. A bit of searching on the Web leads to a tool called
uncompface
, which turns X-Face strings into X-11 bitmaps.
The strings you need to feed to uncompface
are:
X-Face: EsHy^BnXQfNRs3=Mrhx{rd;KLNY)ZRjL:9VF()nCEc67S=j,w$Xyr|{cq u+t4V}a8;4"S^QJ+H2.w/5O$^W>iQ+k$qzA/x"&\!rw-W}09'S}^q\WWpxJ'48X2i O>t3H7S'oH%0Z(X8.J0fuwH{6G4>>~[UK!d=ga<m6zNxMAOzvX`m!JEg~'/swVd$
X-Face: &zh.*N9MOwrMqRs5*]D9HCKDjp,4v4RrPr/}?[+ULtdG&HZ< M2Yy|b2^d+eDz7D+!hOG<*9yU!0'#7?ic?^~|}sd{R#\r,r0iO2S]W~d O-!EP5!jdV-+3Csb1p)UMNWb|?0:6Ogwka<m5K"'D<Wz!Z]#KHJQquFZ
uncompface
is a single string.
From these strings, uncompface
produces
the following X-11 bitmaps:
#define img_width 48 #define img_height 48 static unsigned char img_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x04, 0x00, 0x00, 0x00, 0x80, 0xff, 0x1b, 0x00, 0x00, 0x00, 0x00, 0xad, 0x7f, 0x01, 0x00, 0x00, 0xc0, 0xf7, 0xae, 0x06, 0x00, 0x00, 0x60, 0xff, 0xfb, 0x03, 0x00, 0x00, 0xd0, 0x5d, 0xff, 0x0e, 0x00, 0x00, 0x68, 0xeb, 0xae, 0x1b, 0x00, 0x00, 0x30, 0x02, 0xfa, 0x0f, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x0c, 0x00, 0x80, 0x3a, 0x00, 0x00, 0x04, 0x00, 0x20, 0x3e, 0x00, 0x00, 0x06, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x03, 0x00, 0x80, 0x3d, 0x00, 0x00, 0x03, 0x00, 0x10, 0x3a, 0x00, 0x00, 0x01, 0x00, 0x40, 0x37, 0x00, 0x00, 0x03, 0x00, 0x20, 0x3c, 0x00, 0x00, 0x01, 0x00, 0x9e, 0x1b, 0x00, 0x00, 0xc3, 0x80, 0x7f, 0x76, 0x00, 0x00, 0xf2, 0x83, 0xc0, 0x6c, 0x00, 0x00, 0x08, 0x40, 0x75, 0x7b, 0x00, 0x00, 0xe2, 0x87, 0xbd, 0x34, 0x00, 0x00, 0xa0, 0x40, 0x48, 0x7a, 0x00, 0x00, 0x02, 0x01, 0x22, 0x56, 0x00, 0x00, 0x40, 0x00, 0x80, 0x7a, 0x00, 0x00, 0x02, 0x40, 0x00, 0x2e, 0x00, 0x00, 0x02, 0x00, 0x80, 0x5a, 0x00, 0x00, 0x00, 0xe4, 0x81, 0x36, 0x00, 0x00, 0x00, 0xfe, 0x8d, 0x3a, 0x00, 0x00, 0x80, 0xfa, 0x57, 0x2b, 0x00, 0x00, 0x80, 0xdf, 0x9e, 0x1c, 0x00, 0x00, 0x62, 0xf5, 0xb5, 0x3a, 0x00, 0x00, 0xd0, 0x05, 0xfd, 0x14, 0x00, 0x00, 0x48, 0x82, 0x52, 0x1b, 0x00, 0x00, 0xd4, 0xfe, 0xfc, 0x1d, 0x00, 0x00, 0x48, 0xb5, 0xfb, 0x17, 0x00, 0x00, 0xf0, 0xdd, 0xfd, 0x0f, 0x00, 0x00, 0x50, 0x77, 0xef, 0x3b, 0x00, 0x00, 0xe0, 0xc9, 0xfa, 0x36, 0x00, 0x00, 0xe0, 0x77, 0xff, 0xef, 0x00, 0x00, 0x00, 0xbd, 0x7f, 0xbb, 0x01, 0x00, 0x80, 0xef, 0xfe, 0xed, 0x00, 0x00, 0x00, 0xff, 0x5f, 0x9b, 0x01, 0x00, 0x80, 0xfa, 0xf7, 0x36, 0x00, 0x00, 0x80, 0xbe, 0x7f, 0x5b, 0x00, 0x00, 0x00, 0xe5, 0xae, 0x05, 0x00, 0x00, 0x40, 0xba, 0x5b, 0x28, 0x00};
#define img_width 48 #define img_height 48 static char img_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x80, 0xff, 0xff, 0x07, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7e, 0x00, 0x00, 0xfe, 0xff, 0x7f, 0x7c, 0x00, 0x00, 0xfe, 0x03, 0x04, 0xf8, 0x00, 0x00, 0xfe, 0x01, 0x00, 0xf8, 0x00, 0x00, 0xff, 0x01, 0x00, 0xf8, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf8, 0x00, 0x80, 0x3f, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf8, 0x00, 0x80, 0x3f, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x7f, 0x0b, 0xf8, 0xf0, 0x01, 0x80, 0x9f, 0x1f, 0xfc, 0xf0, 0x00, 0x00, 0xdf, 0x3e, 0xfe, 0xf3, 0x00, 0x00, 0xff, 0x73, 0xfe, 0xf4, 0x00, 0x00, 0xdf, 0x29, 0x40, 0x30, 0x00, 0x00, 0x0e, 0x38, 0x00, 0x90, 0x00, 0x00, 0x1c, 0x20, 0x00, 0x50, 0x00, 0x00, 0x0c, 0x20, 0x00, 0x10, 0x00, 0x00, 0x18, 0x20, 0x00, 0x18, 0x00, 0x00, 0x08, 0x30, 0x00, 0x08, 0x00, 0x00, 0x78, 0x18, 0x38, 0x0e, 0x00, 0x00, 0xf8, 0xb6, 0xb7, 0x17, 0x00, 0x00, 0xb8, 0xed, 0xa1, 0x17, 0x00, 0x00, 0xac, 0x0c, 0xb4, 0x05, 0x00, 0x00, 0x90, 0x14, 0x38, 0x05, 0x00, 0x00, 0x18, 0x3c, 0x3e, 0x06, 0x00, 0x00, 0x30, 0x7c, 0x9e, 0x06, 0x00, 0x00, 0xa8, 0x39, 0xc0, 0x06, 0x00, 0x00, 0xd0, 0x90, 0xac, 0x06, 0x00, 0x00, 0xc0, 0xa0, 0xcf, 0x03, 0x00, 0x00, 0x40, 0x23, 0x40, 0x07, 0x00, 0x00, 0x80, 0x2d, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x05, 0xd0, 0x01, 0x00, 0x00, 0x80, 0x0f, 0xf0, 0x01, 0x00, 0x00, 0x80, 0x3b, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xdf, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2f, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00};
xv
.
Going through all of this correctly, the decoded X-Faces yield the following two images:
Of course, these are the Easter eggs.
The X-Face on the left is Michi's, and the one on the right is Steve's. We used an image editing program to cut the images out of the pictures on our respective home pages and to reduce them to 48x48 black and white bitmaps. The source images appear below.
That's it! Thanks to everyone who participated, and we hope you all had fun hunting for the eggs!
Michi and Steve