<?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>Zulius</title>
	<atom:link href="http://www.zulius.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.zulius.com</link>
	<description>Advanced Application Development</description>
	<lastBuildDate>Fri, 26 Feb 2010 12:04:09 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Resolve Windows netbios names from Linux</title>
		<link>http://www.zulius.com/how-to/resolve-windows-netbios-names-from-linux/</link>
		<comments>http://www.zulius.com/how-to/resolve-windows-netbios-names-from-linux/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 11:59:57 +0000</pubDate>
		<dc:creator>Tim White</dc:creator>
				<category><![CDATA[how-to]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[netbios]]></category>
		<category><![CDATA[samba]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.zulius.com/?p=704</guid>
		<description><![CDATA[p>Platforms: any *nix distro
What You'll Need: Samba

In a heterogeneous LAN it is often useful to resolve network addresses by a computer's name (ie. netbios name).  This is especially true if the LAN does not have a DNS server so that host names can be used instead of IP addresses (which if dynamically assigned, could [...]]]></description>
			<content:encoded><![CDATA[<p><div class="wp-caption alignleft" style="width: 159px"><img alt="Ping a Windows box" src="/img/blog/resolveWindowsNetbiosTitleImate.png" title="Ping a Windows box" width="150" height="110" /><p class="wp-caption-text">Ping a Windows box</p></div>
<p><strong>Platforms: </strong><br />any *nix distro</p>
<p><strong>What You'll Need:</strong><br /> <a href="http://www.samba.org/">Samba</a></p>
<p>
In a heterogeneous LAN it is often useful to resolve network addresses by a computer's name (ie. <a href="http://en.wikipedia.org/wiki/NetBIOS">netbios</a> name).  This is especially true if the LAN does not have a DNS server so that host names can be used instead of IP addresses (which if dynamically assigned, could change often).</p>
<p>
To enable Windows netbios name resolution from a Linux computer, make sure that <a href="http://www.samba.org/">Samba</a> is installed (although the smb service does not need to be running).  The Samba suite includes <a href="http://www.samba.org/samba/docs/man/Samba-HOWTO-Collection/winbind.html">winbind</a>, which enables Windows host names to be resolved.</p>
<p>Then edit /etc/nsswitch.conf and change this line:</p>
<pre class="brush: plain;">hosts:      files dns</pre>
<p>to this:</p>
<pre class="brush: plain;">hosts:      files dns wins</pre>
<p>Then test by pinging the computer name of Windows machine on the LAN:</p>
<pre class="brush: plain;">$ ping windowsbox
PING windowsbox (192.168.0.100) 56(84) bytes of data.
64 bytes from 192.168.0.100: icmp_seq=1 ttl=128 time=0.117 ms
64 bytes from 192.168.0.100: icmp_seq=2 ttl=128 time=0.127 ms
64 bytes from 192.168.0.100: icmp_seq=3 ttl=128 time=0.127 ms
64 bytes from 192.168.0.100: icmp_seq=4 ttl=128 time=0.127 ms
64 bytes from 192.168.0.100: icmp_seq=5 ttl=128 time=0.128 ms</pre>
<p>This setting really comes in handy when mounting a shared folder of a dynamically IP'ed Windows box from Linux.  Instead of using the Windows' box IP address, just specify it's netbios name.  Example entry in /etc/fstab:</p>
<pre class="brush: plain;">
//windowsbox/my_share/ /mnt/my_mount_point/ cifs rw,username=xxx,password=xxx,domain=xxx 0 0
</pre>
<img src="http://www.zulius.com/blog/?ak_action=api_record_view&id=704&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.zulius.com/how-to/resolve-windows-netbios-names-from-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Send multidimensional arrays to PHP with jQuery and AJAX</title>
		<link>http://www.zulius.com/how-to/send-multidimensional-arrays-php-with-jquery-ajax/</link>
		<comments>http://www.zulius.com/how-to/send-multidimensional-arrays-php-with-jquery-ajax/#comments</comments>
		<pubDate>Sat, 26 Dec 2009 14:48:46 +0000</pubDate>
		<dc:creator>Tim White</dc:creator>
				<category><![CDATA[how-to]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.zulius.com/?p=656</guid>
		<description><![CDATA[AJAX communication between the client browser and web server is a handy method of transferring data without forcing the user to refresh the page.  Typically, the data sent to the server is a simple set of form fields or flags.  However, it is also possible to submit more complex structured data.  This [...]]]></description>
			<content:encoded><![CDATA[<div class="wp-caption alignleft" style="width: 170px"><img alt="AJAX" src="/img/blog/assocArrayPhpJqueryAjax.png" title="AJAX" width="150" height="110" /><p class="wp-caption-text">javascript array</p></div>
<p><a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29">AJAX</a> communication between the client browser and web server is a handy method of transferring data without forcing the user to refresh the page.  Typically, the data sent to the server is a simple set of form fields or flags.  However, it is also possible to submit more complex structured data.  This tutorial will demonstrate 3 different methods used to pass multidimensional javascript arrays using <a href="http://jquery.com/">jQuery</a> and AJAX to a <a href="http://www.php.net/">PHP</a> web server.</p>
<h2>The Wrong Way</h2>
<p>My first instinct was that multidimensional JS arrays could be passed directly to jQuery's AJAX functions.  I expected that the array would be automatically preserved in the request, and show up in PHP's $_GET/$_POST variables.  The following example shows this doesn't work.</p>
<p>The code below attempts to post a JS associative array ("data", line 9) to the web server using jQuery's <a href="http://docs.jquery.com/Ajax/jQuery.ajax">$.ajax()</a> function.  The $.ajax() function is jQuery's lowest level AJAX function, but still provides a high level approach and lots of options.</p>
<pre class="brush: xml; first-line: 1; gutter: true;">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; dir=&quot;ltr&quot; lang=&quot;en-US&quot;&gt;
    &lt;head profile=&quot;http://gmpg.org/xfn/11&quot;&gt;
        &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;
        &lt;title&gt;jQuery AJAX arrays&lt;/title&gt;
        &lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&quot;&gt;&lt;/script&gt;
        &lt;script type=&quot;text/javascript&quot;&gt;
                sendAjax = function(){
                    var data = {
                                  foo:  123,
                                  bar:  456,
                                  rows: [
                                          {
                                            column1 : 'hello',
                                            column2 : 'hola',
                                            column3 : 'bonjour',
                                          },
                                          {
                                            column1 : 'goodbye',
                                            column2 : 'hasta luego',
                                            column3 : 'au revoir',
                                          },
                                        ],
                                  test1:{
                                          test2: {
                                                   test3:  'baz'
                                                 }
                                        }
                                };

                    $.ajax({
                            type:           'post',
                            cache:          false,
                            url:            './ajax/',
                            data:           data
                           });
                }

        &lt;/script&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;input type=&quot;button&quot; style=&quot;width: 130px; height: 60px&quot; value=&quot;send AJAX&quot; onclick=&quot;sendAjax();&quot; /&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>When the button is clicked, the following data shows up in PHP's $_POST variable:</p>
<pre class="brush: plain;">
Array
(
    [foo] =&gt; 123
    [bar] =&gt; 456
    [rows] =&gt; [object Object]
    [test1] =&gt; [object Object]
)
</pre>
<p>As shown, the first level of the array data is preserved (keys "foo" and "bar").  However, jQuery simply calls .toString() on the nested arrays at keys "rows" and "test1", and they get passed to PHP with the useless values "[object Object]".</p>
<h2>Method 1 - Form input arrays</h2>
<p>It's possible to name the keys of the JS array as HTML form input arrays (ie. named with square brackets) so that <a href="http://php.net/manual/en/language.variables.external.php">PHP decodes the array's key names as nested arrays</a>.  I don't recommend this method because it does not maintain the JS array's original structure in the Javascript.  However, it can be used if you just need to get the AJAX request working without using JSON.</p>
<p>
The original JS "data" array can be renamed/restructured as:
</p>
<pre class="brush: jscript;">
sendAjax = function(){
	var data = {
				  foo:  123,
				  bar:  456,
				  'rows[0][column1]':    'hello',
				  'rows[0][column2]':    'hola',
				  'rows[0][column3]':    'bonjour',
				  'rows[1][column1]':    'goodbye',
				  'rows[1][column2]':    'hasta luego',
				  'rows[1][column3]':    'au revoir',
				  'test1[test2][test3]': 'baz'
				};
	$.ajax({
			type:           'post',
			cache:          false,
			url:            './ajax/',
			data:           data
		   });
}
</pre>
<p>And the data is correctly received in PHP's $_POST variable:</p>
<pre class="brush: plain;">
Array
(
    [foo] =&gt; 123
    [bar] =&gt; 456
    [rows] =&gt; Array
        (
            [0] =&gt; Array
                (
                    [column1] =&gt; hello
                    [column2] =&gt; hola
                    [column3] =&gt; bonjour
                )

            [1] =&gt; Array
                (
                    [column1] =&gt; goodbye
                    [column2] =&gt; hasta luego
                    [column3] =&gt; au revoir
                )
        )

    [test1] =&gt; Array
        (
            [test2] =&gt; Array
                (
                    [test3] =&gt; baz
                )
        )
)
</pre>
<h2>Method 2 - JSON string parameter</h2>
<p>This method converts the JS array to a <a href="http://www.json.org/">JSON</a> string, and passes it as a POST or GET parameter, which can be manually decoded back into an array by PHP.  Modern browsers (Firefox 3, IE 8) now have a native JSON object that can be used to stringify JS arrays to JSON strings.  The following example uses the <a href="http://developer.yahoo.com/yui/json/">YUI JSON utility</a> to convert the JS array to a string ( <a href="http://www.json.org/json2.js">json2</a> is another populary lightweight utility for handling JSON).</p>
<pre class="brush: jscript;">
sendAjax = function(){
	var data = {
				  foo:  123,
				  bar:  456,
				  rows: [
						  {
							column1 : 'hello',
							column2 : 'hola',
							column3 : 'bonjour',
						  },
						  {
							column1 : 'goodbye',
							column2 : 'hasta luego',
							column3 : 'au revoir',
						  },
						],
				  test1:{
						  test2: {
								   test3:  'baz'
								 }
						}
				};
	data = YAHOO.lang.JSON.stringify(data);

	$.ajax({
			type:           'post',
			cache:          false,
			url:            './ajax/',
			data:           {myJson:  data}
		   });
}
</pre>
<p>On the PHP side, it's necessary to use <a href="http://us2.php.net/manual/en/function.json-decode.php">json_decode()</a> to convert the JSON $_POST parameter string (named "myJson") to an array:</p>
<pre class="brush: php;">
&lt;?php
$data = json_decode($_POST['myJson'], true);
print_r($data);
</pre>
<p>And the array is good to go:</p>
<pre class="brush: plain;">
Array
(
    [foo] =&gt; 123
    [bar] =&gt; 456
    [rows] =&gt; Array
        (
            [0] =&gt; Array
                (
                    [column1] =&gt; hello
                    [column2] =&gt; hola
                    [column3] =&gt; bonjour
                )

            [1] =&gt; Array
                (
                    [column1] =&gt; goodbye
                    [column2] =&gt; hasta luego
                    [column3] =&gt; au revoir
                )
        )

    [test1] =&gt; Array
        (
            [test2] =&gt; Array
                (
                    [test3] =&gt; baz
                )
        )
)
</pre>
<h2>Method 3 - JSON content-type</h2>
<p>My favorite method is to simply JSON stringify the JS array, and pass it as the AJAX request's body.  This requires that the content-type of the request be changed from the default "application/x-www-form-urlencoded" to "application/json", and that $.ajax()'s <a href="http://docs.jquery.com/Ajax/jQuery.ajax#options">processData</a> parameter be set to false so that the JSON data is not converted into a query string.  Also, the type of request must be POST, as the GET method does not support submitting data in the request body.</p>
<pre class="brush: jscript;">
sendAjax = function(){
	var data = {
				  foo:  123,
				  bar:  456,
				  rows: [
						  {
							column1 : 'hello',
							column2 : 'hola',
							column3 : 'bonjour',
						  },
						  {
							column1 : 'goodbye',
							column2 : 'hasta luego',
							column3 : 'au revoir',
						  },
						],
				  test1:{
						  test2: {
								   test3:  'baz'
								 }
						}
				};
	data = YAHOO.lang.JSON.stringify(data);

	$.ajax({
			type:           'post',
			cache:          false,
			url:            './ajax/',
			data:           data,
			processData:    false,
			contentType:   'application/json'
		   });
}
</pre>
<p>On the PHP side, it's necessary to manually read the JSON string directly from the request body using the <a href="http://php.net/manual/en/wrappers.php.php">php://input</a> stream.  The returned string can then be decoded into an array:</p>
<pre class="brush: php;">
&lt;?php
$data = file_get_contents('php://input');
$data = json_decode($data, true);
print_r($data);
</pre>
<p>Which gives us the array:</p>
<pre class="brush: plain;">
Array
(
    [foo] =&gt; 123
    [bar] =&gt; 456
    [rows] =&gt; Array
        (
            [0] =&gt; Array
                (
                    [column1] =&gt; hello
                    [column2] =&gt; hola
                    [column3] =&gt; bonjour
                )

            [1] =&gt; Array
                (
                    [column1] =&gt; goodbye
                    [column2] =&gt; hasta luego
                    [column3] =&gt; au revoir
                )
        )

    [test1] =&gt; Array
        (
            [test2] =&gt; Array
                (
                    [test3] =&gt; baz
                )
        )
)
</pre>
<p>Hopefully this tutorial has helped you get multidimensional array data passed to your webserver using AJAX.  If you know of another method, please submit it in the comments - thanks!</p>
<img src="http://www.zulius.com/blog/?ak_action=api_record_view&id=656&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.zulius.com/how-to/send-multidimensional-arrays-php-with-jquery-ajax/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Get numlock working with PuTTY and vim</title>
		<link>http://www.zulius.com/how-to/get-numlock-working-with-putty-and-vim/</link>
		<comments>http://www.zulius.com/how-to/get-numlock-working-with-putty-and-vim/#comments</comments>
		<pubDate>Sat, 19 Dec 2009 08:34:45 +0000</pubDate>
		<dc:creator>Tim White</dc:creator>
				<category><![CDATA[how-to]]></category>
		<category><![CDATA[putty]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://www.zulius.com/?p=643</guid>
		<description><![CDATA[By default, your keyboard's numlock enabled number pad doesn't work well with console applications running on a PuTTY SSH connection.  The numpad's numbers seem to get mapped to inserting the characters "q" thru "y".  This is especially annoying when using vim.
To get numlock working, open PuTTY's configuration window, goto Terminal > Features.  [...]]]></description>
			<content:encoded><![CDATA[<div class="wp-caption alignleft" style="width: 170px"><img alt="PuTTY" src="/img/blog/putty-vim-numpad/puttyTitleImage.jpg" title="PuTTY" width="150" height="110" /><p class="wp-caption-text">PuTTY</p></div>
<p>By default, your keyboard's numlock enabled number pad doesn't work well with console applications running on a PuTTY SSH connection.  The numpad's numbers seem to get mapped to inserting the characters "q" thru "y".  This is especially annoying when using vim.</p>
<p>To get numlock working, open PuTTY's configuration window, goto <b>Terminal > Features</b>.  Enable the "Disable application keypad mode" checkbox.</p>
<p>  If you want this setting to persist, make sure to select a saved session and click "Save".</p>
<p style="padding: 15px 0 0 0"><img class="alignnone" src="/img/blog/putty-vim-numpad/terminal-features.jpg" alt="Putty Configuration" /></p>
<img src="http://www.zulius.com/blog/?ak_action=api_record_view&id=643&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.zulius.com/how-to/get-numlock-working-with-putty-and-vim/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP: close browser connection and keep on executing</title>
		<link>http://www.zulius.com/how-to/close-browser-connection-continue-execution/</link>
		<comments>http://www.zulius.com/how-to/close-browser-connection-continue-execution/#comments</comments>
		<pubDate>Fri, 20 Nov 2009 05:31:55 +0000</pubDate>
		<dc:creator>Tim White</dc:creator>
				<category><![CDATA[how-to]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[prototype]]></category>

		<guid isPermaLink="false">http://www.zulius.com/?p=543</guid>
		<description><![CDATA[Sometimes you need to execute a really long process after displaying a web page.  For example, you may need to evaluate the data a user submitted, and that operation may take a lot of time.  And since you're a thoughtful programmer, you don't want make the user stare at a blank page while [...]]]></description>
			<content:encoded><![CDATA[<div class="wp-caption alignleft" style="width: 170px"><img alt="Close the browser's connection" src="/img/blog/php-close-browser-connection/titleImage.jpg" title="Close the browser's connection" width="150" height="110" /><p class="wp-caption-text">Close the browser's connection</p></div>
<p>Sometimes you need to execute a really long process after displaying a web page.  For example, you may need to evaluate the data a user submitted, and that operation may take a lot of time.  And since you're a thoughtful programmer, you don't want make the user stare at a blank page while they wait for the process to finish.</p>
<p>A good solution is to display a confirmation page and then close the browser's connection to the web server.  Closing the browser's connection will cause the browser to stop "spinning" and display a "Done" status.  The user can then feel assured that their part in the matter is over with, and can navigate elsewhere.  In the meantime, your PHP (or whatever language) continues executing on the server.  You could even get fancy with it, and use AJAX to display the script's execution progress to the user on the confirmation page.</p>
<p>The key to doing this are the two HTTP header fields:</p>
<pre style="margin: -5px 0 10px 0">
Connection: close
Content-Length: n (n = size of output in bytes )
</pre>
<p>The <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.10">"Connection: close"</a> header lets the browser know that it should not maintain a persistent connection.  The <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13">"Content-Length: "</a> header tells the browser how much data to expect.  Thus, it's necessary to supply the size of the output (in bytes) using "Content-Length: ".  Then the browser knows when it's downloaded everything and can terminate the connection.</p>
<h2>Example 1 - Basic Usage</h2>
<p>&nbsp;</p>
<pre class="brush: php; first-line: 1; gutter: true;">
&lt;?php
// buffer all upcoming output
ob_start();
echo &quot;Here's my awesome web page&quot;;

// get the size of the output
$size = ob_get_length();

// send headers to tell the browser to close the connection
header(&quot;Content-Length: $size&quot;);
header('Connection: close');

// flush all output
ob_end_flush();
ob_flush();
flush();

/******** background process starts here ********/
</pre>
<h2>Example 2 - embedded PHP with execution progress updates</h2>
<p><a target="_blank" href="/blog/scripts/examples/php/close-browser-connection/example1.php"class="demo">View the demo</a></p>
<p>This basic example executes some arbitrary time consuming code in the background, after the user clicks the submit button.  Notice that after clicking submit, the browser displays the web page and stops downloading.  Also, as a bonus, the execution progress of the script is displayed periodically using Prototype's PeriodicUpdater ajax calls.</p>
<ul>
<li><strong>Lines 02 - 19:</strong>&nbsp;&nbsp;AJAX handler that returns the progress of the background execution to the AJAX calls.  It's basically reading the contents of the progress file to the browser.</li>
<li><strong>Lines 22 - 35:</strong>&nbsp;&nbsp;Creates a uniquely named temporary file to track the background process's execution.  It also buffers all output (Line 034) so that we can calculate the size of all the content.  The size will be sent in the "Content-Length: " header.</li>
<li><strong>Lines 37 - 85:</strong>&nbsp;&nbsp;HTML content.  The javascript in Lines 68 - 80 setup a Prototype PeriodicUpdater.  It checks on the status of the background script every 1 second.</li>
<li><strong>Line 88:</strong>&nbsp;&nbsp;Calculates the size of the buffered output in bytes.</li>
<li><strong>Lines 90 -98:</strong>&nbsp;&nbsp;Sends the 2 necessary headers to the browser, and flushes all buffered output to the browser.</li>
<li><strong>Lines 100 - 115:</strong>&nbsp;&nbsp;This is where the background process should be executed.  In the example, some time consuming code is executed, and it's progress (ie. "Executing step n...") is written to a temporary progress file.</li>
</ul>
<p>Demo source code</p>
<pre class="brush: php; first-line: 1; gutter: true;">
&lt;?php
    // ajax updater handler
    if (isset($_POST['ajax']) &amp;&amp; $_POST['pidFile']){
        // clean input
        $pidFile = preg_replace('/[^\w\d]/', '', $_POST['pidFile']);
        $pidFile = &quot;../cache/$pidFile&quot;;

        if (! file_exists($pidFile)){
            header('HTTP/1.1 500 Internal Server Error');
            exit;
        }
        if(! $progress = file_get_contents($pidFile)){
            header('HTTP/1.1 500 Internal Server Error');
            exit;
        }

        echo nl2br($progress);
        exit;
    }

    // was form submitted?
    if(isset($_POST['submitted'])){
        // create a unique file to track script progress
        $pidFile = tempnam('../cache', '');

        // create the file for writing
        $fh = fopen($pidFile, 'wrx+');
        if (! $fh){
            print &quot;failed to create the file&quot;;
            exit;
        }

        // buffer all upcoming output
        ob_start();
    }
?&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
    &lt;head profile=&quot;http://gmpg.org/xfn/11&quot;&gt;
        &lt;title&gt;Zulius :: Close Browser Connection :: Example #1 Inline PHP&lt;/title&gt;
        &lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js&quot;&gt;&lt;/script&gt;
        &lt;style&gt;
            body{ text-align: center; margin: 20px auto; font-family: Arial, Helvetica, sans-serif;}
            div#progress{ min-height: 220px; margin: 10px auto}
        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h1&gt;
        &lt;?php
        if(isset($_POST['submitted'])){
            echo 'background process started';
        }
        else{
            echo 'click to start background process';
        }
        ?&gt;
        &lt;/h1&gt;
        &lt;div id=&quot;progress&quot;&gt;
        &lt;/div&gt;
        &lt;form method=&quot;POST&quot;&gt;
            &lt;input type=&quot;submit&quot; name=&quot;submitted&quot; value=&quot;Go!&quot;&gt;
        &lt;/form&gt;
    &lt;/body&gt;
    &lt;?php
        if(isset($_POST['submitted'])){
        // show progress in browser
    ?&gt;
        &lt;script type=&quot;text/javascript&quot;&gt;
            updater = new Ajax.PeriodicalUpdater({success: 'progress'}, '&lt;?php echo $_SERVER['REQUEST_URI'] ?&gt;',
                                                { method: 'post',
                                                  frequency: 1,
                                                  decay: 1,
                                                  parameters: {
                                                               ajax: 1,
                                                               pidFile: '&lt;?php echo basename($pidFile) ?&gt;'
                                                             },
                                                  onFailure: function(){ this.stop(); }
                                                });
            setTimeout('updater.stop()', 15000);
        &lt;/script&gt;
    &lt;?php
        }
    ?&gt;
&lt;/html&gt;
&lt;?php
if(isset($_POST['submitted'])){
    // get the size of the output
    $contentLength = ob_get_length();

    // these headers tell the browser to close the connection
    // once all content has been transmitted
    header(&quot;Content-Length: $contentLength&quot;);
    header('Connection: close');

    // flush all output
    ob_end_flush();
    ob_flush();
    flush();

    /******** background process starts here ********/
    for($i=1;$i&lt;=10;$i++){
        if(fwrite($fh, &quot;Executing step $i...\n&quot;) == false){
            print &quot;failed to write to the file: &quot; . error_get_last();
            exit;
        }
        sleep(1);
    }

    fwrite($fh, &quot;Done!\n&quot;);
    sleep(2);

    fclose($fh);

    // delete the progress file
    unlink($pidFile);

}
</pre>
<h2>Example 3 - include embedded PHP file</h2>
<p>If you've separated the HTML from your main script, it's very easy to close the browser connection. Just capture the output from your include command, get the size of the content, and send the headers and content:</p>
<pre class="brush: php; first-line: 1; gutter: true;">
// capture output of include file in buffer
ob_start();
include '/path/to/your/content/file';

// get the size of the output
$contentLength = ob_get_length();

// these headers tell the browser to close the connection
// once all content has been transmitted
header(&quot;Content-Length: $contentLength&quot;);
header('Connection: close');

// flush all output
ob_end_flush();
ob_flush();
flush();

/******** background process code here ********/
</pre>
<h2>Background Process</h2>
<p>If your background process is vital and could take a lot of time, make sure to set these flags at the top of your script:</p</p>
<pre class="brush: php; first-line: 1; gutter: true;">
ignore_user_abort(true);
set_time_limit(0);
</pre>
<p><span style="font-family:  'Lucida Console', 'Courier New', Courier, monospace;">ignore_user_abort(true)</span> will prevent the script from halting if the user happens to push the browser's stop button before the connection is closed.  <span style="font-family:  'Lucida Console', 'Courier New', Courier, monospace;">set_time_limit(0)</span> will prevent your script from being terminated if it surpasses the <span style="font-family:  'Lucida Console', 'Courier New', Courier, monospace;">max_execution_time</span> set in php.ini.</p>
<p>Related post: <a href="/how-to/close-browser-connection-zend-framework">Close browser connection with Zend Framework</a></p>
<img src="http://www.zulius.com/blog/?ak_action=api_record_view&id=543&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.zulius.com/how-to/close-browser-connection-continue-execution/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>bash-beauty: formatted output for bash scripts</title>
		<link>http://www.zulius.com/freebies/bash-beauty-output-for-bash-scripts/</link>
		<comments>http://www.zulius.com/freebies/bash-beauty-output-for-bash-scripts/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 23:46:33 +0000</pubDate>
		<dc:creator>Tim White</dc:creator>
				<category><![CDATA[freebies]]></category>
		<category><![CDATA[bash]]></category>

		<guid isPermaLink="false">http://www.zulius.com/?p=408</guid>
		<description><![CDATA[A bash function library for displaying beautiful script progress output.]]></description>
			<content:encoded><![CDATA[<div style="margin: 0 auto; text-align: center"><a title="Download" href="/scripts/bash-beauty.sh" target="_blank"><img src="/img/button-dl-orange.png" alt="" width="202" height="62" /></a></div>
<div style="float: right; padding: 0 5px; margin: 25px 0 0 0;width: 160px">
<div style="clear: both">
<div class="wp-caption alignright" style="width: 160px"><a id="ss1" href="/img/blog/bash-beauty/bash-beauty-ss1.jpg" rel="colorbox"><img title="bash-beauty screenshot #1" src="/img/blog/bash-beauty/bash-beauty-ss1-thumb.jpg" alt="bash-beauty screenshot #1" width="150" height="110" /></a><p class="wp-caption-text">screenshot #1</p></div><br />
<script type="text/javascript">jQuery(document).ready(function(){jQuery("#ss1").colorbox({title: 'basic usage'});});</script>
</div>
<div style="clear: both">
<div class="wp-caption alignright" style="width: 160px"><a id="ss2" href="/img/blog/bash-beauty/bash-beauty-ss2.jpg" rel="colorbox"><img title="bash-beauty screenshot #2" src="/img/blog/bash-beauty/bash-beauty-ss2-thumb.jpg" alt="bash-beauty screenshot #2" width="150" height="110" /></a><p class="wp-caption-text">screenshot #2</p></div><br />
<script type="text/javascript">jQuery(document).ready(function(){jQuery("#ss2").colorbox({title: 'Print multi-colored result statuses'});});</script><br />

</div>
<div style="clear: both">
<div class="wp-caption alignright" style="width: 160px"><a id="ss3" href="/img/blog/bash-beauty/bash-beauty-ss3.jpg" rel="colorbox"><img title="bash-beauty screenshot #3" src="/img/blog/bash-beauty/bash-beauty-ss3-thumb.jpg" alt="bash-beauty screenshot #3" width="150" height="110" /></a><p class="wp-caption-text">screenshot #3</p></div><br />
<script type="text/javascript">jQuery(document).ready(function(){jQuery("#ss3").colorbox({title: 'Prefix each task with a 14 digit timestamp'});});</script>
</div>
</div>
<h2>What is it?</h2>
<p>
Bash function library for displaying script progress output.  The functions imitate the display format of Linux boot messages.</p>
<h2>What does it do?</h2>
<ul>
<li>Logs/echo's script tasks and results in a columnar format</li>
<li>Appends each task line with a colored status result (terminal stdout only)</li>
<li>Makes your script's output look good and readable</li>
</ul>
<h2>Other Features</h2>
<ul>
<li>Customizable message column width</li>
<li>Quiet mode writes only to a specified log file</li>
<li>Optionally prefixes all messages with a 14 digit timestamp</li>
<li>Free</li>
</ul>
<h2>Requirements</h2>
<p style="padding-left: 30px;">
<a title="Perl" href="http://www.gnu.org/software/bash/" target="_blank">GNU Bourne-Again Shell (BASH)</a>
</p>
<h2>Functions</h2>
<p>The bash-beauty.sh library has 5 printing functions: </p>
<ul>
<li>
<h4 style="margin-top: 0">printTask</h4>
<pre>Prints a single task message padded with whitespace to default 80 characters.</pre>
<div>
<h4 class="usage" style="margin-top: 10px">Usage</h4>
<pre style="margin-bottom: 15px">
printTask [OPTION]... MESSAGE
</pre>
<h4 class="usage" style="margin-top: 10px">Options</h4>
<pre style="margin-bottom: 15px">
-t     flag to automatically prepend message with 14 digit timestamp
-l     specify log file to write to
-q     quiet mode. Do not output to stdout, only write to log file if supplied
-w     width of padded message column. Defaults to 80 characters.
</pre>
</div>
</li>
<li>
<h4 style="margin-top: 0">printOk</h4>
<pre>Prints a green OK status result <span style="font-family:  'Lucida Console', 'Courier New', Courier, monospace; color: green">[  OK  ]</span></pre>
<div>
<h4 class="usage" style="margin-top: 10px">Usage</h4>
<pre style="margin-bottom: 15px">
printOk [OPTION]...
</pre>
<h4 class="usage" style="margin-top: 10px">Options</h4>
<pre style="margin-bottom: 15px">
-l     specify log file to write to
-q     quiet mode. Do not output to stdout, only write to log file if supplied
</pre>
</div>
</li>
<li>
<h4 style="margin-top: 0">printFail</h4>
<pre>Prints a red failure status result <span style="font-family:  'Lucida Console', 'Courier New', Courier, monospace; color: red">[FAILED]</span></pre>
<div>
<h4 class="usage" style="margin-top: 10px">Usage</h4>
<pre style="margin-bottom: 15px">
printFail [OPTION]... [MESSAGE]
</pre>
<h4 class="usage" style="margin-top: 10px">Options</h4>
<pre style="margin-bottom: 15px">
-l     specify log file to write to
-q     quiet mode. Do not output to stdout, only write to log file if supplied
</pre>
</div>
</li>
<li>
<h4 style="margin-top: 0">printWarn</h4>
<pre>Prints a yellow warning status result <span style="font-family:  'Lucida Console', 'Courier New', Courier, monospace; color: yellow">[ WARN ]</span></pre>
<div>
<h4 class="usage" style="margin-top: 10px">Usage</h4>
<pre style="margin-bottom: 15px">
 printWarn [OPTION]...
</pre>
<h4 class="usage" style="margin-top: 10px">Options</h4>
<pre style="margin-bottom: 15px">
-l     specify log file to write to
-q     quiet mode. Do not output to stdout, only write to log file if supplied
</pre>
</div>
</li>
<li>
<h4 style="margin-top: 0">printInfo</h4>
<pre>Prints a blue info status result <span style="font-family:  'Lucida Console', 'Courier New', Courier, monospace; color: #2E97D7">[ INFO ]</span></pre>
<div>
<h4 class="usage" style="margin-top: 10px">Usage</h4>
<pre style="margin-bottom: 15px">
 printInfo [OPTION]...
</pre>
<h4 class="usage" style="margin-top: 10px">Options</h4>
<pre style="margin-bottom: 15px">
-l     specify log file to write to
-q     quiet mode. Do not output to stdout, only write to log file if supplied
</pre>
</div>
</li>
</ul>
<h2>Example 1</h2>
<p style="margin-top: 10px">Source the bash-beauty.sh file</p>
<pre class="brush: bash; first-line: 1; gutter: true;">. /path/to/bash-beauty.sh</pre>
<p>Execute the printTask function with a description of your task, execute your code, and then execute an appropriate status function: <span style="font-family:  'Lucida Console', 'Courier New', Courier, monospace;">printOk(), printFail(), printWarn(), printInfo()</span></p>
<pre class="brush: bash; first-line: 2; gutter: true;">printTask &quot;Executing arbitrary code&quot;
# your code here
printOk
</pre>
<p>Output</p>
<div class="wp-caption" style="float: left; margin: -15px 0 15px 0">
<img title="bash-beauty #1 example output" src="/img/blog/bash-beauty/bash-beauty-ss4.jpg" alt="bash-beauty #1 example output"/>
</div>
<div style="clear: both"></div>
<h2>Example 2</h2>
<p>If your tasks are commands that print output to stdout/stderr, then you'll probably want to capture their output to keep things looking nice. You may also want to examine each command's result code to determine the appropriate status to print.</p>
<p>This example script attempts to touch file /foo/bar.  If successful, it prints a green status result <span style="font-family:  'Lucida Console', 'Courier New', Courier, monospace; color: green">[  OK  ]</span>.  If unsuccessful, it prints a red failure status result <span style="font-family:  'Lucida Console', 'Courier New', Courier, monospace; color: red">[FAILED]</span>, the error encountered, and exits.</p>
<pre class="brush: bash; first-line: 1; gutter: true;">
#!/bin/bash

# step 1 - source the function library
. ./lib/bash-beauty.sh

# step 2 - use printTask to display the task message
printTask &quot;Attempting to touch /foo/bar&quot;

# step 3 - execute the command,
# redirect command stderr to stdout,
# capture output to variable OUTPUT
OUTPUT=$(touch /foo/bar 2&gt;&amp;1)

# step 4 - examine the command's result code
if [ ! &quot;$?&quot; == 0 ]; then
  printFail &quot;$OUTPUT&quot;
  exit 1
fi
printOk
</pre>
<p>Output</p>
<div class="wp-caption" style="float: left; margin: -15px 0 15px 0">
<img title="bash-beauty example #2 output" src="/img/blog/bash-beauty/bash-beauty-ss5.jpg" alt="bash-beauty example #2 output"/>
</div>
<div style="clear: both"></div>
<h2>Example 3</h2>
<p style="margin-top: 10px">This example script prints to both the terminal and a log file, prefixes each task with a timestamp, and has a custom task message column width.</p>
<pre class="brush: bash; first-line: 1; gutter: true;">
#!/bin/bash

. ./lib/bash-beauty.sh

# set up log file path variable
LOG_FILE=&quot;/tmp/foobar.log&quot;

printTask -t -w 50 -l &quot;$LOG_FILE&quot; &quot;Process running&quot;
sleep 1s    # your code here
printOk -l &quot;$LOG_FILE&quot;

printTask -t -w 50 -l &quot;$LOG_FILE&quot; &quot;Implementing and executing&quot;
sleep 1s
printOk -l &quot;$LOG_FILE&quot;

printTask -t -w 50 -l &quot;$LOG_FILE&quot; &quot;Doing stuff&quot;
sleep 1s
printOk -l &quot;$LOG_FILE&quot;

printTask -t -w 50 -l &quot;$LOG_FILE&quot; &quot;Gittin 'er done&quot;
sleep 1s
printFail -l &quot;$LOG_FILE&quot; &quot;Max hillbilly tolerance level reached&quot;
</pre>
<p>Output to terminal</p>
<div class="wp-caption" style="float: left; margin: -15px 0 15px 0">
<img title="bash-beauty example #2 output" src="/img/blog/bash-beauty/bash-beauty-ss6.jpg" alt="bash-beauty example #3 output"/>
</div>
<div style="clear: both"></div>
<p>Contents of log file at /tmp/foobar.log</p>
<pre class="brush: plain;">
20091114161952  Process running                   [  OK  ]
20091114161953  Implementing and executing        [  OK  ]
20091114161954  Doing stuff                       [  OK  ]
20091114161955  Gittin 'er done                   [FAILED]

Max hillbilly tolerance level reached
</pre>
<h2>Change Log</h2>
<p><strong>0.0.1 - 20091113</strong></p>
<ul>
<li>initial release</li>
</ul>
<div style="margin: 0 auto; text-align: center"><a title="Download" href="/scripts/bash-beauty.sh" target="_blank"><img src="/img/button-dl-orange.png" alt="" width="202" height="62" /></a></div>
<img src="http://www.zulius.com/blog/?ak_action=api_record_view&id=408&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.zulius.com/freebies/bash-beauty-output-for-bash-scripts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setup Postfix with a remote SMTP relay host</title>
		<link>http://www.zulius.com/how-to/set-up-postfix-with-a-remote-smtp-relay-host/</link>
		<comments>http://www.zulius.com/how-to/set-up-postfix-with-a-remote-smtp-relay-host/#comments</comments>
		<pubDate>Thu, 12 Nov 2009 05:59:24 +0000</pubDate>
		<dc:creator>Tim White</dc:creator>
				<category><![CDATA[how-to]]></category>
		<category><![CDATA[postfix]]></category>
		<category><![CDATA[smtp]]></category>

		<guid isPermaLink="false">http://www.zulius.com/wordpress/?p=3</guid>
		<description><![CDATA[p>Platforms: any Linux distro
What You'll Need: Postfix 2.2+ cyrus-sasl 2.1.19+ email account

A typical email scenario: you're a developer, and you've got a development Linux box at home.  You need to be able to send emails from your code or cron jobs, but you're too lazy to set up a full fledged email server on [...]]]></description>
			<content:encoded><![CDATA[<p><div class="wp-caption alignleft" style="width: 159px"><img alt="Postfix config" src="/img/blog/postfixTitleImage.jpg" title="Postfix config" width="149" height="110" /><p class="wp-caption-text">Postfix config</p></div>
<p><strong>Platforms: </strong><br />any Linux distro</p>
<p><strong>What You'll Need:</strong><br /> <a href="http://www.postfix.org">Postfix 2.2+</a><br /> <a href="http://freshmeat.net/projects/cyrussasl/">cyrus-sasl 2.1.19+</a><br /> email account
</p>
<p>A typical email scenario: you're a developer, and you've got a development Linux box at home.  You need to be able to send emails from your code or cron jobs, but you're too lazy to set up a full fledged email server on your LAN.  Or you just want to use your email account provided by your ISP.</p>
<p>Enter the Postfix.</p>
<p>Most Linux distros come with <a href="http://www.sendmail.org/">Sendmail</a> already installed, and is usually the default mail client used by the running services.  However, Postfix <a href="http://www.akadia.com/services/postfix_mta.html" target="_self">beats the crap out of Sendmail</a> and is a complete, seamless replacement.  Here's how I got it going on my CentOS box.</p>
<h2>Install</h2>
<p>Install Postfix and cyrus-sasl with your application manager of choice.  If you're compiling from source, be sure to make Postfix with the -DUSE_SASL_AUTH flag for SASL support and -DUSE_TLS for TLS support.</p>
<pre class="brush: plain;">$ yum install postfix cyrus-sasl</pre>
<p>Stop the sendmail service</p>
<pre class="brush: plain;">$ /etc/init.d/sendmail stop</pre>
<p>Remove sendmail from the startup runlevels</p>
<pre class="brush: plain;">$ chkconfig --del sendmail</pre>
<h2>Typical Setup</h2>
<p>Edit /etc/postfix/main.cf</p>
<pre class="brush: plain;"># Set this to your server's fully qualified domain name.
# If you don't have a internet domain name,
# use the default or your email addy's domain - it'll keep
# postfix from generating warnings all the time in the logs
mydomain = local.domain
myhostname = host.local.domain

# Set this to your email provider's smtp server.
# A lot of ISP's (ie. Cox) block the default port 25
# to prevent spamming.  So we'll use port 80
relayhost = yourisp.smtp.servername:80

smtpd_sasl_auth_enable = yes
smtpd_sasl_path = smtpd
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_type = cyrus
smtp_sasl_auth_enable = yes

# optional: necessary if email provider uses load balancing and
# forwards emails to another smtp server
# for delivery (ie: smtp.yahoo.com --&amp;gt; smtp.phx.1.yahoo.com)
smtp_cname_overrides_servername = no

# optional: necessary if email provider
# requires passwords sent in clear text
smtp_sasl_security_options = noanonymous</pre>
<p>There's roughly a 99.9% chance that your email provider's SMTP server requires authentication.  We need to set that up with the username and password given by your email provider.</p>
<p>Add the following line to /etc/postfix/sasl_passwd</p>
<pre class="brush: plain;"># The server info must exactly match the value
# for &quot;relayhost&quot; in /etc/postfix/main.cf
yourisp.smtp.servername:80 username:password</pre>
<p>Generate a postfix lookup table from the previous file</p>
<pre class="brush: plain;">$ postmap hash:/etc/postfix/sasl_passwd</pre>
<p>Test the lookup table, if all is good then the following will return the specified username:password</p>
<pre class="brush: plain;">$ postmap -q yourisp.smtp.servername:80 /etc/postfix/sasl_passwd</pre>
<p>Get rid of the clear text password file</p>
<pre class="brush: plain;">$ rm /etc/postfix/sasl_passwd</pre>
<p>Add postfix to be started at boot</p>
<pre class="brush: plain;">$ chkconfig --add postfix</pre>
<p>Fire up Postfix</p>
<pre class="brush: plain;">$ /etc/init.d/postfix start</pre>
<p>Test it out using sendmail from the command prompt</p>
<pre class="brush: plain;">$ sendmail email@example.com
Postfix is all up in dis hizzle.
.</pre>
<h2>Gmail Setup</h2>
<p>
If you're attempting to relay mail using Gmail, then it will be necessary to use TLS with Postfix.  You'll have to point Postfix at your server's trusted CA root certificate bundle, but luckily "<a href="http://www.felipe-alfaro.org/blog/2009/05/10/have-postfix-relay-e-mail-to-gmail/">...client-side certificates are not required when relaying mail to GMail</a>".
</p>
<p>First, double-check that Postfix was configured with SSL support (ie. ldd should return at least one line starting with libssl):</p>
<pre class="brush: plain;">$ whereis -b postfix
postfix: /usr/sbin/postfix /etc/postfix /usr/libexec/postfix
$ ldd /usr/sbin/postfix
...
libssl.so.6 =&gt; /lib/libssl.so.6 (0x00111000)
...
</pre>
<p>Now we need to find your server's CA root certificate bundle, which is typically distributed with openssl.  The bundle file is used by Postfix to verify Gmail's SSL certificate (signed by Thawte). On my CentOS server, this file was located at /etc/pki/tls/certs/ca-bundle.crt, but may be in a different location on your box (ie. /etc/ssl/certs).</p>
<pre class="brush: plain;">$ locate ca-bundle.crt
/etc/pki/tls/certs/ca-bundle.crt
</pre>
<p>Edit /etc/postfix/main.cf with the following values:</p>
<pre class="brush: plain;">
relayhost = smtp.gmail.com:587

# your FQDN, or default value below
mydomain = local.domain

# your local machine name, or default value below
myhostname = host.local.domain
myorigin = $myhostname

# SASL
smtpd_sasl_path = smtpd
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_type = cyrus
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous

# TLS
smtp_sasl_tls_security_options = noanonymous
smtp_use_tls  = yes
smtp_tls_CAfile = /path/to/your/ca-bundle.crt
smtp_sasl_tls_security_options = noanonymous
</pre>
<p>If you haven't already, add the following to /etc/postfix/sasl_passwd</p>
<pre class="brush: plain;"># The server info must exactly match the value
# for &quot;relayhost&quot; in /etc/postfix/main.cf
smtp.gmail.com:587 username:password</pre>
<p>Generate a postfix lookup table from the previous file</p>
<pre class="brush: plain;">$ postmap hash:/etc/postfix/sasl_passwd</pre>
<p>Get rid of the clear text password file</p>
<pre class="brush: plain;">$ rm /etc/postfix/sasl_passwd</pre>
<p>Restart postfix and send a test email</p>
<pre class="brush: plain;">$ postfix reload
$ sendmail email@example.com
Test relay thru Gmail
.</pre>
<h2>Troubleshooting</h2>
<p>Monitor postfix mail log in a separate session with the following command</p>
<pre class="brush: plain;">$ tail -f /var/log/maillog</pre>
<p>If the log is displaying the following error</p>
<pre class="brush: plain; toolbar: false;">(Authentication failed: cannot SASL authenticate to server ...: no mechanism available)</pre>
<p>then set this variable in /etc/postfix/main.cf</p>
<pre class="brush: plain;">smtp_sasl_security_options = noanonymous</pre>
<p>If the log is displaying this error</p>
<pre class="brush: plain; toolbar: false;">553 Sorry, that domain isn't in my list of allowed rcpthosts. (in reply to RCPT TO command)</pre>
<p>check your username and password in /etc/postfix/sasl_passwd.  Your user name is usually your full email address.  If you have to fix it, don't forget to use postmap to generate a new lookup table.</p>
<img src="http://www.zulius.com/blog/?ak_action=api_record_view&id=3&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.zulius.com/how-to/set-up-postfix-with-a-remote-smtp-relay-host/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Turn off TortoiseSVN sounds</title>
		<link>http://www.zulius.com/how-to/turn-off-tortoisesvn-sounds/</link>
		<comments>http://www.zulius.com/how-to/turn-off-tortoisesvn-sounds/#comments</comments>
		<pubDate>Tue, 10 Nov 2009 19:00:14 +0000</pubDate>
		<dc:creator>Tim White</dc:creator>
				<category><![CDATA[how-to]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[tortoisesvn]]></category>

		<guid isPermaLink="false">http://www.zulius.com/?p=393</guid>
		<description><![CDATA[p>TortoiseSVN is an excellent Subersion client for Windows.  By default, TortoiseSVN makes noise when it encounters a warning or an error.  This almost made me crap a brick when TortoiseSVN failed on a commit and I forgot I had my speakers cranked to eleven.
TortoiseSVN does not have an internal setting to disable sounds, [...]]]></description>
			<content:encoded><![CDATA[<p><div class="wp-caption alignleft" style="width: 160px"><img alt="Noise on a commit failure" src="/img/blog/tortoiseSvnSound/error.jpg" title="Noise on a commit failure" width="150" height="110" /><p class="wp-caption-text">Noise on a commit failure</p></div>
<p><a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a> is an excellent <a href="http://subversion.tigris.org/">Subersion</a> client for Windows.  By default, TortoiseSVN makes noise when it encounters a warning or an error.  This almost made me crap a brick when TortoiseSVN failed on a commit and I forgot I had my speakers cranked to eleven.</p>
<p>TortoiseSVN does not have an internal setting to disable sounds, so we'll have to manually disable it's noise in the Windows control panel:</p>
<ol>
<li>Right click anywhere, select TortoiseSVN > Settings > General Menu > Click "Configure" button next to System Sounds.  Or go to Start > Control Panel > Sounds and Audio Devices > Sounds Tab.
<p style="padding: 15px 0 0 0"><img class="alignnone" src="/img/blog/tortoiseSvnSound/tortoisesvn-settings.jpg" alt="TortoiseSVN settings" /></p>
</li>
<li>Look in the “Program Events” box for TortoiseSVN:
<p style="padding: 15px 0 0 0"><img class="alignnone" src="/img/blog/tortoiseSvnSound/sounds.jpg" alt="Sounds and Audio Device Properties" /></p>
</li>
<li>Click on each of TortoiseSVN's events, and select "(None)" from the <strong>Sounds</strong> dropdown.</li>
<li>Click OK.</li>
</ol>
<img src="http://www.zulius.com/blog/?ak_action=api_record_view&id=393&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.zulius.com/how-to/turn-off-tortoisesvn-sounds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Skip .svn directories when using grep</title>
		<link>http://www.zulius.com/how-to/grep-skip-svn-directories/</link>
		<comments>http://www.zulius.com/how-to/grep-skip-svn-directories/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 20:56:08 +0000</pubDate>
		<dc:creator>Tim White</dc:creator>
				<category><![CDATA[how-to]]></category>
		<category><![CDATA[grep]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://www.zulius.com/?p=383</guid>
		<description><![CDATA[What You'll Need: grep 2.5.3+

I can't count how many times a day I use grep.  It is an indispensable tool for searching the contents of configuration files, data files, and source code.
One of the annoying side effects of grep is when searching a Subversion working copy recursively, all the hidden .svn directories also get [...]]]></description>
			<content:encoded><![CDATA[<div class="wp-caption alignleft" style="width: 158px"><img alt="grep returns .svn metadata" src="/img/blog/title-image-grepSkipSvn.jpg" title="grep returns .svn metadata" width="148" height="110" /><p class="wp-caption-text">grep returns .svn metadata files</p></div>
<p><strong>What You'll Need:</strong><br /> <a href="http://www.gnu.org/software/grep/">grep 2.5.3+</a>
</p>
<p>I can't count how many times a day I use grep.  It is an indispensable tool for searching the contents of configuration files, data files, and source code.</p>
<p>One of the annoying side effects of grep is when searching a Subversion working copy recursively, all the hidden .svn directories also get searched.  This can yield a lot of false positive matches since these directories contain <a href="http://svn.collab.net/repos/svn/trunk/doc/user/svn-best-practices.html">"pristine copies of all version-controlled files"</a>.</p>
<p>If you've got grep 2.5.3 or higher, it's easy to ignore .svn directories with the "--exclude-dir" option:</p>
<pre class="brush: plain;">$ grep -r --exclude-dir='.svn' 'my search string' /some/directory</pre>
<p>But that's a lot to type in each time you want to search your source code.  To save keystrokes, try setting up an alias in your home directory's .bashrc file that utilizes the --exclude-dir option (for Mac, use your home directory's .profile file.).  I call mine <strong>devgrep</strong>:</p>
<pre class="brush: plain;">alias devgrep=&quot;grep --exclude-dir='.svn'&quot;</pre>
<p>After adding the alias, don't forget to source your .bashrc:</p>
<pre class="brush: plain;">$ source ~/.bashrc</pre>
<p>Now whenever you need to search a Subversion working copy recursively, use the new alias to skip .svn directories:</p>
<pre class="brush: plain;">$ devgrep -rin 'doctype' /var/www/html/templates
./foo.tpl:1:&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;&gt;
./bar.tpl:1:&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
./baz.phtml:1:&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Frameset//EN&quot; &quot;http://www.w3.org/TR/html4/frameset.dtd&quot;&gt;</pre>
<p>You can also exclude file types when grep'ing.  If you're a vim user, it can be helpful to skip .swp files in your alias:</p>
<pre class="brush: plain;">alias devgrep=&quot;grep --exclude-dir='.svn' --exclude='*.swp'&quot;</pre>
<p>Yet another workaround would be to use <a href="http://betterthangrep.com/">ack</a> - a Perl based, juiced up version of grep with a lot more features.</p>
<img src="http://www.zulius.com/blog/?ak_action=api_record_view&id=383&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.zulius.com/how-to/grep-skip-svn-directories/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>svnbak.pl: perl Subversion repository backup script</title>
		<link>http://www.zulius.com/freebies/perl-script-backup-subversion-repositories/</link>
		<comments>http://www.zulius.com/freebies/perl-script-backup-subversion-repositories/#comments</comments>
		<pubDate>Mon, 12 Jan 2009 05:49:34 +0000</pubDate>
		<dc:creator>Tim White</dc:creator>
				<category><![CDATA[freebies]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[subversion]]></category>

		<guid isPermaLink="false">http://www.zulius.com/blog/?p=167</guid>
		<description><![CDATA[
jQuery(document).ready(function(){jQuery("a[rel='colorbox']").colorbox();});


What is it?

A Perl cron script that creates and rotates backups of one or more Subversion repositories.

What does it do?

Verifies repositories (svnadmin verify)
Hot copies -or- dumps repositories (uses svnadmin hotcopy -or- svnadmin dump)
Archives all repositories to a single tar file
Gzips tar file
Backup rotation

Other Features

Email notifications
Nice output
Free

Requirements
Operating System: *nix
Perl (5.8.5 or higher)
Subversion
tar
gzip

Proc::Reliable
MIME::Lite
Math::Round
Configure
At the top of svnbak.pl [...]]]></description>
			<content:encoded><![CDATA[<div style="margin: 0 auto; text-align: center"><a title="Download" href="http://www.zulius.com/scripts/svnbak.pl-0.0.7.tar.gz" target="_blank"><img src="/img/button-dl-orange.png" alt="" /></a></div>
<div style="float: right; padding: 0 5px; margin: 25px 0 0 0;">
<div class="wp-caption alignright" style="width: 160px"><a href="/img/blog/svnbak.pl/fullsize-ss.png" rel="colorbox"><img title="svnbak.pl executing" src="/img/blog/svnbak.pl/svnbak-titleImage.jpg" alt="svnbak.pl executing" width="150" height="110" /></a><p class="wp-caption-text">svnbak.pl executing</p></div><br />
<script type="text/javascript">jQuery(document).ready(function(){jQuery("a[rel='colorbox']").colorbox();});</script>
</div>
<div style="float: none"></div>
<h2>What is it?</h2>
<p>
A Perl cron script that creates and rotates backups of one or more Subversion repositories.
</p>
<h2>What does it do?</h2>
<ol>
<li>Verifies repositories (<a title="svnadmin verify" href="http://svnbook.red-bean.com/en/1.1/re41.html">svnadmin verify</a>)</li>
<li>Hot copies -or- dumps repositories (uses <a title="svnadmin hotcopy" href="http://svnbook.red-bean.com/en/1.0/re33.html">svnadmin hotcopy</a> -or- <a title="svnadmin dump" href="http://svnbook.red-bean.com/en/1.1/re31.html">svnadmin dump</a>)</li>
<li>Archives all repositories to a single tar file</li>
<li>Gzips tar file</li>
<li>Backup rotation</li>
</ol>
<h2>Other Features</h2>
<ul>
<li>Email notifications</li>
<li>Nice output</li>
<li>Free</li>
</ul>
<h2>Requirements</h2>
<p style="padding-left: 30px;">Operating System: *nix<br />
<a title="Perl" href="http://www.perl.org" target="_blank">Perl</a> (5.8.5 or higher)<br />
<a title="Subversion" href="http://subversion.tigris.org/">Subversion</a><br />
<a title="tar" href="http://www.gnu.org/software/tar/" target="_blank">tar</a><br />
<a title="gzip" href="http://www.gzip.org/" target="_blank">gzip</a>
</p>
<p style="padding-left: 30px;"><a title="Proc::Reliable" href="http://search.cpan.org/~dgold/Proc-Reliable-1.16/Reliable.pm" target="_blank">Proc::Reliable</a><br />
<a title="MIME::Lite" href="http://search.cpan.org/~rjbs/MIME-Lite-3.023/lib/MIME/Lite.pm" target="_blank">MIME::Lite</a><br />
<a title="Math::Round" href="http://search.cpan.org/~grommel/Math-Round-0.05/" target="_blank">Math::Round</a></p>
<h2>Configure</h2>
<div class="wp-caption aligncenter" style="width: 589px"><img style="border: 3px solid #000000;" title="Configuration Section" src="/img/blog/svnbak.pl/ss2.png" alt="svnbak.pl: Configuration Section" width="579" height="207" /><p class="wp-caption-text">svnbak.pl Configuration Section</p></div>
<p>At the top of svnbak.pl is a "Configuration Section" that you must add specific information to in order for the script to work.</p>
<ul>
<li><strong>reposDir</strong>: full path to your Subversion repository, or the parent directory of all your repositories.</li>
<li><strong>destDir</strong>: full path to the directory where the backups should be saved.  To save backups to a network file system, first mount the file system, then specify the mounted path.</li>
<li><strong>maxBaks</strong>: maximum number of backups to retain.  Once this limit is reached, the script will automatically remove the oldest backup based on it's last modified time.</li>
<li><strong>svnBakMethod:</strong> type of Subversion backup to create ('<a title="svnadmin hotcopy" href="http://svnbook.red-bean.com/en/1.0/re33.html">hotcopy</a>' or '<a title="svnadmin dump" href="http://svnbook.red-bean.com/en/1.1/re31.html">dump</a>').</li>
<li><strong>tarballName</strong>: the name of the backup file.  Each backup file will be appended with a 14 digit time stamp to preserve <span>singularity.</span></li>
<li><span><strong>tmpDir</strong>: full path to a <strong>new </strong>temporary directory to store files before tarballing.  This directory should not be an existing directory - it will be deleted!</span></li>
<li><strong>emailPref</strong>: when the admin should receive emails ('always', 'errors', 'none').</li>
<li><strong>displayTime</strong>: display execution time in seconds, per task.</li>
</ul>
<p style="text-align: center;">
<div style="margin: 0 auto; text-align: center"><a title="Download" href="http://www.zulius.com/scripts/svnbak.pl-0.0.7.tar.gz" target="_blank"><img src="/img/button-dl-orange.png" alt="" /></a></div>
<h2>Change Log</h2>
<p><strong>0.0.7 - 20100209</strong></p>
<ul>
<li>fixed failure of external commands running longer than 60 seconds</li>
</ul>
<p><strong>0.0.6 - 20091116</strong></p>
<ul>
<li>fixed fatal error when backing up a single repository</li>
<li>destination directory is created if it does not already exist</li>
<li>changed elapsed time format: 'seconds' -> 's'</li>
</ul>
<p><strong>0.0.5 - 20090326</strong></p>
<ul>
<li>added backup option of dumping repositories via svnadmin dump</li>
<li>increased error checking</li>
<li>fixed: some repositories skipped when there was a large number of repositories</li>
</ul>
<p><strong>0.0.1 - 20090108</strong></p>
<ul>
<li>initial release<strong><br />
</strong></li>
</ul>
<img src="http://www.zulius.com/blog/?ak_action=api_record_view&id=167&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.zulius.com/freebies/perl-script-backup-subversion-repositories/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fix Wordpress Editor on a Free GoDaddy Hosted Site</title>
		<link>http://www.zulius.com/how-to/fix-wordpress-editor-on-a-free-godaddy-hosted-site/</link>
		<comments>http://www.zulius.com/how-to/fix-wordpress-editor-on-a-free-godaddy-hosted-site/#comments</comments>
		<pubDate>Sun, 23 Nov 2008 01:26:56 +0000</pubDate>
		<dc:creator>Tim White</dc:creator>
				<category><![CDATA[how-to]]></category>
		<category><![CDATA[godaddy]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.zulius.com/blog/?p=107</guid>
		<description><![CDATA[Did you register a domain name with GoDaddy? Did you use the "free hosting credit" to setup your website's hosting?  Having problems getting the visual editor to work on your new Wordpress blog?  Then join the club - GoDaddy's infamous injected ads break the Javascript code that makes the TinyMCE visual editor work. [...]]]></description>
			<content:encoded><![CDATA[<p>Did you register a domain name with GoDaddy? Did you use the "free hosting credit" to setup your website's hosting?  Having problems getting the visual editor to work on your new Wordpress blog?  Then join the club - GoDaddy's infamous injected ads break the Javascript code that makes the TinyMCE visual editor work.  Luckily, it's fixable, and here's how.</p>
<h2>The Symptoms</h2>
<p>There are quite a few things that can cause the Wordpress WYSIWYG editor to break.  Using GoDaddy's free hosting service is certainly one of them.  A couple ways that you can tell you're experiencing the "GoDaddy" problem:</p>
<p style="padding-left: 30px;">1.  On the "Write Post" page, the post toolbar looks like this:</p>
<p style="padding-left: 0px;"><img class="alignnone" src="/img/blog/tinyMCE/brokenToolbar.png" alt="broken visual editor" /></p>
<p style="padding-left: 60px;">Instead of this:</p>
<p style="padding-left: 0px;"><img class="alignnone" src="/img/blog/tinyMCE/workingToolbar.png" alt="working visual editor" /></p>
<p style="padding-left: 30px;">2.  After browsing to the "Write Post" page in Firefox, open the error console by going to Tools &gt; Error Console.  This will is displayed:</p>
<p style="padding-left: 0px;"><img class="alignnone" src="/img/blog/tinyMCE/jsError.png" alt="" /></p>
<p style="padding-left: 30px;">
<p style="padding-left: 30px;">3.  Clicking the "HTML" button does nothing.</p>
<h2>The Fix</h2>
<p>Correcting this error involves a slight edit to one of the core Wordpress PHP files, namely "script-loader.php".  Please do so at your own risk.  This fix has been tested on Wordpress 2.6.3 with IE7 and Firefox 3.</p>
<h4 style="padding-left: 30px;">Step 1</h4>
<p style="padding-left: 60px;">Fire up your FTP client and FTP into the website you've got hosted on GoDaddy's server.  I used <a title="FireFTP" href="http://fireftp.mozdev.org/" target="_blank">FireFTP</a> in this example.  From here on, we'll assume that Wordpress is installed in the "/blog" directory.</p>
<h4 style="padding-left: 30px;">Step 2</h4>
<p style="padding-left: 60px;">We've got to get the TinyMCE Javascript code from the Javascript cache on the server.  Browse to the "/blog/wp-content/uploads/js_cache" directory in your FTP client.</p>
<p style="padding-left: 0px;"><img class="alignnone" src="/img/blog/tinyMCE/gzJsFile.png" alt="gzipped TinyMCE" /></p>
<p style="padding-left: 60px;">Look for a file named like this:</p>
<p style="padding-left: 90px;"><strong>tinymce_(a bunch of numbers and letters).gz</strong></p>
<p style="padding-left: 60px;">Download it.  Extract the contents of the file (you can use <a title="WinRar" href="http://www.rarlab.com/" target="_self">WinRar</a>, <a title="winzip" href="http://www.winzip.com/" target="_self">Winzip</a>, or <a title="7-Zip" href="http://www.7-zip.org/" target="_self">7-Zip</a>).  Rename the extracted javascript file from:</p>
<p style="padding-left: 90px;"><strong>tinymce_(a bunch of numbers and letters)</strong></p>
<p style="padding-left: 60px;">to:</p>
<p style="padding-left: 90px;"><strong>tinymce_fixed.js </strong></p>
<p style="padding-left: 0px;">Upload tinymce_fixed.js to the "/blog/wp-content/uploads/js_cache" directory on the GoDaddy server.</p>
<p style="padding-left: 0px;"><img class="alignnone" src="/img/blog/tinyMCE/fixedJsFile.png" alt="TinyMCE javascript" /></p>
<p style="padding-left: 60px;"><strong><i>Note:</i></strong> If the file "tinymce_(a bunch of numbers and letters)<strong>.gz</strong>" doesn't exist on the GoDaddy server, but a file named "tinymce_(a bunch of numbers and letters)<strong>.js</strong>" does, then rename the <strong>.js</strong> file  to "tinymce_fixed.js" without the quotes.  No downloading or extracting is required.</p>
<p style="padding-left: 60px;">If the js_cache directory doesn't exist, then either Wordpress doesn't have write permission to the wp-content folder, or you haven't opened the "Write Post" page yet.</p>
<h4 style="padding-left: 30px;">Step 3</h4>
<p style="padding-left: 60px;">In your FTP client, download the file "/blog/wp-includes/script-loader.php".</p>
<p style="padding-left: 0px;"><img class="alignnone" title="script-loader.php" src="/img/blog/tinyMCE/scriptLoader.png" alt="" /></p>
<p style="padding-left: 60px;">Open script-loader.php in your favorite editor, and comment out line 41.  Beneath that, insert the following new line of code:</p>
<div style="margin: 0 0 0 00px">
<pre class="brush: php; toolbar: false;">$scripts-&gt;add( 'tiny_mce', '/wp-content/uploads/js_cache/tinymce_fixed.js', array('editor_functions'), $mce_version );</pre>
</div>
<p style="padding-left: 60px;">The code should now look like this:</p>
<pre class="brush: php; first-line: 41; gutter: true; toolbar: false;">
//$scripts-&gt;add( 'tiny_mce', '/wp-includes/js/tinymce/tiny_mce_config.php', array('editor_functions'), $mce_version );
$scripts-&gt;add( 'tiny_mce', '/wp-content/uploads/js_cache/tinymce_fixed.js', array('editor_functions'), $mce_version );
</pre>
<p style="padding-left: 60px;">Upload and replace the script-loader.php file on the GoDaddy server.  You should then be good to go.  Also, make sure the "Use the visual editor when writing" option is enabled on your Wordpress profile page.</p>
<h2>Notes</h2>
<p style="padding-left: 30px;">Please be aware that if you upgrade Wordpress, you'll have to repeat this process to get the visual editor working again.  Same thing if you re-configure TinyMCE's settings in any way.</p>
<h2>Conclusion</h2>
<p style="padding-left: 30px;">GoDaddy's free hosting service places an ad at the top of your content using injected Javascript.  This seems to happen regardless of the response content-type headers when a PHP page is requested.</p>
<img src="http://www.zulius.com/blog/?ak_action=api_record_view&id=107&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.zulius.com/how-to/fix-wordpress-editor-on-a-free-godaddy-hosted-site/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
