<?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>Jason Hardy &#187; Programming</title>
	<atom:link href="http://blog.uta.edu/jthardy/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.uta.edu/jthardy</link>
	<description>Personal blog of Jason Hardy</description>
	<lastBuildDate>Wed, 13 Apr 2011 13:34:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Obtaining user information from LDAP using Perl</title>
		<link>http://blog.uta.edu/jthardy/2007/09/14/obtaining-user-information-from-ldap-using-perl/</link>
		<comments>http://blog.uta.edu/jthardy/2007/09/14/obtaining-user-information-from-ldap-using-perl/#comments</comments>
		<pubDate>Fri, 14 Sep 2007 17:29:45 +0000</pubDate>
		<dc:creator>Jason Hardy</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://blog.uta.edu/jthardy/2007/09/14/obtaining-user-information-from-ldap-using-perl/</guid>
		<description><![CDATA[This is much simpler that the PHP example listed a few weeks ago. It demonstrates some of the advantages of Perl (namely, just about anything you want to do is already built as a module by someone who&#8217;s been where you are). Please refer to http://search.cpan.org for Net::LDAP and Net::LDAPS module documentation and usage examples.
In [...]]]></description>
			<content:encoded><![CDATA[<p>This is much simpler that the PHP example listed a few weeks ago. It demonstrates some of the advantages of Perl (namely, just about anything you want to do is already built as a module by someone who&#8217;s been where you are). Please refer to <a href="http://search.cpan.org/">http://search.cpan.org</a> for Net::LDAP and Net::LDAPS module documentation and usage examples.</p>
<p>In this example, we&#8217;ll bind to the LDAP server using an application account (in the cn=applications,dc=uta,dc=edu branch of our directory server) and search the account branch (cn=accounts,dc=uta,dc=edu) for all users (uid=*). We&#8217;ll fetch the NetIDs (uid), e-mail addresses (mail), and the common names (cn) for each account.</p>
<pre>#!/usr/bin/perl -w

use strict;
use Net::LDAPS;
use Data::Dumper;

my $bind_dn       = 'cn=mavapp,cn=applications,dc=uta,dc=edu';
my $bind_password = 'mavAppPass';
my $ldaps         = Net::LDAPS-&gt;new('ldap.cedar.uta.edu');
my $mesg          = $ldaps-&gt;bind( $bind_dn, password =&gt; $bind_password );

my $result  = $ldaps-&gt;search(base =&gt; "cn=accounts,dc=uta,dc=edu",
                                            filter =&gt; "(uid=*)",
                                            attrs =&gt; ['uid','mail','cn'] );

my $entries = $result-&gt;as_struct();

# How many entries did we find?
print scalar $entries . " entries returned\n";

# Print them out
foreach my $dn ( keys %{$entries} ) {
   foreach my $attr ( keys %{$entries-&gt;{$dn}} ) {
      foreach my $val ( @{$entries-&gt;{$dn}-&gt;{$attr}} ) {
         print "$attr - $val\n";
      }
   }
   print "\n";
}</pre>
<p>This last section could be simplified using the Data::Dumper module as:</p>
<pre>
print Dumper( $entries );</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.uta.edu/jthardy/2007/09/14/obtaining-user-information-from-ldap-using-perl/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>My code&#8217;s compiling, leave me alone.</title>
		<link>http://blog.uta.edu/jthardy/2007/08/23/my-codes-compiling-leave-me-alone/</link>
		<comments>http://blog.uta.edu/jthardy/2007/08/23/my-codes-compiling-leave-me-alone/#comments</comments>
		<pubDate>Thu, 23 Aug 2007 21:25:26 +0000</pubDate>
		<dc:creator>Jason Hardy</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://blog.uta.edu/jthardy/2007/08/23/my-codes-compiling-leave-me-alone/</guid>
		<description><![CDATA[
This, in no way, represents the complete professionalism exemplified by our employees during the exceedingly brief interludes while waiting on a compiler.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://xkcd.com/303/"><img src="http://imgs.xkcd.com/comics/compiling.png" height="360" width="413" /><span id="more-23"></span></a><br />
This, in no way, represents the complete professionalism exemplified by our employees during the exceedingly brief interludes while waiting on a compiler.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.uta.edu/jthardy/2007/08/23/my-codes-compiling-leave-me-alone/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Obtaining user information from LDAP using PHP</title>
		<link>http://blog.uta.edu/jthardy/2007/08/08/obtaining-user-information-from-ldap-using-php/</link>
		<comments>http://blog.uta.edu/jthardy/2007/08/08/obtaining-user-information-from-ldap-using-php/#comments</comments>
		<pubDate>Thu, 09 Aug 2007 03:24:09 +0000</pubDate>
		<dc:creator>Jason Hardy</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://blog.uta.edu/jthardy/2007/08/08/obtaining-user-information-from-ldap-using-php/</guid>
		<description><![CDATA[This ought to be in a FAQ somewhere, I certainly get asked it enough: &#8220;How can I retrieve attributes from LDAP of users who log into my web application?&#8221; Well, I&#8217;ll break it down with an example that retrieves information about a user that submits their uid &#38; password to a form. Note that this [...]]]></description>
			<content:encoded><![CDATA[<p>This ought to be in a FAQ somewhere, I certainly get asked it enough: &#8220;How can I retrieve attributes from LDAP of users who log into my web application?&#8221; Well, I&#8217;ll break it down with an example that retrieves information about a user that submits their uid &amp; password to a form. Note that this code could be simplified to handle authentication only by determining if the ldap_bind() succeeds or not &#8212; it&#8217;s usually enough to simply be able to bind to verify someones identity.</p>
<p>I&#8217;ll make my comments after each section of code.<span id="more-17"></span></p>
<pre>&lt;?php
# specify the location of our directory server and
# attempt to establish a connection (note we're not binding yet)

$ds = ldap_connect("ldaps://ldap.example.edu");</pre>
<p>You&#8217;ve got to know the location of your directory (LDAP) server and the method that your administrator allows you to connect (ldaps or ldap). I&#8217;m using the PHP <a href="http://us.php.net/manual/en/function.ldap-connect.php">ldap_connect()</a> function to make the connection. The ldap_connect() function can take a URI for your directory server. It returns an LDAP link identifier on success or <strong><tt>FALSE</tt></strong> on error.</p>
<pre>if ( $ds ) {
   # form the LDAP distinguished name (DN) that we'll bind
   # with from the POST variables $uid and $password

   $uid = $_POST['uid'];
   $password = $_POST['password'];
   $userdn = "uid=$uid,cn=accounts,dc=example,dc=edu";</pre>
<p>I&#8217;m assuming a couple of things in the preceding code: (1) the page that you&#8217;re coding is called from another that passes POST variables, and (2) that the POST variables are called &#8216;uid&#8217; for the userid and &#8216;password&#8217; for the password. We&#8217;ll form the RDN from the &#8216;uid&#8217; and the base for our account tree in LDAP. (Note: It wouldn&#8217;t make any sense to call this page using GET variables &#8212; otherwise your password would have been encoded in the URL. You&#8217;ll also want to ensure that your POST variables are defined <em>before</em> you process any of this code.)</p>
<pre>   # attept to bind to the directory server

   $result = ldap_bind( $ds, $userdn, $password );</pre>
<p>Binding to the directory server is easy using the <a href="http://us.php.net/manual/en/function.ldap-bind.php">ldap_bind()</a> function. You reference the link identifier from the ldap_connect() function and the userdn and password variables stored from the POST. ldap_bind() returns <strong><tt>TRUE</tt></strong> on success or <strong><tt>FALSE</tt></strong> on failure.</p>
<pre>   # search the accounts branch for the entry (uid=$uid) and
   # save the results in an array called $accounts_searchResult

   $accounts_searchResult = ldap_search( $ds, "cn=accounts,dc=example,dc=edu", "uid=$uid" );</pre>
<p>The <a href="http://us.php.net/manual/en/function.ldap-search.php">ldap_search()</a> function does the hard work of searching the directory and returning a data structure with your results. There are many options you can pass to ldap_search(), but only three are required &#8212; the ldap link identifier from your ldap_connect() function, a search base (where to look), and a filter (what to look for).</p>
<pre>   # the elements of the searchResult array are ldap entries. Grab the
   # first entry off the array and examine it

   $entry = ldap_first_entry( $ds, $accounts_searchResult );</pre>
<p>The <a href="http://us.php.net/manual/en/function.ldap-first-entry.php">ldap_first_entry()</a> function will return the first entry (go figure) from the data structure returned by our previous call to ldap_search(). The first entry should be the only one we care about since we were searching for a specific user. If you were trying to search for all users, say you were developing a page that displayed a telephone directory, then you&#8217;d want to investigate into the <a href="http://us.php.net/manual/en/function.ldap-next-entry.php">ldap_next_entry()</a> function, which would &#8212; like it says &#8212; fetch the next entry from the result of your search. Both functions return an entry identifier on success and <strong><tt>FALSE</tt></strong> on error.</p>
<pre>   while ( $entry ) {
      # let's find the DN for this specific entry

      $dn = ldap_get_dn( $ds, $entry );

      echo "dn: $dn&lt;br&gt;n";</pre>
<p>The very first thing this example prints out is the LDAP DN (distinguished name) of the entry. This is useful, as it is the key into your directory for the username that we searched for. The <a href="http://us.php.net/manual/en/function.ldap-get-dn.php">ldap_get_dn()</a> function returns a string containing the DN of the entry or <strong><tt>FALSE</tt></strong> on error. Now let&#8217;s print out the results of the query. I&#8217;m going to use nested HTML unordered lists for the display &#8212; if you can&#8217;t follow along, just remove the &lt;ul&gt; and &lt;li&gt; tags from your code and it will display the same information (only not as fancy).</p>
<pre>
      # let's examine all of the attributes associated with this entry

      $attrs = ldap_get_attributes( $ds, $entry );</pre>
<p>The <a href="http://us.php.net/manual/en/function.ldap-get-attributes.php">ldap_get_attributes()</a> function will return an array of all of our attribute names ( the descriptive name assigned to each piece of information in the entry &#8212; like uid, displayname, mail, etc). Next we loop through each of the attributes and display their values. The following bit of code is a bit convoluted and will probably only make sense if you think of the entry as a two-dimensional array.</p>
<pre>
      echo "&lt;ul&gt;";</pre>
<pre>      for ( $i = 0; $i &lt; $attrs['count']; $i++ ) {
         # the array $attrs will use the attribute name (a string) as the
         # subscript notation. Ex: $attrs[displayname] = 'john doe'

         echo "&lt;li&gt;$attrs[$i]n";

         # some attributes can be multivalued
         # (ie: affliation can be either student, staff, or both student and staff)
         # the value of the attributes is stored in the second dimension of the
         # $attr array: $arrt['attribute_name'][0 .. N] = ( value0, value1, ... valueN )

         echo "&lt;ul&gt;n";

         for ( $j = 0; $j &lt; $attrs[$attrs[$i]]['count']; $j++ ) {
            # print out all of the attributes
            echo "&lt;li&gt;" . $attrs[$attrs[$i]][$j] . "&lt;/li&gt;";
         }

         echo "&lt;/ul&gt;&lt;/li&gt;n";

      }

      echo "&lt;/ul&gt;";</pre>
<p>Phew, we&#8217;re done with that. You did follow it all, didn&#8217;t you? In a nutshell, PHP can reference arrays using keys instead of just plain old integers (like some languages do). So you can reference $attrs['displayname'] to return an array of the values associated with &#8216;displayname&#8217;. To actually see the values we index into the second dimension of the array &#8212; $attrs['displayname'][$index], where $index is a value between 0 and the number of &#8216;displayname&#8217;s.</p>
<pre>      # if there are more entries in the search result, show the next one</pre>
<pre>
      $entry = ldap_next_entry( $ds, $entry );
}</pre>
<p>We&#8217;ve previously discussed the ldap_next_entry() function. What this line of code does is grab a new $entry before the while() loop repeats itself. As previously discussed, ldap_next_entry() will return <strong><tt>FALSE</tt></strong> on error meaning that we&#8217;ll drop out of the while() loop when we reach the last entry.</p>
<pre>   ldap_free_result( $accounts_searchResult );
   ldap_unbind( $ds );
}
?&gt;</pre>
<p>We close with some housecleaning functions. The <a href="http://us.php.net/manual/en/function.ldap-free-result.php">ldap_free_result()</a> function will free up the memory we&#8217;d allocated to holding the search result. Note that all result memory will be automatically freed when the script terminates. If your script isn&#8217;t ending here, calling ldap_free_result() is a good idea as it will keep runtime memory usage low &#8212; and your sysadmin happy. The <a href="http://us.php.net/manual/en/function.ldap-unbind.php">ldap_unbind()</a> function unbinds from the directory server &#8212; and keeps your directory server administrator happy too.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.uta.edu/jthardy/2007/08/08/obtaining-user-information-from-ldap-using-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Have your (Perl) Pie and eat it too!</title>
		<link>http://blog.uta.edu/jthardy/2007/08/02/perl-pie/</link>
		<comments>http://blog.uta.edu/jthardy/2007/08/02/perl-pie/#comments</comments>
		<pubDate>Thu, 02 Aug 2007 13:44:25 +0000</pubDate>
		<dc:creator>Jason Hardy</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://blog.uta.edu/jthardy/2007/08/02/perl-pie/</guid>
		<description><![CDATA[Undoubtedly one of the most frequent tasks a system administrator, or developer, faces involves making inline changes to a file or set of files. This can range from the very complex edit to the very trivial.
Let&#8217;s say you have a series of PHP pages in your web site that access your MySQL server. What happens [...]]]></description>
			<content:encoded><![CDATA[<p>Undoubtedly one of the most frequent tasks a system administrator, or developer, faces involves making inline changes to a file or set of files. This can range from the very complex edit to the very trivial.</p>
<p>Let&#8217;s say you have a series of PHP pages in your web site that access your MySQL server. What happens if you need to change the name of your MySQL server? Would you go into each file individually, search for the line (or lines) of code to edit and save the file? This can be tedious, error-prone and time consuming.</p>
<p>The &#8217;sed&#8217; (string editor) command is often used to accomplish this, where sed is passed a file name and a <a href="http://en.wikipedia.org/wiki/Regular_expression" title="Regular Expression">regular expression</a> for the string substitutions. Output from sed is sent to standard output (usually the terminal) which means that you must redirect it to another file and then copy the new file over the original. This effectively changes the original but requires a lot of excess steps. There&#8217;s got to be a better way, right? Yes, &#8216;perl&#8217; can do it in one shot  &#8211;<span id="more-9"></span></p>
<blockquote>
<h3>SysAdmin Mantra</h3>
<p>A good sysadmin is a lazy sysadmin.</p></blockquote>
<h4>Enter &#8216;Perl Pie&#8217;</h4>
<p>I forget who first introduced me to the concept of &#8216;perl -p -i -e&#8217; (or &#8216;perl -pi -e&#8217;). This has become such a mainstay of my practice that I often mention it to people assuming that everyone knows of such things. Basically, &#8216;Perl Pie&#8217; is a one-line perl program that does inline edits to your file given a regular expression (preserving file ownership and permissions &#8212; a topic that I didn&#8217;t discuss in the &#8217;sed&#8217; example above).  The syntax should look familiar to anyone who&#8217;s used &#8217;sed&#8217; or regular expressions.</p>
<pre>
perl -p -i -e 's/original text string/replacement string' foo</pre>
<p>Note: perl uses the same regex syntax as sed, making this an easy concept to remember</p>
<h3>But Wait, I&#8217;ve got a ton of files to edit</h3>
<p>There are numerous ways to accomplish editing multiple files, but they all share some basic principals:</p>
<ol>
<li>Find a list of files matching your change criteria</li>
<li>With each file, apply the &#8216;Perl Pie&#8217;</li>
</ol>
<p>Most GNU/Linux sysadmins are familiar with the Bash shell. Here&#8217;s a simple example that changes all of those PHP pages we talked about earlier. This example also involves the &#8216;find&#8217; and &#8216;grep&#8217; commands:</p>
<pre>
$ for filename in $( find . -type f -name '*.php' -exec grep -q '$db=OLDMYSQLSERVER' '{}' ';' -print );
do
   perl -p -i -e 's/$db=OLDMYSQLSERVER/$db=NEWMYSQLSERVER/g' $filename
done</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.uta.edu/jthardy/2007/08/02/perl-pie/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
