<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6427421974690377954</id><updated>2012-03-17T02:02:12.428-04:00</updated><category term='linux'/><category term='account lockout'/><category term='xml'/><category term='smimecapabilities'/><category term='attachment'/><category term='aes'/><category term='openbsd'/><category term='emacs'/><category term='primary key'/><category term='java'/><category term='web'/><category term='security'/><category term='thawte'/><category term='perl'/><category term='malware'/><category term='syslog'/><category term='nagios'/><category term='pf'/><category term='tomcat'/><category term='data dictionary'/><category term='bash'/><category term='curl'/><category term='kde'/><category term='oracle'/><category term='time'/><category term='webstart'/><category term='slackware'/><category term='encryption'/><category term='thinkpad'/><category term='algebra'/><category term='nullity'/><category term='taiwan'/><category term='realm'/><category term='md2'/><category term='sql'/><category term='shell'/><category term='s/mime'/><category term='pkcs12'/><category term='windows'/><category term='email'/><category term='valve'/><category term='network'/><category term='code'/><category term='thunderbird'/><category term='crypto'/><category term='google'/><category term='kmail'/><title type='text'>Shade Grown Code</title><subtitle type='html'>Discoveries and thoughts about code.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>31</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-2720145234336171892</id><published>2011-02-04T13:50:00.003-05:00</published><updated>2011-02-04T14:45:18.816-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='syslog'/><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><title type='text'></title><content type='html'>As a follow up to &lt;a href="http://remcojansen.posterous.com/2009/11/how-to-send-tomcats-access-log-to.html"&gt;Remco's How to set up Tomcat logging to Syslog&lt;/a&gt;, I am including my own version of a class that enables Tomcat logging  to Syslog. This class overrides the standard AccessLogValve and logs messages via Log4J API to category &lt;span style="font-family: courier new;"&gt;accesslog&lt;/span&gt;, level &lt;span style="font-family: courier new;"&gt;INFO&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;To compile this class, you will need catalina.jar and servlet-api.jar in your CLASSPATH.&lt;br /&gt;&lt;br /&gt;To configure Tomcat to use this class, edit your conf/server.xml and replace className in the access logging Valve with com.ofc.tomcat.Log4JAccessLogValve. Then, in lib/log4j.properties, configure appenders for category &lt;span style="font-family: courier new;"&gt;accesslog&lt;/span&gt; (property &lt;span style="font-family: courier new;"&gt;log4j.logger.accesslog&lt;/span&gt;)&lt;br /&gt;&lt;pre class="netbeans"&gt;&lt;br /&gt;&lt;span class="keyword-directive"&gt;package&lt;/span&gt; com.ofc.tomcat;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt; * &lt;/span&gt;&lt;span class="comment"&gt;Redirects&lt;/span&gt; &lt;span class="comment"&gt;AccessLogValve&lt;/span&gt; &lt;span class="comment"&gt;logging&lt;/span&gt; &lt;span class="comment"&gt;to&lt;/span&gt; &lt;span class="comment"&gt;Log4J&lt;/span&gt; &lt;span class="comment"&gt;category&lt;/span&gt;&lt;span class="comment"&gt; &amp;quot;&lt;/span&gt;&lt;span class="comment"&gt;accesslog&lt;/span&gt;&lt;span class="comment"&gt;&amp;quot; &lt;/span&gt;&lt;span class="comment"&gt;level&lt;/span&gt; &lt;span class="comment"&gt;info&lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt; * &lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt; * &lt;/span&gt;&lt;span class="ST0"&gt;@author&lt;/span&gt; &lt;span class="comment"&gt;Nicholas&lt;/span&gt; &lt;span class="comment"&gt;Sushkin&lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt; * &lt;/span&gt;&lt;span class="ST0"&gt;@version&lt;/span&gt; &lt;span class="comment"&gt;$Revision&lt;/span&gt;&lt;span class="comment"&gt;: 1&lt;/span&gt;&lt;span class="comment"&gt;.&lt;/span&gt;&lt;span class="comment"&gt;2 &lt;/span&gt;&lt;span class="comment"&gt;$&lt;/span&gt; &lt;span class="comment"&gt;$Date&lt;/span&gt;&lt;span class="comment"&gt;: 2011/02/04 18:45:36 &lt;/span&gt;&lt;span class="comment"&gt;$&lt;/span&gt;&lt;br /&gt; &lt;span class="comment"&gt;*/&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword-directive"&gt;public&lt;/span&gt; &lt;span class="keyword-directive"&gt;class&lt;/span&gt; Log4JAccessLogValve &lt;span class="keyword-directive"&gt;extends&lt;/span&gt; org.apache.catalina.valves.AccessLogValve&lt;br /&gt;{&lt;br /&gt;   &lt;span class="comment"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt;    * &lt;/span&gt;&lt;span class="comment"&gt;The&lt;/span&gt; &lt;span class="comment"&gt;descriptive&lt;/span&gt; &lt;span class="comment"&gt;information&lt;/span&gt; &lt;span class="comment"&gt;about&lt;/span&gt; &lt;span class="comment"&gt;this&lt;/span&gt; &lt;span class="comment"&gt;implementation&lt;/span&gt;&lt;span class="comment"&gt;.&lt;/span&gt;&lt;br /&gt;    &lt;span class="comment"&gt;*/&lt;/span&gt;&lt;br /&gt;    &lt;span class="keyword-directive"&gt;protected&lt;/span&gt; &lt;span class="keyword-directive"&gt;static&lt;/span&gt; &lt;span class="keyword-directive"&gt;final&lt;/span&gt; String info1 =&lt;br /&gt;        &lt;span class="character"&gt;&amp;quot;&lt;/span&gt;&lt;span class="character"&gt;com.ofc.tomcat.Log4JAccessLogValve/1.0&lt;/span&gt;&lt;span class="character"&gt;&amp;quot;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;span class="keyword-directive"&gt;private&lt;/span&gt; &lt;span class="keyword-directive"&gt;static&lt;/span&gt; &lt;span class="keyword-directive"&gt;final&lt;/span&gt; org.apache.log4j.Logger log = &lt;br /&gt;            org.apache.log4j.LogManager.getLogger(&lt;span class="character"&gt;&amp;quot;&lt;/span&gt;&lt;span class="character"&gt;accesslog&lt;/span&gt;&lt;span class="character"&gt;&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    &lt;span class="keyword-directive"&gt;public&lt;/span&gt; &lt;span class="keyword-directive"&gt;void&lt;/span&gt; log(String message)&lt;br /&gt;    {&lt;br /&gt;        log.info(message);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    &lt;span class="keyword-directive"&gt;public&lt;/span&gt; String getInfo()&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="keyword-directive"&gt;return&lt;/span&gt; info1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    &lt;span class="keyword-directive"&gt;protected&lt;/span&gt; &lt;span class="keyword-directive"&gt;void&lt;/span&gt; open()&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-2720145234336171892?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/2720145234336171892/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=2720145234336171892' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/2720145234336171892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/2720145234336171892'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2011/02/as-follow-up-to-remcos-how-to-set-up.html' title=''/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-8581906246326864050</id><published>2010-03-21T22:35:00.009-04:00</published><updated>2010-03-21T22:59:57.471-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pf'/><category scheme='http://www.blogger.com/atom/ns#' term='network'/><category scheme='http://www.blogger.com/atom/ns#' term='openbsd'/><title type='text'>Troubleshooting tftp-proxy in OpenBSD pf</title><content type='html'>Finally figured out OpenBSD firewall configuration in which internal hosts can access TFTP servers on the internet. In OpenBSD pf firewall, you need to configure tftp-proxy. Google search returns a lot of complaints about tftp-proxy not working and not a single success story. I now believe there is a typo in the official manual.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.openbsd.org/faq/pf/ftp.html#tftp-proxy"&gt;OpenBSD FAQ for TFTP proxy&lt;/a&gt; specifies the following redirect rule to redirect outgoing tftp connections to the internal tftp-proxy.&lt;br /&gt;&lt;blockquote  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;rdr pass log on $int_if proto udp from &lt;span style="font-weight: bold;"&gt;$int_if&lt;/span&gt; to port tftp -&gt; 127.0.0.1  port 6969&lt;/span&gt;&lt;/blockquote&gt;However, according to "&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;pfctl -g -s nat|grep tftp&lt;/span&gt;&lt;/span&gt;", my pf expands the rule above to the following.&lt;br /&gt;&lt;blockquote&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;rdr pass log on xl0 inet proto udp from &lt;span style="font-weight: bold;"&gt;192.168.2.1&lt;/span&gt; to any port = tftp -&gt; 127.0.0.1 port 6969&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;It's clear that the expanded rule will will not redirect traffic coming from all of the internal hosts. The rule needs to be changed to&lt;br /&gt;&lt;blockquote  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;rdr pass log on $int_if proto udp from &lt;span style="font-weight: bold;"&gt;$int_net&lt;/span&gt; to any port tftp -&gt; 127.0.0.1 port 6969&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;which expands to&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;rdr pass log on xl0 inet proto udp from &lt;span style="font-weight: bold;"&gt;192.168.2.0/24&lt;/span&gt; to any port = tftp -&gt; 127.0.0.1 port 6969&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;The latter covers the whole internal network instead of just one host 192.168.2.1.&lt;tt&gt;&lt;br /&gt;&lt;/tt&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-8581906246326864050?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/8581906246326864050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=8581906246326864050' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/8581906246326864050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/8581906246326864050'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2010/03/troubleshooting-tftp-proxy-in-openbsd.html' title='Troubleshooting tftp-proxy in OpenBSD pf'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-3044116948398223727</id><published>2010-02-25T21:10:00.003-05:00</published><updated>2010-02-25T21:24:40.480-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='webstart'/><category scheme='http://www.blogger.com/atom/ns#' term='s/mime'/><category scheme='http://www.blogger.com/atom/ns#' term='pkcs12'/><title type='text'>Importing S/MIME certificate into Java</title><content type='html'>Although it is now possible to import a certificate in p12 format, into java, just any S/MIME certificate will not work to sign jars.&lt;br /&gt;&lt;br /&gt;Thawte used to give out free S/MIME certificates and when imported into Java, those certificates could sign java code. I recently tried to import a Comodo S/MIME certificate into a Java keystore and sign a jar. While I managed to export my S/MIME certificate from Firefox in .p12 format and import .p12 keystore into a Java keystore, signing with this certificate generated a warning &lt;span style="font-family: courier new;"&gt;"The signer certificate's ExtendedKeyUsage extension doesn't allow code signing."&lt;/span&gt; Also, Web Start failed to validate the signed jar, generating an exception in com.sun.deploy.security.CertUtils in the following code&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size:85%;"&gt; // Require either all of bits 5,6,7 are false or&lt;br /&gt; // that at least bit 7 be true&lt;br /&gt;if ((getNetscapeCertTypeBit(cert, NSCT_SSL_CA) != false ||&lt;br /&gt;     getNetscapeCertTypeBit(cert, NSCT_S_MIME_CA) != false ||&lt;br /&gt;     getNetscapeCertTypeBit(cert, NSCT_OBJECT_SIGNING_CA) != false) &amp;amp;&amp;amp;&lt;br /&gt;     getNetscapeCertTypeBit(cert, NSCT_OBJECT_SIGNING_CA) == false)&lt;br /&gt;{&lt;br /&gt;  Trace.msgSecurityPrintln("trustdecider.check.basicconstraints.bitvalue");&lt;br /&gt;  return false;&lt;br /&gt;}&lt;/span&gt;&lt;/blockquote&gt;To get my S/MIME certificate from Java, I used Firefox Certificate backup as p12, then the following command to find the alias of my certificate inside the .p12 keystore:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size:85%;"&gt;keytool -list -keystore comodo-nsushkin\@openfinance.com-exp20120930.p12  -storetype PKCS12&lt;/span&gt;&lt;/blockquote&gt;Once I found out the alias "&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;nicholas sushkin's the usertrust network id #3&lt;/span&gt;&lt;/span&gt;", I imported my S/MIME private key and certificate from p12 file into my JKS keystore under alias "&lt;span style="font-family: courier new;"&gt;nsushkin&lt;/span&gt;" using the following command:&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size:85%;"&gt;keytool -importkeystore -deststorepass changeit -destkeypass changeit -destkeystore java-certs.keystore -srckeystore comodo-nsushkin\@openfinance.com-exp20120930.p12 -srcstoretype PKCS12 -alias "nicholas sushkin's the usertrust network id #3" -destalias nsushkin&lt;/span&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-3044116948398223727?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/3044116948398223727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=3044116948398223727' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3044116948398223727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3044116948398223727'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2010/02/importing-smime-certificate-into-java.html' title='Importing S/MIME certificate into Java'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-4553491252034449185</id><published>2009-11-14T17:19:00.005-05:00</published><updated>2009-11-14T18:45:10.566-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='slackware'/><category scheme='http://www.blogger.com/atom/ns#' term='thinkpad'/><title type='text'>Fixing broken sound in flash plugin in Slackware 13.0</title><content type='html'>I upgraded my laptop to Slackware 13.0. In general, hardware support has improved. All hardware was detected automatically by HAL and UDEV. That includes formerly problematic Synaptic touchpad, both monitors attached via DVI and VGA, and Logitech Quickcam. I only needed minor adjustments to get dual screen out of the mirroring mode.&lt;br /&gt;&lt;br /&gt;One of the minor problems was that &lt;span style="font-weight: bold;"&gt;flash plugin in Mozilla wouldn't play sound&lt;/span&gt;. That was despite that my username being a member of the group "audio". It turned out that if you had more than one sound device, Flash would only output sound to the first configured device (alsa card #0). When I booted the laptop with webcam attached through USB, the snd-usb-audio module loaded before snd-hda-intel, resulting in the first configured audio device (webcam) not supporting any audio output.&lt;br /&gt;&lt;br /&gt;The workaround would be to always boot with the webcam unplugged. However, a better solution is to hint the device loading system (udev) that the built-in intel sound device needs to be loaded first. Google found me a solution in a Slackware forum at linuxquestions.org. Add a file in /etc/modprobe.d containing the following instruction: "&lt;span style="font-weight: bold;font-family:courier new;" &gt;options snd slots=snd-hda-intel,snd-usb-audio&lt;/span&gt;". You can check the mapping of sound card slots to modules using "cat /proc/asound/modules"&lt;br /&gt;&lt;br /&gt;References: &lt;a href="http://slackware.com/"&gt;Slackware&lt;/a&gt;, &lt;a href="http://j.mp/se7jh"&gt;Where Alsa looks for default sound card&lt;/a&gt;, &lt;a href="http://en.gentoo-wiki.com/wiki/Synaptics_Touchpad/Xorg_7.3#Configuration"&gt;Synaptics Touchpad with HAL&lt;/a&gt;, &lt;a href="http://www.thinkwiki.org/wiki/Xorg_RandR_1.2"&gt;Dual-screen with xrandr&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-4553491252034449185?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/4553491252034449185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=4553491252034449185' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/4553491252034449185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/4553491252034449185'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2009/11/fixing-broken-sound-in-flash-plugin-in.html' title='Fixing broken sound in flash plugin in Slackware 13.0'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-5249309561051711816</id><published>2009-11-12T16:46:00.003-05:00</published><updated>2009-11-12T16:58:20.359-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='email'/><category scheme='http://www.blogger.com/atom/ns#' term='attachment'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Command line email with attachments</title><content type='html'>This is a perl script which can be used as a replacement for "mail" program, but supporting email attachments.&lt;br /&gt;&lt;pre class="htmlize"&gt;&lt;br /&gt;&lt;span class="comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="comment"&gt;!/usr/bin/perl -w&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="comment"&gt;****h* common/send_files&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;NAME&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;send_files - sends an email with multiple file attachments&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;FUNCTION&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;Uses sendmail to send an email with attachments. Takes message text&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;from the standard input.&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;PARAMETERS&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;--from    - From email address&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;--to      - To email address&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;--subject - Email subject&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;--file    - Attach a file (use multiple times to attach multiple files)&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="comment"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;All the unprocessed options are treated as files to be attached&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="comment"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;EXAMPLE&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;echo "Look here" | send_files --from from@example.com --to to@example.com \&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#                                 &lt;/span&gt;&lt;span class="comment"&gt;--subject "Files" --file /tmp/1.txt --file /tmp/2.txt&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="comment"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;echo "Specify files last" | send_files --from from@example.com --to to@example.com \&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#                                          &lt;/span&gt;&lt;span class="comment"&gt;--subject "Files" --file /tmp/*.txt&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;HISTORY&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;$Header: send_files.pl,v 1.6 2008/04/08 20:53:13 nsushkin Exp $&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;SOURCE&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="comment"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="keyword"&gt;use&lt;/span&gt; &lt;span class="constant"&gt;MIME&lt;/span&gt;::Lite;&lt;br /&gt;&lt;span class="keyword"&gt;use&lt;/span&gt; &lt;span class="constant"&gt;MIME&lt;/span&gt;::Types;&lt;br /&gt;&lt;span class="keyword"&gt;use&lt;/span&gt; &lt;span class="constant"&gt;Getopt&lt;/span&gt;::Long;&lt;br /&gt;&lt;br /&gt;&lt;span class="type"&gt;my&lt;/span&gt; ($&lt;span class="variable-name"&gt;opt_from&lt;/span&gt;, $&lt;span class="variable-name"&gt;opt_to&lt;/span&gt;, $&lt;span class="variable-name"&gt;opt_subject&lt;/span&gt;) = (&lt;span class="string"&gt;""&lt;/span&gt;, &lt;span class="string"&gt;""&lt;/span&gt;, &lt;span class="string"&gt;""&lt;/span&gt;);&lt;br /&gt;&lt;span class="type"&gt;my&lt;/span&gt; @&lt;span class="underline"&gt;&lt;span class="variable-name"&gt;files&lt;/span&gt;&lt;/span&gt; = ();&lt;br /&gt;&lt;span class="type"&gt;my&lt;/span&gt; $&lt;span class="variable-name"&gt;VERSION&lt;/span&gt; = sprintf(&lt;span class="string"&gt;"%d.%03d"&lt;/span&gt;, q&lt;span class="string"&gt;$Revision: 1.6 $&lt;/span&gt; =~ &lt;span class="string"&gt;/(\d+)\.(\d+)/&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;GetOptions(&lt;span class="string"&gt;"from=s"&lt;/span&gt; =&amp;gt; \$&lt;span class="variable-name"&gt;opt_from&lt;/span&gt;,&lt;br /&gt;           &lt;span class="string"&gt;"to=s"&lt;/span&gt; =&amp;gt; \$&lt;span class="variable-name"&gt;opt_to&lt;/span&gt;,&lt;br /&gt;           &lt;span class="string"&gt;"subject=s"&lt;/span&gt; =&amp;gt; \$&lt;span class="variable-name"&gt;opt_subject&lt;/span&gt;,&lt;br /&gt;           &lt;span class="string"&gt;"file=s"&lt;/span&gt; =&amp;gt; \@&lt;span class="underline"&gt;&lt;span class="variable-name"&gt;files&lt;/span&gt;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;push @&lt;span class="underline"&gt;&lt;span class="variable-name"&gt;files&lt;/span&gt;&lt;/span&gt;, @&lt;span class="underline"&gt;&lt;span class="variable-name"&gt;ARGV&lt;/span&gt;&lt;/span&gt;;&lt;br /&gt;$&lt;span class="variable-name"&gt;oldC&lt;/span&gt; = $/;&lt;br /&gt;binmode STDIN; undef $/;&lt;br /&gt;$&lt;span class="variable-name"&gt;message&lt;/span&gt;=&amp;lt;&lt;span class="constant"&gt;STDIN&lt;/span&gt;&amp;gt;;&lt;br /&gt;$/ = $&lt;span class="variable-name"&gt;oldC&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;$&lt;span class="variable-name"&gt;msg&lt;/span&gt; = MIME::Lite-&amp;gt;new(&lt;br /&gt;    From     =&amp;gt; $&lt;span class="variable-name"&gt;opt_from&lt;/span&gt;,&lt;br /&gt;    To       =&amp;gt; $&lt;span class="variable-name"&gt;opt_to&lt;/span&gt;,&lt;br /&gt;    Subject  =&amp;gt; $&lt;span class="variable-name"&gt;opt_subject&lt;/span&gt;,&lt;br /&gt;    Type     =&amp;gt; &lt;span class="string"&gt;'TEXT'&lt;/span&gt;,&lt;br /&gt;    Data     =&amp;gt; $&lt;span class="variable-name"&gt;message&lt;/span&gt;&lt;br /&gt;    );&lt;br /&gt;&lt;br /&gt;$&lt;span class="variable-name"&gt;msg&lt;/span&gt;-&amp;gt;replace(&lt;br /&gt;    &lt;span class="string"&gt;'X-Mailer'&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;"send_files.pl $VERSION"&lt;/span&gt;&lt;br /&gt;    );&lt;br /&gt;&lt;br /&gt;&lt;span class="keyword"&gt;for&lt;/span&gt; $&lt;span class="variable-name"&gt;file&lt;/span&gt; (@&lt;span class="underline"&gt;&lt;span class="variable-name"&gt;files&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;{&lt;br /&gt;    &lt;span class="keyword"&gt;die&lt;/span&gt; &lt;span class="string"&gt;"Not readable $file: $!"&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; -r $&lt;span class="variable-name"&gt;file&lt;/span&gt;;&lt;br /&gt;    chomp (&lt;span class="type"&gt;my&lt;/span&gt; $&lt;span class="variable-name"&gt;mimeTypeS&lt;/span&gt;=&lt;span class="string"&gt;`file -bi "$file"`&lt;/span&gt;);&lt;br /&gt;    &lt;span class="type"&gt;my&lt;/span&gt; MIME::Type $&lt;span class="variable-name"&gt;mimeType&lt;/span&gt; = MIME::Types-&amp;gt;new-&amp;gt;type($&lt;span class="variable-name"&gt;mimeTypeS&lt;/span&gt;);&lt;br /&gt;    chomp (&lt;span class="type"&gt;my&lt;/span&gt; $&lt;span class="variable-name"&gt;fileName&lt;/span&gt;=&lt;span class="string"&gt;`basename "$file"`&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;    $&lt;span class="variable-name"&gt;msg&lt;/span&gt;-&amp;gt;attach(&lt;br /&gt;        Type     =&amp;gt; $&lt;span class="variable-name"&gt;mimeTypeS&lt;/span&gt;,&lt;br /&gt;        Path     =&amp;gt; $&lt;span class="variable-name"&gt;file&lt;/span&gt;,&lt;br /&gt;        Filename =&amp;gt; $&lt;span class="variable-name"&gt;fileName&lt;/span&gt;,&lt;br /&gt;        Encoding =&amp;gt; ($&lt;span class="variable-name"&gt;mimeType&lt;/span&gt;-&amp;gt;mediaType eq &lt;span class="string"&gt;'text'&lt;/span&gt; ? &lt;span class="string"&gt;'quoted-printable'&lt;/span&gt; : &lt;span class="string"&gt;'base64'&lt;/span&gt;)&lt;br /&gt;        );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;$&lt;span class="variable-name"&gt;msg&lt;/span&gt;-&amp;gt;send;&lt;br /&gt;&lt;span class="comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="comment"&gt;***&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-5249309561051711816?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/5249309561051711816/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=5249309561051711816' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/5249309561051711816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/5249309561051711816'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2009/11/command-line-email-with-attachments.html' title='Command line email with attachments'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-2685686951378218422</id><published>2009-08-29T19:10:00.004-04:00</published><updated>2009-08-29T19:28:17.377-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Converting XML Schema to Relax NG</title><content type='html'>Needed to convert W3 XML Schema for web.xml files to Relax NG so that I can edit those files in emacs with XML element expansion and syntax highlighting provided by &lt;a href="http://www.thaiopensource.com/nxml-mode/"&gt;nxml&lt;/a&gt; mode. I found a lot of references on the Internet for Sun's  XSD to RNG converter. However, most links pointing to Sun website were broken. Finally, I found that RNG converter is a part of the &lt;a href="http://msv.dev.java.net/"&gt;Kohsuke Kawaguchi's MS&lt;/a&gt;&lt;a href="http://msv.dev.java.net/"&gt;V&lt;/a&gt; project. After installing rngconv.zip, I downloaded  web-app_2_4.xsd, j2ee_1_4.xsd,  jsp_2_0.xsd from &lt;a href="http://java.sun.com/xml/ns/j2ee/"&gt;Sun's XML Schemas for &lt;/a&gt;&lt;a href="http://java.sun.com/xml/ns/j2ee/"&gt;J2EE&lt;/a&gt;&lt;a href="http://java.sun.com/xml/ns/j2ee/"&gt;&lt;/a&gt; and converted the first one for use with nxml.&lt;br /&gt;&lt;br /&gt;One little quirk was to add in the RNC schema a definition for xsi:schemaLocation attribute to the definition of element web-app&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote style="font-family: courier new;"&gt;namespace xsi = "http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;element web-app {&lt;br /&gt;attribute xsi:schemaLocation { "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" },&lt;br /&gt;...&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-2685686951378218422?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/2685686951378218422/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=2685686951378218422' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/2685686951378218422'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/2685686951378218422'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2009/08/converting-xml-schema-to-relax-ng.html' title='Converting XML Schema to Relax NG'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-496353247868422989</id><published>2009-03-17T11:59:00.004-04:00</published><updated>2009-03-17T12:03:54.713-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='oracle'/><title type='text'>set role plustrace</title><content type='html'>Just spent an hour trying to configure autotrace in Oracle 10.2.0.3.0. It turns out that in addition to granting &lt;span style="font-family: courier new;"&gt;plustrace&lt;/span&gt; role to a user and creating a &lt;span style="font-family: courier new;"&gt;PLAN&lt;/span&gt; table, you also need to enable the &lt;span style="font-family: courier new;"&gt;plustrace&lt;/span&gt; role in the user's session using "&lt;span style="font-family: courier new;"&gt;SET ROLE PLUSTRACE;&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;Read comments at the bottom of &lt;a href="http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:5671636641855#33004281098282"&gt;Tom Kyte's autotrace topic&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-496353247868422989?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/496353247868422989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=496353247868422989' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/496353247868422989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/496353247868422989'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2009/03/set-role-plustrace.html' title='set role plustrace'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-4803837289992833403</id><published>2009-02-27T10:48:00.009-05:00</published><updated>2009-02-27T11:34:17.693-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>What will save the Earth and Wall Street?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/en/b/b9/Xbrl-logo.png"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 188px; height: 94px;" src="http://upload.wikimedia.org/wikipedia/en/b/b9/Xbrl-logo.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;A couple of recent articles in Wired and O'Reilly claim that technology for transparency, specifically XBRL (Extensible Business Reporting Language), is going to be crucial in saving the climate and also Wall Street. Go learn XBRL now!&lt;br /&gt;&lt;br /&gt;In The Wired article, Daniel Roth suggests that XBRL&lt;br /&gt;&lt;blockquote&gt;"...should become the lingua franca of every investment bank, hedge fund, pension fund, insurance company, and endowment fund. ... It is impossible to track any one loan in a CDO [collateralized debt obligation]; when it is combined and divided with other loans, it loses its independent identity... But if those mortgages and loans carried XBRL tags, and everybody who touched them along the way was required to use those tags as well, anyone would have been able to track their circuitous route through the financial industry and judge each CDO based on its actual content."&lt;/blockquote&gt;Chicago Climate Exchange (CCX) is a market for trading offsets of carbon and other climate related emissions, implementing the "trade" component of a "cap and trade" climate control scheme. As far as I understand, currently, CCX takes semi-manual submissions of trades via its website. However, it turns out  XBRL  can be used to automate carbon credit accounting and trading.&lt;br /&gt;&lt;br /&gt;Kurt Cagle writes&lt;br /&gt;&lt;blockquote&gt;"...think of each participant [of smart power grid] as a node in a network. At any given point, the state of that node - how much energy they have available for transmission at that point in time, how much energy they currently need to fulfill demands upon them - can be represented as an XBRL accounting document."&lt;/blockquote&gt;For more information, read the following recent articles&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;a href="http://www.wired.com/techbiz/it/magazine/17-03/wp_reboot"&gt;Road Map for Financial Recovery: Radical Transparency Now!&lt;/a&gt;,&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;a href="http://broadcast.oreilly.com/2009/02/xbrl-and-carbon-credit-account.html"&gt;XBRL: the Solution for Carbon Credit and Smart Grid Accounting&lt;/a&gt;,&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;a href="http://science.howstuffworks.com/chicago-climate-exchange.htm"&gt;How Chicago Climate Exchange Works&lt;/a&gt;, and&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;a href="http://en.wikipedia.org/wiki/XBRL"&gt;Wikipedia on XBRL&lt;/a&gt;.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-4803837289992833403?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/4803837289992833403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=4803837289992833403' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/4803837289992833403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/4803837289992833403'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2009/02/what-will-save-earth-and-wall-street.html' title='What will save the Earth and Wall Street?'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-2367717601886489776</id><published>2009-02-09T14:25:00.002-05:00</published><updated>2009-02-09T14:28:23.046-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='kde'/><title type='text'>Volkerding praises KDE4 again</title><content type='html'>Recently on Slackware ChangeLog, Volkerding wrote:&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;Tue Jan 27 14:33:35 CST 2009&lt;br /&gt; KDE 4.2.0 is released -- congratulations to the KDE development team for such&lt;br /&gt; an amazing job on this beautiful and highly user-friendly desktop environment!&lt;br /&gt; Thanks also to Eric Hameleers, who did a ton of work getting KDE 4.2.0 ready&lt;br /&gt; for Slackware. Once again (for now), these packages are compatible with&lt;br /&gt; Slackware 12.2. Enjoy! :-)&lt;/blockquote&gt;Hopefully Slackware 13 will integrate KDE4 and I will be able to enjoy the new features and eye candy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-2367717601886489776?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/2367717601886489776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=2367717601886489776' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/2367717601886489776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/2367717601886489776'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2009/02/volkerding-praises-kde4-again.html' title='Volkerding praises KDE4 again'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-3991281029237221075</id><published>2009-01-23T17:41:00.001-05:00</published><updated>2009-01-23T17:43:16.160-05:00</updated><title type='text'>Alan Kay on modern programming languages</title><content type='html'>&lt;blockquote&gt;Most software today is very much like an Egyptian pyramid with millions of bricks piled on top of each other, with no structural integrity, but just done by brute force and thousands of slaves.&lt;/blockquote&gt;Read the rest in &lt;a href="http://queue.acm.org/detail.cfm?id=1039523"&gt;A Conversation with Alan Kay&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-3991281029237221075?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/3991281029237221075/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=3991281029237221075' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3991281029237221075'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3991281029237221075'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2009/01/alan-kay-on-modern-programming.html' title='Alan Kay on modern programming languages'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-3923108036670053172</id><published>2008-10-01T09:27:00.002-04:00</published><updated>2008-10-01T09:30:10.336-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>Tuckey Rewrite</title><content type='html'>Note to self, Tomcat mailing list recommends a Url rewrite filter for a servlet container called &lt;a href="http://tuckey.org/urlrewrite/"&gt;Tuckey UrlRewrite&lt;/a&gt;. It functions similarly to the popular apache mod_rewrite. I speculate it may be helpful in a RESTful application to map requests to JSPs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-3923108036670053172?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/3923108036670053172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=3923108036670053172' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3923108036670053172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3923108036670053172'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2008/10/tuckey-rewrite.html' title='Tuckey Rewrite'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-7995204952853866700</id><published>2008-09-03T12:37:00.002-04:00</published><updated>2008-09-03T12:45:38.883-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>$5 multifactor authentication for OpenID</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://i183.photobucket.com/albums/x294/mike6024/PayPalVerisignSecurityTokens.png"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px;" src="http://i183.photobucket.com/albums/x294/mike6024/PayPalVerisignSecurityTokens.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.paypal.com/securitykey"&gt;Paypal provides a $5 unique password security key&lt;/a&gt; which works with Verisign OpenID provider, according to blog &lt;a href="http://ilikeellipses.com/2007/09/01/more-on-verisign-pip-openid/"&gt;"i like ellipses"&lt;/a&gt;. Get it while the introduction price makes it a better deal than the $30 Verisign's own security key.&lt;br /&gt;&lt;br /&gt;Availability of this key is a great news because using a unique password key makes your OpenID identity much more trustworthy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-7995204952853866700?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/7995204952853866700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=7995204952853866700' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/7995204952853866700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/7995204952853866700'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2008/09/5-multifactor-authentication-for-openid.html' title='$5 multifactor authentication for OpenID'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-3860914369915124342</id><published>2008-07-21T19:05:00.005-04:00</published><updated>2008-07-21T19:52:39.339-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='thinkpad'/><title type='text'>Changing fan on Thinkpad T41</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_29OWQQflr4o/SIUhQEXZzUI/AAAAAAAAAnU/KnA_Gexe6l8/s1600-h/old_thinkpad_fan_back.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://1.bp.blogspot.com/_29OWQQflr4o/SIUhQEXZzUI/AAAAAAAAAnU/KnA_Gexe6l8/s400/old_thinkpad_fan_back.jpg" alt="" id="BLOGGER_PHOTO_ID_5225619502566853954" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_29OWQQflr4o/SIUhIPhZPpI/AAAAAAAAAnM/ZVi7jqY0_sA/s1600-h/old_thinkpad_fan.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://1.bp.blogspot.com/_29OWQQflr4o/SIUhIPhZPpI/AAAAAAAAAnM/ZVi7jqY0_sA/s400/old_thinkpad_fan.jpg" alt="" id="BLOGGER_PHOTO_ID_5225619368122597010" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;After four years in service, the fan of my Thinkpad T41 started to fail. The computer either wouldn't boot with "fan error" message at boot time if the fan doesn't start or the fan would whine causing video card to overheat, freezing X11. Time to change the fan.&lt;br /&gt;&lt;br /&gt;I found the fan part number at IBM's website, it was "CPU Fan Long", FRU 13N5341. I searched online shops for the part, finding several listing the fan from anywhere from $30 to $80. At three different cheapest stores, I tried to order the fan and failed, each time the store canceling my order because the fan was out of stock. Then, I found the IBM parts store, 1-800-388-7080. At the IBM store, the fan was $58 and 1-2 day shipping via DHL was $15, an amazing deal. They just changed the part number to 91P9252. I ordered the fan on Friday. On Monday I received a new looking fan, nicely packaged, with thermal gel intact (covered with a removable film) and thermal grease pre-applied in the right place (gel above the video card heat sink and the grease above the CPU).&lt;br /&gt;&lt;br /&gt;The hardest part was removing the old fan. I had to find just the right screwdriver (Philips #1 from my toolkit having Ph 0..3) and applying drops of WD-40 to the fan screws. Once the fan was out, putting new fan and closing the laptop was a piece of cake. The laptop booted just fine and noise disappeared. Let's hope the thermal gel and grease adhere correctly, but it looks like IBM still got the chops. Let's hope new Chinese owners (Lenovo) won't screw it up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-3860914369915124342?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/3860914369915124342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=3860914369915124342' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3860914369915124342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3860914369915124342'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2008/07/changing-fan-on-thinkpad-t41.html' title='Changing fan on Thinkpad T41'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_29OWQQflr4o/SIUhQEXZzUI/AAAAAAAAAnU/KnA_Gexe6l8/s72-c/old_thinkpad_fan_back.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-4024712001561898219</id><published>2008-07-11T22:35:00.004-04:00</published><updated>2008-07-11T22:40:22.171-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='oracle'/><title type='text'>NoClassDefFoundError: oracle/gss/util/NLSLocale</title><content type='html'>When I upgraded my Oracle JDBC driver to 10.2.0.4, Oracle XSQL Utility started giving me the following exception when using "-encoding UTF-8"&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Exception in thread "main" java.lang.NoClassDefFoundError: oracle/gss/util/NLSLocale&lt;br /&gt;      at oracle.xml.sql.XSULocale.getJavaCharset(XSULocale.java:122)&lt;br /&gt;      at OracleXML.To_XML(OracleXML.java:1092)&lt;br /&gt;      at OracleXML.ExecuteGetXML(OracleXML.java:917)&lt;br /&gt;      at OracleXML.main(OracleXML.java:185)&lt;/blockquote&gt;&lt;br /&gt;Ok, it turns out that in Oracle 10.2.0.4, some classes that used to be in&lt;br /&gt;orai18n.jar got separated into their own jars, which are shipped with Oracle&lt;br /&gt;XDK, not with Oracle JDBC drivers. For example, oracle.gss.util.NLSLocale is now in &lt;xdk&gt;$XDKHOME/jlib/orai18n-mapping.jar.&lt;/xdk&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-4024712001561898219?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/4024712001561898219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=4024712001561898219' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/4024712001561898219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/4024712001561898219'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2008/07/noclassdeffounderror.html' title='NoClassDefFoundError: oracle/gss/util/NLSLocale'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-6056941016009877268</id><published>2008-06-11T14:26:00.003-04:00</published><updated>2008-06-11T14:29:34.142-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>LCD text in NetBeans</title><content type='html'>Finally figured out how to enable sub-pixel rendering (also known as LCD text) in NetBeans. Just add &lt;span style="font-weight: bold;"&gt;-J-Dawt.useSystemAAFontSettings=lcd&lt;/span&gt;&lt;span&gt; to netbeans_default_options variable in your ~/.netbeans/6.1/etc/netbeans.conf &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-6056941016009877268?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/6056941016009877268/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=6056941016009877268' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/6056941016009877268'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/6056941016009877268'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2008/06/lcd-text-in-netbeans.html' title='LCD text in NetBeans'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-5229015043193926227</id><published>2008-03-18T16:41:00.005-04:00</published><updated>2008-03-18T16:56:11.225-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><title type='text'>Bash Random Shuffle</title><content type='html'>Here is a bash function which returns a random permutation of the input lines of text.&lt;br /&gt;&lt;pre class="htmlize"&gt;&lt;span class="comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="comment"&gt;****f* shadegrowncode/randomShuffle&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;NAME&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;randomShuffle - prints random permutation of lines in standard input&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;FUNCTION&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;Prints all or the first N lines of a random permutation of the&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;lines of standard input. The random permutation is obtained using&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;Durstenfeld shuffle algorithm. Performance is O(N) in memory and&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;CPU.  Limit the input to 32768 lines or rewrite using a different&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;random generator.&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;SEE ALSO&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;http://en.wikipedia.org/wiki/Knuth_shuffle&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;PARAMETERS&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;* 1 - (optional) return only the first N of the random lines of input&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;SOURCE&lt;br /&gt;&lt;/span&gt;&lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function-name"&gt;randomShuffle&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;span class="builtin"&gt;typeset&lt;/span&gt; -a elements&lt;br /&gt;    &lt;span class="builtin"&gt;typeset&lt;/span&gt; &lt;span class="variable-name"&gt;length&lt;/span&gt;=0&lt;br /&gt;    &lt;span class="keyword"&gt;while &lt;/span&gt;&lt;span class="builtin"&gt;read&lt;/span&gt; line&lt;br /&gt;    &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;        elements[$&lt;span class="variable-name"&gt;length&lt;/span&gt;]=$&lt;span class="variable-name"&gt;line&lt;/span&gt;&lt;br /&gt;        &lt;span class="variable-name"&gt;length&lt;/span&gt;=$(($&lt;span class="variable-name"&gt;length&lt;/span&gt; + 1))&lt;br /&gt;    &lt;span class="keyword"&gt;done&lt;/span&gt;&lt;br /&gt;    &lt;span class="builtin"&gt;typeset&lt;/span&gt; &lt;span class="variable-name"&gt;firstN&lt;/span&gt;=${&lt;span class="variable-name"&gt;1&lt;/span&gt;:-$&lt;span class="variable-name"&gt;length&lt;/span&gt;}&lt;br /&gt;    &lt;span class="keyword"&gt;if&lt;/span&gt; [ $&lt;span class="variable-name"&gt;firstN&lt;/span&gt; -gt $&lt;span class="variable-name"&gt;length&lt;/span&gt; ]&lt;br /&gt;    &lt;span class="keyword"&gt;then&lt;/span&gt;&lt;br /&gt;        &lt;span class="variable-name"&gt;firstN&lt;/span&gt;=$&lt;span class="variable-name"&gt;length&lt;/span&gt;&lt;br /&gt;    &lt;span class="keyword"&gt;fi&lt;/span&gt;&lt;br /&gt;    &lt;span class="keyword"&gt;for&lt;/span&gt; ((&lt;span class="variable-name"&gt;i&lt;/span&gt;=0; $&lt;span class="variable-name"&gt;i&lt;/span&gt; &amp;lt; $&lt;span class="variable-name"&gt;firstN&lt;/span&gt;; i++))&lt;br /&gt;    &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;        &lt;span class="variable-name"&gt;randPos&lt;/span&gt;=$(($&lt;span class="variable-name"&gt;RANDOM&lt;/span&gt; % ($&lt;span class="variable-name"&gt;length&lt;/span&gt; - $&lt;span class="variable-name"&gt;i&lt;/span&gt;) ))&lt;br /&gt;        &lt;span class="builtin"&gt;printf&lt;/span&gt; &lt;span class="string"&gt;"%s\n"&lt;/span&gt; &lt;span class="string"&gt;"${elements[$randPos]}"&lt;/span&gt;&lt;br /&gt;        elements[$&lt;span class="variable-name"&gt;randPos&lt;/span&gt;]=${&lt;span class="variable-name"&gt;elements&lt;/span&gt;[$&lt;span class="variable-name"&gt;length&lt;/span&gt; - $&lt;span class="variable-name"&gt;i&lt;/span&gt; - 1]}&lt;br /&gt;    &lt;span class="keyword"&gt;done&lt;/span&gt;&lt;br /&gt;}&lt;br /&gt;&lt;span class="comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="comment"&gt;***&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Usage examples:&lt;br /&gt;Print three random users from the password file:&lt;br /&gt;&lt;pre class="htmlize"&gt;$ cut -d: -f1 /etc/passwd | randomShuffle 3&lt;br /&gt;sync&lt;br /&gt;sysadmin&lt;br /&gt;vcsa&lt;/pre&gt;&lt;br /&gt;Print a random permutation of digits:&lt;br /&gt;&lt;pre class="htmlize"&gt;$ echo $(printf "%s\n" 0 1 2 3 4 5 6 7 8 9 | randomShuffle)&lt;br /&gt;4 1 0 6 8 7 2 5 3 9&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-5229015043193926227?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/5229015043193926227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=5229015043193926227' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/5229015043193926227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/5229015043193926227'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2008/03/bash-random-shuffle.html' title='Bash Random Shuffle'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-4041125888516695671</id><published>2008-02-15T20:25:00.002-05:00</published><updated>2008-02-15T20:29:28.998-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='slackware'/><category scheme='http://www.blogger.com/atom/ns#' term='kde'/><title type='text'>Volkerding says KDE4 better than MacOS</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.slackware.org/%7Emsimons/slackware/grfx/shared/TrySlackLinux.gif"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 220px; height: 120px;" src="http://www.slackware.org/%7Emsimons/slackware/grfx/shared/TrySlackLinux.gif" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Patrick Volkerding (Slackware Project Lead) gives glowing thumbs up to KDE4 and slates it for inclusion into Slackware 14. Slackware is currently at version 12 and releases once a year. At this rate, KDE4 will be in Slackware in 2009. Among other things, Patrick says the following.&lt;br /&gt;&lt;blockquote&gt;The look of the new [KDE] desktop is stunning, and the use of SVG and hardware acceleration gives (IMHO) even something like MacOS a run for its money in terms of appearance and user-friendliness. We look forward with great anticipation to merging KDE4 when it is mature enough (and it's getting there fast), and then watching it just get better and better.&lt;/blockquote&gt;The full quote can be found in &lt;a href="http://www.slackware.org/"&gt;Slackware&lt;/a&gt; &lt;a href="ftp://ftp.slackware.com/pub/slackware/slackware-current/ChangeLog.txt"&gt;ChangeLog&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-4041125888516695671?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/4041125888516695671/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=4041125888516695671' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/4041125888516695671'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/4041125888516695671'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2008/02/volkerding-says-kde4-better-than-macos.html' title='Volkerding says KDE4 better than MacOS'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-5805303800134567838</id><published>2008-01-10T02:15:00.000-05:00</published><updated>2008-01-10T03:10:44.088-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='time'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><title type='text'>Reason to switch to Linux #11</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_29OWQQflr4o/R4XH2JI7TFI/AAAAAAAAACw/17l-yueuEaY/s1600-h/windows-clock.png"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://3.bp.blogspot.com/_29OWQQflr4o/R4XH2JI7TFI/AAAAAAAAACw/17l-yueuEaY/s200/windows-clock.png" alt="" id="BLOGGER_PHOTO_ID_5153745081575623762" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Windows taskbar clock cannot display seconds since Windows 95.&lt;br /&gt;Why? Because when installed on a 4 Mb machine, Windows 95 was too slow to display seconds. This and other lame excuses are &lt;a href="http://blogs.msdn.com/oldnewthing/archive/2003/10/10/55256.aspx"&gt;blogged at MSDN&lt;/a&gt;. There is a whole shareware industry around Windows to fix this problem. If you want to measure time, use online &lt;a href="http://proft.50megs.com/stopwatch.html"&gt;javascript stop watch&lt;/a&gt; or &lt;a href="http://www.time.gov/timezone.cgi?Eastern/d/-5/java"&gt;US atomic clock at time.gov&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-5805303800134567838?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/5805303800134567838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=5805303800134567838' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/5805303800134567838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/5805303800134567838'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2008/01/reason-to-switch-to-linux-11.html' title='Reason to switch to Linux #11'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_29OWQQflr4o/R4XH2JI7TFI/AAAAAAAAACw/17l-yueuEaY/s72-c/windows-clock.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-5834266831243199475</id><published>2007-12-11T19:59:00.000-05:00</published><updated>2007-12-11T20:04:02.426-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='taiwan'/><title type='text'>Java sighting on a cup of milk</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_29OWQQflr4o/R18zQmKug9I/AAAAAAAAACo/bSIlgHxE2cE/s1600-h/java_on_a_cup_of_soy_milk.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://2.bp.blogspot.com/_29OWQQflr4o/R18zQmKug9I/AAAAAAAAACo/bSIlgHxE2cE/s320/java_on_a_cup_of_soy_milk.jpg" alt="" id="BLOGGER_PHOTO_ID_5142885659696858066" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Looking at this cup of soy milk in Taipei, I thought at first that somebody stole Java logo. Then, looking closer, I realized it's a genuine ad for Java training. Something you won't see on a milk container in the US...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-5834266831243199475?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/5834266831243199475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=5834266831243199475' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/5834266831243199475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/5834266831243199475'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/12/java-sighting-on-cup-of-milk.html' title='Java sighting on a cup of milk'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_29OWQQflr4o/R18zQmKug9I/AAAAAAAAACo/bSIlgHxE2cE/s72-c/java_on_a_cup_of_soy_milk.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-3952253647305472447</id><published>2007-11-02T21:35:00.000-04:00</published><updated>2007-11-02T22:20:40.914-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='curl'/><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><category scheme='http://www.blogger.com/atom/ns#' term='nagios'/><title type='text'>Form based login from a shell script</title><content type='html'>The following code uses only shell scripting and curl to log in to a website protected by a form based authentication and download contents of page "about.jspx". We pay special attention to returning reasonable error messages. These snippets were tested with Tomcat 5.5.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Get user name, password, and the application's URL from the command line,&lt;pre class="htmlize"&gt;&lt;span class="builtin"&gt;eval&lt;/span&gt; set -- $(getopt &lt;span class="string"&gt;"u:p:b:"&lt;/span&gt; &lt;span class="string"&gt;"$@"&lt;/span&gt;)&lt;br /&gt;&lt;span class="keyword"&gt;while&lt;/span&gt; [ &lt;span class="string"&gt;"$1"&lt;/span&gt; != &lt;span class="string"&gt;"--"&lt;/span&gt; ]&lt;br /&gt;&lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;    case&lt;/span&gt; &lt;span class="string"&gt;"$1"&lt;/span&gt;&lt;span class="keyword"&gt; in&lt;/span&gt;&lt;br /&gt;    -u) &lt;span class="builtin"&gt;shift; &lt;/span&gt;&lt;span class="variable-name"&gt;WEB_UID&lt;/span&gt;=&lt;span class="string"&gt;"$1"; &lt;/span&gt;&lt;span class="builtin"&gt;shift&lt;/span&gt;; ;;&lt;br /&gt;    -p) &lt;span class="builtin"&gt;shift; &lt;/span&gt;&lt;span class="variable-name"&gt;WEB_PWD&lt;/span&gt;=&lt;span class="string"&gt;"$1"; &lt;/span&gt;&lt;span class="builtin"&gt;shift&lt;/span&gt;; ;;&lt;br /&gt;    -b) &lt;span class="builtin"&gt;shift; &lt;/span&gt;&lt;span class="variable-name"&gt;BASE_URL&lt;/span&gt;=&lt;span class="string"&gt;"${1%\/}"; &lt;/span&gt;&lt;span class="builtin"&gt;shift; &lt;/span&gt;;;&lt;br /&gt;&lt;span class="keyword"&gt;    esac&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;done&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Store URLs in variables,&lt;br /&gt;&lt;pre class="htmlize"&gt;&lt;span class="builtin"&gt;typeset&lt;/span&gt; &lt;span class="variable-name"&gt;aboutUrl&lt;/span&gt;=&lt;span class="string"&gt;"$BASE_URL/about.jspx"&lt;/span&gt;&lt;br /&gt;&lt;span class="builtin"&gt;typeset&lt;/span&gt; &lt;span class="variable-name"&gt;securityAction&lt;/span&gt;=&lt;span class="string"&gt;"$BASE_URL/j_security_check"&lt;/span&gt;&lt;br /&gt;&lt;span class="builtin"&gt;typeset&lt;/span&gt; &lt;span class="variable-name"&gt;logoffUrl&lt;/span&gt;=&lt;span class="string"&gt;"$BASE_URL/logoff.jsp"&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Access the URL and look for session cookie JSESSIONID,&lt;br /&gt;&lt;pre class="htmlize"&gt;&lt;span class="variable-name"&gt;headers&lt;/span&gt;=&lt;span class="string"&gt;"$(curl -s -S -f -L -D - -o /dev/null --url "&lt;/span&gt;$&lt;span class="variable-name"&gt;aboutUrl&lt;/span&gt;&lt;span class="string"&gt;" 2&amp;gt;&amp;amp;1)"&lt;/span&gt; &lt;span class="sh-escaped-newline"&gt;\&lt;/span&gt;&lt;br /&gt;|| error &lt;span class="string"&gt;"Error accessing $aboutUrl: $headers"&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;if&lt;/span&gt; [[ &lt;span class="string"&gt;"$headers"&lt;/span&gt; =~ &lt;span class="string"&gt;'Set-Cookie: JSESSIONID=([^;]*)'&lt;/span&gt; ]]&lt;br /&gt;&lt;span class="keyword"&gt;then&lt;/span&gt;&lt;br /&gt;&lt;span class="variable-name"&gt;    sid&lt;/span&gt;=&lt;span class="string"&gt;"${BASH_REMATCH[1]}"&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;fi&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;If JSESSIONID cookie is set, submit user name and password to the login form. On success, the application will redirect us to the original URL. Variable "about" will store the page source or the error message.&lt;br /&gt;&lt;pre class="htmlize"&gt;&lt;span class="variable-name"&gt;about&lt;/span&gt;=&lt;span class="string"&gt;"$(curl -s -S -L -f -b "&lt;/span&gt;&lt;span class="variable-name"&gt;JSESSIONID&lt;/span&gt;=$&lt;span class="variable-name"&gt;sid&lt;/span&gt;&lt;span class="string"&gt;" -o - \&lt;br /&gt;-d "&lt;/span&gt;&lt;span class="variable-name"&gt;j_username&lt;/span&gt;=$&lt;span class="variable-name"&gt;WEB_UID&lt;/span&gt;&lt;span class="string"&gt;" \&lt;br /&gt;-d "&lt;/span&gt;&lt;span class="variable-name"&gt;j_password&lt;/span&gt;=$&lt;span class="variable-name"&gt;WEB_PWD&lt;/span&gt;&lt;span class="string"&gt;" \&lt;br /&gt;--url "&lt;/span&gt;$&lt;span class="variable-name"&gt;securityAction&lt;/span&gt;&lt;span class="string"&gt;" 2&amp;gt;&amp;amp;1)"&lt;/span&gt; &lt;span class="sh-escaped-newline"&gt;\&lt;/span&gt;&lt;br /&gt;|| error &lt;span class="string"&gt;"Error submitting credentials to $securityAction: $about"&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Parse the page for some useful information (looking for &amp;lt;sysdate date="20071102"&amp;gt;)&lt;br /&gt;&lt;pre class="htmlize"&gt;&lt;span class="keyword"&gt;if&lt;/span&gt; [[ &lt;span class="string"&gt;"$about"&lt;/span&gt; =~ &lt;span class="string"&gt;'sysdate date=\"([^\"]*)\"'&lt;/span&gt; ]]&lt;br /&gt;&lt;span class="keyword"&gt;then&lt;/span&gt;&lt;br /&gt;&lt;span class="variable-name"&gt;    date&lt;/span&gt;=&lt;span class="string"&gt;"${BASH_REMATCH[1]}"&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;fi&lt;/span&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Finally, hit the logoff URL so that the application may clean up.&lt;br /&gt;&lt;pre class="htmlize"&gt;&lt;span class="comment-delimiter"&gt;&lt;/span&gt;curl -s -f -b &lt;span class="string"&gt;"JSESSIONID=$sid"&lt;/span&gt; --url &lt;span class="string"&gt;"$logoffUrl"&lt;/span&gt; -o /dev/null&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;For more information, see  &lt;a href="http://curl.haxx.se/"&gt;&lt;b&gt;cURL&lt;/b&gt; and libcurl&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-3952253647305472447?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/3952253647305472447/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=3952253647305472447' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3952253647305472447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3952253647305472447'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/11/form-based-login-from-shell-script.html' title='Form based login from a shell script'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-2588140264428185327</id><published>2007-09-25T14:48:00.001-04:00</published><updated>2007-09-25T15:14:27.186-04:00</updated><title type='text'>Sun NetBeans day</title><content type='html'>September 11th was a Sun NetBeans day in Boston. Here's what I learned:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;NetBeans keeps improving. NetBeans 6 consolidates six independent Java parsers of version 5 into one. Syntax highlighting and refactoring can now use more semantic information; it is now faster and more powerful and accurate.&lt;/li&gt;&lt;li&gt;Profiler is now improved and built-in into NetBeans. It can be enabled or disabled at runtime using profiling points. More info at &lt;a href="http://profiler.netbeans.org"&gt;Netbeans profiler pages&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The most active site about NetBeans is &lt;a href="http://wiki.netbeans.org/"&gt;NetBeans Wiki&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;New England has an active Java User Group, which organizes nice talks. See &lt;a href="http://www.nejug.org/"&gt;NEJUG.org&lt;/a&gt;&lt;/li&gt;&lt;li&gt;A lot of introductory presentation about Java technology inluding RIA and REST is posted by one of the speakers at &lt;a href="http://www.javapassion.com/handsonlabs"&gt;JavaPassion.com.&lt;/a&gt; The speaker himself was speaking way too fast with a Korean accent, but his presentations must be filled with information.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-2588140264428185327?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/2588140264428185327/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=2588140264428185327' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/2588140264428185327'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/2588140264428185327'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/09/sun-netbeans-day.html' title='Sun NetBeans day'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-105608580090360992</id><published>2007-09-21T20:10:00.000-04:00</published><updated>2007-09-21T22:10:36.910-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='s/mime'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='slackware'/><category scheme='http://www.blogger.com/atom/ns#' term='kde'/><category scheme='http://www.blogger.com/atom/ns#' term='thinkpad'/><title type='text'>Upgraded to Slackware 12</title><content type='html'>Updated my Thinkpad T40 from Slackware 11 to &lt;a href="http://www.slackware.com/"&gt;Slackware&lt;/a&gt; 12. The 2 hour upgrade went without a hitch. I was pleasantly surprised to find out that Paul compiled KDE &lt;a href="http://www.gnupg.org/aegypten2/index.html"&gt;KMail with S/MIME support&lt;/a&gt;. Great, I don't need to roll my own packages any more.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_29OWQQflr4o/RvRiAKFnGrI/AAAAAAAAABE/Q1y3bOM_EsM/s1600-h/kmail-smime.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_29OWQQflr4o/RvRiAKFnGrI/AAAAAAAAABE/Q1y3bOM_EsM/s320/kmail-smime.png" alt="" id="BLOGGER_PHOTO_ID_5112819231819766450" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-105608580090360992?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/105608580090360992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=105608580090360992' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/105608580090360992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/105608580090360992'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/09/upgraded-to-slackware-12.html' title='Upgraded to Slackware 12'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_29OWQQflr4o/RvRiAKFnGrI/AAAAAAAAABE/Q1y3bOM_EsM/s72-c/kmail-smime.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-3736754285213295060</id><published>2007-05-04T13:42:00.000-04:00</published><updated>2007-05-07T16:36:19.960-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smimecapabilities'/><category scheme='http://www.blogger.com/atom/ns#' term='s/mime'/><category scheme='http://www.blogger.com/atom/ns#' term='crypto'/><category scheme='http://www.blogger.com/atom/ns#' term='kmail'/><category scheme='http://www.blogger.com/atom/ns#' term='thunderbird'/><category scheme='http://www.blogger.com/atom/ns#' term='aes'/><category scheme='http://www.blogger.com/atom/ns#' term='md2'/><title type='text'>Fixed S/MIME interoperability between KDE KMail and Mozilla Thunderbird</title><content type='html'>Nelson Bolyard fixed interoperability problem between Thunderbird and KMail (or rather gpgsm). There was a bug in how gpgsm encoded cipher preferences, which Thunderbird could not understand and was falling back to RC2/40 cipher. In gpgsm, RC2/40 was not implemented for &lt;a href="http://www.nabble.com/forum/ViewPost.jtp?post=10012362&amp;amp;framed=y"&gt;patently political&lt;br /&gt;reasons&lt;/a&gt;. Thunderbird crypto library was made more lenient in what it accepted. So, now, TB would correctly responds to KMail using 3DES instead of RC/40. More details are in &lt;a href="https//bugzilla.mozilla.org/show_bug.cgi?id=379625"&gt;Bugzilla&lt;/a&gt; and &lt;a href="http://groups.google.com/group/mozilla.dev.tech.crypto/browse_frm/thread/44ab6f2b918fb9f7/8c11fa85d64f4155?tvc=1"&gt;Usenet&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Still causing minor problems are the following bugs. Vote for or fix them!&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=379753"&gt;support of AES by Thunderbird&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=84213"&gt;Thunderbird should not support weak crypto&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.intevation.de/roundup/aegypten/issue754"&gt;correct generation of SMimeCapabilities by gpgsm&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.intevation.de/roundup/aegypten/issue430"&gt;gpgsm does not recognize Verisign certs because of MD2 hash algorithm&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-3736754285213295060?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/3736754285213295060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=3736754285213295060' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3736754285213295060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3736754285213295060'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/05/fixed-smime-interoperability-between.html' title='Fixed S/MIME interoperability between KDE KMail and Mozilla Thunderbird'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-550903265476867717</id><published>2007-04-26T16:07:00.000-04:00</published><updated>2007-04-26T16:24:32.627-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nullity'/><category scheme='http://www.blogger.com/atom/ns#' term='algebra'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>Does Google know math?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_29OWQQflr4o/RjEG0fV2hnI/AAAAAAAAAAk/4IKFKyvsTnY/s1600-h/google-0-to-0th-power%3D1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_29OWQQflr4o/RjEG0fV2hnI/AAAAAAAAAAk/4IKFKyvsTnY/s320/google-0-to-0th-power%3D1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5057831355349894770" /&gt;&lt;/a&gt;&lt;br /&gt;According to Google Calculator, &lt;a href="http://www.google.com/search?q=0%5E0"/&gt;0^0&lt;/a&gt;=1. What else would you expect from a Stanford dropout son of a professor of mathematics... ;) At least Google has no opinion on &lt;a href="http://www.google.com/search?q=0%2F0"&gt;0/0&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-550903265476867717?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/550903265476867717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=550903265476867717' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/550903265476867717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/550903265476867717'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/04/according-to-google-calculator-00-1.html' title='Does Google know math?'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_29OWQQflr4o/RjEG0fV2hnI/AAAAAAAAAAk/4IKFKyvsTnY/s72-c/google-0-to-0th-power%3D1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-3224590785510288515</id><published>2007-04-24T17:35:00.000-04:00</published><updated>2007-04-24T17:45:56.733-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='thawte'/><category scheme='http://www.blogger.com/atom/ns#' term='s/mime'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><category scheme='http://www.blogger.com/atom/ns#' term='encryption'/><title type='text'>Encrypt your email</title><content type='html'>Everyone should be able to encrypt their email and assure others of their identity. Get your free Thawte email certificate and join Thawte web of trust. Do it even if your company gives you an email certificate. If you are in Central Massachusetts, Boston, or Manhattan, I may be able to &lt;a href="http://www.sushkins.net/thawte-notary.html"&gt;assure your identity and help you join the web of trust.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-3224590785510288515?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/3224590785510288515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=3224590785510288515' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3224590785510288515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/3224590785510288515'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/04/encrypt-your-email.html' title='Encrypt your email'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-4064356762548164505</id><published>2007-04-20T09:51:00.000-04:00</published><updated>2007-04-20T10:00:43.495-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><category scheme='http://www.blogger.com/atom/ns#' term='primary key'/><category scheme='http://www.blogger.com/atom/ns#' term='data dictionary'/><category scheme='http://www.blogger.com/atom/ns#' term='oracle'/><title type='text'>Find all tables missing a primary key in an Oracle database</title><content type='html'>Typically all tables in a database have primary keys. For some reason in ours some primary keys have disappeared. It must've been a botched export re-import operation. Anyway, here is an Oracle data dictionary query returning all tables in the current schema without a primary key. &lt;pre class="htmlize"&gt;&lt;span class="keyword"&gt;select&lt;/span&gt; &lt;span class="keyword"&gt;table_name&lt;/span&gt; &lt;br /&gt;&lt;span class="keyword"&gt;from&lt;/span&gt; user_tables &lt;br /&gt;&lt;span class="keyword"&gt;where&lt;/span&gt; &lt;span class="keyword"&gt;table_name&lt;/span&gt; &lt;span class="keyword"&gt;not&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt;&lt;br /&gt;(&lt;br /&gt;  &lt;span class="keyword"&gt;select&lt;/span&gt; &lt;span class="keyword"&gt;distinct&lt;/span&gt; &lt;span class="keyword"&gt;table_name&lt;/span&gt; &lt;br /&gt;  &lt;span class="keyword"&gt;from&lt;/span&gt; user_constraints &lt;br /&gt;  &lt;span class="keyword"&gt;where&lt;/span&gt; constraint_type=&lt;span class="string"&gt;'P'&lt;/span&gt;&lt;br /&gt;)&lt;br /&gt;&lt;span class="keyword"&gt;order&lt;/span&gt; &lt;span class="keyword"&gt;by&lt;/span&gt; &lt;span class="keyword"&gt;table_name&lt;/span&gt;;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-4064356762548164505?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/4064356762548164505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=4064356762548164505' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/4064356762548164505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/4064356762548164505'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/04/find-all-tables-missing-primary-key-in.html' title='Find all tables missing a primary key in an Oracle database'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-92206000679014734</id><published>2007-04-17T21:51:00.000-04:00</published><updated>2007-04-18T12:08:33.809-04:00</updated><title type='text'>Windows for Professional Users</title><content type='html'>Sam Gentile, a windows programmer wishes for a &lt;a href="http://codebetter.com/blogs/sam.gentile/archive/2007/04/15/Wanted_3A00_-A-Windows-Edition-for-Non_2D00_Idiots.aspx"&gt;Windows Edition for Power Users&lt;/a&gt;. He's so good - he has been using Windows in Administrator mode for 25 years and is not going to change. My guess is that if he browsed with Internet Explorer in Administrator mode, he's been rooted so deeply, his antivirus does not know it. He also looked at Unix in the 80s, so he does not want to hear about Linux. Poor chap, he does not have much choice between grandmommy's Vista and geek's Linux.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-92206000679014734?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/92206000679014734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=92206000679014734' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/92206000679014734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/92206000679014734'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/04/windows-for-professional-users.html' title='Windows for Professional Users'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-5016635645902553375</id><published>2007-03-27T23:33:00.000-04:00</published><updated>2007-09-25T22:00:20.453-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='account lockout'/><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><category scheme='http://www.blogger.com/atom/ns#' term='realm'/><title type='text'>Account Lockout Realm in Tomcat</title><content type='html'>&lt;span style="font-size:85%;"&gt;(Quick links: &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;a href="http://sourceforge.net/projects/lockout-realm/"&gt;SourceForge&lt;/a&gt;, &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;a href="http://sourceforge.net/cvs/?group_id=193094"&gt;CVS)&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I am describing here a way to implement Account Lockout. We want to lock out those users who within a short period of time made multiple authentication attempts and failed. The Account Lockout feature is commonly used in Tomcat hardening and requested in security audit.&lt;br /&gt;&lt;br /&gt;I derive my AccountLockoutDatasourceRealm from Tomcat's DataSourceRealm to include account lockout logic and return the reason for authentication failure. Finally, I modify login failure JSP to show a message specifying if the account is locked or password is merely incorrect.&lt;br /&gt;&lt;br /&gt;To keep track of the password failures, I add two columns to the User table: LoginFailures number and LastLoginFailure date/time.&lt;br /&gt;&lt;pre class="htmlize"&gt;&lt;span class="keyword"&gt;alter&lt;/span&gt; &lt;span class="keyword"&gt;table&lt;/span&gt; &lt;span class="function-name"&gt;User&lt;/span&gt; &lt;span class="keyword"&gt;add&lt;/span&gt; (&lt;br /&gt; LoginFailures &lt;span class="type"&gt;number&lt;/span&gt; &lt;span class="keyword"&gt;default&lt;/span&gt; 0,&lt;br /&gt; LastLoginFailure &lt;span class="type"&gt;date&lt;/span&gt;&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;&lt;span class="keyword"&gt;comment&lt;/span&gt; &lt;span class="keyword"&gt;on&lt;/span&gt; &lt;span class="keyword"&gt;column&lt;/span&gt; User.LoginFailures &lt;span class="keyword"&gt;is&lt;/span&gt;&lt;br /&gt;  &lt;span class="string"&gt;'Number of consecutive login failures for the purposes of implementing Account Lockout'&lt;/span&gt;;&lt;br /&gt;&lt;span class="keyword"&gt;comment&lt;/span&gt; &lt;span class="keyword"&gt;on&lt;/span&gt; &lt;span class="keyword"&gt;column&lt;/span&gt; User.LastLoginFailure &lt;span class="keyword"&gt;is&lt;/span&gt;&lt;br /&gt;  &lt;span class="string"&gt;'Date/time of the last login failure for the purposes of implementing Account Lockout'&lt;/span&gt;;&lt;/pre&gt; The new AccountLockoutDatasourceRealm provides getters and setters for properties configuring account lockout, overrides &lt;code&gt;authenticate()&lt;/code&gt; method using logic described below, and implements &lt;code&gt;setExtendedStatus&lt;/code&gt; method of &lt;code&gt;ExtendedStatusSetter&lt;/code&gt; interface.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;New Realm Properties&lt;/h2&gt; &lt;dl&gt;&lt;!-- --&gt;&lt;dt&gt;&lt;code&gt;failedAttemptsBeforeLockout&lt;/code&gt; &lt;/dt&gt;&lt;dd&gt; The maximum number of login failure attempts before the accounts is locked out or zero to disable lockout&lt;/dd&gt;&lt;!-- --&gt;&lt;dt&gt;&lt;code&gt;lockoutDuration&lt;/code&gt; &lt;/dt&gt;&lt;dd&gt; The duration of lockout in minutes or zero for permanent lockout&lt;/dd&gt;&lt;!-- --&gt;&lt;dt&gt;&lt;code&gt;getLoginStatsForUserStatement&lt;/code&gt; &lt;/dt&gt;&lt;dd&gt; SQL statement with one JDBC parameter (?) returning three values: the number of login failures, the date/time of the last login failure, and the current database date/time for the user whose id is specified by the parameter. For example, &lt;div class="fragment"&gt;&lt;pre class="htmlize"&gt; &lt;span style="color:brown;"&gt;SELECT&lt;/span&gt; LoginFailures, LastLoginFailure, &lt;span style="color:brown;"&gt;SYSDATE&lt;/span&gt; &lt;span style="color:brown;"&gt;FROM&lt;/span&gt; &lt;span style="color:brown;"&gt;User&lt;/span&gt; WHERE Id = ? &lt;/pre&gt;&lt;/div&gt;&lt;/dd&gt;&lt;!-- --&gt;&lt;dt&gt;&lt;code&gt;resetAccountLockoutForUserStatement&lt;/code&gt; &lt;/dt&gt;&lt;dd&gt; SQL update statement with one JDBC parameter (?) resetting the number of login failures for the user whose id is specified by the parameter. For example, &lt;div class="fragment"&gt;&lt;pre class="htmlize"&gt; &lt;span style="color:brown;"&gt;UPDATE&lt;/span&gt; &lt;span style="color:brown;"&gt;User&lt;/span&gt; &lt;span style="color:brown;"&gt;SET&lt;/span&gt; LoginFailures = 0 WHERE Id = ? &lt;/pre&gt;&lt;/div&gt;&lt;/dd&gt;&lt;!-- --&gt;&lt;dt&gt;&lt;code&gt;recordFailureForUserStatement&lt;/code&gt; &lt;/dt&gt;&lt;dd&gt; SQL update statement with one JDBC parameter (?) incrementing the number of login failures and updating the date/time of the last login for the user whose id is specified by the parameter. For example, &lt;div class="fragment"&gt;&lt;pre class="htmlize"&gt; &lt;span style="color:brown;"&gt;UPDATE&lt;/span&gt; &lt;span style="color:brown;"&gt;User&lt;/span&gt; &lt;span style="color:brown;"&gt;SET&lt;/span&gt; LoginFailures = &lt;span style="color:teal;"&gt;NVL&lt;/span&gt;(LoginFailures, 0) + 1, LastLoginFailure = &lt;span style="color:brown;"&gt;SYSDATE&lt;/span&gt; where Id = ? &lt;/pre&gt;&lt;/div&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;!-- --&gt;&lt;h2&gt;Account Lockout Logic&lt;/h2&gt;&lt;!-- --&gt;&lt;ol&gt;&lt;li&gt; Lockout feature is enabled if &lt;code&gt;failedAttemptsBeforeLockout&lt;/code&gt; is greater than 0. &lt;/li&gt;&lt;!-- --&gt;&lt;li&gt; If lockout is enabled, read login stats (LoginFailures, LastLoginFailure, and DatabaseDate) from the database.&lt;/li&gt;&lt;!-- --&gt;&lt;li&gt; Lockout is considered expired, when&lt;br /&gt;&lt;ol&gt;&lt;li&gt; lockout feature is not enabled, or &lt;/li&gt;&lt;!-- --&gt;&lt;li&gt; lockout is not permanent and LastLoginFailure is more than &lt;code&gt;lockoutDuration&lt;/code&gt; minutes before DatabaseDate.&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;!-- --&gt;&lt;li&gt; Account is considered locked, when the lockout is enabled and the LoginFailures is equal to or greater then &lt;code&gt;failedAttemptsBeforeLockout&lt;/code&gt;.&lt;/li&gt;&lt;!-- --&gt;&lt;li&gt; If lockout is enabled, account IS NOT locked, and lockout has expired, reset the lockout and reread the login stats.&lt;/li&gt;&lt;!-- --&gt;&lt;li&gt; If lockout is enabled, account IS locked, lockout has expired, and the lockout is not permanent, reset the lockout and reread the login stats.&lt;/li&gt;&lt;!-- --&gt;&lt;li&gt; If lockout is enabled and account IS locked, &lt;strong&gt;fail&lt;/strong&gt; the login without checking the password and return.&lt;/li&gt;&lt;!-- --&gt;&lt;li&gt; Otherwise (if lockout is not enabled or account is not locked), user check the password against the database.&lt;/li&gt;&lt;!-- --&gt;&lt;li&gt; If password is not correct, increment LoginFailures and set LastLoginFailure to DatabaseDate in the database.&lt;/li&gt;&lt;!-- --&gt;&lt;li&gt; Reread login stats. If account lockout enabled and account is locked according to the rules above, &lt;strong&gt;fail&lt;/strong&gt; the login due to account lockout and return. &lt;/li&gt;&lt;!-- --&gt;&lt;li&gt; If password is correct, reset the lockout and return login &lt;strong&gt;success&lt;/strong&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;!-- --&gt;&lt;h2&gt;Returning Login Failure Reason&lt;/h2&gt;&lt;br /&gt;We use code described in the post &lt;a href="http://www.shadegrowncode.com/2007/03/returning-login-failure-reason-in.html"&gt;returning reason from a Tomcat Realm&lt;/a&gt;&lt;span style="font-size:100%;"&gt;&lt;a href="http://sourceforge.net/projects/lockout-realm/"&gt;.&lt;/a&gt;&lt;/span&gt; In &lt;code&gt;setExtendedStatus&lt;/code&gt; method we check if account is locked and if it is, we pass the message using a request attribute as follows.&lt;br /&gt;&lt;pre class="htmlize"&gt;&lt;span class="keyword"&gt;if&lt;/span&gt; (isLockoutEnabled() &amp;amp;&amp;amp; isAccountLocked(failureStats))&lt;br /&gt;{&lt;br /&gt;  setMessage(request, &lt;span class="string"&gt;"Account locked"&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="keyword"&gt;protected&lt;/span&gt; &lt;span class="type"&gt;void&lt;/span&gt; &lt;span class="function-name"&gt;setMessage&lt;/span&gt;(&lt;span class="type"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="variable-name"&gt;request&lt;/span&gt;, &lt;span class="type"&gt;String&lt;/span&gt; &lt;span class="variable-name"&gt;message&lt;/span&gt;)&lt;br /&gt;{&lt;br /&gt;  containerLog.debug(&lt;span class="string"&gt;"Setting extended status message to "&lt;/span&gt; + message);&lt;br /&gt;  request.setAttribute(&lt;span class="constant"&gt;ExtendedStatusSetter&lt;/span&gt;.&lt;span class="jde-java-font-lock-constant"&gt;LOGIN_FAILURE_MESSAGE_ATTR&lt;/span&gt;, message);&lt;br /&gt;}&lt;/pre&gt;&lt;h2&gt;Displaying Login Failure Reason&lt;/h2&gt;&lt;br /&gt;Tomcat form authentication configures an error JSP, which is displayed when login fails. To display extended login failure reason, we check for the existence of our request attribute with the following code: &lt;pre class="htmlize"&gt;   &lt;span class="nxml-tag-delimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nxml-element-local-name"&gt;p&lt;/span&gt; &lt;span class="nxml-attribute-local-name"&gt;class&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;error&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nxml-text"&gt;Access Denied:&lt;br /&gt;    &lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nxml-element-prefix"&gt;c&lt;/span&gt;&lt;span class="nxml-element-colon"&gt;:&lt;/span&gt;&lt;span class="nxml-element-local-name"&gt;choose&lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class="nxml-tag-delimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nxml-element-prefix"&gt;c&lt;/span&gt;&lt;span class="nxml-element-colon"&gt;:&lt;/span&gt;&lt;span class="nxml-element-local-name"&gt;when&lt;/span&gt; &lt;span class="nxml-attribute-local-name"&gt;test&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;${!(empty requestScope['com.ofc.tomcat.LOGIN_FAILURE_MESSAGE'])}&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="nxml-tag-delimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nxml-element-prefix"&gt;c&lt;/span&gt;&lt;span class="nxml-element-colon"&gt;:&lt;/span&gt;&lt;span class="nxml-element-local-name"&gt;out&lt;/span&gt; &lt;span class="nxml-attribute-local-name"&gt;value&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;${requestScope['com.ofc.tomcat.LOGIN_FAILURE_MESSAGE']}&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-tag-slash"&gt;/&lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class="nxml-tag-delimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nxml-tag-slash"&gt;/&lt;/span&gt;&lt;span class="nxml-element-prefix"&gt;c&lt;/span&gt;&lt;span class="nxml-element-colon"&gt;:&lt;/span&gt;&lt;span class="nxml-element-local-name"&gt;when&lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class="nxml-tag-delimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nxml-element-prefix"&gt;c&lt;/span&gt;&lt;span class="nxml-element-colon"&gt;:&lt;/span&gt;&lt;span class="nxml-element-local-name"&gt;otherwise&lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nxml-text"&gt;Invalid username and/or password&lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nxml-tag-slash"&gt;/&lt;/span&gt;&lt;span class="nxml-element-prefix"&gt;c&lt;/span&gt;&lt;span class="nxml-element-colon"&gt;:&lt;/span&gt;&lt;span class="nxml-element-local-name"&gt;otherwise&lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="nxml-tag-delimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nxml-tag-slash"&gt;/&lt;/span&gt;&lt;span class="nxml-element-prefix"&gt;c&lt;/span&gt;&lt;span class="nxml-element-colon"&gt;:&lt;/span&gt;&lt;span class="nxml-element-local-name"&gt;choose&lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nxml-tag-delimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nxml-tag-slash"&gt;/&lt;/span&gt;&lt;span class="nxml-element-local-name"&gt;p&lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;To build the code, compile AccountLockoutDatasourceRealm below and &lt;a href="http://snippets.dzone.com/posts/show/3715"&gt;ExtendedStatusFormAuthenticator and ExtendedStatusSetter&lt;/a&gt; from dzone snippet. Package the code and the mbeans-descriptor.xml into a jar, place the jar into Tomcat's server/lib, and restart tomcat.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Configuration&lt;/h2&gt;&lt;br /&gt;To configure your application, add the following lines to your context.xml &lt;pre class="htmlize"&gt;  &lt;span class="nxml-comment-delimiter"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="nxml-comment-content"&gt; Override Pragma:no-cache to work around the IE bug when app is served via SSL.&lt;br /&gt; See http://www.mail-archive.com/tomcat-user%40jakarta.apache.org/msg151294.html&lt;br /&gt;&lt;/span&gt;&lt;span class="nxml-comment-delimiter"&gt;--&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nxml-element-local-name"&gt;Valve&lt;/span&gt; &lt;span class="nxml-attribute-local-name"&gt;className&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;com.ofc.tomcat.ExtendedStatusFormAuthenticator&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;      &lt;span class="nxml-attribute-local-name"&gt;disableProxyCaching&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;false&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt; &lt;span class="nxml-tag-slash"&gt;/&lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nxml-element-local-name"&gt;Realm&lt;/span&gt; &lt;span class="nxml-attribute-local-name"&gt;className&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;com.ofc.tomcat.AccountLockoutDatasourceRealm&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;   &lt;span class="nxml-attribute-local-name"&gt;dataSourceName&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;realm.datasource&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;   &lt;span class="nxml-attribute-local-name"&gt;userTable&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;User&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;   &lt;span class="nxml-attribute-local-name"&gt;userRoleTable&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;UserRole&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;   &lt;span class="nxml-attribute-local-name"&gt;userNameCol&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;ID&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;   &lt;span class="nxml-attribute-local-name"&gt;userCredCol&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;PASSWORD&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;   &lt;span class="nxml-attribute-local-name"&gt;roleNameCol&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;ROLEID&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;   &lt;span class="nxml-attribute-local-name"&gt;failedAttemptsBeforeLockout&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;3&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;   &lt;span class="nxml-attribute-local-name"&gt;lockoutDuration&lt;/span&gt;=&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;30&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;   &lt;span class="nxml-attribute-local-name"&gt;getLoginStatsForUserStatement&lt;/span&gt;=&lt;br /&gt;   &lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;SELECT LoginFailures, LastLoginFailure, SYSDATE FROM User where Id = ?&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;   &lt;span class="nxml-attribute-local-name"&gt;resetAccountLockoutForUserStatement&lt;/span&gt;=&lt;br /&gt;   &lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;UPDATE User SET LoginFailures = 0 WHERE Id = ?&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;   &lt;span class="nxml-attribute-local-name"&gt;recordFailureForUserStatement&lt;/span&gt;=&lt;br /&gt;   &lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;span class="nxml-attribute-value"&gt;UPDATE User SET LoginFailures = NVL(LoginFailures, 0) + 1, LastLoginFailure = SYSDATE where Id = ?&lt;/span&gt;&lt;span class="nxml-attribute-value-delimiter"&gt;"&lt;/span&gt;&lt;br /&gt;   &lt;span class="nxml-tag-slash"&gt;/&lt;/span&gt;&lt;span class="nxml-tag-delimiter"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;h2&gt;Documentation and Source&lt;/h2&gt;&lt;br /&gt;I published &lt;a href="http://lockout-realm.cvs.sourceforge.net/lockout-realm/"&gt;source code&lt;/a&gt; in &lt;a href="http://sourceforge.net/projects/lockout-realm"&gt;sourceforge lockout-realm project&lt;/a&gt;. Instructions are forthcoming.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Credits&lt;/h2&gt;&lt;br /&gt;This work was sponsored by &lt;a href="http://www.openfinance.com/"&gt;Open Finance - a leading enabler of data consolidation for the financial services industry&lt;/a&gt; and &lt;a href="http://www.wealthinformationexchange.com/"&gt;Wealth Information Exchange - A Consolidated View of Wealth&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-5016635645902553375?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/5016635645902553375/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=5016635645902553375' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/5016635645902553375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/5016635645902553375'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/03/implementing-account-lockout-in-tomcat.html' title='Account Lockout Realm in Tomcat'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-334431538309677036</id><published>2007-03-23T12:50:00.000-04:00</published><updated>2007-03-23T13:53:51.216-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>Shell script to locate a Java class</title><content type='html'>The following shell script will locate a Java class in CLASSPATH and additional jars, zip files, or directories specified on the command line. For example,&lt;br /&gt;&lt;pre class="htmlize"&gt;$ CLASSPATH= findClass DataSourceRealm /usr/local/tomcat/server/lib/*.jar&lt;br /&gt;---- Searching for DataSourceRealm&lt;br /&gt;---- Searching in /usr/local/tomcat/server/lib/catalina-ant.jar&lt;br /&gt;---- Searching in /usr/local/tomcat/server/lib/catalina.jar&lt;br /&gt;org/apache/catalina/realm/DataSourceRealm.class&lt;br /&gt;---- Searching in /usr/local/tomcat/server/lib/commons-beanutils.jar&lt;br /&gt;...&lt;br /&gt;**** DataSourceRealm found in /usr/local/tomcat/server/lib/catalina.jar&lt;br /&gt;&lt;/pre&gt;&lt;h2&gt;Source&lt;/h2&gt;&lt;pre class="htmlize"&gt;&lt;span class="comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="comment"&gt;!/bin/&lt;/span&gt;&lt;span class="keyword"&gt;bash&lt;/span&gt;&lt;span class="comment"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="comment"&gt;****h* bin/findClass&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;NAME&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;findClass - searches for a Java class in directories, jars, zip files, and CLASSPATH&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;ARGUMENTS&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;* 1 - Java class name or substring&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;* ... - additional directories, jars, zip files&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;RETURN VALUE&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;* exit code 0, if the class is found&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;#   &lt;/span&gt;&lt;span class="comment"&gt;* exit code 1, if the class is not found&lt;br /&gt;&lt;/span&gt;&lt;span class="comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="comment"&gt;SOURCE&lt;br /&gt;&lt;/span&gt;&lt;span class="keyword"&gt;if&lt;/span&gt; [ $&lt;span class="variable-name"&gt;#&lt;/span&gt; -eq 0 ]; &lt;span class="keyword"&gt;then&lt;/span&gt;&lt;br /&gt;    &lt;span class="builtin"&gt;echo&lt;/span&gt; &lt;span class="string"&gt;"Usage: findClass &amp;lt;CLASSNAME&amp;gt; [ FILE ... ]"&lt;/span&gt;&lt;br /&gt;    &lt;span class="keyword"&gt;exit&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;fi&lt;/span&gt;&lt;br /&gt;&lt;span class="variable-name"&gt;class&lt;/span&gt;=&lt;span class="string"&gt;`echo $1| tr . /`&lt;/span&gt;&lt;br /&gt;&lt;span class="builtin"&gt;shift&lt;/span&gt;&lt;br /&gt;&lt;span class="variable-name"&gt;allDirs&lt;/span&gt;=&lt;span class="string"&gt;"$(echo "&lt;/span&gt;$&lt;span class="variable-name"&gt;@&lt;/span&gt;&lt;span class="string"&gt;" $CLASSPATH| perl -F: -ane 'print join("&lt;/span&gt; &lt;span class="string"&gt;",@F);')"&lt;/span&gt;&lt;br /&gt;&lt;span class="builtin"&gt;printf&lt;/span&gt; -- &lt;span class="string"&gt;"---- Searching for %s\n"&lt;/span&gt; &lt;span class="string"&gt;"$class"&lt;/span&gt; &amp;gt;&amp;amp;2&lt;br /&gt;&lt;span class="variable-name"&gt;foundIn&lt;/span&gt;=()&lt;br /&gt;&lt;span class="keyword"&gt;for&lt;/span&gt; dir&lt;span class="keyword"&gt; in&lt;/span&gt; $&lt;span class="variable-name"&gt;allDirs&lt;/span&gt;; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;    &lt;span class="builtin"&gt;printf&lt;/span&gt; -- &lt;span class="string"&gt;"---- Searching in %s\n"&lt;/span&gt; &lt;span class="string"&gt;"$dir"&lt;/span&gt; &amp;gt;&amp;amp;2&lt;br /&gt;    &lt;span class="keyword"&gt;case&lt;/span&gt; $&lt;span class="variable-name"&gt;dir&lt;/span&gt;&lt;span class="keyword"&gt; in&lt;/span&gt;&lt;br /&gt;        *.zip)&lt;br /&gt;            unzip -v &lt;span class="string"&gt;"$dir"&lt;/span&gt; | grep $&lt;span class="variable-name"&gt;class&lt;/span&gt; &amp;amp;&amp;amp; foundIn[${#&lt;span class="variable-name"&gt;foundIn&lt;/span&gt;}]=&lt;span class="string"&gt;"$dir"&lt;/span&gt;&lt;br /&gt;            ;;&lt;br /&gt;        *.jar)&lt;br /&gt;            jar -tf &lt;span class="string"&gt;"$dir"&lt;/span&gt; | grep $&lt;span class="variable-name"&gt;class&lt;/span&gt; &amp;amp;&amp;amp; foundIn[${#&lt;span class="variable-name"&gt;foundIn&lt;/span&gt;}]=&lt;span class="string"&gt;"$dir"&lt;/span&gt;&lt;br /&gt;            ;;&lt;br /&gt;        *)&lt;br /&gt;            find &lt;span class="string"&gt;"$dir"&lt;/span&gt; -print | grep $&lt;span class="variable-name"&gt;class&lt;/span&gt; &amp;amp;&amp;amp; foundIn[${#&lt;span class="variable-name"&gt;foundIn&lt;/span&gt;}]=&lt;span class="string"&gt;"$dir"&lt;/span&gt;&lt;br /&gt;            ;;&lt;br /&gt;    &lt;span class="keyword"&gt;esac&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;done&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;if&lt;/span&gt; [ ${#&lt;span class="variable-name"&gt;foundIn&lt;/span&gt;} -eq 0 ]; &lt;span class="keyword"&gt;then&lt;/span&gt;&lt;br /&gt;    &lt;span class="builtin"&gt;printf&lt;/span&gt; -- &lt;span class="string"&gt;"**** %s not found\n"&lt;/span&gt; &lt;span class="string"&gt;"$class"&lt;/span&gt; &amp;gt;&amp;amp;2&lt;br /&gt;    &lt;span class="keyword"&gt;exit&lt;/span&gt; 1&lt;br /&gt;&lt;span class="keyword"&gt;else&lt;/span&gt;&lt;br /&gt;    &lt;span class="builtin"&gt;printf&lt;/span&gt; -- &lt;span class="string"&gt;"**** %s found in %s\n"&lt;/span&gt; &lt;span class="string"&gt;"$class"&lt;/span&gt; &lt;span class="string"&gt;"${foundIn[*]}"&lt;/span&gt; &amp;gt;&amp;amp;2&lt;br /&gt;&lt;span class="keyword"&gt;fi&lt;/span&gt;&lt;br /&gt;&lt;span class="comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="comment"&gt;****&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-334431538309677036?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/334431538309677036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=334431538309677036' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/334431538309677036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/334431538309677036'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/03/shell-script-to-locate-java-class.html' title='Shell script to locate a Java class'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-5835517486847827437</id><published>2007-03-22T11:31:00.000-04:00</published><updated>2007-03-23T08:25:17.938-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='malware'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><title type='text'>I am glad I am not using Windows</title><content type='html'>Just read a scary and fascinating story  about Gozi Windows trojan, which   sees through SSL and steals bank passwords, security questions, and the newfangled security pictures. I am so glad my desktop machine runs Linux, in which malware will not be able to install itself as a layer between the browser and the SSL code. &lt;a href="http://www.secureworks.com/research/threats/gozi/"&gt;More details&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-5835517486847827437?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/5835517486847827437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=5835517486847827437' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/5835517486847827437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/5835517486847827437'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/03/i-am-so-glad-i-am-not-using-windows.html' title='I am glad I am not using Windows'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6427421974690377954.post-6572439051741107308</id><published>2007-03-22T09:46:00.000-04:00</published><updated>2007-03-23T13:53:27.957-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='valve'/><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><category scheme='http://www.blogger.com/atom/ns#' term='realm'/><title type='text'>Returning login failure reason in a Tomcat Realm</title><content type='html'>When Tomcat Realm authenticates a user via its Realm, there is no way for the Realm to tell the application the exact reason of a failure. The realm either succeeds and returns a &lt;span class="monospace"&gt;Principal&lt;/span&gt; object or fails and returns &lt;span class="monospace"&gt;null&lt;/span&gt;. So, when I needed to implement account lockout after several unsuccessful logins, I couldn't  show the user the difference between a wrong password and account being locked out.&lt;br /&gt;&lt;br /&gt;Digging deeper into Tomcat code, I found that the Realm is being invoked from FormAuthenticator Valve. It is possible to extend the Valve so that in case of authentication failure, the Valve adds failure reason as an HttpServletRequest attribute. More details in &lt;a href="http://snippets.dzone.com/posts/show/3715"&gt;ExtendedStatusFormAuthenticator&lt;/a&gt; code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6427421974690377954-6572439051741107308?l=www.shadegrowncode.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.shadegrowncode.com/feeds/6572439051741107308/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6427421974690377954&amp;postID=6572439051741107308' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/6572439051741107308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6427421974690377954/posts/default/6572439051741107308'/><link rel='alternate' type='text/html' href='http://www.shadegrowncode.com/2007/03/returning-login-failure-reason-in.html' title='Returning login failure reason in a Tomcat Realm'/><author><name>Nicholas Sushkin</name><uri>http://www.blogger.com/profile/13580158096973753230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
