<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>$coderfoo</title>
    <link rel="alternate" type="text/html" href="http://www.coderfoo.com/blog/" />
    <link rel="self" type="application/atom+xml" href="http://www.coderfoo.com/blog/atom.xml" />
    <id>tag:www.coderfoo.com,2009-07-07:/blog//1</id>
    <updated>2009-11-04T18:45:31Z</updated>
    <subtitle>code samples and one-liners</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.261</generator>

<entry>
    <title>YUI DataTable: Context Menu with &quot;Select/Unselect All&quot; rows</title>
    <link rel="alternate" type="text/html" href="http://www.coderfoo.com/blog/2009/11/yui-datatable-context-menu-with-selectunselect-all-rows.html" />
    <id>tag:www.coderfoo.com,2009:/blog//1.9</id>

    <published>2009-11-02T18:06:20Z</published>
    <updated>2009-11-04T18:45:31Z</updated>

    <summary><![CDATA[This is an&nbsp;example of YUI DataTable that uses Context Menu options to select/unselect rows.&nbsp; Also, the rowClickEvent listener&nbsp;has a muli-select/unselect function attached.&nbsp; Follow the link below to see the example. http://www.coderfoo.com/examples/datatable-multi-row-select.html DataTable selectAllRows extension:// Extend YUI DataTable which is missing...]]></summary>
    <author>
        <name>Andy</name>
        
    </author>
    
        <category term="Web" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="YUI" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-US" xml:base="http://www.coderfoo.com/blog/">
        <![CDATA[<p>This is an&nbsp;example of YUI DataTable that uses Context Menu options to select/unselect rows.&nbsp; Also, the rowClickEvent listener&nbsp;has a muli-select/unselect function attached.&nbsp; Follow the link below to see the example.</p>
<p><u><font color="#810081"><a href="http://www.coderfoo.com/examples/datatable-multi-row-select.html">http://www.coderfoo.com/examples/datatable-multi-row-select.html</a></font></u></p>
<p>DataTable selectAllRows extension:</p><pre class="brush:jscript">// Extend YUI DataTable which is missing a selectAllRows method
YAHOO.lang.augmentObject(
  YAHOO.widget.DataTable.prototype, {

    _selectAllTrEls : function() {
      var selectedRowsEven = YAHOO.util.Dom.getElementsByClassName(YAHOO.widget.DataTable.CLASS_EVEN, "tr",this._elTbody);
      YAHOO.util.Dom.addClass( selectedRowsEven , YAHOO.widget.DataTable.CLASS_SELECTED);

      var selectedRowsOdd = YAHOO.util.Dom.getElementsByClassName(YAHOO.widget.DataTable.CLASS_ODD, "tr",this._elTbody);
      YAHOO.util.Dom.addClass( selectedRowsOdd, YAHOO.widget.DataTable.CLASS_SELECTED);
    },

  /* Selects all rows. * * @method selectAllRows */
  selectAllRows : function() {
    // Remove all rows from tracker
    var tracker = this._aSelections || [];
    for(var j=tracker.length- 1; j&gt;-1; j--) {
      if(YAHOO.lang.isString( tracker[j] )){
        tracker.splice( j,1);
      }
    }
    // Update tracker
    this._aSelections = tracker;
    // Update UI
    this._selectAllTrEls();
    // Get all highlighted rows and make yahoo aware they are selected
    var selectedRowsEven = YAHOO.util.Dom.getElementsByClassName(YAHOO.widget.DataTable.CLASS_SELECTED, "tr",this._elTbody);
    for (i=0;i&lt;selectedRowsEven.length; i++){
      this.selectRow(i);
    }
  }
});
// End YUI Datatable extension
</pre>]]>
        
    </content>
</entry>

<entry>
    <title>Web monitor using Perl and curl</title>
    <link rel="alternate" type="text/html" href="http://www.coderfoo.com/blog/2009/09/site-monitor-using-perl-and-curl.html" />
    <id>tag:www.coderfoo.com,2009:/blog//1.8</id>

    <published>2009-09-30T16:20:18Z</published>
    <updated>2009-11-04T18:52:54Z</updated>

    <summary><![CDATA[Monitoring your website or webapp for issues is crucial.&nbsp; There are many options available, both open source and vendor.&nbsp; In the past I've used Nagios, which works great.&nbsp; As with any "end all be all" infrastructure monitoring software, Nagios is...]]></summary>
    <author>
        <name>Andy</name>
        
    </author>
    
        <category term="General Administration" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Web" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-US" xml:base="http://www.coderfoo.com/blog/">
        <![CDATA[<p>Monitoring your website or webapp for issues is crucial.&nbsp; There are many options available, both open source and vendor.&nbsp; In the past I've used Nagios, which works great.&nbsp; As with any "end all be all" infrastructure monitoring software, Nagios is not exactly a quick easy install and&nbsp;configuration.&nbsp; However if you have the time I do recommend&nbsp;using Nagios.&nbsp; When properly setup and configured, it makes life&nbsp;*much* easier as a Sys Admin.&nbsp; And you don't have to worry about a user, or worse,&nbsp;management finding the problem first.</p>
<p>The alternative to monitoring software is good ol' fashioned scripts via cron.&nbsp; When time and&nbsp;resources don't allow, scripts work great if done right.&nbsp; For this post, I'm sharing a Perl script which uses libcurl via WWW::Curl to monitor a web application and will send an email alert if there is a problem.&nbsp; Initially I had used Net::HTTP to issue a simple HTTP request and parse the resulting HTTP code.&nbsp; This works fine, but what if I need to login to the site first?&nbsp; Curl&nbsp;is basically a command line&nbsp;web browser so it&nbsp;will allow you to login to a site, store cookies, follow redirects, etc.&nbsp; This script uses a config file for it's&nbsp;options.&nbsp; I tried just plain command-line switches at first, but it started getting messy and I'd like to support all of libcurl's options.&nbsp; That being said, the hardest part&nbsp;of using this script is figuring out which of the&nbsp;libcurl options you need and how they work together.&nbsp; If you're familiar with the curl command, most of the switches directly map to the <a href="http://curl.haxx.se/libcurl/c/libcurl-easy.html">libcurl-easy interface</a>&nbsp;options.&nbsp; </p>
<p>On to some of the specifics.&nbsp; Here are the prerequisites for the script:</p>
<ul>
<li>Linux/UNIX</li>
<li>Perl</li>
<li>curl</li>
<li>Getopt::Long</li>
<li>Mail::Sendmail</li>
<li>HTTP::Status</li>
<li>WWW::Curl</li>
<li>Config::General</li></ul>
<p>The general logic of the script is as follows:</p>
<p>READ config<br />SET curl options<br />PERFORM curl request<br />PARSE result<br />CHECK http code<br />&nbsp;&nbsp;ALERT IF http error code<br />&nbsp;&nbsp;ALERT IF unexpected http code<br />&nbsp;&nbsp;ALERT IF&nbsp;timeout reached<br />DONE</p>
<p>If no HTTP codes are specified in the config file the defaults will be used.&nbsp; That is, an error code is anything greater than or equal to&nbsp;400 and unexpected codes&nbsp;are any other than 200 and less than 400.&nbsp; See <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">here</a> for specifics on&nbsp;status codes.&nbsp; </p>
<p>The configuration options are case insensitive so feel free to use whatever case you like for readability.&nbsp; Below is an example configuration.&nbsp; Using these settings will simply hit the URL and send an alert email if there is a problem.</p><pre class="brush:plain"># ---------------------------------------------------------------------------
# monitor-site.pl Config File
# ---------------------------------------------------------------------------

# General settings
repeat = 1        # Only repeat the alert once
threshhold = 3600 # Only alert an hour later after the initial alert
timeout = 600     # Alert if the request takes longer than 10 seconds

# Alert email options
&lt;alert&gt;
  # Required
  To = andy@coderfoo.com

  # Optional
  From = admin@coderfoo.com
  Subject = "Critical Issue!" 

  # Define HTTP Code alerts. Any code not defined here will be "unexpected"
  Error = 400-417,500-505
  Ok = 200
&lt;/alert&gt;

# Libcurl options, all are supported
&lt;curlopts&gt;
  # Required
  CURLOPT_URL = http://www.coderfoo.com

  # Optional (See the libcurl docs for options)
&lt;/curlopts&gt;
</pre>
<p>Note that the only required options are "to" within the &lt;alert&gt; block and "curlopt_url" in the &lt;curlopts&gt; block.&nbsp; If&nbsp;the "repeat" and/or "threshhold" options are used,&nbsp;a hidden file called .monitor will be created to track the results of the last run.</p>
<p>Here is&nbsp;a link to&nbsp;a tar-gz of the&nbsp;monitor:</p>
<p><a href="http://www.coderfoo.com/source/monitor-site.tar.gz">http://www.coderfoo.com/source/monitor-site.tar.gz</a></p>
<p>See the README file in this package for information on installation and running the script.</p>]]>
        
    </content>
</entry>

<entry>
    <title>YUI TreeView: Drag and Drop nodes</title>
    <link rel="alternate" type="text/html" href="http://www.coderfoo.com/blog/2009/07/yui-treeview-with-drag-and-drop-nodes.html" />
    <id>tag:www.coderfoo.com,2009:/blog//1.7</id>

    <published>2009-07-22T00:58:34Z</published>
    <updated>2009-11-04T18:46:28Z</updated>

    <summary><![CDATA[I recently had a need for a YUI (Yahoo! User Interface) TreeView with Drag &amp; Drop nodes. &nbsp;Here's a little background on the project. &nbsp;My web application uses YUI Menu for navigation and is driven by a single database table....]]></summary>
    <author>
        <name>Andy</name>
        
    </author>
    
        <category term="Web" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="YUI" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-US" xml:base="http://www.coderfoo.com/blog/">
        <![CDATA[I recently had a need for a YUI (Yahoo! User Interface) TreeView with Drag &amp; Drop nodes. &nbsp;Here's a little background on the project. &nbsp;My web application uses YUI Menu for navigation and is driven by a single database table. &nbsp;Initially I threw together a quick and dirty CGI CRUD interface to manage the menu. &nbsp;But, the more I had to modify the menu with this interface the more I needed something easier to use. &nbsp;So I decided to scrap the CGI interface and start over with a nice 100% Ajax interface with a YUI TreeView to represent the YUI Menu. &nbsp;Adding, changing, and deleting nodes is pretty easy, but to easily change the order of the Menu items, I added YUI Drag &amp; Drop to the TreeView. &nbsp; 
<div><br /></div>
<div>
<div>The example I created is essentially a merge of two YUI examples with some tweaks. &nbsp;The base code I used for this example is the <a href="http://developer.yahoo.com/yui/examples/treeview/default_tree.html">Default TreeView</a>&nbsp;example. &nbsp;For my web app, the TreeView is dynamically loaded. &nbsp;Either way, drag and drop will work. &nbsp;The <a href="http://developer.yahoo.com/yui/examples/dragdrop/dd-reorder.html">Reordering a list</a> example was the best fit for my needs so it is used for drag and drop.</div>
<div><br /></div>
<div>Here is the onDragOver function with tweaks to allow for dragging a nested node over it's parent without <i>too</i> much quirkiness:</div><pre class="brush:jscript">  onDragOver: function(e, id) {
    var srcEl = this.getEl();
    var destEl = Dom.get(id);

    // We are only concerned with menu items, we ignore the dragover
    // notifications for anything else.
    if (destEl.id.match(/^ygtv[0-9]+$/)) {
      var orig_p = srcEl.parentNode;
      var p = destEl.parentNode;
      var destIdx = destEl.id.match(/[0-9]+$/);
      var destTreeNode = oTextNodeMap['ygtvlabelel' + destIdx];

      // Ignore any parent that is expanded
      // If !expanded
      if (! destTreeNode.expanded) {
        if (this.goingUp) {
          p.insertBefore(srcEl, destEl); // insert above
          lastDestId = destEl.id;
        } 
        else {
          p.insertBefore(srcEl, destEl.nextSibling); // insert below
          lastDestId = destEl.id;
        }
      }

      DDM.refreshCache();
    }
  }
</pre>
<div>The finished example of the TreeView with Drag &amp; Drop: 
<div><br /></div>
<div><a href="http://www.coderfoo.com/examples/treeview-dragdrop.html">http://www.coderfoo.com/examples/treeview-dragdrop.html</a></div></div></div>]]>
        
    </content>
</entry>

<entry>
    <title>Resolving Subversion merge conflicts </title>
    <link rel="alternate" type="text/html" href="http://www.coderfoo.com/blog/2009/07/easily-resolving-subversion-merge-conflicts.html" />
    <id>tag:www.coderfoo.com,2009:/blog//1.6</id>

    <published>2009-07-14T20:25:03Z</published>
    <updated>2009-07-24T13:58:34Z</updated>

    <summary><![CDATA[Merging an entire branch back into the trunk can be a pain.&nbsp; I've found that if you only want to keep the changes made to the branch then the following steps should help. Using svnmerge.py makes the whole process a...]]></summary>
    <author>
        <name>Andy</name>
        
    </author>
    
        <category term="General Development" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Subversion" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-US" xml:base="http://www.coderfoo.com/blog/">
        <![CDATA[<div>Merging an entire branch back into the trunk can be a pain.&nbsp; I've found that if you only want to keep the changes made to the branch then the following steps should help. Using svnmerge.py makes the whole process a bit easier by automatically tracking revision number ranges.&nbsp; Information on svnmerge.py can be found
here:&nbsp; <a href="http://www.orcaware.com/svn/wiki/Svnmerge.py">http://www.orcaware.com/svn/wiki/Svnmerge.py</a><br /><br />Here are the steps: <br /><br /></div><ol><li>Begin by following the steps for merging the branch here (assumes you are using svnmerge.py):<br /><a href="http://www.orcaware.com/svn/wiki/Svnmerge.py#Merging_development_branches_back_to_trunk">http://www.orcaware.com/svn/wiki/Svnmerge.py#Merging_development_branches_back_to_trunk</a> <br /><br /></li><li>Handle conflicts. If the branch is up-to-date, simply copy the latest revision file to the conflicted file.&nbsp;<div><br /></div><div>Example: Let's say the latest revision is 100 and after merging a branch to the trunk, conflicts are present. The following shell one-liner will automatically resolve the conflicts, but only if the branch version is authoritative. If the trunk version has features not yet added to the branch version, you must manually resolve the conflict.&nbsp;</div><div><br /></div><div style="border: 3px solid rgb(119, 119, 119); padding: 3px; font-family: courier; background-color: rgb(0, 0, 0); color: rgb(255, 255, 255);">prompt:~# for a in *.r100; do b=`perl -e 'print split /\.merge-right.r100/, shift;' $a`; echo "copying $a $b"; cp $a $b; svn resolved $b; echo; done</div><br />If this makes you nervous you can always consult the manual: <a href="http://svnbook.red-bean.com/en/1.5/svn.tour.cycle.html#svn.tour.cycle.resolve">http://svnbook.red-bean.com/en/1.5/svn.tour.cycle.html#svn.tour.cycle.resolve</a><br /><br /></li><li>Commit the merge: svn ci -F svnmerge-commit-message.txt</li></ol>Your branch should now be successfully merged into the trunk!<br /><div></div>]]>
        
    </content>
</entry>

<entry>
    <title>Dynamically build SQL statements for Perl DBI</title>
    <link rel="alternate" type="text/html" href="http://www.coderfoo.com/blog/2009/07/dynamically-build-sql-statements-for-dbi.html" />
    <id>tag:www.coderfoo.com,2009:/blog//1.5</id>

    <published>2009-07-09T15:50:54Z</published>
    <updated>2009-11-10T16:41:13Z</updated>

    <summary><![CDATA[I like to use join and map in order to cut down on too much static code and to simplify building SQL statements to pass to DBI.&nbsp; Ideally, some sort of database abstraction should be used, but it is not...]]></summary>
    <author>
        <name>Andy</name>
        
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-US" xml:base="http://www.coderfoo.com/blog/">
        <![CDATA[I like to use join and map in order to cut down on too much static code and to simplify building SQL statements to pass to DBI.&nbsp; Ideally, some sort of database abstraction should be used, but it is not always an option.<br /><br />Below is an example block of code that handles a CGI form submission with an action of "Add" or "Update".&nbsp; The SQL is built according to the action and passed to a single prepare and execute.<br /><pre class="brush:perl">my $sql;
my @fields = qw(field1 field2 field3 field4 field5);
my @bind_values;
if ($input-&gt;{action} eq "Add") {
  $sql =
  "INSERT INTO datatable (" .
    join(", ", @fields) .
  ") VALUES (" .
    join(", ", map {"?"} @fields) .
  ")";
  map {push @bind_values, $input-&gt;{$_} } @fields;
}
elsif ($input-&gt;{action} eq "Update") {
  $sql =
    "UPDATE datatable SET " .
      join(", ", map {"$_ = ?"} @fields) .
    " WHERE primarykey = ?";
  map { push @bind_values, $input-&gt;{$_} } @fields;
  push @bind_values, $input-&gt;{primarykey};
}

if (length $sql) {
  my $sth = $dbh-&gt;prepare($sql);
  $sth-&gt;execute(@bind_values);
}
</pre>]]>
        
    </content>
</entry>

<entry>
    <title>Recursively find files containing carriage returns</title>
    <link rel="alternate" type="text/html" href="http://www.coderfoo.com/blog/2009/07/find-files-with-a-specific-character-recursively.html" />
    <id>tag:www.coderfoo.com,2009:/blog//1.3</id>

    <published>2009-07-07T14:42:46Z</published>
    <updated>2009-11-10T16:42:48Z</updated>

    <summary><![CDATA[This is a "one-liner" that I use sometimes to find files that contain carriage returns.&nbsp; Some files containing carriage returns were committed to a Subversion repository that I manage. These files caused the diff to be corrupt when diffing against...]]></summary>
    <author>
        <name>Andy</name>
        
    </author>
    
        <category term="General Administration" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="One-liners" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-US" xml:base="http://www.coderfoo.com/blog/">
        <![CDATA[This is a "one-liner" that I use sometimes to find files that contain carriage returns.&nbsp; Some files containing carriage returns were committed to a Subversion repository that I manage. These files caused the diff to be corrupt when diffing against a file without the \r.&nbsp; Not a huge issue, but annoying.<br /><br />This command basically uses a for loop with find to recursively list all files starting from the current directory.&nbsp; In the loop, each file is dumped into a small Perl one-liner that checks each line for a \r and increments a counter.&nbsp; The grep at the end filters out all files with a zero count.&nbsp; You could change \r to anything you want to find.<br /><br />
<div style="BORDER-RIGHT: rgb(119,119,119) 3px solid; PADDING-RIGHT: 3px; BORDER-TOP: rgb(119,119,119) 3px solid; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; BORDER-LEFT: rgb(119,119,119) 3px solid; COLOR: rgb(255,255,255); PADDING-TOP: 3px; BORDER-BOTTOM: rgb(119,119,119) 3px solid; FONT-FAMILY: courier; BACKGROUND-COLOR: rgb(0,0,0)">prompt:~# for a in `find . -type f`; do echo -n "$a: "; perl -e 'my $cr = 0; while (&lt;STDIN&gt;){ $cr += tr/\r//; } print $cr;' &lt; $a; echo; done | grep -v '0$'</div><br />This produces a list of files with a count of characters found.<br /><br />
<div style="BORDER-RIGHT: rgb(119,119,119) 3px solid; PADDING-RIGHT: 3px; BORDER-TOP: rgb(119,119,119) 3px solid; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; BORDER-LEFT: rgb(119,119,119) 3px solid; COLOR: rgb(255,255,255); PADDING-TOP: 3px; BORDER-BOTTOM: rgb(119,119,119) 3px solid; FONT-FAMILY: courier; BACKGROUND-COLOR: rgb(0,0,0)">./someapp.cgi: 36<br />./anotherapp.cgi: 41<br />./somedir/yetanother.cgi: 199<br /></div>]]>
        
    </content>
</entry>

<entry>
    <title>Welcome</title>
    <link rel="alternate" type="text/html" href="http://www.coderfoo.com/blog/2009/07/welcome.html" />
    <id>tag:www.coderfoo.com,2009:/blog//1.2</id>

    <published>2009-07-07T02:28:51Z</published>
    <updated>2009-07-23T12:46:46Z</updated>

    <summary><![CDATA[Welcome to my new blog coderfoo.com. &nbsp;My intention is to publish tips and code that I've found to make my life easier as a LAMP Developer, Linux/UNIX SA, and MySQL DBA.&nbsp; Hopefully these posts will help you too.Stay tuned. 743vidxfw6...]]></summary>
    <author>
        <name>Andy</name>
        
    </author>
    
    
    <content type="html" xml:lang="en-US" xml:base="http://www.coderfoo.com/blog/">
        <![CDATA[Welcome to my new blog coderfoo.com. &nbsp;My intention is to publish tips and code that I've found to make my life easier as a LAMP Developer, Linux/UNIX SA, and MySQL DBA.&nbsp; Hopefully these posts will help you too.<br /><div><br /></div><div>Stay tuned.</div><div><br /></div>

743vidxfw6]]>
        
    </content>
</entry>

</feed>
