<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Linden LAN &#187; Hacking</title>
	<atom:link href="http://www.lindenlan.net/tag/hacking/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lindenlan.net</link>
	<description></description>
	<lastBuildDate>Sat, 29 Nov 2014 04:54:20 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	
	<item>
		<title>Spoof The iPad User-Agent And See The “AdLib” Framework In Action</title>
		<link>http://www.lindenlan.net/2010/04/08/spoof-the-ipad-user-agent-and-see-the-adlib-framework-in-action/</link>
		<comments>http://www.lindenlan.net/2010/04/08/spoof-the-ipad-user-agent-and-see-the-adlib-framework-in-action/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 07:19:45 +0000</pubDate>
		<dc:creator><![CDATA[Brian]]></dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Hacking]]></category>

		<guid isPermaLink="false">http://www.lindenlan.net/?p=382</guid>
		<description><![CDATA[As reported on Almost Done, Apple apparently has its own iPad-specific web framework, which Jim Hoskins has dubbed AdLib. If you don’t own an iPad, you can still have a look at it by spoofing the user-agent courtesy of LifeHacker. Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>As reported on Almost Done, Apple apparently has its own iPad-specific web framework, which Jim Hoskins has dubbed <a href="http://almost.done21.com/2010/04/adlib-apples-secret-ipad-web-framework/">AdLib</a>.  If you don’t own an iPad, you can still have a look at it by spoofing the user-agent courtesy of <a href="http://lifehacker.com/5508260/how-to-use-gmails-attractive-new-tablet+friendly-interface-on-your-regular-old-computer">LifeHacker</a>.</p>
<pre class="brush: bash">
Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10
</pre>
<p>I tried Firefox and Chrome using their respective user-agent switcher plugins, but didn’t get very far.  So go into Safari and select Develop-&gt;User Agent-&gt;Other…  Paste in the above string, click OK, and make sure it’s active.  Next navigate to <a href="http://help.apple.com/ipad/mobile/interface/">iPad User Guide</a> and check it out.  Here’s hoping Apple will be releasing it independently or as a part of the SDK.  Here’s also hoping it’s iPhone-compatible.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lindenlan.net/2010/04/08/spoof-the-ipad-user-agent-and-see-the-adlib-framework-in-action/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To Watch Your Cat From Across The Country</title>
		<link>http://www.lindenlan.net/2009/12/28/how-to-watch-your-cat-from-across-the-country/</link>
		<comments>http://www.lindenlan.net/2009/12/28/how-to-watch-your-cat-from-across-the-country/#comments</comments>
		<pubDate>Tue, 29 Dec 2009 03:27:13 +0000</pubDate>
		<dc:creator><![CDATA[Brian]]></dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.lindenlan.net/?p=364</guid>
		<description><![CDATA[I went to Florida for my Christmas holiday. In order to not stress out the cat too much, the cat stayed home rather than go to a kennel. No professional pet sitter was available where I live. So I opted to create a home surveillance system from hardware I had lying around and free software. [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I went to Florida for my Christmas holiday.  In order to not stress out the cat too much, the cat stayed home rather than go to a kennel.  No professional pet sitter was available where I live.  So I opted to create a home surveillance system from hardware I had lying around and free software.</p>
<p><span id="more-364"></span></p>
<p>Obtained a dynamic DNS hostname from DynDNS.  Even though my IP address doesn’t change all that often, it is dynamic.  Therefore, there’s no guarantee that the IP would work.  This was an extra precaution I wanted to take.  Plus it gave me something easier to remember.</p>
<p>Installed LogMeIn.  I did not require any of the features you get in the pay version.  This allowed me to start/stop software as needed and manage the pictures captured by the webcam.  Other remote admin services would work as well.  VNC is a great alternative.</p>
<p>Flashed my router with the Tomato firmware.  The WRT54G stock firmware doesn’t let you forward the magic packet to use wake-on-LAN to turn on a computer.  Tomato lets you log into the admin interface and send the packet to any MAC address on the LAN side of the network.  I did this just in case the power went out and I needed to turn-on the computer again.</p>
<p>I tried out two different webcam servers for Windows, Broadcam and TinCam.  Broadcam is much easier to setup and will automatically setup port forwarding if your router supports UPnP, but it is limited to live video.  TinCam has a lot more features, but it isn’t as user-friendly and you have to manually open up a port on the router.  Both have trial periods, but are fully functional during the trial period.  I tried setting up a Linux webcam server, but a lack of GUI or an easy to use config file meant it was faster to use Windows.  I did not test any Mac webcam servers since my MacBook was coming with me.  I ultimately settled on using TinCam day-to-day because I could schedule it to record a pic every 5 minutes of every hour (e.g., 1:00, 1:05, 1:10, and so on).  Furthermore, the date and time of day is used for the filename.  TinCam won’t let you capture pictures and run the video server simultaneously.  You can run the image server though which updates every 5 seconds.  So if you need an image log and live video, neither will work for you.</p>
<p>With the image server, I was able to watch what was on the webcam currently.  In order to see the log, I installed Dropbox.  Then I configured TinCam to save the captured images in a Dropbox folder.  Now I can see a picture log not just on my laptop but also on my iPhone using the Dropbox app.  This was VERY convenient.  Furthermore, the app overlays the filename so I can see when the pic was taken.</p>
<p>Finally, I installed Skype on the computer with the webcam so I could occasionally talk to the cat.  I created an account specifically for this.  I configured Skype to auto-answer and maximize when video is initiated.  Though I think as comforting as a familiar sound is to a pet, the cat appeared both excited and confused hearing a disembodied voice. </p>
<p>That’s how I mashed up available hardware and software to keep an eye on my cat while I was gone.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lindenlan.net/2009/12/28/how-to-watch-your-cat-from-across-the-country/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MyGoogleCal is now RESTYLEgc</title>
		<link>http://www.lindenlan.net/2009/07/06/mygooglecal-is-now-restylegc/</link>
		<comments>http://www.lindenlan.net/2009/07/06/mygooglecal-is-now-restylegc/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 16:24:40 +0000</pubDate>
		<dc:creator><![CDATA[Admin]]></dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[RESTYLEgc]]></category>

		<guid isPermaLink="false">http://www.lindenlan.net/?p=323</guid>
		<description><![CDATA[I finally got around to spinning off MyGoogleCal as a separate website. I opted to rename the script to RESTYLEgc to avoid stepping on Google’s toes. It was something that’s been gestating over the past year. I completed the site over the holiday weekend since I had the time available. The new site is at [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I finally got around to spinning off MyGoogleCal as a separate website.  I opted to rename the script to RESTYLEgc to avoid stepping on Google’s toes.  It was something that’s been gestating over the past year.  I completed the site over the holiday weekend since I had the time available.  The new site is at <a href="http://www.restylegc.com/">www.restylegc.com</a>.  I’m also hosting the script at <a href="http://code.google.com/p/restylegc">Google Code</a>, and I even added a <a href="http://groups.google.com/group/RESTYLEgc">Google Group</a> to facilitate discussions.  After seeing the comments top 100, I realize a blog really isn’t suitable for lengthy discussions.  Hopefully, the forum and wiki features will be better for the end-user.</p>
<p>I updated MyGoogleCal4 with a small bugfix this weekend as well.  That will be the last update.  Future development will continue with RESTYLEgc.  Since the code was originally public domain, I opted to go with an MIT open source license.  I also got the code in a Subversion repository which I should’ve done a long time ago.  With the Issues tab at Google Code, I can better track and encourage bug reports and feature requests.</p>
<p>The code is still free, but paid support is available.  I’ve also got some other ideas of where I want to take the site.  So stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lindenlan.net/2009/07/06/mygooglecal-is-now-restylegc/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Restyle Google Calendar 4</title>
		<link>http://www.lindenlan.net/2008/12/04/restyle-google-calendar-4/</link>
		<comments>http://www.lindenlan.net/2008/12/04/restyle-google-calendar-4/#comments</comments>
		<pubDate>Thu, 04 Dec 2008 07:00:55 +0000</pubDate>
		<dc:creator><![CDATA[Brian]]></dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.lindenlan.net/?p=252</guid>
		<description><![CDATA[As a few users of MyGoogleCal3 have already pointed out, the script no longer works properly. That’s the bad news. The good news is version 4 does work. In fact, with the latest changes Google made to their code, ALL the features that were broken in 3 appear to be working now—Agenda/Week view, the calendar [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>As a few users of <a href="http://www.lindenlan.net/2008/04/23/restyle-google-calendar-3/">MyGoogleCal3</a> have already pointed out, the script no longer works properly.  That’s the bad news.  The good news is version 4 does work.  In fact, with the latest changes Google made to their code, ALL the features that were broken in 3 appear to be working now—Agenda/Week view, the calendar navigation buttons, and IE is fixed.   Please download and test out the latest version, and report any bugs in the comments and I’ll try to resolve them as time allows.</p>
<p><span id="more-252"></span><br />
<strong>UPDATE (2009 July 5):</strong> <a href="http://www.lindenlan.net/2009/07/06/mygooglecal-is-now-restylegc/">MyGoogleCal is now RESTYLEgc</a>.</p>
<p><strong>UPDATE (2009 June 23):</strong> Google’s recent update broke the jQuery injection.  In fact, the update is incompatible with injecting jQuery, Prototype, and MooTools.  The only JavaScript framework that works is Dojo.  I updated the code to inject that framework instead.  For those people who value stability over having the latest and greatest features, I also added a comment to MyGoogleCal4js.php that explains how to freeze the calendar version.  That should hopefully help all you fellow developers who tire of your clients calling you when their calendar breaks.</p>
<p><strong>UPDATE (2009 May 3):</strong> <span style="text-decoration: line-through;">MyGoogleCal4 now supports jQuery manipulation of the DOM.</span>  This gives the ability to apply styles after page load.  As an example, the default code removes the inline style on the body tag allowing the stylesheet to set the background color.  The default code also removes the width property from the inline style of the bubble class so that its width can be set in the stylesheet as well.  This should help overcome many of the problems that can’t be solved directly using a stylesheet.  You can thank <a href="http://techtriad.com/">TechTriad.com</a> for funding this new feature.</p>
<p>Download: <a href='http://www.lindenlan.net/wp-content/uploads/2008/12/mygooglecal4.zip'>mygooglecal4.zip</a>.  Contains MyGoogleCal4.php, MyGoogleCal4js.php, mygooglecal4.css, and images.  The CSS file is not guaranteed to be up-to-date so you may have to follow the instructions described in the PHP file to download the latest version from Google.  phpinfo.php is used for diagnostic purposes to make sure your PHP installation is working and that it has the required plugins.  In the archive folder, you can find previous versions of Google’s Javascript and CSS files, in case you want to use those (see MyGoogleCal4js.php).</p>
<pre class="brush: php">
&lt;?php
/*******************************************************************************
 * FILE: MyGoogleCal4.php
 *
 * DESCRIPTION:
 *  This script is an intermediary between an iframe and Google Calendar that
 *  allows you to override the default style.
 *
 * USAGE:
 *  &lt;iframe src=&quot;MyGoogleCal4.php?src=user%40domain.tld&quot;&gt;&lt;/iframe&gt;
 *
 *  where user@domain.tld is a valid Google Calendar account.
 *
 * VALID QUERY STRING PARAMETERS:
 *    title:         any valid url encoded string 
 *                   if not present, takes title from first src
 *    showTitle:     0 or 1 (default)
 *    showNav:       0 or 1 (default)
 *    showDate:      0 or 1 (default)
 *    showTabs:      0 or 1 (default)
 *    showCalendars: 0 or 1 (default)
 *    mode:          WEEK, MONTH (default), AGENDA
 *    height:        a positive integer (should be same height as iframe)
 *    wkst:          1 (Sun; default), 2 (Mon), or 7 (Sat)
 *    hl:            en, zh_TW, zh_CN, da, nl, en_GB, fi, fr, de, it, ja, ko, 
 *                   no, pl, pt_BR, ru, es, sv, tr
 *                   if not present, takes language from first src
 *    bgcolor:       url encoded hex color value, #FFFFFF (default)
 *    src:           url encoded Google Calendar account (required)
 *    color:         url encoded hex color value     
 *                   must immediately follow src
 *    
 *    The query string can contain multiple src/color pairs.  It&#039;s recommended 
 *    to have these pairs of query string parameters at the end of the query 
 *    string.
 *
 * HISTORY:
 *   03 December 2008 - Original release
 *                      Uses technique from MyGoogleCal2 for all browsers,
 *                      rather than giving IE special treatment.
 *   16 December 2008 - Modified MyGoogleCal4js.php so that the regex does a
 *                      general match rather than specifically look for the
 *                      variable &#039;Ac&#039;.
 *   Mar--Apr    2009 - Added jQuery for modifying the style after page load
 *   23 June     2009 - Replaced jQuery with Dojo since jQuery, Prototype, and
 *                      MooTools are not compatible
 *   05 July     2009 - Fixed bug to remove width style from bubble
 *                      
 *   
 * ACKNOWLEDGMENTS:
 *   Michael McCall (http://www.castlemccall.com/) for pointing out &quot;htmlembed&quot;
 *   Mike (http://mikahn.com/) for the link to the online CSS formatter
 *   TechTriad.com (http://techtriad.com/) for requesting and funding the 
 *       Javascript code to edit CSS properties and for selflessly letting the
 *       code be published for everyone&#039;s use and benefit.
 *   
 *
 * copyright (c) by Brian Gibson
 * email: bwg1974 yahoo com
 ******************************************************************************/

/* URL for overriding stylesheet
 * The best way to create this stylesheet is to 
 * 1) Load &quot;http://www.google.com/calendar/embed?src=user%40domain.tld&quot; in a
 *    browser,
 * 2) View the source (e.g., View-&gt;Page Source in Firefox),
 * 3) Copy the relative URL of the stylesheet (i.e., the href value of the 
 *    &lt;link&gt; tag), 
 * 4) Load the stylesheet in the browser by pasting the stylesheet URL into 
 *    the address bar so that it reads similar to:
 *    &quot;http://www.google.com/calendar/d003e2eff7c42eebf779ecbd527f1fe0embedcompiled.css&quot;
 * 5) Save the stylesheet (e.g., File-&gt;Save Page As in Firefox)
 * Edit this new file to change the style of the calendar.
 *
 * As an alternative method, take the URL you copied in Step 3, and paste it
 * in the URL field at http://mabblog.com/cssoptimizer/uncompress.html.
 * That site will automatically format the CSS so that it&#039;s easier to edit.
 */
$stylesheet = &#039;mygooglecal4.css&#039;;

/*******************************************************************************
 * DO NOT EDIT BELOW UNLESS YOU KNOW WHAT YOU&#039;RE DOING
 ******************************************************************************/

// URL for the calendar
$url = &quot;&quot;;
if(count($_GET) &gt; 0) {
  $url = &quot;http://www.google.com/calendar/embed?&quot; . $_SERVER[&#039;QUERY_STRING&#039;];
}

// Request the calendar
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$buffer = curl_exec($ch);
curl_close($ch);

// Point stylesheet and javascript to custom versions
$pattern = &#039;/(&lt;link.*&gt;)/&#039;;
$replacement = &#039;&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;&#039; . $stylesheet . &#039;&quot; /&gt;&#039;;
$buffer = preg_replace($pattern, $replacement, $buffer);

$pattern = &#039;/src=&quot;(.*js)&quot;/&#039;;
$replacement = &#039;src=&quot;MyGoogleCal4js.php?$1&quot;&#039;;  
$buffer = preg_replace($pattern, $replacement, $buffer);

// Add a hook to the window onload function
$pattern = &#039;/}\);}&lt;\/script&gt;/&#039;;
$replacement = &#039;}); myGoogleCal();}&lt;/script&gt;&#039;;
$buffer = preg_replace($pattern, $replacement, $buffer);

// Use DHTML to modify the DOM after the calendar loads
$pattern = &#039;/(&lt;\/head&gt;)/&#039;;
$replacement = &lt;&lt;&lt;MGC
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/dojo/1.3.1/dojo/dojo.xd.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
function myGoogleCal() {
    // remove inline style from body so background-color can be set using the stylesheet
    dojo.removeAttr(dojo.body(),&#039;style&#039;);

    // iterate over each bubble and remove the width property from the style attribute
    // so that the width can be set using the stylesheet
    dojo.query(&#039;.bubble&#039;).forEach(function(node){
        dojo.attr(node, {style:{&#039;width&#039;: &#039;&#039;}});
    });

    // see Dojo documentation for other ways to edit DOM
    // http://dojotoolkit.org/
}
&lt;/script&gt;
&lt;/head&gt;
MGC;
$buffer = preg_replace($pattern, $replacement, $buffer);

// display the calendar
print $buffer;
?&gt;

?&gt;
</pre>
<p>If you look at lines 39–41 in MyGoogleCal4js.php, you’ll see how simple the fix is.  No more XmlHttpRequest bugs.  Thank you, Google.</p>
<pre class="brush: php">
&lt;?php header(&quot;Content-type: application/x-javascript&quot;);
/*******************************************************************************
 * FILE: MyGoogleCal4js.php
 *
 * DESCRIPTION:
 *  Companion file for MyGoogleCal4.php to edit the javascript file that
 *  generates the Google Calendar.
 *   
 * USAGE:
 *  There are no user-editable parameters.
 *
 * copyright (c) by Brian Gibson
 * email: bwg1974 yahoo com
 ******************************************************************************/
// URL for the javascript
$url = &quot;&quot;;
if(count($_GET) &gt; 0) {
  $url = &quot;http://www.google.com/calendar/&quot; . $_SERVER[&#039;QUERY_STRING&#039;];
}

/* If you would like to freeze the calendar version, download the Javascript
 * file using the same method for downloading the CSS file, as described in
 * the main script.  You can find some previous versions in the archive folder.
 * NOTE: You should use the corresponding CSS file as well.
 *
 * Edit and uncomment the following line to freeze the calendar version.
 */
//$url = &quot;http://myserver.tld/path/to/archive/6a3eb8ba4a07edb76f79a18d6bdb8933embedcompiled__en.js&quot;;

// Request the javascript
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$buffer = curl_exec($ch);
curl_close($ch);

// Fix URLs in the javascript
$pattern = &#039;/this\.[a-zA-Z]{2}\+&quot;calendar/&#039;;
$replacement = &#039;&quot;http://www.google.com/calendar&#039;;
$buffer = preg_replace($pattern, $replacement, $buffer);

// Display the javascript
print $buffer;
?&gt;
</pre>
<p>The installation of MyGoogleCal4 is the same as the <a href="http://www.lindenlan.net/2008/03/22/how-to-install-mygooglecal2php/">installation for MyGoogleCal2</a> except you download the zip file above.  You can ignore step 3 regarding the .htaccess file.  As far as I can tell, it’s no longer needed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lindenlan.net/2008/12/04/restyle-google-calendar-4/feed/</wfw:commentRss>
		<slash:comments>134</slash:comments>
		</item>
		<item>
		<title>Restyle Google Calendar 3</title>
		<link>http://www.lindenlan.net/2008/04/23/restyle-google-calendar-3/</link>
		<comments>http://www.lindenlan.net/2008/04/23/restyle-google-calendar-3/#comments</comments>
		<pubDate>Thu, 24 Apr 2008 05:46:09 +0000</pubDate>
		<dc:creator><![CDATA[Brian]]></dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.lindenlan.net/2008/04/23/restyle-google-calendar-3/</guid>
		<description><![CDATA[MyGoogleCal2 no longer works 100% in Internet Explorer. A runtime error occurs when navigating month-to-month or when switching to Agenda mode. The workaround is to simply hide the navigation interface. Now, I don’t know if this bug was introduced when Google updated the code last month, or if it’s always been there and I just [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.lindenlan.net/2007/10/14/restyle-google-calendar-2/">MyGoogleCal2</a> no longer works 100% in Internet Explorer.  A runtime error occurs when navigating month-to-month or when switching to Agenda mode.  The workaround is to simply hide the navigation interface.  Now, I don’t know if this bug was introduced when Google updated the code last month, or if it’s always been there and I just never noticed.  In any case, the runtime error occurs when <code>//"+a.host+"/calendar</code> is replaced by <code>//www.google.com/calendar</code>.  Given the poor debugging available in IE, I didn’t get very far with figuring out why IE breaks.  I suspect that when IE makes an XmlHttpRequest, it’s double checking that the request URL matches up with the server host, or something to that effect.  Since Google obfuscates the Javascript code, it’s just way too hard to try and fix it.  Instead, I’ve opted to create a new version of MyGoogleCal that uses the <a href="http://www.lindenlan.net/2006/10/08/restyle-google-calendar/">original technique</a> for IE but uses the technique from MyGoogleCal2 for all other browsers.</p>
<p><span id="more-57"></span></p>
<p><strong>UPDATE:</strong> MyGoogleCal now has a <a href="http://www.lindenlan.net/2008/12/04/restyle-google-calendar-4/">fourth version</a>.</p>
<p>Download: <a href='http://www.lindenlan.net/wp-content/uploads/2008/04/mygooglecal3.zip' title='MyGoogleCal3 Zip file'>mygooglecal3.zip</a>.  Contains MyGoogleCal3.php, MyGoogleCal3js.php, mygooglecal3.css, mygooglecal3ie.css, and an .htaccess file.  The CSS files are not guaranteed to be up-to-date so you may have to follow the instructions described in the PHP file to download the latest version from Google.</p>
<pre class="brush: php">
&lt;?php
/*******************************************************************************
 * FILE: MyGoogleCal3.php
 *
 * DESCRIPTION:
 *  This script is an intermediary between an iframe and Google Calendar that
 *  allows you to override the default style.
 *
 * USAGE:
 *  &lt;iframe src=&quot;MyGoogleCal3.php?src=user%40domain.tld&quot;&gt;&lt;/iframe&gt;
 *
 *  where user@domain.tld is a valid Google Calendar account.
 *
 * VALID QUERY STRING PARAMETERS:
 *    title:         any valid url encoded string 
 *                   if not present, takes title from first src
 *    showTitle:     0 or 1 (default)
 *    showNav:       0 or 1 (default)
 *    showDate:      0 or 1 (default)
 *    showTabs:      0 or 1 (default)
 *    showCalendars: 0 or 1 (default)
 *    mode:          WEEK, MONTH (default), AGENDA
 *    height:        a positive integer (should be same height as iframe)
 *    wkst:          1 (Sun; default), 2 (Mon), or 7 (Sat)
 *    hl:            en, zh_TW, zh_CN, da, nl, en_GB, fi, fr, de, it, ja, ko, 
 *                   no, pl, pt_BR, ru, es, sv, tr
 *                   if not present, takes language from first src
 *    bgcolor:       url encoded hex color value, #FFFFFF (default)
 *    src:           url encoded Google Calendar account (required)
 *    color:         url encoded hex color value     
 *                   must immediately follow src
 *    
 *    The query string can contain multiple src/color pairs.  It&#039;s recommended 
 *    to have these pairs of query string parameters at the end of the query 
 *    string.
 *
 * HISTORY:
 *   21 June     2008 - Reverted to an older custom JavaScript file
 *   18 May      2008 - Corrected a bunch of typos 
 *   24 April    2008 - Original release
 *                      Uses the technique from MyGoogleCal for IE browsers and
 *                      the technique from MyGoogleCal2 for the rest.
 *   
 * ACKNOWLEDGMENTS:
 *   Michael McCall (http://www.castlemccall.com/) for pointing out &quot;htmlembed&quot;
 *   Mike (http://mikahn.com/) for the link to the online CSS formatter
 *
 * copyright (c) by Brian Gibson
 * email: bwg1974 yahoo com
 ******************************************************************************/

/* URL for overriding stylesheet
 * The best way to create this stylesheet is to 
 * 1) Load &quot;http://www.google.com/calendar/embed?src=user%40domain.tld&quot; in a
 *    browser,
 * 2) View the source (e.g., View-&gt;Page Source in Firefox),
 * 3) Copy the relative URL of the stylesheet (i.e., the href value of the 
 *    &lt;link&gt; tag), 
 * 4) Load the stylesheet in the browser by pasting the stylesheet URL into 
 *    the address bar so that it reads similar to:
 *    &quot;http://www.google.com/calendar/embed/d003e2eff7c42eebf779ecbd527f1fe0embedcompiled.css&quot;
 * 5) Save the stylesheet (e.g., File-&gt;Save Page As in Firefox)
 * Edit this new file to change the style of the calendar.
 *
 * As an alternative method, take the URL you copied in Step 3, and paste it
 * in the URL field at http://mabblog.com/cssoptimizer/uncompress.html.
 * That site will automatically format the CSS so that it&#039;s easier to edit.
 */
$stylesheet = &#039;mygooglecal3.css&#039;;

/* For the IE stylesheet replace &quot;embed&quot; with &quot;htmlembed&quot; in step (1) 
 */
$stylesheet_ie = &#039;mygooglecal3ie.css&#039;;

/*******************************************************************************
 * DO NOT EDIT BELOW UNLESS YOU KNOW WHAT YOU&#039;RE DOING
 ******************************************************************************/

// URL for the calendar
$url = &quot;&quot;;
$is_ie = FALSE;
if(count($_GET) &gt; 0) {
  if(stristr($_SERVER[&#039;HTTP_USER_AGENT&#039;], &#039;msie&#039;) === FALSE) {
    $url = &quot;http://www.google.com/calendar/embed?&quot; . $_SERVER[&#039;QUERY_STRING&#039;];
  } else {
    $url = &quot;http://www.google.com/calendar/htmlembed?&quot; . $_SERVER[&#039;QUERY_STRING&#039;];
    $is_ie = TRUE;
  }
}

// Request the calendar
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$buffer = curl_exec($ch);
curl_close($ch);

if($is_ie) {
  // Fix hrefs, image sources, and stylesheet
  $pattern = &#039;/(href=&quot;render)/&#039;;
  $replacement = &#039;href=&quot;http://www.google.com/calendar/render&#039;;
  $buffer = preg_replace($pattern, $replacement, $buffer);

  $pattern = &#039;/(href=&quot;event)/&#039;;
  $replacement = &#039;href=&quot;http://www.google.com/calendar/event&#039;;
  $buffer = preg_replace($pattern, $replacement, $buffer);

  $pattern = &#039;/(http:\/\/www.google.com\/calendar\/htmlembed)/&#039;;
  $replacement = &#039;MyGoogleCal3.php&#039;;
  $buffer = preg_replace($pattern, $replacement, $buffer);

  $pattern = &#039;/(src=&quot;images)/&#039;;
  $replacement = &#039;src=&quot;http://www.google.com/calendar/images&#039;;
  $buffer = preg_replace($pattern, $replacement, $buffer);

  $pattern = &#039;/(&lt;link.*&gt;)/&#039;;
  $replacement = &#039;&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;&#039; . $stylesheet_ie . &#039;&quot; /&gt;&#039;;
  $buffer = preg_replace($pattern, $replacement, $buffer);
} else {
  // Point stylesheet and javascript to custom versions
  $pattern = &#039;/(&lt;link.*&gt;)/&#039;;
  $replacement = &#039;&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;&#039; . $stylesheet . &#039;&quot; /&gt;&#039;;
  $buffer = preg_replace($pattern, $replacement, $buffer);

  $pattern = &#039;/src=&quot;(.*js)&quot;/&#039;;
  $replacement = &#039;src=&quot;MyGoogleCal3js.php?$1&quot;&#039;;
  $buffer = preg_replace($pattern, $replacement, $buffer);
}

// display the calendar
print $buffer;
?&gt;
</pre>
<p>The installation of MyGoogleCal3 is more or less the same as the <a href="http://www.lindenlan.net/2008/03/22/how-to-install-mygooglecal2php/">installation for MyGoogleCal2</a> except you download the zip file above.  Also MyGoogleCal3 uses two stylesheets, one for IE and one for all the other browsers.</p>
<p>There is a minor bug.  Despite changing the URL from <code>../images/ext/poweredby.png</code> to <code>images/poweredby.png</code> in the IE CSS file, this does not make the Powered by Google logo appear in the lower right.  I think that’s OK since it doesn’t appear on Google’s site either.</p>
<p><strong>Update (21 Jun 2008):</strong> Google changed the JavaScript once again and this time very radically.  I’ve been keeping snapshots of their JavaScript code, so I’ve changed the script to load an older customized .js file.  This is a quick fix.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lindenlan.net/2008/04/23/restyle-google-calendar-3/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>How To Install MyGoogleCal2.php</title>
		<link>http://www.lindenlan.net/2008/03/22/how-to-install-mygooglecal2php/</link>
		<comments>http://www.lindenlan.net/2008/03/22/how-to-install-mygooglecal2php/#comments</comments>
		<pubDate>Sun, 23 Mar 2008 05:12:37 +0000</pubDate>
		<dc:creator><![CDATA[Brian]]></dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.lindenlan.net/2008/03/22/how-to-install-mygooglecal2php/</guid>
		<description><![CDATA[One of my readers asked for a step-by-step set of instructions to install MyGoogleCal2.php. My original posts for restyling Google Calendar did assume a certain level of expertise. This should hopefully help those who are still confused. Download mygooglecal2.zip. Unzip the file on your server, typically into a subfolder named ‘mygooglecal’. If your web server [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>One of my readers asked for a step-by-step set of instructions to install <a href="http://www.lindenlan.net/2007/10/14/restyle-google-calendar-2/">MyGoogleCal2.php</a>.  My original posts for restyling Google Calendar did assume a certain level of expertise.  This should hopefully help those who are still confused.</p>
<p><span id="more-54"></span></p>
<ol>
<li>
<p>Download <a href='http://www.lindenlan.net/wp-content/uploads/2007/10/mygooglecal2.zip' title='MyGoogleCal2 zip file'>mygooglecal2.zip</a>.</p>
</li>
<li>
<p>Unzip the file on your server, typically into a subfolder named ‘mygooglecal’.</p>
</li>
<li>
<p>If your web server supports .htaccess files and your site does not already have one, just move the .htaccess file that was in the zip file to the root of your site.  If your web site already has an .htaccess file, then you will need to copy the mod_rewrite rules from the the zip file’s .htaccess file to the existing one.</p>
</li>
<li>
<p>If you have not already done so, go to the <a href="http://www.google.com/calendar/embed/EmbedHelper_en.html">Embeddable Calendar Helper</a> and generate the HTML code for the calendar.  Place this code into the page that will display the calendar.</p>
</li>
<li>
<p>The HTML code for the Google Calendar is an &lt;iframe&gt; tag.  You need to edit the src attribute to point to MyGoogleCal2.php <em>on your server</em> and not http://www.google.com/calendar/embed.  See ‘USAGE:’ in the MyGoogleCal2.php file for an example.</p>
</li>
<li>
<p>That’s the basic installation.  You should be able to edit the included CSS file.  If you want to use a different CSS file or move it somewhere else, make sure to update the $stylesheet variable in MyGoogleCal2.php.  Remember, the CSS file is not guaranteed to be up-to-date so you may have to download your own copy.  Just follow the directions listed in MyGoogleCal2.php.</p>
</li>
</ol>
<p>Some additional notes:</p>
<ul>
<li>
<p>Some of the colors that the Google Calendar uses are: #c3d9ff, #bcd, #cde, #e8eef7, #e5ecf9, and #112abb.  That should help when editing the CSS file.  I highly recommend using Firefox and the <a href="https://addons.mozilla.org/en-US/firefox/addon/1843">Firebug extension</a>.  The extension has an Inspect feature that let’s you select a DOM object and see its element ID, class, and style attributes.  That will help identify which CSS rule you need change.</p>
</li>
<li>
<p>If the display of the calendar is blank, that usually means your PHP configuration is wrong and most likely the curl module is not installed or disabled.  Open the phpinfo.php file included in the zip file.  This will list a bunch of debug information about your web server’s PHP configuration.  If you do not see curl listed or curl is listed but disabled, then you will need to talk to your system administrator to fix it.</p>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.lindenlan.net/2008/03/22/how-to-install-mygooglecal2php/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Wolf Around the World</title>
		<link>http://www.lindenlan.net/2008/02/27/wolf-around-the-world/</link>
		<comments>http://www.lindenlan.net/2008/02/27/wolf-around-the-world/#comments</comments>
		<pubDate>Thu, 28 Feb 2008 05:06:38 +0000</pubDate>
		<dc:creator><![CDATA[Brian]]></dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Anime]]></category>
		<category><![CDATA[Gaming]]></category>
		<category><![CDATA[Hacking]]></category>

		<guid isPermaLink="false">http://www.lindenlan.net/2008/02/27/wolf-around-the-world/</guid>
		<description><![CDATA[I watch anime. That, Lego blocks, and video games are the three childhood vices I never outgrew. It’s just that my hobbies have matured along with me. I now prefer games that are rated M even though I still enjoy those that are rated E. I now prefer Technic sets over LEGOLAND Space sets. I [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I watch anime.  That, Lego blocks, and video games are the three childhood vices I never outgrew.  It’s just that my hobbies have matured along with me.  I now prefer games that are rated M even though I still enjoy those that are rated E.  I now prefer Technic sets over LEGOLAND Space sets.  I now prefer anime that deal with mature themes (e.g. Sayonara Zetsubou Sensei, Seirei no Moribito) over those that are juvenile (Pokemon).  I wish more animated shows in the US were more like those from Japan.</p>
<p><span id="more-49"></span></p>
<p>Most US animated features are just derivatives of live action sitcoms (The Simpsons, Family Guy, etc.) or purposefully aim at a younger audience as a means to market toys.  That’s not to say the Japanese don’t do it.  You only have to look as far as Bandai and Gundam to see they do it too, but at least some of the series they’ve produced aren’t dumbed down and actually have recognizable (if not Oscar-caliber) character and plot development (Gundam 00, Gundam 0080, etc.).  Which is why I applaud Warner Brothers for taking a queue from Japan, when they produced Animaniacs and the more recent DC Comics series.  It doesn’t hurt to put some smarts into your shows.  Same goes for Pixar.  Nickolodeon takes the crown, though, for their epic series Avatar: The Last Airbender.  It’s appealing to adults the same reason Harry Potter is; it’s just good old fashioned storytelling.  Not since The Mysterious Cities of Gold has Nick had such a great show.  To put things in perspective, it was 15 years from when MCoG ended to when Avatar started, and MCoG originally began airing in 1982!</p>
<p>In any case, even though I do prefer smarter, more mature animated features, I do occasionally watch shows that don’t fit in that category.  For example, I’ve watched Kanon 2006 and I’m currently watching Clannad and Shakugan no Shana.  They have a high level of production.  I’m also in the middle of <a href="http://www.spicy-wolf.com/">Spice and Wolf</a> (<a href="http://en.wikipedia.org/wiki/Spice_and_Wolf">English</a>).  It’s something to watch as the winter season winds down and until the spring season starts.  It doesn’t hurt that the characterization of the female protagonist appeals to me—sassy and smart.  Plus being a wolf goddess and cute, I was inspired to turn her into a Firefox icon—a small piece of functional fanart.  It gave me a chance to flex my (meager) Photoshop skills.  Those who watch the show will recognize Horo from the ending credits where she’s hugging a giant apple.  After making the icon and I can’t help but think that a complete Spice and Wolf Firefox theme would be kind of cool, or perhaps a full Gnome/KDE theme.  Maybe someone can take this icon and run with it.  The zip file contains .png icons at various sizes and should be compatible with Gnome and KDE.  I don’t feel like making an .ico file for Windows.  A Photoshop 7.0 file is included.  The file can be imported into <a href="http://gimp.org/">The GIMP</a>, but you’ll need to adjust the saturation of the top layer to something between 60 and 80 to match the Photoshop setting of 40.  </p>
<p><a href='http://www.lindenlan.net/wp-content/uploads/2008/02/firefox-horo.zip' title='Firefox Horo Icons'><img src='http://www.lindenlan.net/wp-content/uploads/2008/02/firefox-horo.png' alt='Firefox Horo' /></a> <a href='http://www.lindenlan.net/wp-content/uploads/2008/02/firefox-horo.zip' title='Firefox Horo Icons'>firefox-horo.zip</a></p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lindenlan.net/2008/02/27/wolf-around-the-world/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Calendar Casting Call</title>
		<link>http://www.lindenlan.net/2008/01/10/calendar-casting-call/</link>
		<comments>http://www.lindenlan.net/2008/01/10/calendar-casting-call/#comments</comments>
		<pubDate>Fri, 11 Jan 2008 02:51:24 +0000</pubDate>
		<dc:creator><![CDATA[Brian]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Hacking]]></category>

		<guid isPermaLink="false">http://www.lindenlan.net/2008/01/10/calendar-casting-call/</guid>
		<description><![CDATA[Did you restyle your embedded Google Calendar using MyGoogleCal? Maybe you’ve restyled Google Calendar Gadget by following my instructions to modify the XML configuration? Do you want to show off how you integrated your calendar into your site? Just leave a URL comment with a link to your web site.]]></description>
				<content:encoded><![CDATA[<p>Did you restyle your embedded Google Calendar using <a href="http://www.lindenlan.net/2007/10/14/restyle-google-calendar-2/">MyGoogleCal</a>?  Maybe you’ve <a href="http://www.lindenlan.net/2007/06/18/restyle-google-calendar-gadget/">restyled Google Calendar Gadget</a> by following my instructions to modify the XML configuration?  Do you want to show off how you integrated your calendar into your site?  Just leave a URL comment with a link to your web site.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lindenlan.net/2008/01/10/calendar-casting-call/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Restyle Google Calendar 2</title>
		<link>http://www.lindenlan.net/2007/10/14/restyle-google-calendar-2/</link>
		<comments>http://www.lindenlan.net/2007/10/14/restyle-google-calendar-2/#comments</comments>
		<pubDate>Mon, 15 Oct 2007 04:38:54 +0000</pubDate>
		<dc:creator><![CDATA[Brian]]></dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.lindenlan.net/2007/10/14/restyle-google-calendar-2/</guid>
		<description><![CDATA[The long awaited new version of MyGoogleCal is here. It supports the new AJAX-enabled Javascript method Google switched to last month. As a bonus, the new version has native support for multiple calendars each with their own colors! Other changes to the code include officially switching from fopen to curl to retrieve the data. Furthermore, [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>The long awaited new version of <a href="http://www.lindenlan.net/2006/10/08/restyle-google-calendar/">MyGoogleCal</a> is here.  It supports the new AJAX-enabled Javascript method Google switched to last month.  As a bonus, the new version has native support for multiple calendars each with their own colors!  Other changes to the code include officially switching from fopen to curl to retrieve the data.  Furthermore, the code replaces much less HTML since it’s encapsulated in Javascript.  Without further ado…</p>
<p><span id="more-39"></span></p>
<p><strong>UPDATE:</strong> MyGoogleCal now has a <a href="http://www.lindenlan.net/2008/04/23/restyle-google-calendar-3/">third version</a>.</p>
<p>Download: <a href='http://www.lindenlan.net/wp-content/uploads/2007/10/mygooglecal2.zip' title='mygooglecal2.zip'>mygooglecal2.zip</a>.  Contains MyGoogleCal2.php, mygooglecal2.css, MyGoogleCal2js.php, and an .htaccess file.  The CSS file is not guaranteed to be up-to-date so you may have to follow the instructions described in the PHP file to download the latest version from Google.</p>
<pre class="brush: php">
&lt;?php
/*******************************************************************************
 * FILE: MyGoogleCal2.php
 *
 * DESCRIPTION:
 *  This script is an intermediary between an iframe and Google Calendar that
 *  allows you to override the default style.
 *
 * USAGE:
 *  &lt;iframe src=&quot;MyGoogleCal2.php?src=user%40domain.tld&quot;&gt;&lt;/iframe&gt;
 *
 *  where user@domain.tld is a valid Google Calendar account.
 *
 * VALID QUERY STRING PARAMETERS:
 *    title:         any valid url encoded string 
 *                   if not present, takes title from first src
 *    showTitle:     0 or 1 (default)
 *    showNav:       0 or 1 (default)
 *    showDate:      0 or 1 (default)
 *    showTabs:      0 or 1 (default)
 *    showCalendars: 0 or 1 (default)
 *    mode:          WEEK, MONTH (default), AGENDA
 *    height:        a positive integer (should be same height as iframe)
 *    wkst:          1 (Sun; default), 2 (Mon), or 7 (Sat)
 *    hl:            en, zh_TW, zh_CN, da, nl, en_GB, fi, fr, de, it, ja, ko, 
 *                   no, pl, pt_BR, ru, es, sv, tr
 *                   if not present, takes language from first src
 *    bgcolor:       url encoded hex color value, #FFFFFF (default)
 *    src:           url encoded Google Calendar account (required)
 *    color:         url encoded hex color value     
 *                   must immediately follow src
 *    
 *    The query string can contain multiple src/color pairs.  It&#039;s recommended 
 *    to have these pairs of query string parameters at the end of the query 
 *    string.
 *
 * HISTORY:
 *   22 March    2008 - Replaced the custom javascript with a PHP script that 
 *                      uses the same technique as MyGoogleCal.php
 *   14 March    2008 - Update to match Google changes to javascript code
 *   14 January  2008 - Fixed Add to Calendar URL to point to Google
 *    3 January  2008 - Reverted back to customized javascript code to fix
 *                      bug where no data is displayed when navigating
 *                      into future or past
 *                      Note: imported calendars (e.g. iCal) should work again
 *   29 October  2007 - Update to match Google changes to javascript code
 *                      Note: imported calendars (e.g. iCal) do not work
 *   14 October  2007 - Original release
 *   
 * copyright (c) by Brian Gibson
 * email: bwg1974 yahoo com
 ******************************************************************************/

/* URL for overriding stylesheet
 * The best way to create this stylesheet is to 
 * 1) Load &quot;http://www.google.com/calendar/embed?src=user%40domain.tld&quot; in a
 *    browser,
 * 2) View the source (e.g., View-&gt;Page Source in Firefox),
 * 3) Copy the relative URL of the stylesheet (i.e., the href value of the 
 *    &lt;link&gt; tag), 
 * 4) Load the stylesheet in the browser by pasting the stylesheet URL into 
 *    the address bar so that it reads similar to:
 *    &quot;http://www.google.com/calendar/embed/d003e2eff7c42eebf779ecbd527f1fe0embedcompiled.css&quot;
 * 5) Save the stylesheet (e.g., File-&gt;Save Page As in Firefox)
 * Edit this new file to change the style of the calendar.
 *
 * As an alternative method, take the URL you copied in Step 3, and paste it
 * in the URL field at http://mabblog.com/cssoptimizer/uncompress.html.
 * That site will automatically format the CSS so that&#039;s more easily editable.
 */
$stylesheet = &#039;mygooglecal2.css&#039;;

/*******************************************************************************
 * DO NOT EDIT BELOW UNLESS YOU KNOW WHAT YOU&#039;RE DOING
 ******************************************************************************/

// URL for the calendar
$url = &quot;&quot;;
if(count($_GET) &gt; 0) {
  $url = &quot;http://www.google.com/calendar/embed?&quot; . $_SERVER[&#039;QUERY_STRING&#039;];
}

// Request the calendar
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$buffer = curl_exec($ch);
curl_close($ch);

// Point stylesheet and javascript to custom versions
$pattern = &#039;/(&lt;link.*&gt;)/&#039;;
$replacement = &#039;&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;&#039; . $stylesheet . &#039;&quot; /&gt;&#039;;
$buffer = preg_replace($pattern, $replacement, $buffer);

$pattern = &#039;/src=&quot;(.*js)&quot;/&#039;;
$replacement = &#039;src=&quot;MyGoogleCal2js.php?$1&quot;&#039;;
$buffer = preg_replace($pattern, $replacement, $buffer);

// display the calendar
print $buffer;
?&gt;
</pre>
<p>Use is similar to the original MyGoogleCal.php.  To help create the &lt;iframe&gt;, you can use the <a href="http://www.google.com/calendar/embed/EmbedHelper_en.html">Embeddable Calendar Helper</a>.  Just remember to update the src attribute to point to MyGoogleCal2.php and not http://www.google.com/calendar/embed.  </p>
<p><span style="text-decoration: line-through;">In addition to a custom CSS file the script makes use of a custom Javascript file.  Each URL is set after the script’s header and includes instructions on how to download versions of these files from Google.  This is important since it appears that the Javascript file is localized.  (I included copies that I downloaded in the above Zip file.)</span> </p>
<p><strong>Update (22 Mar 08):</strong> I created a new PHP file, MyGoogleCal2js.php, which downloads the JavaScript code and edits the code on-the-fly.  This negates the need to maintain a customized version of the JavaScript code on the same server as the MyGoogleCal.php script.   This should also lessen the chance that MyGoogleCal2.php will break when Google updates the code as long as the changes are minor.</p>
<p>The UI images are no longer contained in the CSS file.  You have two options on how to handle this.  If your site runs off of Apache, you can create a rewrite rule to hotlink to the Google images.  (I included an .htaccess file in the Zip file above that has a sample rule.)  The other, more conventional option is to create an “images” subfolder where the script is located and place copies of these images there.  You will definitely have to do this if you want to replace those images with customized versions. (I included images in the Zip file.)</p>
<p>What I’m hung-up on right now is figuring out a way to not have to save and rewrite the Javascript file.  The Javascript file is responsible for drawing the calendar, retrieving the XML data from Google, and then putting that data into the calendar.   The <code>_init()</code> function dynamically creates the URL from which to retrieve the XML data by using the browser’s window.location.host property.  Since the browser will presumably be pointing to your site, the host property will not be www.google.com.  As a result, the Javascript <span style="text-decoration: line-through;">hangs at the XML loading stage</span> fails to retrieve data when navigating into the future or past.  My attempts at circumventing this problem has been met with little success.</p>
<p>I tried the passthru directive in .htaccess file like so:</p>
<pre class="brush: xhtml">
RewriteRule ^(calendar/feeds/.*)$ http://www.google.com/$1 [P]
</pre>
<p>The browser spits out a 502 error.    </p>
<p>A redirect, [R] instead of [P], only works half-way.  The XmlHttpRequest goes thru but the data is rejected because it’s considered insecure since you can’t load data retrieved from an external domain.</p>
<p>I also tried ProxyPass/ProxyPassReverse to map</p>
<pre class="brush: xhtml">
/calendar/
</pre>
<p>to</p>
<pre class="brush: xhtml">

http://www.google.com/calendar

</pre>
<p>but it simply results in an error.  I’ll have to consult with my host to figure if the error is the configuration on their end or mine.</p>
<p><strong>Update (03 Jan 08):</strong> <em>After talking with my hosting provider it turns out this error is the fault of my virtual server and it won’t be fixed since they’re retiring the hardware.  I’ve been placed in the queue to migrate my account over to a new (hopefully problem-free) server.  In any case, I’ll definitely revisit this solution after the migration is over and test it then.</em></p>
<p>For more info, checkout: <a href="http://www.xml.com/pub/a/2005/11/09/fixing-ajax-xmlhttprequest-considered-harmful.html">Fixing AJAX: XMLHttpRequest Considered Harmful</a> or <a href="http://developer.yahoo.com/javascript/howto-proxy.html">Use a Web Proxy for Cross-Domain XMLHttpRequest Calls</a>.  The last one has pretty pictures.</p>
<p>Failed experiments include:</p>
<ul>
<li>
<p>Use the Javascript prototype mechanism to somehow override the window.location.host property to return a string of my choosing.</p>
</li>
<li>
<p>Rewrite a request to www.google.com to point to MyGoogleCal2.php so that I could inject code into the calendar page.  I thought this had a lot promise up until the point I realized I couldn’t put an .htaccess file at google.com. This was one of those “Duh!” moments.</p>
</li>
<li>
<p>Manipulate the &lt;iframe&gt; DOM in order to change its document.styleSheets property directly.  Due to security reasons, you can’t modify, let alone read, the DOM properties across different domains.</p>
</li>
<li>
<p>Proxy the XmlHttpRequest thru a curl script.  This almost worked.  The curl request succeeded in getting the JSON data, but for whatever reason, the Javascript code failed to do anything with it.  Depending on the content-type requested for the response, either nothing happening or the browser would spit out a Javascript error.  I’m sure it had to with an incomplete request header or returning just the response data instead of the entire response.  But whatever reason it was, this solution seemed more trouble than it was worth.</p>
</li>
</ul>
<p><span style="text-decoration: line-through;"><strong>Update (29 Oct 07):</strong> <em>Google’s new version of the Javascript code does not require any customization.  Do you suppose some Google developer read my post? <img src="http://www.lindenlan.net/wp-includes/images/smilies/icon_smile.gif" alt=":-)" class="wp-smiley" /> However, a side-effect is that imported calendars do not work.  I’m betting it has to do with XmlHttpRequest permissions, but I won’t know for certain without further investigation.</em></span> </p>
<p>When you’re done restyling your calendar, <a href="http://www.lindenlan.net/2008/01/10/calendar-casting-call/">show it off</a>!  Oh and don’t forget to Digg the article.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lindenlan.net/2007/10/14/restyle-google-calendar-2/feed/</wfw:commentRss>
		<slash:comments>79</slash:comments>
		</item>
		<item>
		<title>Restyle Google Calendar Gadget</title>
		<link>http://www.lindenlan.net/2007/06/18/restyle-google-calendar-gadget/</link>
		<comments>http://www.lindenlan.net/2007/06/18/restyle-google-calendar-gadget/#comments</comments>
		<pubDate>Tue, 19 Jun 2007 00:16:34 +0000</pubDate>
		<dc:creator><![CDATA[Brian]]></dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.lindenlan.net/2007/06/18/restyle-google-calendar-gadget/</guid>
		<description><![CDATA[My how-to for restyling Google Calendar is by far this blog’s most popular post so far. Right from the start, people had requested that I adjust the code to accommodate Google Calendar’s mini-mode. It certainly was possible using the technique I used, but it did break the agenda which was flaky to begin with given [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>My <a href="http://www.lindenlan.net/2006/10/08/restyle-google-calendar/">how-to for restyling Google Calendar</a> is by far this blog’s most popular post so far.  Right from the start, people had requested that I adjust the code to accommodate Google Calendar’s mini-mode.  It certainly was possible using the technique I used, but it did break the agenda which was flaky to begin with given the fact the feature was experimental.  Every once in a while, I’d check on the stability of mini-mode to determine if it was ripe for some hacking.  Then one day the mode simply didn’t work anymore.  It was weird, but after further research I found out why.  Mini-mode was superseded by the <a href="http://www.google.com/ig/directory?synd=open&#038;num=24&#038;url=http://www.google.com/ig/modules/calendar-for-your-site.xml">Google Calendar Gadget</a>.  The configuration form does provide some customization of the style, but it is certainly limited.  So just like before, I poked and prodded the code until I was able to find the means to restyle the gadget.</p>
<p><span id="more-29"></span></p>
<p>First step is to go to the <a href="http://www.google.com/ig/directory?synd=open&#038;num=24&#038;url=http://www.google.com/ig/modules/calendar-for-your-site.xml">Google Calendar Gadget</a> page.  Click on the “Add to Your Webpage” button.  The reason I don’t provide a direct link is because clicking on the button appears to set some locale settings.  Once there you can roughly style the calendar the way you want—like the overall size, what border, whether you want to display the calendar, agenda, or both, which calendar(s) you want to load, the link color for each event (which can be different for each calendar), etc.  Note that the calendar URL that you want to use is the XML one.  You get the URL by going to your <a href="http://www.google.com/calendar/">Google Calendar</a>, click on “Manage Calendars,” click the specific calendar, and then clicking the XML button under “Calendar Address.”  Just copy and paste the address into the form.  After you are done previewing the calendar, you’ll want to click the “Get the Code” button which will generate a script block that will be the foundation on which we’ll build.  </p>
<p>Let’s dissect the generated HTML.</p>
<pre class="brush: plain">
&lt;script src=&quot;http://gmodules.com/ig/ifr
</pre>
<p>This is some JavaScript that’s part of iGoogle and the Google Gadget framework.  A lot of the behind the scenes magic happens here.  What I’ve determined so far is that this creates a table and iframe to contain the gadget.  There’s some bad news because of this, but I’ll get to that later.</p>
<pre class="brush: plain">
?url=http://www.google.com/ig/modules/calendar-for-your-site.xml
</pre>
<p>This XML file is what defines the gadget itself.  This is where we’ll be doing most of our restyling.</p>
<pre class="brush: plain">
&amp;up_showCalendar2=1
&amp;up_showAgenda=1
&amp;up_calendarFeeds=(%7B%7D)
&amp;up_firstDay=Sunday
&amp;up_syndicatable=true
&amp;up_stylesheet=
&amp;up_sub=1
</pre>
<p>Now I added carriage returns to improve readability.  Most of these settings map directly to settings you set in the form.  Supposedly you can supply your own stylesheet, but the fact of the matter is it gets ignored because, as we’ll see later, the gadget provides it’s own styles inline.  </p>
<pre class="brush: plain">
&amp;up_c0u=http%3A%2F%2Fwww.google.com%2Fcalendar%2Ffeeds%2Fuser%2540domain.tld%2Fpublic%2Fbasic
&amp;up_c0c=
&amp;up_c1u=
&amp;up_c1c=
&amp;up_c2u=
&amp;up_c2c=
&amp;amp;up_c3u=
&amp;amp;up_c3c=
</pre>
<p>These are the XML feeds for each of the calendars.  You can embed up to four calendars and each can have a different color.  The colors won’t show up in the calendar view but will show up in the agenda view for each event link as well as each subscription link.</p>
<pre class="brush: plain">
&amp;up_min=
&amp;up_start=
&amp;up_timeFormat=1%3A00pm
&amp;up_calendarFeedsImported=0
&amp;synd=open
&amp;w=320
&amp;h=450
&amp;title=Google+Calendar
&amp;border=%23ffffff%7C3px%2C1px+solid+%23999999
&amp;output=js&quot;&gt;&lt;/script&gt;
</pre>
<p>Some more settings.  You can have a blank title if you want.  This is also where the border is defined.  Again you can have a blank border or you can be very fancy with your border design as long as it’s valid <a href="http://www.string-functions.com/urlencode.aspx">URL encoded</a> CSS.  You can also tweak the width and height if the need arises.</p>
<p>The next step is download the <a href="http://www.google.com/ig/modules/calendar-for-your-site.xml">source code</a> for the gadget.  (You can select “File-&gt;Save Page As” in Firefox if you load the source code in the browser.)  This way we now have a copy of the gadget that we can modify.  Open up the XML file in your favorite editor.  Scroll down until you find the style block.  This is where most of the style changes can be made.  Anywhere you see <code>#c3d9ff</code> or <code>rgb(195, 217, 255)</code> is Google blue.    Most of the class selectors are self-explanatory.  The one style that’s not in the style block that you may wish to change is the one contained in the table with the id <code>pickerContainer__MODULE_ID__</code>.  This is the color for the “Loading…” splash.  </p>
<p>The last step is to change the script block that loads the gadget.  Instead of </p>
<pre class="brush: plain">
&lt;script src=&quot;http://gmodules.com/ig/ifr?url=http://www.google.com/ig/modules/calendar-for-your-site.xml
</pre>
<p>you need to change it to</p>
<pre class="brush: plain">
&lt;script src=&quot;http://gmodules.com/ig/ifr?url=http://mywebsite.com/path/to/file/calendar-for-your-site.xml
</pre>
<p>Don’t forget to upload the edited XML file to your web site.  That should do it.  </p>
<p>Now about that problem I alluded to earlier.  The JavaScript that loads the gadget unfortunately has some hard coded styles, in particular, it sets the background to white.  White is certainly a popular background color, but obviously not all web sites follow that convention.  The only way to do that is to use JavaScript to dynamically change the style.  In the XML file, locate this script block at the bottom:</p>
<pre class="brush: js">
if (navigator.userAgent.toLowerCase().indexOf(&#039;msie&#039;) != -1) {
  document.body.onload = function() { new _CalendarModule(__MODULE_ID__); };
} else {
  new _CalendarModule(__MODULE_ID__);
}
</pre>
<p>and change it to</p>
<pre class="brush: js">
if (navigator.userAgent.toLowerCase().indexOf(&#039;msie&#039;) != -1) {
  document.body.onload = function() { new _CalendarModule(__MODULE_ID__); document.body.style.backgroundColor = &quot;gray&quot;; };
} else {
  new _CalendarModule(__MODULE_ID__);
  document.body.style.backgroundColor = &quot;gray&quot;;
}
</pre>
<p>Of course feel free to change the color string to match your web site.  Now don’t be surprised if after reloading the page, the background doesn’t change.  I’m not a 100% sure why this is the case.  My best guess is that the code is being cached, but clearing it on the client side doesn’t seem to have an effect.  So there appears to be some server-side caching going on.  The good news is that eventually the cached version times out and the correct background color will display.  This technique can also be used to load a background image or change other style settings.</p>
<p>Assuming you do change the background color you will have to host your own corner images on your web site.  Locate these lines in the style block of the XML file.</p>
<pre class="brush: xml">
td.tl {background:url(&quot;http://www.google.com/calendar/images/corner_tl.gif&quot;) top left}
td.bl {background:url(&quot;http://www.google.com/calendar/images/corner_bl.gif&quot;) bottom left}
td.tr {background:url(&quot;http://www.google.com/calendar/images/corner_tr.gif&quot;) top right}
td.br {background:url(&quot;http://www.google.com/calendar/images/corner_br.gif&quot;) bottom right}
</pre>
<p>You will need to download, edit those GIF files to match your background color, and then upload the files to your site.  Once that’s done, you’ll need to update the XML file to reflect the new URLs for those images.</p>
<p>Happy styling!  When you’re done restyling your calendar, <a href="http://www.lindenlan.net/2008/01/10/calendar-casting-call/">show it off</a>!</p>
<p>P.S. The technique used to <a href="http://www.lindenlan.net/2006/10/08/restyle-google-calendar/">restyle Google Calendar</a> can be used to edit the XML file.  I leave this as an exercise for the reader.  The technique described above doesn’t require PHP so will be most applicable to those non-programmers out there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lindenlan.net/2007/06/18/restyle-google-calendar-gadget/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
	</channel>
</rss>
