<?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"
	>

<channel>
	<title>John Peloquin's Blog</title>
	<atom:link href="http://blogs.whardy.com/john/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogs.whardy.com/john</link>
	<description>John Peloquin's technology blog at W. Hardy Interactive, Inc.</description>
	<pubDate>Thu, 04 Sep 2008 06:49:04 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Interval Calendar Control</title>
		<link>http://blogs.whardy.com/john/2008/05/27/interval-calendar-control/</link>
		<comments>http://blogs.whardy.com/john/2008/05/27/interval-calendar-control/#comments</comments>
		<pubDate>Tue, 27 May 2008 23:59:39 +0000</pubDate>
		<dc:creator>John</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[Tech Notes]]></category>

		<category><![CDATA[calendar]]></category>

		<category><![CDATA[calendargroup]]></category>

		<category><![CDATA[control]]></category>

		<category><![CDATA[custom control]]></category>

		<category><![CDATA[date range]]></category>

		<category><![CDATA[interval]]></category>

		<category><![CDATA[yahoo]]></category>

		<category><![CDATA[yahoo calendar]]></category>

		<category><![CDATA[yui]]></category>

		<category><![CDATA[yui calendar]]></category>

		<category><![CDATA[yui calendargroup]]></category>

		<guid isPermaLink="false">http://blogs.whardy.com/john/?p=7</guid>
		<description><![CDATA[When preparing to implement a calendar interface for our Vermont travel planner site GoVermont.com which would allow users to specify hotel arrival and departure dates, we experimented with alternatives to the typical approach of having two separate calendars for arrival and departure, respectively...]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://developer.yahoo.com/yui/calendar/">Yahoo! User Interface (YUI) library Calendar control</a> is a very useful item for any dynamic web application requiring users to input dates&#8211;for example, when scheduling bill payments, searching for plane flights, booking hotel accommodations, and so on. The YUI control is particularly nice because it is programmatically rich and yet easily customizable.</p>
<p><span id="more-7"></span></p>
<p>When preparing to implement a calendar interface for our Vermont travel planner site <a href="http://govermont.com/">GoVermont</a> which would allow users to specify hotel arrival and departure dates, we experimented with alternatives to the typical approach of having two separate calendars for arrival and departure, respectively. Personally I have always thought this interface to be a little odd. After all, when people use real, physical calendars to mark off the days of a trip (say), they don&#8217;t put two calendars side-by-side and mark the arrival date on one, and then the departure date on the other. Instead, they typically just circle or mark off a block of days on the calendar&#8211;in other words, they define an <i>interval</i> of days on the calendar.</p>
<p>The near standardization on the web of the two-calendar interface stems primarily, I think, from the underlying form-based HTML input mechanism where there is one field for arrival date and a separate field for departure date. Given this framework, it seems natural to just attach a separate calendar to each field. But stepping back from HTML forms for a minute, it seems more natural to me, if one is going to implement a clickable calendar at all, to make it more like a real calendar, and for purposes such as the above just allow the user to easily define an interval of dates on a <i>single</i> calendar.</p>
<p>With this idea in mind I created an extension of the YUI CalendarGroup control (a generalization of the YUI Calendar supporting multiple pages) called the iCalendarGroup, which is designed specifically for user selection of an interval of dates. On this calendar, one simply clicks on two different dates to define an interval, and clicks a third time to start over. It functions similarly to the non-multi-select version of the YUI CalendarGroup, but the basic unit is now an interval of dates instead of a single date. Here is a working example:</p>
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.5.1/build/calendar/assets/skins/sam/calendar.css">
<script type="text/javascript" src="http://yui.yahooapis.com/2.5.1/build/yahoo-dom-event/yahoo-dom-event.js"></script><br />
<script type="text/javascript" src="http://yui.yahooapis.com/2.5.1/build/calendar/calendar-min.js"></script><br />
<script type="text/javascript" src="http://www.whardy.com/js/icalendargroup-min.js"></script></p>
<div class="yui-skin-sam">
<div id="iCalSample" style="margin-right: 10px; margin-bottom: 10px;"></div>
</div>
<p><script type="text/javascript">
var ical = new YAHOO.whardy.widget.iCalendarGroup('iCalSample', { pages: 1, title: 'iCalendarGroup Sample' });
ical.render();
</script></p>
<p>When using this control in an application, you can easily set and reset the interval selection programmatically, as well as obtain the lower and upper dates for use with other user interface elements (e.g. fields for arrival and departure date, etc.). You can also respond to selection events and take advantage of the other things that the YUI CalendarGroup provides.</p>
<p>The code for this example is extremely simple. The HTML consists of:</p>
<pre>
&lt;div class=&quot;yui-skin-sam&quot;&gt;
 &lt;div id=&quot;iCalSample&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>The Javascript consists of:</p>
<div style="clear: both;"></div>
<pre>
// create interval calendar control
var ical = new YAHOO.whardy.iCalendarGroup('iCalSample',
               { pages: 1, title: 'iCalendar Sample' });
ical.render();
</pre>
<p>Here is a working two page example, obtained by changing the &#8216;pages&#8217; value above:</p>
<div class="yui-skin-sam">
<div id="iCalSample2" style="margin-bottom: 10px;"></div>
</div>
<p><script type="text/javascript">
var ical = new YAHOO.whardy.widget.iCalendarGroup('iCalSample2', { pages: 2, title: 'iCalendarGroup Two Page Sample' });
ical.render();
</script></p>
<div style="clear: both;"></div>
<p>You can obtain the complete, fully documented JavaScript source code for this control <a href="http://www.whardy.com/js/icalendargroup.js">here</a>.</p>
<p>Thanks to Eric and Satyen at the YUI team, this control is also now available on the YUI site <a href="http://developer.yahoo.com/yui/examples/calendar/intervalcal.html">here</a>.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.whardy.com/john/2008/05/27/interval-calendar-control/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Linking into Google Maps</title>
		<link>http://blogs.whardy.com/john/2008/05/18/linking-into-google-maps/</link>
		<comments>http://blogs.whardy.com/john/2008/05/18/linking-into-google-maps/#comments</comments>
		<pubDate>Sun, 18 May 2008 23:51:55 +0000</pubDate>
		<dc:creator>John</dc:creator>
		
		<category><![CDATA[Tech Notes]]></category>

		<category><![CDATA[google]]></category>

		<category><![CDATA[google maps]]></category>

		<category><![CDATA[links]]></category>

		<category><![CDATA[map]]></category>

		<category><![CDATA[maps]]></category>

		<category><![CDATA[marker]]></category>

		<category><![CDATA[markers]]></category>

		<category><![CDATA[trigger]]></category>

		<category><![CDATA[triggers]]></category>

		<guid isPermaLink="false">http://blogs.whardy.com/john/?p=6</guid>
		<description><![CDATA[The GMarker, GEvent, GInfoWindow and related classes in the Google Maps API allow you to easily create markers on a map which are interactive and which provide valuable information to users. Often it is convenient to extend such interaction beyond the actual map itself, allowing other elements in the web application to alter markers on the map, retrieve and show information, and so on. In this tech note, I provide a simple example of this, demonstrating how to make simple HTML links trigger Google Maps markers and display information.]]></description>
			<content:encoded><![CDATA[<p>The GMarker, GEvent, GInfoWindow and related classes in the Google Maps API allow you to easily create markers on a map which are interactive and which provide valuable information to users. Often it is convenient to extend such interaction beyond the actual map itself, allowing other elements in the web application to alter markers on the map, retrieve and show information, and so on. In this tech note, I provide a simple example of this, demonstrating how to make simple HTML links trigger Google Maps markers and display information.</p>
<p><span id="more-6"></span></p>
<p>In the code that follows I use both the Google Maps API as well as the Yahoo! User Interface (YUI) API. The YUI API is only used to simplify HTML DOM event handling, and can be easily replaced with equivalent code from elsewhere.</p>
<p>Let&#8217;s take a look at the main JavaScript code first:</p>
<pre>// some places
var places = [
	{
		name: 'San Francisco',
		lat: 37.798391,
		lon: -122.419968,
		link_id: 'maplink_sf'
	},
	{
		name: 'Berkeley',
		lat: 37.878918,
		lon: -122.270622,
		link_id: 'maplink_bky'
	},
	{
		name: 'Mill Valley',
		lat: 37.912378,
		lon: -122.548199,
		link_id: 'maplink_mv'
	}
];

if(GBrowserIsCompatible()) {
	// create map
	var map = new GMap2(document.getElementById(&#8217;map&#8217;),
				{ size: new GSize(500,300) });

	// initialize map
	map.setCenter(new GLatLng(places[0].lat, places[0].lon), 10);
	map.addControl(new GSmallMapControl());
	map.addControl(new GMapTypeControl());

	// mark places and set links
	var coords;
	var marker;
	for(var i = 0; i &lt; places.length; i++) {
		// create and add marker
		coords = new GLatLng(places[i].lat, places[i].lon);
		marker = new GMarker(coords);
		marker.bindInfoWindowHtml(places[i].name);
		map.addOverlay(marker);

		if(places[i].link_id) {
			// set link
			set_map_link(places[i].link_id, map, marker);
		}
	}
}</pre>
<p>This code first defines an array of places, each of which has a name, geographical coordinates, and a link identifier. The link identifier is just the ID of an HTML link (anchor) that exists in the HTML and will be used to trigger the map marker associated with the place.</p>
<p>The code then creates a Google Map, places markers on the map corresponding to each place, and for each marker calls a function <code>set_map_link</code> which configures an HTML link to be able to trigger the marker. This function can be implemented as follows (using the YUI API):</p>
<pre>// function which makes a link trigger a map marker
function set_map_link(id, map, marker) {
	YAHOO.util.Event.addListener(id, 'click',
		function(e) {
			map.setCenter(marker.getPoint(), 12);
			GEvent.trigger(marker, 'click');
		}
	);
}</pre>
<p>This code simply registers an event handler for the &#8216;click&#8217; event on the specified HTML element (in our case, a link). The event handler centers the Google Map on the specified marker (adjusting the zoom a bit), and then triggers the &#8216;click&#8217; event on the marker in order to open the info window associated with it.</p>
<p>The corresponding HTML code might look as follows:</p>
<pre>&lt;p&gt;Check out these locations on the map:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a id="maplink_sf" href="#"&gt;San Francisco&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a id="maplink_bky" href="#"&gt;Berkeley&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a id="maplink_mv" href="#"&gt;Mill Valley&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;</pre>
<p>The end result is that, whenever any of these links is clicked, the appropriate marker is displayed on the Google Map, and the info window for that marker pops up. To see this code in action, <a href="http://whardy.com/gm/mapit.html">click here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.whardy.com/john/2008/05/18/linking-into-google-maps/feed/</wfw:commentRss>
		</item>
		<item>
		<title>An Interesting Case of Session State Corruption</title>
		<link>http://blogs.whardy.com/john/2008/03/21/an-interesting-case-of-session-state-corruption/</link>
		<comments>http://blogs.whardy.com/john/2008/03/21/an-interesting-case-of-session-state-corruption/#comments</comments>
		<pubDate>Fri, 21 Mar 2008 23:46:41 +0000</pubDate>
		<dc:creator>John</dc:creator>
		
		<category><![CDATA[Tech Notes]]></category>

		<category><![CDATA[ajax]]></category>

		<category><![CDATA[blank image source]]></category>

		<category><![CDATA[blank image src]]></category>

		<category><![CDATA[image]]></category>

		<category><![CDATA[image source]]></category>

		<category><![CDATA[image src]]></category>

		<category><![CDATA[session]]></category>

		<category><![CDATA[session corruption]]></category>

		<category><![CDATA[session data]]></category>

		<category><![CDATA[session state]]></category>

		<category><![CDATA[session state corruption]]></category>

		<guid isPermaLink="false">http://blogs.whardy.com/john/?p=5</guid>
		<description><![CDATA[Recently I encountered an interesting (and very frustrating) case of session state corruption occurring in one of our ColdFusion/AJAX-based search applications. The application allows users to search for various types of listings using an interface that features AJAX pagination. This means that as users navigate through pages of search results, an entire HTML document is not reloaded; instead, asynchronous JS requests are made to pull in new result sets, and user HTML is updated dynamically on the client side...]]></description>
			<content:encoded><![CDATA[<p>Recently I encountered an interesting (and very frustrating) case of session state corruption occurring in one of our ColdFusion/AJAX-based search applications. The application allows users to search for various types of listings using an interface that features AJAX pagination. This means that as users navigate through pages of search results, an entire HTML document is not reloaded; instead, asynchronous JS requests are made to pull in new result sets, and user HTML is updated dynamically on the client side.</p>
<p><span id="more-5"></span></p>
<p>I needed to add a feature to one part of the application that required recall of the user&#8217;s most recent search. It needed to take into account any AJAX page changes, so that the most recent page would always be recalled. After considering several options, I decided to copy the user&#8217;s latest search parameters into session data on each search request. The other component could then later read the stored data and reconstruct the user&#8217;s most recent search.</p>
<p>Of course, this raised the issue of preserving the integrity of session data in the presence of AJAX components. As is <a href="http://chipmunkninja.com/article/asyncsessions">well documented elsewhere</a>, when one or more asynchronous requests can occur during the course of a page load, or during the course of user interaction with a page, corruption of any shared data (such as session data) can occur. Asynchronous requests can, for example, modify such data in ways that the rest of the application ignores or does not account for. The variable timing of such requests can also create race conditions, and prevent coordination of different parts of the application.</p>
<p>While I recognized this and took efforts to prevent it, still something like this was exactly what seemed to be causing a problem in our application. The search parameters were being correctly stored in the session on non-AJAX requests, but with AJAX requests, the behavior was intermittent; sometimes the correct parameters were stored, and other times they would seemingly get reset to the most recent non-AJAX parameters.</p>
<p>But after doing some logging on the server, I noticed that in these instances <i>two</i> requests were actually happening on an AJAX page change&#8211;one for the newly selected page, followed by one for the page corresponding to the latest non-AJAX search. This was very bizarre. And it was not (totally) browser dependent; both Firefox and IE (6 and 7) exhibited this behavior. After enabling the Firebug request logger in Firefox, I could even see the second requests happening&#8211;right as new result sets were being loaded in. But I had no idea <i>why</i> they were occurring.</p>
<p>Of course, nothing in the AJAX code suggested that they should be. After examining a number of different things with no success in locating the problem, I thought perhaps this was some sort of obscure bug (or feature?) within either the YUI Connection Manager (which we use to initiate AJAX requests) or else the asynchronous request mechanisms implemented in both Firefox and IE. Googling for help, I initially located nothing useful until I finally stumbled across a <a href="http://weblogs.asp.net/pglavich/archive/2007/09/09/obscure-asp-net-problem-ajax-control-toolkit-collapsiblepanelextender-image-controls-pages-loading-more-than-once.aspx">helpful blog post&#8230;</a></p>
<p>In the post, the author describes experiencing a superfluous request on page load when an HTML IMG tag on his site contained an empty SRC attribute. And (guess what?) this just happened to be the case for some of our own images! Because some of our images were created as part of a JS-based UI component, being dynamically assigned SRC values by JS code on page load, the SRC attributes were left blank in the HTML. But this was causing both Firefox and IE to (usually) send requests to the current document&#8217;s URL&#8211;the one in the address bar&#8211;when these IMG tags were encountered. This wasn&#8217;t a critical problem for non-AJAX search requests since in those cases the document URL contained the latest search parameters; but on AJAX page changes, this was a very critical problem, as it was causing the stored AJAX search parameters to be overwritten!</p>
<p>The fix was, of course, to just point the offending tags to some placeholder image until the JS code updated them on page load. Once this was done, everything worked fine.</p>
<p>While this problem was only indirectly caused by a JS/AJAX component, it illustrates the need to take great care in preserving shared data integrity when building AJAX-enabled applications. All parts of the application must be built with AJAX in mind, accounting for the fact that shared data might be modified in unexpected ways as a result of asynchronous requests.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.whardy.com/john/2008/03/21/an-interesting-case-of-session-state-corruption/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Moodle on Solaris</title>
		<link>http://blogs.whardy.com/john/2008/01/02/moodle-on-solaris/</link>
		<comments>http://blogs.whardy.com/john/2008/01/02/moodle-on-solaris/#comments</comments>
		<pubDate>Wed, 02 Jan 2008 23:29:43 +0000</pubDate>
		<dc:creator>John</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[moodle]]></category>

		<category><![CDATA[mysql]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[server]]></category>

		<category><![CDATA[solaris]]></category>

		<category><![CDATA[sun]]></category>

		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blogs.whardy.com/john/?p=4</guid>
		<description><![CDATA[Recently I had the opportunity to install Moodle--a PHP-driven, open source course management system for online learning--on one of our enterprise class servers running Sun Solaris 10 and Sun Java System Web Server 7.0. While there were a number of packages available to simplify the installations of some versions of PHP and Moodle, I needed to install Moodle 1.9, for which there were not suitable packages readily available. In this entry I document the steps I took to perform manual installations of both pieces of software, as well as some of the technical issues I ran into along the way.]]></description>
			<content:encoded><![CDATA[<p>Recently I had the opportunity to install <a href="http://moodle.org/">Moodle</a>&mdash;a <a href="http://php.net/">PHP</a>-driven, open source course management system for online learning&mdash;on one of our enterprise class servers running <a href="http://sun.com/software/solaris/">Sun Solaris 10</a> and <a href="http://sun.com/software/products/web_srvr/">Sun Java System Web Server 7.0</a>. While there were a number of packages available to simplify the installations of some versions of PHP and Moodle, I needed to install Moodle 1.9, for which there were not suitable packages readily available. In this entry I document the steps I took to perform manual installations of both pieces of software, as well as some of the technical issues I ran into along the way.</p>
<p><span id="more-4"></span><br />
<b>Contents</b></p>
<ul>
<li><a href="#sec_prelims">Preliminary Installations</a>
<ul>
<li><a href="#sec_prereqs">Installing Prerequisite Packages</a></li>
<li><a href="#sec_mysql">Installing MySQL</li>
<li><a href="#sec_php">Installing PHP</li>
</ul>
</li>
<li><a href="#sec_config">Configuring Sun Web Server</a></li>
<li><a href="#sec_moodle">Installing Moodle</li>
<li><a href="#sec_slash">Slash Arguments</li>
</ul>
<p></p>
<p><a name="sec_prelims"></a><br />
<b>Preliminary Installations</b></p>
<p>As the <a href="http://docs.moodle.org/en/Installing_Moodle">documentation</a> indicates, Moodle requires several pieces of software to be installed before it can run. First it requires a web server, which in my case was the Sun Java System Web Server 7.0. Second, the web server must have a fairly recent version of PHP installed, with a number of options and extension modules enabled (see below). Finally, a database server is required, which in my case was going to be <a href="http://mysql.com/">MySQL</a>.</p>
<p>The PHP installation needs the following options and extensions to be enabled for best results:</p>
<ul>
<li>The mysql extension&mdash;or the pgsql extension if you are using a PostgreSQL server (required).</li>
<li>The <a href="http://www.libgd.org/">GD</a> and <a href="http://www.freetype.org/">FreeType 2</a> libraries.</li>
<li>The mbstring option.</li>
<li>Basic extensions: tokenizer, session, etc. (usually enabled by default).</li>
<li>Other extensions: iconv, zlib, curl, and openssl.</li>
<li>Additional extensions if you are using some more advanced Moodle features (see Moodle docs).</li>
</ul>
<p>You also, of course, need a suitable compiler and make utility for compiling and installing PHP with the above options configured (and also for your web and database server software if those are not already compiled or installed).</p>
<p>Since the Sun web server was already installed and running on our server, I only needed to install PHP, MySQL, and all other prerequisite software on which these two items depended.</p>
<p><a name="sec_prereqs"></a><br />
<i>Installing Prerequisite Packages</i></p>
<p>For the prerequisites, I used the packages available at <a href="http://sunfreeware.com/">Sunfreeware.com</a>. The installations were very straightforward for the most part (just a bit tedious in high concentration!), so I will not document them in detail. As an example, to install the zlib package on our server, I downloaded the file <code>zlib-1.2.3-sol10-x86-local.gz</code> to <code>/tmp</code>, and then ran the following commands from the shell (as root):</p>
<pre>
cd /tmp
gunzip zlib-1.2.3-sol10-x86-local.gz
pkgadd -d zlib-1.2.3-sol10-x86-local
</pre>
<p>Note that a number of the packages have dependencies on other packages, which must be installed as well. Most of the packages are installed to <code>/usr</code> or <code>/usr/local</code>. Also, for the GD package, you have the option of either installing it separately or using the bundled GD package that comes with PHP. I simply used the bundled package.</p>
<p><a name="sec_mysql"></a><br />
<i>Installing MySQL</i></p>
<p>The MySQL server software can also be downloaded as a package from Sunfreeware, but it requires some additional manipulation. The relevant additional instructions are placed in <code>/usr/local/doc/mysql</code>. They involve adding a new system user/group, adjusting permissions, running a script to set up the basic grant tables, and starting the server daemon. It is also necessary to configure default MySQL user accounts and secure the server properly. I am not documenting these procedures here; see the <a href="http://dev.mysql.com/doc/refman/5.0/en/installing-cs.html">MySQL installation docs</a> for more information. (Note: if you are using a MySQL package from a different source, or are compiling it manually, you must use a version that is compatible with the PHP distribution you are installing. For example, if you will be running a 32-bit installation of PHP, you must install a 32-bit version of MySQL, or else you will get errors. Note also that &#8217;strict mode&#8217; should remain turned off in the configuration file for MySQL to work with Moodle.)</p>
<p>Once MySQL is installed and running, it is necessary to create a new empty database for Moodle to use, and this database must be configured to use the <code>utf8</code> character set. Using the command line MySQL client, I did this as follows:</p>
<pre>
cd /usr/local/mysql/bin
./mysql -u root -p
...
mysql&gt; CREATE DATABASE moodle;
mysql&gt; ALTER DATABASE moodle
    -&gt; DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
</pre>
<p>It is also recommended to create a MySQL user account specifically for Moodle:</p>
<pre>
mysql&gt; GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,CREATE TEMPORARY TABLES,
    -&gt; DROP,INDEX,ALTER ON moodle.*
    -&gt; TO moodleuser@localhost IDENTIFIED BY 'somepassword';
mysql&gt; QUIT
...
./mysqladmin -u root -p reload
...
</pre>
<p>(Note the password above should be changed for an actual installation.)</p>
<p><a name="sec_php"></a><br />
<i>Installing PHP</i></p>
<p>Once MySQL and all of the prerequisite packages were installed, I was able to begin the PHP installation. I downloaded <code>php-5.2.5.tar.gz</code> from the PHP web site to <code>/tmp</code>, and got the source files extracted:</p>
<pre>
cd /tmp
gunzip php-5.2.5.tar.gz
tar -xvf php-5.2.5.tar
cd php-5.2.5
</pre>
<p>I was now ready to run the included <code>configure</code> script to configure the PHP build. This step involves enabling the options and extensions mentioned above, specifying the install locations of any relevant dependencies, and also specifying any other parameters necessary for build.</p>
<p>The installation of PHP with the Sun Java System Web Server actually presents several options at this junction: PHP can be compiled as a regular CGI module, a FastCGI module, or an NSAPI module. Roughly, these options are in order from the simplest but least efficient to the more complicated but most efficient. I decided to take the middle ground and install PHP as a FastCGI module. (For more information on the different types of installations and their pros and cons, see <a href="http://developers.sun.com/webtier/reference/techart/php2.html">Sun documentation</a>.)</p>
<p>Below is the code I used to configure the build. (Note that it is necessary to export the install location of your C compiler to <code>PATH</code>, so that the <code>configure</code> script can make use of it. In my case, I was using the Sunfreeware gcc package. If you are using a different compiler, make the appropriate adjustments.)</p>
<pre>
PATH=/usr/local/bin:$PATH
export PATH

./configure --prefix=/usr/local \
  --enable-fastcgi \
  --enable-force-cgi-redirect \
  --enable-mbstring \
  --with-mysql=/usr/local/mysql \
  --with-gd \
  --with-png-dir=/usr \
  --with-jpeg-dir=/usr \
  --with-xpm-dir=/usr \
  --with-freetype-dir=/usr \
  --with-zlib=/usr/local \
  --with-curl=/usr/local \
  --with-openssl=/usr/local/ssl
</pre>
<p>(Note: if you are installing an older version of PHP, you may run into an error at this point stating that the &#8216;GD build test failed&#8217;. A closer inspection of the <code>config.log</code> file may reveal that the build test for GD failed because it was unable to locate necessary libiconv symbols. If this is the case, you may need to adjust environment variables manually or edit the <code>configure</code> script directly by adding <code>-liconv</code> wherever <code>-lgd</code> appears in a build. For more information, see <a href="http://www.dotvoid.com/view.php?id=22">this article</a>.)</p>
<p>Once the <code>configure</code> script completed successfully, it was time to build and install PHP:</p>
<pre>
make
make install
</pre>
<p>This installed PHP in <code>/usr/local</code>. In particular, it installed <code>/usr/local/bin/php-cgi</code>, which was the FastCGI module.</p>
<p>To configure additional PHP options after it is installed, it is necessary to use a <code>php.ini</code> file. You can copy one of the distribution files into <code>/usr/local/lib</code> and then edit it, e.g.:</p>
<pre>
cp php.ini-recommended /usr/local/lib/php.ini
</pre>
<p>The following options should be set in <code>php.ini</code> for Moodle to work:</p>
<pre>
; The memory limit must be at least 16M
memory_limit = 128M
safe_mode = Off
file_uploads = 1
session.auto_start = 0
session.bug_compat_warn = 0
session.save_handler = files
magic_quotes_runtime = 0
; The following setting is recommended
magic_quotes_gpc = 1
</pre>
<p>Consult the PHP documentation for more information on <code>php.ini</code>.</p>
<p><a name="sec_config"></a><br />
<b>Configuring Sun Web Server</b></p>
<p>Sun Java System Web Server 7.0 now needed to be configured to use my PHP FastCGI module. This involved editing a few different configuration files. First I navigated to the appropriate directory (note that the path below is specific to my setup, which was running on <code>moodle.whardy.com</code>):</p>
<pre>
cd /var/opt/SUNWwbsvr7/https-moodle.whardy.com/config
</pre>
<p>Then I enabled the FastCGI module by adding the following line to the file <code>magnus.conf</code>:</p>
<pre>
Init fn=load-modules shlib="libfastcgi.so"
</pre>
<p>Next I had to add a Service type directive to the file <code>obj.conf</code>, placing it inside the default object as follows:</p>
<pre>
&lt;Object name="Default"&gt;

  Service type="magnus-internal/php"
          fn="responder-fastcgi"
          app-path="/usr/local/bin/php-cgi"
          bind-path="localhost:3101"
          app-env="PHPRC=/usr/local/lib"
          app-env="PHP_FCGI_CHILDREN=2"
          app-env="PHP_FCGI_MAX_REQUEST=200"
          app-env="FCGI_WEB_SERVER_ADDRS=127.0.0.1"
          app-env="LD_LIBRARY_PATH=/usr/local/lib/php"

  PathCheck fn="find-index"
            index-names="index.php,index.html,home.html,index.jsp"

  ...
&lt;/Object&gt;
</pre>
<p>Note that the PathCheck directive above includes <code>index.php</code>. This allows the web server to run a PHP script (named <code>index.php</code>) as the default document in a directory. Note also that there are usually lots of other directives in the <code>obj.conf</code> file, which I am not displaying above for brevity.</p>
<p>Finally, I associated file extensions with the new type by adding a line to <code>mime.types</code>:</p>
<pre>
type=magnus-internal/php exts=php,php3,php4,php5
</pre>
<p>The web server needed to be restarted for the changes to take effect:</p>
<pre>
../bin/stopserv
../bin/startserv
</pre>
<p><a name="sec_moodle"></a><br />
<b>Installing Moodle</b></p>
<p>At long last I was ready to install Moodle! Well, almost. First I needed to create a data directory outside of web root where Moodle would be able to store course documents, user pictures, and so on. I created it directly above the web root (note again the path below is specific to my server setup):</p>
<pre>
cd /var/opt/SUNWwbsvr7/https-moodle.whardy.com
mkdir moodledata
chmod -R 770 moodledata
</pre>
<p>Finally, I was able to run the web-based installer at <code>http://moodle.whardy.com/install.php</code>. Here I entered basic configuration parameters including database type/host/username/password/table, web root path, data directory path, etc. These parameters were all obtained from the installation steps above. After this, I accessed <code>http://moodle.whardy.com/admin/</code> to complete the installation. (Note: the installation scripts provide status information during installation. If you run these scripts and encounter errors, consult the <a href="http://docs.moodle.org/en/Installing_Moodle">Moodle installation docs</a> for information on the possible causes.)</p>
<p>Once these steps were complete, Moodle was ready to go! Or was it?</p>
<p><a name="sec_slash"></a><br />
<b>Slash Arguments</b></p>
<p>After setting up some test courses and adding documents to the courses, I noticed what seemed to be some bugginess in the displaying of uploaded files. When I would click on any links to access files, I would just get a page that said &quot;No input file specified&quot;. In addition, none of my user pictures were showing up in my profile. All of this despite the fact that the files had been successfully uploaded into my <code>moodledata</code> folder.</p>
<p>After poking around, I realized that the URL&#8217;s for these resources in Moodle&#8217;s HTML output looked a little funky, coming out in the form:</p>
<pre>http://moodle.whardy.com/file.php/1/mycourse/myfile.html</pre>
<p>It turns out this is a feature, however, not a bug, in Moodle&#8217;s implementation. Moodle writes the URL&#8217;s in this way by default in order to improve caching performance for clients and proxy servers. It&#8217;s called the &#8217;slasharguments&#8217; feature, and while it means well, it unfortunately did not work well with my server setup.</p>
<p>Luckily there are ways around it! The simplest workaround is to just disable slasharguments. From the Moodle administrator, you go to Server -&gt; HTTP, uncheck &#8216;Use slash arguments&#8217;, and click &#8216;Save Changes&#8217;. Easy enough. URL&#8217;s will then be written in the form:</p>
<pre>http://moodle.whardy.com/file.php?file=/1/mycourse/myfile.html</pre>
<p>But what if you like the caching benefits provided by the slash URL format? It is possible to keep the slashes when running Moodle on the Sun Java System Web Server; you just have to code silent URL rewriting into the web server configuration. This is done by first returning to the web server configuration files:</p>
<pre>
cd /var/opt/SUNWwbsvr7/https-moodle.whardy.com/config
</pre>
<p>Then you make the following addendum to <code>obj.conf</code>, again in the default object:</p>
<pre>
&lt;Object name="Default"&gt;
 ...

 &lt;If $uri =~ "^/file\\.php/(.*)$"&gt;
  NameTrans fn="restart" uri="/file.php?file=/$1"
 &lt;/If&gt;

&lt;/Object&gt;
</pre>
<p>Of course the web server must be restarted for the changes to take effect:</p>
<pre>
../bin/stopserv
../bin/startserv
</pre>
<p>And now Moodle should work fine even with slasharguments enabled.</p>
<p>To see our Moodle installation in action, visit <a href="http://sunstudentcourses.com/">www.SunStudentCourses.com</a></p>
<p><b>References</b></p>
<ul>
<li><a href="http://sun.com/software/solaris/">Sun Solaris 10</a></li>
<li><a href="http://sun.com/software/products/web_srvr/">Sun Java System Web Server 7.0</a></li>
<li><a href="http://www.sunfreeware.com/">Sunfreeware</a></li>
<li><a href="http://dev.mysql.com/doc/refman/5.0/en/installing-cs.html">Installing MySQL Server</a></li>
<li><a href="http://www.php.net/manual/en/install.php">Installing PHP</a></li>
<li><a href="http://developers.sun.com/webtier/reference/techart/php2.html">Using PHP on Sun Java System Web Server</a></li>
<li><a href="http://docs.moodle.org/en/Installing_Moodle">Installing Moodle</a></li>
<li><a href="http://www.dotvoid.com/view.php?id=22">MySQL 4, Apache 1.3 and PHP 4.3 on Solaris x86</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blogs.whardy.com/john/2008/01/02/moodle-on-solaris/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
