<rss xmlns:atom='http://www.w3.org/2005/Atom' version='2.0'>
 <channel>
    <title>hccp.org</title>
    <link>http://www.hccp.org/</link>
    <description>Hacks, essays, and code.</description>
    <language>en-us</language>
    <pubDate>Tue, 1 Jun 2010 02:00:00 PST</pubDate>
    <atom:link href='http://www.hccp.org/rss.xml' rel='self' type='application/rss+xml'/>


<item><title>Full Screen Terminal in OS X</title><link>http://www.hccp.org/full-screen-xterm.html</link><description><![CDATA[<h2>Full Screen Terminal in OS X</h2><p>I've often used <a href='http://www.hogbaysoftware.com/products/writeroom'>WriteRoom</a> for distraction-free text editing, but I've often wanted the same full-screen experience with <i>Terminal.app</i>. While <i>Terminal.app</i> does not  support this behavior, one can create a reasonable approximation using <i>X11.app</i> and <i>xterm</i>. Here is how to set it up:</p><p>
	Open up the <i>X11.app</i> plist using the <i>Property List Editor.app</i>:<pre>
		
 &gt; open -a /Developer/Applications/Utilities/Property\ List\ Editor.app ~/Library/Preferences/org.x.X11.plist

</pre>
Make the following edits:
<ul>
	<li><i>apps_to_run</i>: we don't want multiple <i>xterm</i>s to start, so we need to suppress the default behavior of X11.app. Replace the inital start of <i>xterm</i> with a dummy command like "logger -s 'this is a dummy command for x11 startup'" (you must have some command defined here, or X11.app will default to starting an <i>xterm</i> instance)<br/><br/></li>
	<li><i>login_shell</i>: set this entry to <i>/bin/bash</i>. This has no impact on the full screen behavior of <i>xterm</i>, but I personally prefer <i>/bin/bash</i> over <i>/bin/sh</i> and it is the default shell of <i>Terminal.app</i>.<br/><br/></li>
	<li><i>rootless</i>: un-checking this box makes <i>X11.app</i> use full screen mode (this is the same behaviour as selecting "full screen" from the Preferences tab in <i>X11.app</i>). To toggle out of this mode use <i>Command-Option-A</i></li>  	
</ul>
<div align='center'><img alt='screenshot of plist editor' border='1' src='x11-plist.gif'/></div> 
</p><p>Next, set up a <i>.xinitrc</i> file to launch an <i>xterm</i> instance at the launch of <i>X11.app</i>, specifying the default size of the window. (Note the settings listed here are specific to my 15'' MacBook Pro with the default font and font-size.):<pre>
	
 &gt; echo 'exec xterm -geometry 239x69' > ~/.xinitrc
	
</pre>
Restart <i>X11.app</i> and you should find yourself with a fullscreen terminal session. (Remember, to toggle out of full screen mode, use <i>Command-Option-A</i>)</p><p>Additional <i>.xinitrc</i> configurations:
	<ul>
		<li>Setting colors: append <i> -fg &lt;color&gt; -bg &lt;color&gt; </i> to the <i>xterm</i> invocation in <i>.xinitrc</i> (i.e. <i> -fg green -bg black </i>)</li>
		<li>Turn off audio and visual bell: put <i>xset -b</i> at start of  <i>.xinitrc</i></li>
		
	</ul>
</p><p class='footer'>6/26/2010</p>]]></description><author>igb@hccp.org</author><pubDate>Sat, 26 Jun 2010 00:00:00 PST</pubDate><guid>http://www.hccp.org/full-screen-xterm.html</guid></item><item><title>Simple SMTP Sender for Erlang</title><link>http://www.hccp.org/simple-smtp-sender.html</link><description><![CDATA[<h2>Simple SMTP Sender for Erlang</h2><p>I've never been able to fathom why SMTP isn't part of the OTP, nor why I can't find a <i>simple</i> third-party SMTP client written in Erlang for sending emails. Anyway, <a href='simple_smtp_sender.erl'>here</a> is a trivial SMTP client for sending emails, hacked together in a few minutes...YMMV.
<pre>
	
	-module(simple_smtp_sender).

	-export([send/4, send/5, send/6, send/7]).

	send(To, From, Subject, Message)->
		Server="localhost",
		send(To, From, Subject, Message, Server).

	send(To, From, Subject, Message, Server)->
		PortNo=25,	
		send(To, From, Subject, Message, Server, PortNo).

	send(To, From, Subject, Message, Server, PortNo)->
		{ok, Hostname}=inet:gethostname(),
		send(To, From, Subject, Message, Server, PortNo, Hostname).

	send(To, From, Subject, Message, Server, PortNo, LocalDomain)->
		{ok,Sock}=gen_tcp:connect(Server,PortNo,[{active, false}]),
		{ok, "220"++_}=gen_tcp:recv(Sock, 0),
		gen_tcp:send(Sock, lists:append(["HELO ", LocalDomain, [13, 10]])),
		{ok, "250"++_}=gen_tcp:recv(Sock, 0),
		gen_tcp:send(Sock, lists:append(["MAIL FROM: ", From, [13, 10]])),
		{ok, "250"++_}=gen_tcp:recv(Sock, 0),
		gen_tcp:send(Sock, lists:append(["RCPT TO: ", To, [13, 10]])),
		{ok, "250"++_}=gen_tcp:recv(Sock, 0),
		gen_tcp:send(Sock, lists:append(["DATA", [13, 10]])),
		{ok, "354"++_}=gen_tcp:recv(Sock, 0),
		gen_tcp:send(Sock, lists:append(["Subject: ", Subject, [13, 10],[13, 10]])),
		gen_tcp:send(Sock, lists:append([Message])),
		gen_tcp:send(Sock, lists:append([[13, 10],".",[13, 10],[13, 10]])),
		{ok, "250"++_}=gen_tcp:recv(Sock, 0),
		gen_tcp:send(Sock,lists:append("QUIT", [13, 10])),
		{ok, "221"++_}=gen_tcp:recv(Sock, 0),
		gen_tcp:close(Sock),
		ok.	
	
	
</pre>
</p><h3>Usage</h3><p>
<pre>
	
	Erlang R13B02 (erts-5.7.3) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]

	Eshell V5.7.3  (abort with ^G)
	1> simple_smtp_sender:send("spam@hccp.org", "spam@hccp.org", "this is a subject", "and this is a message",  "smtp.hccp.org", 25).
	ok	

</pre>	
</p><p class='footer'>
6/11/2010</p>]]></description><author>igb@hccp.org</author><pubDate>Sat, 06 Nov 2010 00:00:00 PST</pubDate><guid>http://www.hccp.org/simple-smtp-sender.html</guid></item><item><title>Extracting POST data from an HTTP request when using gen_tcp</title><link>http://www.hccp.org/erlang-and-post.html</link><description><![CDATA[<h2>Extracting POST data from an HTTP request when using <i>gen_tcp</i><</h2><h3>A Simple Webserver</h3><p>Let's implement a simple loop, using <a href='http://www.erlang.org/doc/man/gen_tcp.html'>gen_tcp</a> to listen on a particular port, and spawn a handler process for each incoming request (note that we have not defined <i>handle_request/1</i> yet). When setting up the initial socket, we are going to specify that incoming packets be packaged according as <i>HttpPacket</i> types, as defined in <a href='http://www.erlang.org/doc/man/erlang.html#decode_packet-3'>decode_packet/3</a> built-in function (BIF).
	<pre>
		
 start(Port)->
  {ok, ListenSock}=gen_tcp:listen(Port, [list,{active, false},{packet,http}]),
  ?MODULE:loop(ListenSock).
 
 loop(ListenSock) ->	
  {ok, Sock}=gen_tcp:accept(ListenSock),
  spawn(?MODULE, <b>handle_request</b>, [Sock]),
  ?MODULE:loop(ListenSock).

</pre>
</p><h3>Determining the HTTP Request Method</h3><p>Since we are going to deal with POST request data we will need to differentiate between POST methods and non-POST methods (i.e. GET, PUT, etc.). The 2nd element of the HttpRequest tuple (<i>{http_request, HttpMethod, HttpUri, HttpVersion}</i>) will provide us with an atom matching one of the seven HTTP method types, so we can dispatch requests to the appropriate handler for a given method type.
<pre>
	
 handle_request(Sock) ->
  {ok, {http_request, Method, Path, Version}}=gen_tcp:recv(Sock, 0),
  case (Method) of
   'POST' -> handle_post(Sock);
   _ -> send_unsupported_error(Sock)
  end.

</pre>		
</p><h3>Iterating over a Request's HTTP Headers</h3><p>In order to retrieve the data contained in the body of a POST request we will first need to determine the length of the data. This information can be found in the <i>Content-Length</i> header, and we can get this information by iterating over the headers with a case statement and a little recursion, returning once we find the value we are looking for:
<pre>

 get_content_length(Sock) ->
  case gen_tcp:recv(Sock, 0, 60000) of
   {ok, {http_header, _, 'Content-Length', _, Length}} -> list_to_integer(Length);
   {ok, {http_header, _, Header, _, _}}  -> get_content_length(Sock)
 end.

</pre>
</p><h3>Extracting the Data</h3><p>Now, all we need to do is iterate over the remaining headers until we get to the <i>http_eoh</i> atom indicated the end of header ("eoh") information...we can then turn off the HTTP type wrapping and read the raw POST data from the socket. 
<pre>

 get_body(Sock, Length) ->
  case gen_tcp:recv(Sock, 0) of
   {ok, http_eoh} ->inet:setopts(Sock, [{packet, raw}]),{ok,Body}=gen_tcp:recv(Sock, Length),Body;
   _ -> get_body(Sock, Length)
  end.

</pre>
Putting it all together, our <i>handle_post/1</i> function would look something like this:
<pre>
	
 handle_post(Sock) ->
  Length=get_content_length(Sock),
  PostBody=get_body(Sock, Length),
  io:fwrite(PostBody),
  send_accept(Sock).

</pre> 	
</p><h3>Misc. Items</h3><p>While not really in scope of this article, let's fill in a few functions we referenced above.
<pre>
	
 send_accept(Sock) ->
	gen_tcp:send(Sock, "HTTP/1.1 202 Accepted\r\nConnection: close\r\nContent-Type: text/html; charset=UTF-8\r\nCache-Control: no-cache\r\n\r\n"),
	gen_tcp:close(Sock).
	
 send_unsupported_error(Sock) ->
	gen_tcp:send(Sock, "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\nAllow: POST\r\nContent-Type: text/html; charset=UTF-8\r\nCache-Control: no-cache\r\n\r\n"),
	gen_tcp:close(Sock).	
	
</pre>	
</p><p class='footer'>
6/1/2010</p>]]></description><author>igb@hccp.org</author><pubDate>Tue, 01 Jun 2010 00:00:00 PST</pubDate><guid>http://www.hccp.org/erlang-and-post.html</guid></item><item><title>Persisting method metadata at runtime and checking metadata correctness at compile time using annotations in Java 1.6</title><link>http://www.hccp.org/compile-time-annotation-verification.html</link><description><![CDATA[<h2>Persisting method metadata at runtime and checking metadata correctness at compile time using annotations in Java 1.6</h2><p>A few weeks ago I was cobbling together a web service for API authentication, and figured I could simply expose an existing class as a simple XML-over-HTTP web service. Since this was the beginning of a larger project  at our company to provide API access to a some legacy internal services, I didn't want to manually write a wrapper for each service class. To avoid that onerous task, I figured I'd hack together a code generator or a generic server that could dynamically create endpoints from these classes via reflection (similar, but simpler, than <a href='http://ws.apache.org/axis/'>Apache Axis</a>, <a href='http://java.sun.com/webservices/docs/2.0/tutorial/doc/JAXWS.html'>JAX-WS</a> or other RPC/remoting frameworks).</p><p>Java's reflection API is a pretty handy way of iterating over a given class's available methods, and you can use this facility to create and map web service calls to class instances in a given runtime. If a method name is, say <i>getNewsItems()</i> (which you can determine via the Method class object's <i>getName()</i> method), and has a return type of List&lt;String> (which you can determine via the Method class's <i>getReturnType()</i> method) you could, perhaps, create a virtual endpoint at runtime at the path <i>/news-items/</i> and return an XML representation of a  list of strings for each HTTP GET request received by your server.</p><p>What you do not have access to via reflection, at least as of 1.6, is access to to the names assigned to the parameters in the source code of the method definition. This is problematic if you are attempting to provide a semantically sensible message or serialization format for a method signature containing one or more parameters. Frameworks that operate purely on reflection (like Axis) tend to generate stubs and skeletons with parameter names like "s0" or "i2" relying on an impoverished metadata set consisting of type and ordering information. However, an easy way to add metadata to a class or method is to create a custom annotation...for our purposes, here is a simple annotation that contains an array of Strings in a property called "parameterNames": 
<pre>
	
 package org.hccp.annotations;

 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;

 @Retention(RetentionPolicy.RUNTIME)  @interface ParameterNames {
    String[] parameterNames();
 }

</pre>
We can now use this annotation in normal Java classes to add information that we can inspect at runtime:
<pre>
 package  org.hccp.dummy;

 import org.hccp.annotations.ParameterNames;
 
 public class Dummy {
 
  @ParameterNames(parameterNames = {"foo", "bar"})
  public String annotationTest(String foo, int bar) {
  	return foo + bar;
  }
 }
 </pre>
Now we  can query the class for this info:		
<pre>
	
 Method[] methods = org.hccp.dummy.Dummy.class.getMethods();
 for (int i = 0; i &lt; methods.length; i++) {
  Method method = methods[i];
  if (method.isAnnotationPresent(org.hccp.annotations.ParameterNames.class)) {
   org.hccp.annotations.ParameterNames parameterNames = method.getAnnotation(org.hccp.annotations.ParameterNames.class);
   Class&lt;?>[] parameterTypes=method.getParameterTypes();
   for (int i = 0; i &lt; parameterTypes.length; i++) {
    Class&lt;?> paramTypeClass = classes[i];
    String parameterName = parameterNames[i]; <i>// these array are gonna be the same length, right?</i>
    System.out.println("Parameter " +  + "is of type " + paramTypeClass.getName());
   }
  }
 }

</pre>
An obvious weakness in the above metadata convention is that  we are relying on developer diligence to keep the metadata in sync as the method parameter list changes, evolves, is refactored, etc. We can work around this by adding a runtime check (i.e.  <i>parameterTypes.length == parameterNames.length</i>) to ensure that the list length of the annotated parameter names is the same as the parameter types returned by the reflection query, however this means that 1) we would defer detection of a length mismatch until runtime when it might too late to take corrective action and 2) it won't actually detect deviations or mismatches that preserve the length but change order or replace variables outright. Compile time is a much better place to check the correctness of the metadata, especially given that we have access to the source code (and therefore the original parameter names). Lucky for us the annotations framework provides a mechanism for processing annotated source (via the poorly named <i>apt</i> tool in JDK 1.5, and with <i>javac</i> as of JDK 1.6). So let's dive right in and create an implementation of <i>javax.annotation.processing.Processor</i>, the 1.6 interface that defines the hooks for compile-time annotation, uh, processing.
<pre>
	
 package org.hccp.annotations;

 import javax.annotation.processing.*;
 import javax.lang.model.SourceVersion;
 import javax.lang.model.element.*;
 import javax.tools.Diagnostic;
 import java.util.List;
 import java.util.Set;

 @SupportedAnnotationTypes(value = {"org.hccp.annotations.ParameterNames"})
 @SupportedSourceVersion(SourceVersion.RELEASE_6)
 public class ParameterNamesProcessor extends AbstractProcessor {

  @Override
  public boolean process(Set&lt;? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   Set&lt;? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(org.hccp.annotations.ParameterNames.class);
   for (Element element : annotatedElements) {
    if (ElementKind.METHOD.equals(element.getKind())) {
     ParameterNames parameterNamesAnnotation = element.getAnnotation(ParameterNames.class);
     String[] parameterNames = parameterNamesAnnotation.parameterNames();
     
     ExecutableElement executableElement = (ExecutableElement) element;
     List&lt;? extends VariableElement> parameters = executableElement.getParameters();
     if (parameterNames.length != parameters.size()) {
      processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Mismatch in number of annotated" +
                           "parameter names and the actual parameters declared in the annotated method.");
      return true;
	 }
     int i = 0;
     for (VariableElement parameter : parameters) {
      if (!parameter.getSimpleName().toString().equals(parameterNames[i])) {
       processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Asserted paramter name at position " + i 
                          + " is " + parameterNames[i] 
                          + " and does not match actual parameter name at same position: "
                          + parameter.getSimpleName().toString());
       return true;
      }
      
      i++;
     }
     processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Asserted parameter names successfully" +
                "matched against annotated method.");
     return true;
	}

   }
   return false;
  }
 }
	
</pre>

To use this processor at compile time, we simply invoke <i>javac</i> with the <i>-processor</i> flag to indicate what processor implementation we should be using. Here is what a successful run would look like: 
<pre>
	
 <i>> javac  -cp path/including/compiled/processor <b>-processor org.hccp.annotations.ParameterNamesProcessor</b> src/org/hccp/dummy/Dummy.java</i>
 ><i> Note: Asserted parameter names successfully matched against annotated method.</i>
 >	</pre>
And here is what a failure might look at if a parameter name had been changed (in the Dummy.java example above, we have changed "bar" to "yikes" but did not update the annotation):
<pre>
	
 ><i> javac  -cp path/including/compiled/processor <b>-processor org.hccp.annotations.ParameterNamesProcessor</b> src/org/hccp/dummy/Dummy.java</i>
 ><i> error: Asserted paramter name at position 1 is bar and does not match actual parameter name at same position: yikes</i>
 ><i> 1 error</i>
 >	
</pre>
</p><p>By ensuring correctness of metadata at compile time, you can enforce implicit runtime contracts in your code. Dependency on convention becomes less risky, as assertions and relationships can be tested during build of classes and components.</p><p class='footer'>
4/6/2010</p>]]></description><author>igb@hccp.org</author><pubDate>Tue, 06 Apr 2010 00:00:00 PST</pubDate><guid>http://www.hccp.org/compile-time-annotation-verification.html</guid></item><item><title>Comet Tail</title><link>http://www.hccp.org/comet-tail.html</link><description><![CDATA[<h2>Comet Tail</h2><h3>Comet</h3><p><a href='http://en.wikipedia.org/wiki/Comet_(programming)'>Comet</a> is a technique for HTTP content delivery that uses persistent connections between server and browser. <a href='http://www.w3.org/Protocols/rfc2616/rfc2616.html'>HTTP 1.1</a> introduced a "chunked" transfer encoding, allowing data to be sent in "chunks" to the client over an extended period of time. Most modern web browsers will render or process each chunk of data as it is received, creating a stream of page items, executable scriptlets, or raw data.</p><h3>tail -f</h3><p>When invoked with the <a href='http://en.wikipedia.org/wiki/Tail_(Unix)#File_monitoring'>"-f"</a> option, the unix command <a href='http://www.thelinuxblog.com/linux-man-pages/1/tail'>tail</a> will continuously print newly added lines from  a given file to stdout. This is pretty handy when monitoring logs, debugging servers, tracking progress of a running application, etc. </p><h3>"tailing" logs over HTTP using Comet</h3><h4>Implementing tail -f in Erlang</h4><p>First off, we are going to need a mechanism for "tailing" a given file. Handily, Erlang's <a href='http://ftp.sunet.se/pub/lang/erlang/doc/man/io.html'>io</a> module provides a function for reading from a file, line by line...here is a simple set of functions that read a file from beginning to end, printing each line, and then blocking while waiting for further appendations to that file (and printing each newly appended line):
	<pre>
		
 %% read a line from a file and print it...
 %% ... if at end of file, try and try again until a new line appears
		
 tail(File) ->
  case io:get_line(File, "") of
   eof  -> tail(File);
   Line ->	io:fwrite(Line),
            tail(File)
  end.

  %% example:
  %% {ok, MyFile}=file:open("/path/to/my/file", [read]).
  %% tail(MyFile). 	
		
	</pre>
	</p><h4>A Tiny Comet Server</h4><p>Erlang is a pretty handy language for writing networked IO-driven applications and it's support for TCP socket manipulation out of the box (using the OTP gen_tcp module),  make it pretty easy to hack together a tiny, specific-purpose webserver. Let's fire up <a href=''>erl</a> and execute a few lines to create an HTTP server listening on a non-standard port (in this example, port <i>9999</i>):
<pre>

 <b>Erlang R13B02 (erts-5.7.3) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]
 Eshell V5.7.3  (abort with ^G)</b>

 1> {ok, ListenSock}=gen_tcp:listen(9999, [list,{active, false},{packet,http}]).
 <i>{ok,#Port&lt;0.455>}</i>
 2> {ok, Sock}=gen_tcp:accept(ListenSock).
	
</pre>
<i>gen_tcp:accept/1</i> will block until an HTTP request is recieved...let's use <a href=''>curl</a> or <a href=''>wget</a> to initiate a request:
<pre>

 > curl -v http://127.0.0.1:9999
 <i>* About to connect() to 127.0.0.1 port 9999 (#0)
 *   Trying 127.0.0.1... connected
 * Connected to 127.0.0.1 (127.0.0.1) port 9999 (#0)
 > GET / HTTP/1.1
 > User-Agent: curl/7.19.4 (universal-apple-darwin10.0) libcurl/7.19.4 OpenSSL/0.9.8l zlib/1.2.3
 > Host: 127.0.0.1:9999
 > Accept: */*
 ></i> 

</pre>
<i>curl</i> will now be blocking, waiting on a response from the server...and if we switch back to our erl session, we will see that the <i>gen_tcp:accept/1</i> function has returned a socket for us to which we can write data. So what should we write? Well, first, let's inform the waiting client that we will be sending data using "chunking". We will send an HTTP 200 back to the client, but instead of providing <i>"Content-Length"</i>  header we will send back <i>"Transfer-Encoding: chunked"</i>. We won't close the connection, and we won't send any data right now.:
<pre>

 ...
 2> {ok, Sock}=gen_tcp:accept(ListenSock).	
 <i>{ok,#Port&lt;0.461>}</i>
 3> gen_tcp:send(Sock, "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\nCache-Control: no-cache\r\n<b>Transfer-Encoding: chunked</b>\r\n\r\n").
 <i>ok</i>

</pre>	 	
<i>curl</i> will receive the sent headers, and keep the connection open, awaiting more data
<pre>

 <i>&lt; HTTP/1.1 200 OK
 &lt; Content-Type: text/html; charset=UTF-8
 &lt; Cache-Control: no-cache
 &lt; Transfer-Encoding: chunked
 &lt;</i> 

</pre>
Now, let's write a small function to send data to the client. For each "chunk" of data, we will need to calculate the size, in bytes, and send that number, hex-encoded, ahead of each chunk. The termination of the chunk is indicated by a carriage return: "\r\n".
<pre>

 4>  SendChunk=fun(Sock, Data) -> Length=io_lib:format("~.16B", [length(Data)]),
	gen_tcp:send(Sock, Length),
	gen_tcp:send(Sock, "\r\n"),
	gen_tcp:send(Sock, Data),
	gen_tcp:send(Sock, "\r\n") 
      end.
 <i>#Fun&lt;erl_eval.12.113037538></i>
 5> SendChunk(Sock, "Hello World!").
 <i>ok</i>
 6> SendChunk(Sock, "Chunky Bacon! Chunky Bacon!").
 <i>ok</i>
 7> SendChunk(Sock, "Hexapodia as the key insight").
 <i>ok</i>

</pre>
Flipping back over to our <i>curl</i> session, we should see the chunks arriving:
<pre>
	
 <i>C
 Hello World!
 1B
 Chunky Bacon! Chunky Bacon!
 1C
 Hexapodia as the key insight</i>
			
</pre>
Now let's see how a browser behaves with a chunked stream...open up Firefox or Google Chrome (don't try Safari or IE yet--we'll explain why later on in this post) and point it to http://127.0.0.1:9999/ . Switch back to our <i>erl</i> session so we can accept the browser's request, create a socket, and start writing chunks to the browser...
<pre>

 8> {ok, BrowserSock}=gen_tcp:accept(ListenSock). 
 <i>{ok,#Port&lt;0.483>}</i>
 9>  gen_tcp:send(BrowserSock, "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\nCache-Control: no-cache\r\nTransfer-Encoding: chunked\r\n\r\n").
 <i>ok</i>
 10> SendChunk(BrowserSock, "&lt;head>&lt;body>").
 <i>ok</i>	
 11> SendChunk(BrowserSock, "&lt;h1>One conversation centered on the ever accelerating progress of technology and changes...&lt;/h1>").	 
 <i>ok</i>	
 12> SendChunk(SafariSock, "&lt;script language='JavaScript'>alert('8.68 days since Fall of Relay');&lt;/script>").
 <i>ok</i>	

</pre>	
If you watch your browser window, you will see the page render the &lt;H1> text as it is sent/received, and then execute the subsequently sent scriptlet
<div align='center'><br/><img src='comet-script-screen-sm.gif' align='center'/></div>
</p><h4>Putting it all together</h4><p>
Pretty cool, eh? Ok, let's go back and take a look at the tail function we created earlier...it's pretty obvious we can send each line to a socket instead of merely printing to standard out. Having covered the basic steps above,  I won't walk through the complete solution line by line, but you can download the source  <a href='comet_tail.erl'> here</a> ( <a href='comet_tail.erl'>comet_tail.erl</a> ) and I'll walk though a usage example below. 
</p><p>Let's fire up <i>erl</i> and  compile the module, and start up a server on a given port (the first parameter of <i>comet_tail:start/2</i>). The second parameter is the directory prefix that will be prepended to file paths provided as request parameters:
<pre>
	
 > erl -sname node1@localhost
 <b>Erlang R13B02 (erts-5.7.3) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]
 Eshell V5.7.3  (abort with ^G)</b> 
 <b>(node1@localhost)1></b> c(comet_tail).
 {ok,comet_tail}
 <b>(node1@localhost)2></b> comet_tail:start(9999, "/var/log/apache2/").

</pre>
Now you have a tail -f server running on port 9999, serving up files in the <i>/var/log/apache2/</i> directory (if you are on a recent version of OSX this is where your apache access logs are). Files streams are requested by passing a query string consisting of the filename relative to the base dir we started the server with. (Again, for OS X you should be able to view a tailed file with the above configuration by visiting <a href='http://127.0.0.1:9999/comet-tail?access_log'>http://127.0.0.1:9999/comet-tail?access_log</a>) 
<br/>
<br/>
Here is a live example streaming a tail of this webserver's acess log: <a href='http://www.hccp.org:9999/comet-tail?access_log' rel='nofollow'>http://www.hccp.org:9999/comet-tail?access_log</a> You can play along at home by visiting pages on <a href='http://www.hccp.org'>http://www.hccp.org</a> and watching requests show up at tail of stream.</p><h3>Various and Sundry Hacks</h3><h4>Scrolling</h4><p>While the chunked stream will render, line by line in your browser, the default window behavior is to keep the view of a file positioned at the top, even as new content loads below the fold. To provide a tail-like scrolling experience, we will need to use a bit of HTML-hackery. One way to accomplish this scroll is to place the streaming content in an IFrame, and use JavaScript to constantly reposition the IFrame scroll to the end of the window. Here is the script that we use to manipulate the IFrame:
<pre>
	
 function loop() { 
	if(navigator.userAgent.indexOf('Safari') > 0) { 	
		window.frames['logframe'].scrollBy(0 , 10000000); 
	} else  { 
		document.getElementById('logframe').contentWindow.scrollBy(0, 100000); 
	} 
	setTimeout('loop()', 1000); 
 } 
 loop(); 

</pre>


</p><h4>IFrames and the JavaScript Security Model</h4><p>Another pain point is that most browsers will not allow a parent window to access/manipulate DOM properties of a child IFrame (this is a good thing as it prevents phishing attacks that wrap legit windows and steal passwords, debit bank accounts and other nasty stuff). In order to scroll an internal frame, both the parent and the child IFrame <i>must</i> be served by the same host <i>and</i> port. Since I didn't want to have to proxy the Comet-tail server in order to provide a uniform endpoint to consumers of the parent and child IFrame, I decided to enhance the purpose-specific webserver to also serve up a static parent wrapper for the IFramed stream. 

</p><h4>Buffering in Safari (and IE?)</h4><p>Safari will not render content until a 1KB buffer has been filled. To get around this, we add a 1KB empty comment to each line we send.
<pre>

 %% generate a ~n kb comment for Safari and other lame-o browsers in order to force flush...
 generate_comment_for_length([], Length) ->
	generate_comment_for_length("&lt;!--", Length - 4);
 generate_comment_for_length(Comment, 0) ->
		lists:append(Comment, "-->");	
 generate_comment_for_length(Comment, Length) ->
	generate_comment_for_length(lists:append(Comment, " "), Length -1).
	
</pre>	
</p><p class='footer'>
3/18/2010</p>]]></description><author>igb@hccp.org</author><pubDate>Thu, 18 Mar 2010 00:00:00 PST</pubDate><guid>http://www.hccp.org/comet-tail.html</guid></item><item><title>Supervisors in Erlang</title><link>http://www.hccp.org/supervisors.html</link><description><![CDATA[<h2>Supervisors in Erlang</h2><p>Erlang (or, to be specific, <a href='http://www.erlang.org/faq/introduction.html#1.2'>the OTP</a>) provides built-in support for monitoring and restarting processes that error out or terminate unexpectedly through the  <a href='http://www.erlang.org/doc/design_principles/sup_princ.html'>supervisor behavior</a>. This is a pretty handy feature when building concurrent, distributed systems with strict uptime SLAs. Let's take a look at a simple demonstration of this functionality. First up, a simple program that fails in a deterministic fashion:
		<pre>
			
 -module(my_supervisor_example).
 -export([loop/1]).

 loop(Count) ->
 	io:fwrite("Counting down...currently at ~p.~n", [Count]),
	timer:sleep(1000),
	case Count of
		0 -> erlang:raise(exit, "Boom!", []);
		_ -> loop(Count - 1)
	end.
	</pre>
If we compile and run this example, we get a little countdown and then the program exits with an error:	
<pre>
	
 1> c(my_supervisor_example).
<i> {ok,my_supervisor_example}</i>
 2> my_supervisor_example:loop(5).  
<i> Counting down...currently at 5.
 Counting down...currently at 4.
 Counting down...currently at 3.
 Counting down...currently at 2.
 Counting down...currently at 1.
 Counting down...currently at 0.
 <b>** exception exit: "Boom!"</b></i>

</pre>	
</p><p>Since we are concerned with the lifecycle of a given <i>process</i>, we will want to run this loop as a separate process using <i>spawn_link/3</i>. This function takes a function as an argument, forks a process to run it, and returns the Pid of the forked process. That Pid is what we will pass to the supervisor so it can monitor that process, watching for an exit. So, rather than invoking our exploding loop directly, let's create a wrapper function that starts the loop using spawn_link:
<pre>
 -module(my_supervisor_example).
 <b>-export([start/1]).</b>
 -export([loop/1]).
 .
 .
 .
 <b>start(Count) ->
	io:fwrite("Starting...~n"),
 	Pid=spawn_link(my_supervisor_example, loop, [Count]),
	<i>{ok, Pid}.</i></b>
	
</pre>	
Note the return type of this function is of the form <i>{ok, Pid}</i>. This is the pattern that the supervisor is expecting the process id to be passed back as. If it get's a different pattern back, the supervisor will exit with an error, so be careful.	
	</p><p>Supervisor is a behaviour in Erlang. Implementing a behavior is similar to inheriting from an abstract class in Java, where you must implement certain  functions in order to compile without raising a warning, or to run without raising an error. These functions are  callbacks that the underlying behavior will use to interact with your program. In the case of supervisor, we must implement the function <i>init/1</i> which returns a tuple containing the information the supervisor needs to determine the monitoring and restart policy for this process. Here is what we will add to our program:
<pre>
 -module(my_supervisor_example).
 <b>-behaviour(supervisor).
 -export([init/1])</b>
 -export([start/1]).
 -export([loop/1]).
 .
 .
 . 
 <b>init([Count]) ->
	{ok, {{one_for_one, 1,60},
		[{my_supervisor_example, {my_supervisor_example, start, [Count]},
			permanent, brutal_kill, worker, [my_supervisor_example]}]}}.</b>	

</pre>
</p><p>Now we can start our program using the supervisor framework:</p><pre>
	
 1> c(my_supervisor_example).
 {ok,my_supervisor_example}
 <b>2> supervisor:start_link(my_supervisor_example, [5]).</b>
 Starting...
 Counting down...currently at 5.
 <b>{ok,&lt;0.38.0>}</b>
 Counting down...currently at 4.
 Counting down...currently at 3.
 Counting down...currently at 2.
 Counting down...currently at 1.
 Counting down...currently at 0.
 <b>Starting...</b>
 Counting down...currently at 5.
 Counting down...currently at 4.
 Counting down...currently at 3.
 Counting down...currently at 2.
 Counting down...currently at 1.
 Counting down...currently at 0.
 <b>** exception error: shutdown</b>
 3>

</pre><p>Huh?!? It looks like the loop was successfully restarted once, but then it errored out at the end of it's second run! How come the supervisor didn't restart again? Well, the answer lies within the restart policy we returned in the <i>init/1</i> function. Specifically, the behavior defined by the tuple <i>{one_for_one, 1,60}</i>. <i>one_for_one</i> is a behavior that says, in effect: "replace every exited process with one started process", and the <i>1</i> and the <i>60</i> state that we should limit the restarts to at most 1 every 60 seconds. If we exceed that threshhold, do not start any more processes. In our example above, we exceeded that threshold after the first restart. To run indefinitely, choose an appropriate interval for your purposes. For example, if we set those parameters to <i>..or_one, <b>30</b>,<b>60</b></i> ... then if we recompile and run:
	
<pre>
	
 1> c(my_supervisor_example).                         
 {ok,my_supervisor_example}
 2> supervisor:start_link(my_supervisor_example, [5]).
 Starting...
 Counting down...currently at 5.
 {ok, &lt;0.53.0>}
 Counting down...currently at 4.
 Counting down...currently at 3.
 Counting down...currently at 2.
 Counting down...currently at 1.
 Counting down...currently at 0.
 Starting...
 Counting down...currently at 5.
 Counting down...currently at 4.
 Counting down...currently at 3.
 Counting down...currently at 2.
 Counting down...currently at 1.
 Counting down...currently at 0.
 Starting...
 Counting down...currently at 5.
 Counting down...currently at 4.
 Counting down...currently at 3.
 Counting down...currently at 2.
 Counting down...currently at 1.
 Counting down...currently at 0.
 Starting...
 Counting down...currently at 5.
 Counting down...currently at 4.
 Counting down...currently at 3.
 Counting down...currently at 2.
 Counting down...currently at 1.
 Counting down...currently at 0.
 Starting...
 .
 .
 .

</pre>
And there you go, a repeatedly failing process repeatedly restarted. While this example is trivial, you can probably see it's usefulness in many real-world scenarios.		
	</p><p class='footer'>
2/27/2010</p>]]></description><author>igb@hccp.org</author><pubDate>Sat, 27 Feb 2010 01:00:00 PST</pubDate><guid>http://www.hccp.org/supervisors.html</guid></item><item><title>Posting Status Updates to Twitter Using Erlang</title><link>http://www.hccp.org/twitter-erlang-posting.html</link><description><![CDATA[<h2>Posting Status Updates to Twitter Using Erlang</h2><p>My buddy Raja was heading up to Tahoe  for the first time last weekend, and was asking about road conditions, chain control, etc. I showed him the <a href='http://www.dot.ca.gov/hq/roadinfo/i80'>California DOT I-80 status page</a> which provides status updates in a simple text file:
		<pre>
			
		I 80 
		    [IN THE SAN FRANCISCO BAY AREA]
		    THERE IS A DENSE FOG ADVISORY IN EFFECT AT THE SAN FRANCISCO-OAKLAND BAY 
		BRIDGE /IN SAN FRANCISCO/ - MOTORISTS ARE ADVISED TO DRIVE WITH CAUTION

		    [IN NORTHERN CALIFORNIA &amp; THE SIERRA NEVADA]
		    NO TRAFFIC RESTRICTIONS ARE REPORTED FOR THIS AREA.
		
</pre>
While this is pretty easy to bookmark on your mobile phone and access on the road, we figured it would be a neat service to post updates of this resource to Twitter. I also wanted to mess around a bit more with Erlang, and figured this would be a fun, quick project. So after a couple of early AM hacking sessions the <a href='http://twitter.com/i80x140'>i80x140 Twitter account</a> now provides updates for I-80 road conditions in the SF Bay Area and the Sierra Nevadas. Biggest challenge was the parsing of semi structured data...Erlang is definitely not the best language for string parsing/manipulation. To <a href='http://www.jetcafe.org/~npc/doc/euc00-sendmail.html'>quote</a> the Sendmail team: <i>"Erlang's treatment of strings as lists of bytes is as elegant as it is impractical"</i></p><p>It's built-in HTTP support, on the other hand, is pretty robust. While there are <a href='http://github.com/ngerakines/erlang_twitter'>fully fledged implementations</a> of Twitter API clients in Erlang, you can post a status update easily with a little bit of Erlang's built-in HTTP module:<pre>
 
 %% start inets...
 inets:start(),	
	
 %% Create the Basic Auth token . . .	
 UsernameAndPassword=lists:append([Username, ":", Password]),
 EncodedUsernameAndPassword=base64:encode_to_string(UsernameAndPassword),
 BasicAuthHeaderValue=lists:append("Basic ", EncodedUsernameAndPassword),

 %% POST a status update to Twitter . . .
 TwitterEndpoint="http://twitter.com/statuses/update.xml",
 Headers=[{"Authorization", BasicAuthHeaderValue}],
 ContentType="application/x-www-form-urlencoded",
 MessageBody="status=Hello World!",
 
 {ok, {{_, 200, _}, _, _}}=http:request(post, {TwitterEndpoint, Headers, ContentType, MessageBody}, [],[]),

</pre></p><p>Not much too it really. Only issue I ran into during this exercise was Twitter's <a href='http://techcrunch.com/2009/10/14/cleaning-up-the-stream-twitter-kills-duplicate-tweets/'>suppression of duplicate or recurring status updates</a>. It isn't clear what the window is on duplicate/recurrence detection, but for a service where the status can go from "NO TRAFFIC RESTRICTIONS ARE REPORTED FOR THIS AREA." to "THERE IS A DENSE FOG ADVISORY IN EFFECT..." and then back to "NO TRAFFIC RESTRICTIONS ARE REPORTED FOR THIS AREA." within an hour, the suppression of these updates would be problematic. The simple fix for this is to  append a timestamp or other unique token. Obviously, this is less than ideal as it eats into the 140 character limit, but until Twitter provides a better spam algorithm or account classification scheme, this is really the only way to avoid duplicate/recurring status suppression.</p><p class='footer'>
2/17/2010</p>]]></description><author>igb@hccp.org</author><pubDate>Wed, 17 Feb 2010 00:00:00 PST</pubDate><guid>http://www.hccp.org/twitter-erlang-posting.html</guid></item><item><title>Dynamic Class Loading/Unloading in Ruby</title><link>http://www.hccp.org/dynamic-class-loading-in-ruby.html</link><description><![CDATA[<h2>Dynamic Class Loading/Unloading in Ruby</h2><p>A recent project at work required a look at Ruby's facilities for dynamically loading, and more importantly, unloading classes. Here are the basic steps for taking a serialized-to-string class def and loading it, then unloading it...</p><p>First, let's define a class in a string . . .
<pre>

 my_class_def= &lt;&lt;-EOS
 class MyClassFoo 

  def hello()
    puts "Hello Foo!" 
  end

 end
 EOS	

</pre>
</p><p>Next, let's load this class definition, by using class_eval . . .	<pre> 
 Object.class_eval my_class_def
		</pre>
</p><p>Now, let's try and instantiate and access our class . . . 
<pre>
	
  foo=MyClassFoo.new
  foo.hello		

</pre>
 . . . we should see "Hello Foo!" printed by our new class instance.
</p><p>Having loaded a class dynamically into the current runtime, we will now try to unload that class definition. To do this, we will call the private method <i>remove_const</i>, passing the constant's name (the name of our class, in this case) to remove that definition from the current runtime's list of constants . . .
<pre>

 Object.send(:remove_const, "MyClassFoo")

</pre>
 . . . now let's try to create a new instance of <i>MyClassFoo</i> . . .
<pre>

 bar=MyClassFoo.new

</pre>	 		 
 . . . you should get the following exception raised by the runtime: <b>NameError: uninitialized constant MyClassFoo</b>. This is expected, as having removed the class's name from the runtime's list of constants "MyClassFoo" no longer resolves to any defined object. But what about our previous instance of <i>MyClassFoo</i>? The instance <i>foo</i>? Let's see what happens when we try and access it . . .
<pre>

  foo.hello		
	</pre>
	 . . . once again we should see "Hello Foo!" printed. It is important to note that while the underlying class defintion is no longer accessible, previous instances are still available and unmodified in their behavior.
</p><p class='footer'>
1/30/2010</p>]]></description><author>igb@hccp.org</author><pubDate>Sat, 30 Jan 2010 00:00:00 PST</pubDate><guid>http://www.hccp.org/dynamic-class-loading-in-ruby.html</guid></item><item><title>Wetsuit Repair</title><link>http://www.hccp.org/wetsuit-repair.html</link><description><![CDATA[<h2>Wetsuit Repair</h2><p>I had a wetsuit that was disintegrating at the seams, but with a bit of dental floss and neoprene cement, I was able to extend it's life a bit. Here is a simple walk through of how to do a basic repair:</p><ol>
		<li><p>First step is to sew up the split. For thread I used dental floss (waxed or unwaxed) and heavy duty needles (Singer makes a cheap pack for ~$3). Both can be found at your local Walgreen's or neighborhood drugstore.</p>
	<a href='http://www.flickr.com/photos/igb/4179793104/' title='Wetsuit Repair by igb, on Flickr'><img src='http://farm5.static.flickr.com/4008/4179793104_42e4c13149.jpg' height='375' alt='Wetsuit Repair' width='500'/></a></li>
	<li><p>I can't sew to save my life, but a simple spiral stich, keeping the edges of the tear or split linded up an unpuckered is within the ability of even the most remedial home ec students.</p>
	<a href='http://www.flickr.com/photos/igb/4179798296/' title='Wetsuit Repair by igb, on Flickr'><img src='http://farm5.static.flickr.com/4006/4179798296_dc9be5ebdd.jpg' height='375' alt='Wetsuit Repair' width='500'/></a>
	</li>
	<li><p>Finish up the stitch securely at both ends.</p><a href='http://www.flickr.com/photos/igb/4179043719/' title='Wetsuit Repair by igb, on Flickr'><img src='http://farm3.static.flickr.com/2708/4179043719_a0e71c862a.jpg' height='500' alt='Wetsuit Repair' width='375'/></a></li>
	
	<li><p>End result may not be pretty, but it does the job.</p><a href='http://www.flickr.com/photos/igb/4179890284/' title='Wetsuit Repair by igb, on Flickr'><img src='http://farm3.static.flickr.com/2509/4179890284_8974777342.jpg' height='500' alt='Wetsuit Repair' width='375'/></a></li>
	<li><p>Next step is to coat the stitched seam with <a href='http://www.amazon.com/s/ref=nb_ss?url=search-alias%3Dsporting&amp;field-keywords=neoprene+cement&amp;x=0&amp;y=0'>neoprene cement</a>. Coat the inside stitched seam, let dry for 10 minutes, then apply a second coat. Wait another 10 minutes, turn suit inside out, and apply two more coats to the other side. </p>
		<table cellspacing='0' border='0' cellpadding='0' width='100%'><tr>
			<td><a href='http://www.flickr.com/photos/igb/4177947630/' title='Neoprene cement. by igb, on Flickr'><img src='http://farm5.static.flickr.com/4005/4177947630_7a67a44332_m.jpg' height='240' alt='Neoprene cement.' width='180'/></a></td>
			<td><a href='http://www.flickr.com/photos/igb/4179047157/' title='Wetsuit Repair by igb, on Flickr'><img src='http://farm3.static.flickr.com/2761/4179047157_eb42b347f0_m.jpg' height='240' alt='Wetsuit Repair' width='180'/></a></td><td>
		<a href='http://www.flickr.com/photos/igb/4179589221/' title='Wetsuit Repair by igb, on Flickr'><img src='http://farm3.static.flickr.com/2730/4179589221_296591e6a6_m.jpg' height='240' alt='Wetsuit Repair' width='180'/></a></td>
		<td><a href='http://www.flickr.com/photos/igb/4179662093/' title='Wetsuit Repair by igb, on Flickr'><img src='http://farm5.static.flickr.com/4044/4179662093_73ea81c600_m.jpg' height='240' alt='Wetsuit Repair' width='180'/></a></td>
		
		</tr></table>
		</li>
	</ol><p class='footer'>
	12/13/2009</p>]]></description><author>igb@hccp.org</author><pubDate>Sun, 13 Dec 2009 00:00:00 PST</pubDate><guid>http://www.hccp.org/wetsuit-repair.html</guid></item><item>
	<title>STOMP Client for Erlang</title>
	<link>http://www.hccp.org/erlang-stomp-client.html</link>
	<description><![CDATA[

			<h3>STOMP Client for Erlang</h3>

			<p><a href="http://www.hccp.org/erlang/stomp.erl">stomp.erl</a> is a simple client library for message brokers that support the <a href="http://stomp.codehaus.org/">STOMP</a> <a href="http://stomp.codehaus.org/Protocol">protocol</a>. It's usage is pretty straight forward, and below, I walk through a basic interaction with a broker and go into the public functions in greater detail. These examples will be using <a href="http://activemq.apache.org/">ActiveMQ</a> as the broker. ActiveMQ is a free open source message broker, written in Java, that is pretty easy to install, set up, and run. Go ahead and start up <i>erl</i> in the same directory as <i>stomp.erl</i> and compile the stomp client module. 
			<pre> > c(stomp).</pre></p>
			<p><h4>Opening a connection.</h4>The first thing we are going to do is open a connection to the broker. Underneath this call we will be opening a socket connection to the broker (stomp.erl uses the <a href="http://erlang.org/doc/man/gen_tcp.html">gen_tcp</a> module bundled with Erlang) and  sending some simple protocol messages to set up a session with the broker. As mentioned above, these examples are assuming that ActiveMQ is up and running in your local environment, with the STOMP handler enabled, and listening on the default port (61613).</p><p>The <i>connect</i> function takes four arguments (the broker's hostname or address, the port number, a login, and a passcode for authentication), and returns a Connection that we will be using throughout the subsequent exchanges: 
				<pre> > Conn = stomp:connect("localhost", 61613, "", "").</pre></p>
			<p>Note that in this instance we do not require any authentication on the broker, and are passing in empty strings for the login and passcode parameters.</p>
			<p><h4>Sending messages.</h4></p>
			<p>Ok, let's send a few messages to a queue (<i>we will use a queue called "foobar" . . . ActiveMQ can create queues and topics "on demand" . . . there is no need to do any explicit administration or configuration, just send a message to the desired destination, and if it does not already exist, the ActiveMQ broker will automatically create it</i>). To send a message, we will need to specify the underlying connection for transmission, the destination queue or topic, any headers we want to send (as a list of tuples), and  the body of the message. Here is a simple example:
				<pre> > stomp:send(Conn, "/queue/foobar", [], "hello world").
 > stomp:send(Conn, "/queue/foobar", [{"priority","20"}], "we are specifying priority for this hello world").</pre></p>
			<p>Note that I am using the "priority" header in the example above to illustrate how to specify headers during a send operation. ActiveMQ does not currently re-order messages based on priority, though the header will be passed to the receiving client, so actions/prioritizing can occur within the consuming application.</p>
			<p><h4>Subscribing to a queue or topic.</h4> Before we can recieve messages from the broker, we must register ourselves as a subscriber to a particular queue or topic. To do this, we will pass the connection we instantiated during the first step,  along with a destination (the queue or topic we are interested in), and a list of two-tuples representing the names and values of any optional headers we wish to send:
				<pre> > stomp:subscribe("/queue/foobar", Conn, [{"ack", "client"}]).</pre></p>
				<p>We are now subscribed to the queue "foobar", and have told the broker to wait for an ack before removing retrieved messages from the queue.</p>
			<p><h4>Retrieving messages.</h4>
			Now that we have subscribed to the queue "foobar", let's  download those pending messages we sent earlier. To pull messages from a queue or topic, we can use the <i>get_messages</i> function. <i>get_messages</i> takes a connection as it's single argument, will pull down all available messages ("available" means available per broker and subscription policy, and not necessarily all pending messages), blocking if none are available. The return type is a list of messages, each message itself  a list of  3 tuples: type, headers and message body. For example, here is what we get back if we call <i>get_messages</i> after sending the messages from the earlier step:
			<pre> > get_messages(Conn).
[[{type,"MESSAGE"},
  {headers,[{"destination","/queue/foobar"},
  	{"timestamp","1247956667243"},
  	{"priority","0"},
  	{"expires","0"},
  	{"message-id",
 		"ID:phosphorus-53442-1247930100064-2:5:-1:1:1"}]},
  {body,"hello world"}],
 [{type,"MESSAGE"},
  {headers,[{"destination","/queue/foobar"},
			{"timestamp","1247956684233"},
			{"priority","20"},
			{"expires","0"},
			{"message-id",
				"ID:phosphorus-53442-1247930100064-2:5:-1:1:2"}]},
   {body,"we are specifying priority for this hello world"}]]</pre></p>
			<p><h4>Ack'ing messages.</h4>
			When we subscribed to the queue "foobar", you may have noticed that we passed in an optional header of the form	 <i>{"ack", "client"}</i>. This header tells the broker to not count a message as delivered until the client as explicitly acknowledged it's receipt...in fact if you examine the queue contents in the ActiveMQ broker console (<a href="http://localhost:8161/admin/browse.jsp?JMSDestination=foobar">http://localhost:8161/admin/browse.jsp?JMSDestination=foobar</a>), you will see that the two messages we sent are still pending. In order to prevent another subscriber from picking up one of these messages, we will need to send a message acknowledging our receipt. To dod this, use the <i>ack</i> function, which takes a connection and a message id as parameters. The message id for each of the messages we have downloaded is present in the accompanying headers (<i>{"message-id","ID:phosphorus-53442-1247930100064-2:5:-1:1:1"}</i> and <i>{"message-id","ID:phosphorus-53442-1247930100064-2:5:-1:1:2"}</i>). Example:
			<pre> > stomp:ack(Conn, "ID:phosphorus-53442-1247930100064-2:5:-1:1:1").
 > stomp:ack(Conn, "ID:phosphorus-53442-1247930100064-2:5:-1:1:2").</pre>	 
				</p>
			<p>Note, now if you check the queue, you will see these messages are no longer present, receipt by our subscriber having been confirmed.</p>	

			<p><h4>Transactions.</h4>
			STOMP provides transaction semantics for grouping <i>send</i> and <i>ack</i> messages with commit/rollback facilities. The <i>begin_transaction</i>, <i>commit_transaction</i>, and <i>abort_transaction</i> functions provide a means of sending those message types, along with the <i>ack (Connection, MessageId, TransactionId)</i> function and an optional <i>"transaction"</i> header for <i>send</i> operations. Examples:
			<pre> > stomp:begin_transaction(Conn, "MyUniqueTransactionIdBlahBlahBlah1234567890").
			 > stomp:send(Conn, "/queue/foobar", [{"transaction", "MyUniqueTransactionIdBlahBlahBlah1234567890"}], "transactional hello world").</pre></p>
			<p>At this point, we have successfully sent a message to the broker, but if we inspect the queue contents in the ActiveMQ broker console (<a href="http://localhost:8161/admin/browse.jsp?JMSDestination=foobar">http://localhost:8161/admin/browse.jsp?JMSDestination=foobar</a>), we will see that there are no pending messages  . . . this is because we sent the last message as part of a transaction that has not been committed yet. To close the transaction, we use the <i>commit_transaction</i> function:
			<pre> > stomp:commit_transaction(Conn, "MyUniqueTransactionIdBlahBlahBlah1234567890").
			 > stomp:get_messages(Conn).
			[[{type,"MESSAGE"},
			  {headers,[{"destination","/queue/foobar"},
			            {"transaction",
			             "MyUniqueTransactionIdBlahBlahBlah1234567890"},
			            {"timestamp","1248013136111"},
			            {"priority","0"},
			            {"expires","0"},
			            {"message-id",
			             "ID:phosphorus-53442-1247930100064-2:7:-1:1:5"}]},
			  {body,"transactional hello world"}]]</pre>	
			<p><h4>on_message</h4>
			stomp.erl also provides an "on message" handler, that allows you to pass in a function that will be called on each recieved message. Unlike <i>get_messages</i> it will block <i>continuously</i> (<i>get_messages</i> will return after getting all available messages), waiting for messages to arrive on the queue. Example:
			<pre> > stomp:send(Conn, "/queue/foobar", [], "message one").
 > stomp:send(Conn, "/queue/foobar", [], "message two").
 > stomp:send(Conn, "/queue/foobar", [], "message three").	
 > MyFunction=fun([_, _, {_, X}]) -> io:fwrite("message ~s ~n", [X]) end.
#Fun&lt;erl_eval.6.13229925>
 > stomp:on_message(MyFunction, Conn).
message message one 
message message two 
message message three


				</pre>

			</p>
			<p class="footer">
			7/19/2009</p>
		
		
		
		 ]]>
		        </description>
		        <author>igb@hccp.org</author>
				<pubDate>Sun, 19 Jul 2009 09:00:00 PST</pubDate>
				<guid>http://www.hccp.org/erlang-stomp-client.html</guid>
		    </item>
		
<item>
        <title>A Ruby Quine</title>
        <link>http://www.hccp.org/ruby-quine.html</link>
        <description>
        <![CDATA[
<h3>A Ruby Quine</h3>
<p>Messing around with Ruby <i>(not really anything Ruby-specific about this exercise)</i> on the way back from visiting the folks back east. . . wrote <a href="quine.rb">this</a> simple, useless <a href="http://en.wikipedia.org/wiki/Quine_(computing)">quine</a> . . .</p>
<pre>
require "base64"

class Quine
  
  def doSomething(operation)
     puts "#{Base64.decode64(operation)}
     encodedBody=\"#{operation}\"
     Quine.new.doSomething(encodedBody)"
    end
end
     encodedBody="cmVxdWlyZSAiYmFzZTY0IgoKY2xhc3MgUXVpbmUKICAKICBkZWYgZG9Tb21l
dGhpbmcob3BlcmF0aW9uKQogICAgIHB1dHMgIiN7QmFzZTY0LmRlY29kZTY0
KG9wZXJhdGlvbil9CiAgICAgZW5jb2RlZEJvZHk9XCIje29wZXJhdGlvbn1c
IgogICAgIFF1aW5lLm5ldy5kb1NvbWV0aGluZyhlbmNvZGVkQm9keSkiCiAg
ICBlbmQKZW5k"
     Quine.new.doSomething(encodedBody)



</pre>
<p class="footer">
1/3/2009</p>
        ]]>
        </description>
        <author>igb@hccp.org</author>
		<pubDate>Sat, 3 Jan 2009 10:00:00 PST</pubDate>
		<guid>http://www.hccp.org/ruby-quine.html</guid>
    </item>




<item>
        <title>HOW-TO: Share iTunes Music Across Networks</title>
        <link>http://www.hccp.org/bridging-itunes-over-airport.html</link>
        <description>
        <![CDATA[
<h3>HOW-TO: Share iTunes Music Across Networks</h3>
<p>My apartment has a WiFi network (using an Airport base station) <i>and</i> a wired LAN with several servers and a few desktops. The Airport has it's own static IP address, on the same subnet as the desktops and servers. Hosts availing themselves of wireless connectivity, however, are assigned IP address on a different, local subnet (192.168.1.*), with the Airport doing NAT for all external connections.</p>
<p>This configuration presents some issues, however, when trying to discover and share services using Bonjour (a.k.a. mDNS), as multicast packets are not relayed across the subnets by the Airport base station.</p>
<p>Here is a simple hack for allowing sharing across the networks for two particular hosts:</p>
<ol>
<li>Configure Airport to map tunnel and iTunes comm. ports:
<p>We will map port <i>10000</i> for the multicast tunnel and (the default) port <i>3689</i> for iTunes sharing.</p><p>Using the Airport Admin Utility, open up the  "Port Mapping" panel for your Airport base station, and, using the IP address of the "wireless" host (in this example 192.168.1.2), add the appropriate port mappings:<br/>
<p><img src="images/airportmap.gif"></p></li>
<li><p>Download and install <a href="http://www.cdt.luth.se/~peppar/progs/mTunnel/">mTunnel</a> on each host.</p><p>mTunnel is a simple UDP unicast tunneler written in Java by <a href="http://www.parnes.com/">Peter Parnes</a>.</p></li>
<li>Start mTunnel on each host:
<ul>
<li><p>on the LAN host, pass in the static IP or hostname of the Airport base station and the port mapped for NAT pass through: <tt>mtunnel  airport.hccp.org/10000</tt></p></li>
<li><p>on the wireless host, pass in the static IP or hostname of the LAN host and the configured port: <tt>mtunnel  lan-desktop.hccp.org/10000</tt></p></li>
</ul></li>
<li>Configure mtunnel:
<p>
<ol>
<li>Point a browser to the wireless host at port <i>9000</i> to view the mTunnel web admin console.</li>
<li>Create a new tunnel:
<p><img src="images/mtunnel-admin-001.gif"/></p>
<p><img src="images/mtunnel-admin-002.gif"/></p>
<p><img src="images/mtunnel-admin-003.gif"/></p>
</li>
<li>Configure the tunnel:
<p>Set the group field to <i>224.0.0.251</i>, the reserved multicast address for mDNS/Bonjour, and the baseport field to the UDP port of <i>5353</i><sup><a href="#dns">1</a></sup></p>

<p>Name and media fields can be set to whatever you prefer, as they have no effect on the behavior of our tunnel.</p>
<p><img src="images/mtunnel-admin-004.gif"/></p>
</li>
<li>Turn ON tunnelling by clicking on the Yes/No toggle link in the tunnel detail page. (it is OFF by default)<p><img src="images/mtunnel-admin-005.gif"/></p>
</li>

</ol>
</p></li>
<li>In short order, the iTunes applications will discover each other and you will be able to share music across the networks.</li>
</ol>
<p><a name="dns"><tt><i><sup>1</sup>the TCP port for DNS is </i>53<i>, natch</i></tt></p>
<p class="footer">
3/24/2007</p>

        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Sat, 24 Mar 2007 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/bridging-itunes-over-airport.html</guid>
    </item>







<item>
        <title>InfoCard and CardSpace Selector For Safari / OS X (v0.2.1219)</title>
        <link>http://www.hccp.org/safari-plug-in.html</link>
        <description>
        <![CDATA[

<h3>InfoCard Selector for Safari</h3>
<p>
This is currently still at the proof of concept stage, and is lacking  most of the features found in the official CardSpace selector from Microsoft. In the latest version (<i>0.2.1219</i>), multiple "self-asserted" or "personal" cards can be created, stored, and selected. The selector plug-in will seed new InfoCards by pulling the logged in account's personal information from the AddressBook application. It should work with existing installs of Safari, and with most relying parties. 
</p>
<p>
The plug-in itself is a wrapper around <a href="http://xmldap.blogspot.com/">Chuck Mortimore</a>'s Java <a href="http://xmldap.org/">implementation</a> of an InfoCard token generator. For those of you out there using Firefox, check out Chuck's cross-platform <a href="http://xmldap.org/">Firefox InfoCard selector</a>.
</p>
<p>So download the Safari Plug-In below and give it a spin. Send me any feedback at <b>igb at hccp.org</b></p>
<p>I'll post new releases here as features are added and bugs are fixed.</p>
<p><a href="safari-selector.xml"><img  border=0 src="images/rssbadge.gif"></a> An RSS feed of releases and project news is available here: <a href="safari-selector.xml">http://www.hccp.org/safari-selector.xml</a>.
<h4><a name="releaseNotes"/>New Features/Enhancements in v0.2.1219:</h4>
				<ul>
					<li>multiple card support</li>
					<li>site usage history</li>
					<li>site usage affinity</li>
					<li>site/card specific PPIDs</li>
					<li>indication of required attributes in UI</li>
					<li>Mac OS X Package (.pkg) Installer</li>																									
				</ul>



<h4><a name="downloads"/>Downloads:</h4>
<p>Currently there are two versions, one for the new Intel-based Apple's, and one for the PowerPC-based machiines. At some point I'll figure out how to get XCode to generate a Universal Binary. (<i>I suppose the PowerPC build might work on the Intel Macs, that's what <a href="http://www.apple.com/rosetta/">Rosetta</a> is all about right? But it hasn't been tested on the Intel arch, so YMMV.</i>)
</p>
<table>
    <tr>
        <td><a href="http://www.hccp.org/SafariInfoCardSelector-0.2.1219.pkg.zip"><img  border=0 src="./images/pkg_sm.gif"/></a></td><td>
<a class="download" href="http://www.hccp.org/SafariInfoCardSelector-0.2.1219.pkg.zip">Intel version</a><br>
<a  class="download" href="http://www.hccp.org/SafariInfoCardSelector-0.2.1219.pkg.zip">http://www.hccp.org/SafariInfoCardSelector-0.2.1219.pkg.zip</a>
</td>
</tr></table>
<br/>
<br/>
<table>
    <tr>
        <td><a  class="download" href="http://www.hccp.org/SafariInfoCardSelector-0.2.1219-PPC.pkg.zip"><img  border=0  src="./images/pkg_sm.gif"/></a></td><td><a href="http://www.hccp.org/SafariInfoCardSelector-0.2.1219-PPC.pkg.zip" class="download">PowerPC version</a><br>
<a class="download" href="http://www.hccp.org/SafariInfoCardSelector-0.2.1219-PPC.pkg.zip">http://www.hccp.org/SafariInfoCardSelector-0.2.1219-PPC.pkg.zip</a>
</td>
</tr></table>
<h4><a name="installation"/>Installation:</h4>
<p>Installation is pretty simple. After downloading the ZIP file, extract the archive. You should now have a <b>.pkg</b> file. Just double click on the <b>.pkg</b> file and step through the installer wizard. After installation, just fire up Safari and off you go!</p>

<h4><a name="demo"/>Demos:</h4>
<table>
<tr><td  valign="top">
<p align="center"><a name="simple-demo"/><b>Simple Login to Identity Blog and Bandit Wiki</b></p>
For the faint of heart, or for those running those other operating systems, here's a short screencast of the selector in action, authN'ing against Novell and <a href="http://osis.netmesh.org/wiki/Main_Page">OSIS</a>'s <a href="https://woof.bandit-project.org/wiki/index.php?title=Special:Userlogin">Bandit project</a> as well as <a href="https://www.identityblog.com/wp-login.php">Kim Cameron's PHP/WordPress RP</a>:</td>

<td valign="top">
<p align="center"><a name="optional-login-demo"/><b>Login Using Optional Claims</b></p>
A short demonstration of the selector interacting with the <a href="https://xmldap.org/relyingparty/">xmldap.org sample relying party</a>, which allows users to submit a set of optional claims:</td></tr>


<tr>
<td>
<p align="center"><a href="movies/infocard-0.2.1219.mov"><img border=0 alt="click to download movie" src="images/infocard-0.2.1219.gif"/></a></p></td>


<td>
<p align="center"><a href="movies/infocard-0.2.1219-opt-claims.mov"><img border=0 alt="click to download movie" src="images/infocard-0.2.1219-opt-claim.gif"/></a></td>



</tr>


</table>



<h4><a name="credits"/>Credits</h4>
Mad props go out to <a href="http://laurie.rae.myopenid.com/">Laurie Rae</a>, <a href="http://www.davidhuska.com/">David Huska</a>, and <a href="http://fundoublog.blogspot.com/">Anil Edakkunni</a> for technical advice and no small amount of testing.
<br>
<h4><a name="previous-versions"/>Previous Versions</h4>

<br><img border=0 src="images/rssbadge.gif"/>
<p class="footer">12/29/2006</p>


        ]]>
        </description>
        		    <author>igb@hccp.org</author>
					<guid>http://www.hccp.org/safari-plug-in.html#2</guid>
        			<pubDate>Fri, 29 Dec 2006 15:00:00 PST</pubDate>

    </item>








	<item>
	        <title>Release: InfoCard Selector for Safari (v0.2.1219)</title>
	        <link>http://www.hccp.org/safari-plug-in.html</link>
	        <description>
				<![CDATA[ 
				<b>New Features/Enhancements:</b>
				<ul>
					<li>multiple card support</li>
					<li>site usage history</li>
					<li>site usage affinity</li>
					<li>site/card specific PPIDs</li>
					<li>indication of required attributes in UI</li>
					<li>Mac OS X Package (.pkg) Installer</li>																									
				</ul>
				]]>
		    </description>
		    <author>igb@hccp.org</author>
			<pubDate>Thu, 21 Dec 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/safari-plug-in.html</guid>
			<enclosure length='2253379' type='application/zip' url='http://www.hccp.org/SafariInfoCardSelector-0.2.1219.pkg.zip'/>
    </item>

	<item>
	        <title>Release: InfoCard Selector for Safari (Power PC build) (v0.2.1219)</title>
	        <link>http://www.hccp.org/safari-plug-in.html</link>
	        <description>
				<![CDATA[ 
				<b>New Features/Enhancements:</b>
				<ul>
					<li>multiple card support</li>
					<li>site usage history</li>
					<li>site usage affinity</li>
					<li>site/card specific PPIDs</li>
					<li>indication of required attributes in UI</li>
					<li>Mac OS X Package (.pkg) Installer</li>																									
				</ul>
				]]>
		    </description>
		    <author>igb@hccp.org</author>
			<pubDate>Thu, 21 Dec 2006 15:00:00 PST</pubDate>
			<enclosure length='2224551' type='application/zip' url='http://www.hccp.org/SafariInfoCardSelector-0.2.1219-PPC.pkg.zip'/>
    </item>
    
    
    
<item>
        <title>Detecting a Safari InfoCard PlugIn Using JavaScript</title>
        <link>http://www.hccp.org/plugin-detect.html</link>
        <description>
        <![CDATA[


<h3>Detecting a Safari InfoCard PlugIn Using JavaScript</h3>

<p>

A few weeks ago <a href="http://www.openrowley.com/">Pete Rowley</a> <a href="http://www.openrowley.com/2006/10/11/web-2-oh-dear-opinity-only-wants-microsoft-identity-selectors/">pointed out</a> an issue with <a href="https://secure.opinity.com/1.5/home/login.php">Opinity's InfoCard support</a>. It would appear that the folks at Opinity decided to refuse InfoCard tokens from non-IE7 selectors. So, for instance, if I attempt to log in using the <a href="http://www.hccp.org/safari-plug-in.html">Safari-based selector</a>, I get the following alert:
</p>
<div align="center"><img src="images/opinity-login.gif"/></div>
<p>While I can understand that the webmaster at Opinity might be trying to help out users who are attempting to use a non-Microsoft browser, a more appropriate way to do this would be to ask the browser itself, via some simple JavaScript, if it understands embedded objects of type <i>"application/x-informationcard"</i>.
<p>So, for those of you out there that are running a relying party that understands InfoCard/Cardspace, and you want to limit access to that particular login medium to browsers that understand the protocol, here is a small snippet of JavaScript that will query a browser's installed plug-ins and check for InfoCard support:
<pre>

 &lt;script language="JavaScript">
 var infoCardMimeType="application/x-informationcard"; //InfoCard MIME Type

 function isInfoCardSupportedByPlugIn() {
    if (navigator.plugins && navigator.plugins.length > 0) {
	   var pluginsArrayLength = navigator.plugins.length;
	   // for each plugin...
	   for (pluginsArrayCounter=0; pluginsArrayCounter < pluginsArrayLength; pluginsArrayCounter++ ) {
	       // check to see if plugin has assoc. MIME type and 
	       // if so, if it is of type "application/x-informationcard"
	       if (navigator.plugins[pluginsArrayCounter][0] 
	            && infoCardMimeType == navigator.plugins[pluginsArrayCounter][0].type) {
	           return true;
	       }
	   }
	   return false;
	}
 }
 &lt;/script>
 
</pre>
</p>
<p>
Using the above code, here's what we are able to discern about the  browser with which you are currently using to view this page: 
<div  align="center" class="message">
Since this is an RSS feed description, we cannot execute JavaScript. :-(
</div>
</p>
<p>So, hopefully the Opinity people will take the time to let us choose the credential types that we would prefer to log in with, without forcing us to make unnecessary choices about browsers and operationg systems.
<p class="footer">
10/25/2006</p>
        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Wed, 25 Oct 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/plugin-detect.html</guid>
    </item>





<item>
        <title>InfoCard and CardSpace Selector For Safari / OS X</title>
        <link>http://www.hccp.org/safari-plug-in.html</link>
        <description>
        <![CDATA[

<h3>InfoCard Selector for Safari</h3>
<p>
This is currently still at the proof of concept stage, and is lacking  most of the features found in the official CardSpace selector from Microsoft. At present, only a single self-asserted card can be selected. The "selector" will currently pull the logged in account's personal information from the AddressBook application, and allow you to use that AddressBook entry as a self-asserted InfoCard with various RPs. It should work with existing installs of Safari, and with most relying parties. 
</p>
<p>
The plug-in itself is a wrapper around <a href="http://xmldap.blogspot.com/">Chuck Mortimore</a>'s Java <a href="http://xmldap.org/">implementation</a> of an InfoCard token generator. For those of you out there using Firefox, check out Chuck's cross-platform <a href="http://xmldap.org/">Firefox InfoCard selector</a>.
</p>
<p>So download the Safari Plug-In below and give it a spin. Send me any feedback at <b>igb at hccp.org</b></p>
<p>I'll post new releases here as features are added and bugs are fixed.</p>
<h4 class="large">Downloads</h4>
<p>Currently there are two versions, one for the new Intel-based Apple's, and one for the PowerPC-based machiines. At some point I'll figure out how to get XCode to generate a Universal Binary. (<i>I suppose the PowerPC build might work on the Intel Macs, that's what <a href="http://www.apple.com/rosetta/">Rosetta</a> is all about right? But it hasn't been tested on the Intel arch, so YMMV.</i>)
</p>
<table>
    <tr>
        <td><a href="http://www.hccp.org/InfocardPlugin.bundle.zip"><img src="./images/plugin_sm.gif"/></a></td><td>
<a class="large" href="http://www.hccp.org/InfocardPlugin.bundle.zip">Intel version</a><br>
<a class="small" href="http://www.hccp.org/InfocardPlugin.bundle.zip">http://www.hccp.org/InfocardPlugin.bundle.zip</a>
</td>
</tr></table>
<br/>
<br/>
<table>
    <tr>
        <td><a  href="http://www.hccp.org/InfocardPluginPPC.bundle.zip"><img src="./images/plugin_sm.gif"/></a></td><td><a class="large" href="http://www.hccp.org/InfocardPluginPPC.bundle.zip">PowerPC version</a><br>
<a class="small" href="http://www.hccp.org/InfocardPluginPPC.bundle.zip">http://www.hccp.org/InfocardPluginPPC.bundle.zip</a>
</td>
</tr></table>
<h4 class="large">Installation</h4>
<p>Installation is pretty simple. After downloading the ZIP file, extract the archive. You should now have a file called <b>InfocardPlugin.bundle</b>. Just copy that to the <i>Library/Internet Plug-Ins</i> directory <i>under your home directory</i>. restart Safari, and off you go.</p>
<h4 class="large">Demo</h4>
For the faint of heart, or for those running those other operatinf systems, here's a short screencast of the selector in action, authN'ing against <a href="https://www.identityblog.com/wp-login.php">Kim Cameron's RP</a>:<br/>
<p align="center"><a href="movies/safari-selector.mov"><img alt="click to download movie" src="images/safari-selector-movie.gif"/></a>
<p class="footer">9/12/2006</p>

        ]]>
        </description>
          <author>igb@hccp.org</author>
			<pubDate>Tue, 12 Sep 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/safari-plug-in.html#1</guid>
    </item>



<item>
        <title>. . . but the plug-in failed to load successfully.</title>
        <link>http://www.hccp.org/webkit-plug-in-issue.html</link>
        <description>
        <![CDATA[
<h3> . . . but the plug-in failed to load successfully.</h3>
<p>I was hacking around with WebKit plug-ins this weekend, and ran into a frustrating issue. Initially, I had gotten my plug-in working, with a single object (the plug-in) in the bundle. However, after adding a second object to the bundle, the plug-in stopped loading. All I the info I could get out of Safari/WebKit was the unhelpful dialog displayed below:</p>

<p  align="center"><img src="images/plug-in-load.gif" alt="A screenshot of a Safari browser window, displaying an error dialog."/></p>
<p>After some digging around, comparing my project to the example plug-ins that ship with XCode, I discovered I was missing the <i>NSPrincipalClass</i> key in my bundle's <i>Info.plist</i>. After adding the definition:<pre>
&lt;key>NSPrincipalClass&lt;/key>
&lt;string>MyPlugIn&lt;/string>
</pre> the plug-in loaded without issue. AFAICT, the introduction of the new class created an ambiguity for the plug-in manager as far as what class should be instantiated as the plug-in implementation.</p>

<p class="footer">
9/9/2006</p>

        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Sat, 9 Sep 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/webkit-plug-in-issue.html</guid>
    </item>

<item>
        <title>Talk to the Pop!</title>
        <link>http://www.hccp.org/talk-to-the-pop.html</link>
        <description>
        <![CDATA[
<h3>Talk to the Pop!</h3>
<a href="http://www.ocupop.com"/><img src="images/ocupop.gif" border=0/></a>
<p>Hey, <a href="http://www.ocupop.com/home/workwithus.php">Jeff and Mike</a> finally updated <a href="http://www.ocupop.com/home/workwithus.php">the website!</a></p>
<p>And that's a good thing, as they have built up quite the <a href="http://www.ocupop.com/home/id.php">portfolio</a> over the years.</p>
<p class="footer">9/1/2006</p>

        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Fri, 1 Sep 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/talk-to-the-pop.html</guid>
    </item>


<item>
        <title>Making Architecture More Connected&#174;</title>
        <link>http://www.hccp.org/making-arch-conn.html</link>
        <description>
        <![CDATA[
<h3>Making Architecture More Connected&trade;</h3>
<p><img src="images/montage.gif"/></p>
<p><a href="http://www.soa.com/">SOA</a>/<a href="http://www.bluetitan.com">BlueTitan</a> Senior Software Engineers Sadhana Jain and Anil Eddakkuni demonstrating their awesome presentation kung-fu.</p>
<p class="footer">8/31/2006</p>

        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Thu, 31 Aug 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/making-arch-conn.html</guid>
    </item>



<item>
        <title>Generating a correctly formatted xsd:dateTime using the Unix date command</title>
        <link>http://www.hccp.org/xsd-date.html</link>
        <description>
        <![CDATA[
<h3>Generating a correctly formatted <i>xsd:dateTime</i> using the Unix <i>date</i> command</h3>
<p><pre>
> date -u  "+%Y-%m-%dT%H:%M:%SZ"
<i>2006-08-17T06:28:58Z</i>
</pre>
For reference: <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">W3C XML Schema dateTime format.</a>
</p>
<p class="footer">2006-08-17T06:28:58Z</p>

        ]]>
        </description>
                <author>igb@hccp.org</author>
			<pubDate>Thu, 17 Aug 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/xsd-date.html</guid>
    </item>




<item>
        <title>InfoCard/Cardspaces "Hack"?</title>
        <link>http://www.hccp.org/cardspaces-hack.html</link>
        <description>
        <![CDATA[



<h3>InfoCard/Cardspaces "Hack"?</h3>
<i class="flag"><a class="flag" href="#update2">updated 12:27 AM PST, 8/27/2006</a></i><br/>
<s><i class="flag"><a class="flag" href="#update">updated 9:14 AM PST, 8/16/2006</a></i></s>
<p>An interesting post appeared on Kim Cameron's <a href="http://www.identityblog.com/">IdentityBlog</a> yesterday afternoon. <a href="http://www.rohanpinto.com/">Rohan Pinto</a> apparently circumvented the security on the  blog (which runs on WordPress), and vaguely implied that the exploit was enabled by  Kim's use of InfoCard/Cardspaces:</p>
<div align="center"><cite>"I thought os a small infocard exploit, and just tried it on this site not expecting it to work on the first attempt. but it did . . ."</cite> </div>
<p>It isn't immediately clear to me that the hack was particular to InfoCard/Cardspaces for a couple of reasons:
<ol>
<li>Rohan seems to have been correctly identified by the site as <i>"Rohan Pinto"</i> in both the original post as well as the follow up comment. (i.e. He wasn't able to post as <i>"Kim Cameron"</i> or some other user's identity)<br/><br/></li>
<li>The "hack" seems to be an exploit around entitlements or permissions within the application. Unless the asserted identity contained <i>falsified</i> credentials that allowed the user to assume an admin role (vs. a naiive trust of unqualified or unsigned attributes), then the exploit would not seem to be specific to the protocols that comprise InfoCard/Cardspaces.</li>
</ol>
</p>
<p>Based on these observations, I suspect that the exploit is particular to either Kim's PHP InfoCard <i>implementation</i>, or an issue with his WordPress configuration.</p><p>Kim or Rohan, any details you are able to share regarding this would be appreciated, as if there is an exploit that is common across InfoCard/Cardspace implementations, then I'm sure the community would be interested in hearing about it.</p>
<p>Rohan, while I can understand your reluctance to share the techincal details of your exploit, perhaps you could disclose any occurrences of this vulnerability in other public RP implementations ( <a href="https://infocard.pingidentity.com/sp/">Ping Identity</a>, <a href="https://xmldap.org/relyingparty/">xmldap.org</a> ). Is the attack feasible against <i>all</i> InfoCard enabled sites?
<p class="update">
<a name="update"/><span class="flag">[UPDATE]</span> Rohan has confirmed <a class="update" href="http://www.rohanpinto.com/2006/08/15/a-clarification/">here</a> that, indeed, the exploit was unrelated to InfoCard, and was simply a WordPress specific exploit.
</p>
<p>Kim has since removed Rohan's post, so I've included a screenshot below, and a copy of the item can be found <a href="kim-rohan-hack.html">here</a>.
<div align="center"><a href="kim-rohan-hack.html"><img src="images/kim-rohan-screen.gif"/></a></div>
<p class="update">
<a name="update2"/><span class="flag">[UPDATE]</span> Rohan called and asked me to remove my link to a search for the term "Rohan Pinto", as he feels he has been the victim of a <a href="http://en.wikipedia.org/wiki/Google_bomb">"google bombing"</a> campaign by other parties in a dispute over copyright infringement. I have obliged Rohan, and am now linking directly to his <a href="http://www.rohanpinto.com">blog</a>.
</p>
<p class="footer">8/16/2006</p>


        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Wed, 16 Aug 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/cardspaces-hack.html</guid>
    </item>



<item>
        <title>Using XSLT to inline an imported schema in WSDL.</title>
        <link>http://www.hccp.org/xslt-wsdl-schema.html</link>
        <description>
        <![CDATA[

<h3>Using XSLT to inline an imported schema in WSDL.</h3>
<p>For a recent project, I created a simple web service, with a one-way operation using a simple, reasonably-typed<sup>TM</sup> message. Rather than inline the XML schema for the message types, I chose to import the externally defined schema, using a relative path on my local filesystem. Here is the WSDL:
<pre>&lt;?xml version="1.0" encoding="utf-8"?>
&lt;wsdl:definitions
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:tns="http://ws.hccp.org/cc-build" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://ws.hccp.org/cc-build">
    <b>&lt;wsdl:types>
        &lt;xs:import namespace="http://ws.hccp.org/cc-build" schemaLocation="../schema/build-notification.xsd"/>
    &lt;/wsdl:types>
    </b>&lt;wsdl:message name="buildNotificationMessage">
        &lt;wsdl:part name="message" element="tns:build-notification"/>
    &lt;/wsdl:message>
    &lt;wsdl:portType name="buildNotificationPortType">
        &lt;wsdl:operation name="buildNotificationOperation">
            &lt;wsdl:input message="tns:buildNotificationMessage"/>
        &lt;/wsdl:operation>
    &lt;/wsdl:portType>
    &lt;wsdl:binding name="buildNotificationBinding" type="tns:buildNotificationPortType">
        &lt;soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
        &lt;wsdl:operation name="buildNotificationOperation">
            &lt;soap:operation style="document" soapAction="buildNotification"/>
            &lt;wsdl:input>
                &lt;soap:body use="literal"/>
            &lt;/wsdl:input>
        &lt;/wsdl:operation>
    &lt;/wsdl:binding>
&lt;/wsdl:definitions>
</pre>

</p>
<p>While the use of the <tt>{http://www.w3.org/2001/XMLSchema}import</tt> element allows me a certain amount of flexibility during development, it is a solution that is less than acceptable from a deployment perspective. In many cases, deployment of services can occur in environments and server configurations in which externally defined schemata are not accessible. So, rather than hardcode the schema definition in the original WSDL, I'd like to automatically replace the reference with the actual schema during the build or deployment of the service, thereby retaining the indirection and normalization of my schema definitions and service descriptions.</p>
<p>A solution can be provided through the creation of a simple XSLT. First, let's start with a simple identity transformation. This stylesheet will output, for any XML document, a copy of the input document. The identity transform is the basic building block for many transformations:
<pre>
&lt;xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    &lt;xsl:output method="xml"/>
    &lt;xsl:template match="node() | @*">
        &lt;xsl:copy>
            &lt;xsl:apply-templates select="node() | @*"/>
        &lt;/xsl:copy>
    &lt;/xsl:template>
&lt;/xsl:stylesheet>
</pre>
</p>
<p>Running the above transformation will, as expected, return the original WSDL, unchanged. Now, with a simple addition of a template matching the <tt>{http://www.w3.org/2001/XMLSchema}import</tt> element, we can extract the value of the <tt>schemaLocation</tt> attribute and use the <tt>document</tt> function retrieve the referenced schema. We then continue to apply the identity transformation template to the schema document: 
<pre>
&lt;xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    <b>xmlns:xs="http://www.w3.org/2001/XMLSchema"</b>
    version="1.0">
    &lt;xsl:output method="xml" indent="no"/>
    &lt;xsl:template match="node() | @*">
        &lt;xsl:copy>
            &lt;xsl:apply-templates select="node() | @*"/>
        &lt;/xsl:copy>
    &lt;/xsl:template>    
    <b>&lt;xsl:template match="xs:import">
        &lt;xsl:variable name="schema" select="@schemaLocation"/>
        &lt;xsl:apply-templates select="document($schema)"/>
    &lt;/xsl:template></b>
&lt;/xsl:stylesheet>
</pre>
</p>
<p>Now, if we run the above transformation, we get output like this:
<pre>&lt;?xml version="1.0" encoding="utf-8"?>
&lt;wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:tns="http://ws.hccp.org/cc-build" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://ws.hccp.org/cc-build">
    &lt;wsdl:types>
<b>        &lt;xs:schema xmlns:hccp="http://ws.hccp.org/build-notification"
            xmlns="http://ws.hccp.org/cc-build" elementFormDefault="qualified"
            targetNamespace="http://ws.hccp.org/cc-build">
            &lt;xs:element name="build-notification" type="hccp:build-notification"/>
            &lt;xs:complexType name="build-notification">
                &lt;xs:sequence>
                    &lt;xs:element name="status" maxOccurs="1" minOccurs="1" type="hccp:build-status"/>
                &lt;/xs:sequence>
            &lt;/xs:complexType>
            &lt;xs:simpleType name="build-status">
                &lt;xs:restriction base="xs:string">
                    &lt;xs:enumeration value="PASS"/>
                    &lt;xs:enumeration value="FAIL"/>
                &lt;/xs:restriction>
            &lt;/xs:simpleType>
        &lt;/xs:schema></b>
    &lt;/wsdl:types>
    &lt;wsdl:message name="buildNotificationMessage">
        &lt;wsdl:part name="message" element="tns:build-notification"/>
    &lt;/wsdl:message>
    &lt;wsdl:portType name="buildNotificationPortType">
        &lt;wsdl:operation name="buildNotificationOperation">
            &lt;wsdl:input message="tns:buildNotificationMessage"/>
        &lt;/wsdl:operation>
    &lt;/wsdl:portType>
    &lt;wsdl:binding name="buildNotificationBinding" type="tns:buildNotificationPortType">
        &lt;soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
        &lt;wsdl:operation name="buildNotificationOperation">
            &lt;soap:operation style="document" soapAction="buildNotification"/>
            &lt;wsdl:input>
                &lt;soap:body use="literal"/>
            &lt;/wsdl:input>
        &lt;/wsdl:operation>
    &lt;/wsdl:binding>
&lt;/wsdl:definitions>
</pre>
</p>
<p>So now we have a simple set of steps for creating a deployable WSDL. Plus it's trivial to add the above steps to an Ant task:
<pre>&lt;project...>
    &lt;target...>
    ... 
        &lt;xslt in="${wsdl.src.dir}/build-notification-endpoint.wsdl"
              out="${build.dir}/build-notification-endpoint.wsdl"
              style="${xslt.src.dir}/import-schema.xsl"/>
    ...
    &lt;/target>
&lt;/project>    
</pre>
</p>
<p class="footer">
8/13/2006</p>


        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Sun, 13 Aug 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/xslt-wsdl-schema.html</guid>
    </item>




<item>
        <title>State Of Alert Software</title>
        <link>http://www.hccp.org/state-of-alert.html</link>
        <description>
        <![CDATA[

<h3 align="center">State Of Alert Software</h3>
<p align="center"><a href="http://www.soa.com"><img src="images/soa.jpg"/></a></p>
<p align="center">Oh yeah, we are totally <a href="http://en.wikipedia.org/wiki/State_of_Alert">hardcore</a>.<p> 

<p class="footer">
8/7/2006</p>


        ]]>
        </description>
        
        <author>igb@hccp.org</author>
			<pubDate>Mon, 7 Aug 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/state-of-alert.html</guid>
    </item>








<item>
        <title>Starbucks Handles</title>
        <link>http://www.hccp.org/starbucks-names.html</link>
        <description>
        <![CDATA[
    <h3>Starbucks Handles</h3>
<p>There is no local independent coffee house within striking distance of the <a href="http://www.bluetitan.com">BlueTitan</a>/<a href="http://www.soa.com">SOA</a> <a href="http://maps.google.com/maps?f=q&hl=en&q=81+Bluxome,+San+Francisco,+CA&ie=UTF8&ll=37.776227,-122.397459&spn=0.004868,0.013561&t=h&om=1">HQ</a>. Therefore, my colleagues and I must resort to patronizing the nearby Starbucks. Since Starbucks  <a href="http://www.eaipatterns.com/ramblings/18_starbucks.html">processes drink orders asynchronously</a>, the customer must provide a name to the dispatching barista in order to be notified of drink delivery.</p>
<p>Problems often occur during the transmission of names when the provided identifier is unfamiliar, or of foreign origin, to the receiving barista. For instance, if the barista is an American-educated<a href="#1"><sup>1</sup></a> English speaker, the name Srinivasa Ramanujan stands little chance of being retransmitted with acceptable fidelity.</p>
<p>All of my San Francisco-based colleagues at <a href="http://www.bluetitan.com">BlueTitan</a>/<a href="http://www.soa.com">SOA</a> have similarly barista-unfriendly names, and have each adopted Starbucks-specific "handles" that are provided in lieu of their actual names in order to facilitate the exchange of money and caffeine.</p>
<p> Here are a few examples:
<p align="center">
<table border="0" cellpadding="3" cellspacing=1 width="400">
<tr><th>Name</th><th>Handle</th></tr>
<tr><td>Sadhana Jain</td><td>"Jane"</td></tr>
<tr><td>Anil Edakkunni</td><td>"Neal", "Ed", or "Ed O'Neal"</td></tr>
<tr><td>Eberhard Hummel</td><td>"Abe"</td></tr>
<tr><td>Fabrice Medio</td><td>"Vijay Nahasapeemapetilon"</td></tr>
</table>
</p>
<p>Perhaps Starbucks should think of applying some technology to handle the identifier issue:
</p>
<p  align="center"><img src="images/number-dispenser.jpg"/></p>
<p class="footnote"><a name="1"/><sup>1</sup>No comment on the current state of American education and the ability of American-educated students to compete in a job market that is increasingly non-US centric.<p> 

<p class="footer">
8/6/2006</p>

        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Sun, 6 Aug 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/starbucks-names.html</guid>
    </item>












<item>
        <title>The Garden of Forking Paths  by Jorge Luis Borges</title>
        <link>http://www.hccp.org/borges-garden.html</link>
        <description>
        <![CDATA[
    

<h2>The Garden of Forking Paths</h2>
<h3>by Jorge Luis Borges</h3>
<p><i>For Victor Ocampo</i></p>
<p>On page 22 of Liddell Hart's <i>History of World War I</i> you will read that an
attack against the Serre-Montauban line by thirteen British divisions
(supported by 1,400 artillery pieces), planned for the 24th of July, 1916, had
to be postponed until the morning of the 29th. The torrential rains, Captain
Liddell Hart comments, caused this delay, an insignificant one, to be sure.
</p><p>The following statement, dictated, reread and signed by Dr. Yu Tsun,
former professor of English at the Hochschule at Tsingtao, throws an
unsuspected light over the whole affair. The first two pages of the document
are missing.</p>
". . . and I hung up the receiver. Immediately afterwards, I recognized the
voice that had answered in German. It was that of Captain Richard Madden.
Madden's presence in Viktor Runeberg's apartment meant the end of our
anxieties and--but this seemed, <i>or should have seemed</i>, very secondary to me--
also the end of our lives. It meant that Runeberg had been arrested or
murdered.<sup><a href="#1">1</a></sup> Before the sun set on that day, I would encounter the same fate.
Madden was implacable. Or rather, he was obliged to be so. An Irishman at
the service of England, a man accused of laxity and perhaps of treason, how
could he fail to seize and be thankful for such a miraculous opportunity: the
discovery, capture, maybe even the death of two agents of the German
Reich? I went up to my room; absurdly I locked the door and threw myself
on my back on the narrow iron cot. Through the window I saw the familiar
roofs and the cloud-shaded six o'clock sun. It seemed incredible to me that

day without premonitions or symbols should be the one of my inexorable
death. In spite of my dead father, in spite of having been a child in a
symmetrical garden of Hai Feng, was I--now--going to die? Then I reflected
that everything happens to a man precisely, precisely now. Centuries of
centuries and only in the present do things happen; countless men in the air,
on the face of the earth and the sea, and all that really is happening is
happening to me . . . The almost intolerable recollection of Madden's
horselike face banished these wanderings. In the midst of my hatred and
terror (it means nothing to me now to speak of terror, now that I have
mocked Richard Madden, now that my throat yearns for the noose) it
occurred to me that tumultuous and doubles happy warrior did not suspect
that I possessed the Secret. The name of the exact location of the new British
artillery park on the River Ancre. A bird streaked across the gray sky and
blindly I translated it into an airplane and that airplane into many (against the
French sky) annihilating the artillery station with vertical bombs. If only my
mouth, before a bullet shattered it, could cry out that secret name so it could
be heard in Germany . . . My human voice was very weak. How might I make
it carry to the ear of the Chief? To the ear of that sick and hateful man who
knew nothing of Runeberg and me save that we were in Staffordshire and
who was waiting in vain for our report in his arid office in Berlin, endlessly
examining newspapers . . . I said out loud: <i>I must see.</i> I sat up noiselessly, in a useless perfection of silence, as if Madden were already lying in wait for me.
Something--perhaps the mere vain ostentation of proving my resources were
nil--made me look through my pockets. I found what I knew I would find.
The American watch, the nickel chain and the square coin, the key ring with
the incriminating useless keys to Runeberg's apartment, the notebook, a letter
which I resolved to destroy immediately (and which I did not destroy), a
crown, two shillings and a few pence, the red and blue pencil, the
handkerchief, the revolver with one bullet. Absurdly, I took it in my hand and
weighed it in order to inspire courage within myself. Vaguely I thought that a
pistol report can be heard at a great distance. In ten minutes my plan was
perfected. The telephone book listed the name of the only person capable of
transmitting the message; he lived in a suburb of Fenton, less than a half
hour's train ride away.</p>
<p>I am a cowardly man. I say it now, now that I have carried to its end a
plan whose perilous nature no one can deny. I know its execution was
terrible. I didn't do it for Germany, no. I care nothing for a barbarous
country which imposed upon me the abjection of being a spy. Besides, I
know of a man from England --a modest man--who for me is no less great
than Goethe. I talked with him for scarcely an hour, but during that hour he
was Goethe . . . I did it because I sensed that the Chief somehow feared
people of my race--for the innumerable ancestors who merge within me. I
wanted to prove to him that a yellow man could save his armies. Besides, I
had to flee from Captain Madden. His hands and his voice could call at my
door at any moment. I dressed silently, bade farewell to myself in the mirror,
went downstairs, scrutinized the peaceful street and went out. The station
was not far from my home, but I judged it wise to take a cab. I argued that in
this way I ran less risk of being recognized; the fact is that in the deserted
street I felt myself visible and vulnerable, infinitely so. I remember that I told
the cab driver to stop a short distance before the main entrance. I got out
with voluntary, almost painful slowness; I was going to the village of
Ashgrove but I bought a ticket for a more distant station. The train left
within a very few minutes, at eight-fifty. I hurried; the next one would leave
at nine-thirty. There was hardly a soul on the platform. I went through the
coaches; I remember a few farmers, a woman dressed in mourning, a young
boy who was reading with fervor the <i>Annals</i> of Tacitus, a wounded and
happy soldier. The coaches jerked forward at last. A man whom I recognized
ran in vain to the end of the platform. It was Captain Richard Madden.
Shattered, trembling, I shrank into the far corner of the seat, away from the
dreaded window.</p>
<p>From this broken state I passed into an almost abject felicity. I told
myself that the duel had already begun and that I had won the first encounter
by frustrating, even if for forty minutes, even if by a stroke of fate, the attack
of my adversary. I argued that this slightest of victories foreshadowed a total
victory. I argued (no less fallaciously) that my cowardly felicity proved that I
was a man capable of carrying out the adventure successfully. From this
weakness I took strength that did not abandon me. I foresee that man will
resign himself each day to more atrocious undertakings; soon there will be no
one but warriors and brigands; I give them this counsel: <i>The author of an
atrocious undertaking ought to imagine that he has already accomplished it, ought to impose
upon himself a future as irrevocable as the past.</i> Thus I proceeded as my eyes of a
man already dead registered the elapsing of that day, which was perhaps the
last, and the diffusion of the night. The train ran gently along, amid ash trees.
It stopped, almost in the middle of the fields. No one announced the name
of the station. "Ashgrove?" I asked a few lads on the platform. "Ashgrove,"
they replied. I got off.</p>
<p>A lamp enlightened the platform but the faces of the boys were in
shadow. One questioned me, "Are you going to Dr. Stephen Albert's house?"
Without waiting for my answer, another said, "The house is a long way from
here, but you won't get lost if you take this road to the left and at every
crossroads turn again to your left." I tossed them a coin (my last), descended
a few stone steps and started down the solitary road. It went downhill, slowly.
It was of elemental earth; overhead the branches were tangled; the low, full
moon seemed to accompany me.</p>
For an instant, I thought that Richard Madden in some way had
penetrated my desperate plan. Very quickly, I understood that was
impossible. The instructions to turn always to the left reminded me that such
was the common procedure for discovering the central point of certain
labyrinths. I have some understanding of labyrinths: not for nothing am I the
great grandson of that Ts'ui P&ecirc;n who was governor of Yunnan and who
renounced worldly power in order to write a novel that might be even more
populous than the <i>Hung Lu Meng</i> and to construct a labyrinth in which all
men would become lost. Thirteen years he dedicated to these heterogeneous
tasks, but the hand of a stranger murdered him--and his novel was incoherent
and no one found the labyrinth. Beneath English trees I meditated on that
lost maze: I imagined it inviolate and perfect at the secret crest of a mountain;
I imagined it erased by rice fields or beneath the water; I imagined it infinite,
no longer composed of octagonal kiosks and returning paths, but of rivers
and provinces and kingdoms . . . I thought of a labyrinth of labyrinths, of one
sinuous spreading labyrinth that would encompass the past and the future
and in some way involve the stars. Absorbed in these illusory images, I forgot
my destiny of one pursued. I felt myself to be, for an unknown period of time, an abstract perceiver of the world. The vague, living countryside, the
moon, the remains of the day worked on me, as well as the slope of the road
which eliminated any possibility of weariness. The afternoon was intimate,
infinite. The road descended and forked among the now confused meadows.
A high-pitched, almost syllabic music approached and receded in the shifting
of the wind, dimmed by leaves and distance. I thought that a man can be an
enemy of other men, of the moments of other men, but not of a country: not
of fireflies, words, gardens, streams of water, sunsets. Thus I arrived before a
tall, rusty gate. Between the iron bars I made out a poplar grove and a
pavilion. I understood suddenly two things, the first trivial, the second almost
unbelievable: the music came from the pavilion, and the music was Chinese.
For precisely that reason I had openly accepted it without paying it any heed.
I do not remember whether there was a bell or whether I knocked with my
hand. The sparkling of the music continued.</p>
<p>From the rear of the house within a lantern approached: a lantern that
the trees sometimes striped and sometimes eclipsed, a paper lantern that had
the form of a drum and the color of the moon. A tall man bore it. I didn't see
his face for the light blinded me. He opened the door and said slowly, in my
own language: "I see that the pious Hsi P'eng persists in correcting my
solitude. You no doubt wish to see the garden?"<p>
<p>I recognized the name of one of our consuls and I replied, disconcerted,
"The garden?"</p>
<p>"The garden of forking paths."</p>
<p>Something stirred in my memory and I uttered with incomprehensible
certainty, "The garden of my ancestor Ts'ui P&ecirc;n."</p>
<p>"Your ancestor? Your illustrious ancestor? Come in."</p>
<p>The damp path zigzagged like those of my childhood. We came to a
library of Eastern and Western books. I recognized bound in yellow silk
several volumes of the Lost Encyclopedia, edited by the Third Emperor of
the Luminous Dynasty but never printed. The record on the phonograph
revolved next to a bronze phoenix. I also recall a famille rose vase and another,
many centuries older, of that shade of blue which our craftsmen copied from
the potters of Persia . . .</p>
<p>Stephen Albert observed me with a smile. He was, as I have said, very
tall, sharp-featured, with gray eyes and a gray beard. He told me that he had
been a missionary in Tientsin "before aspiring to become a Sinologist."
We sat down--I on a long, low divan, he with his back to the window and
a tall circular clock. I calculated that my pursuer, Richard Madden, could not
arrive for at least an hour. My irrevocable determination could wait.</p>
<br/><br/><p>"An astounding fate, that of Ts'ui P&ecirc;n," Stephen Albert said. "Governor of
his native province, learned in astronomy, in astrology and in the tireless
interpretation of the canonical books, chess player, famous poet and
calligrapher--he abandoned an this in order to compose a book and a maze.
He renounced the pleasures of both tyranny and justice, of his populous
couch, of his banquets and even of erudition--all to close himself up for
thirteen years in the Pavilion of the Limpid Solitude. When he died, his heirs
found nothing save chaotic manuscripts. His family, as you may be aware,
wished to condemn them to the fire; but his executor--a Taoist or Buddhist
monk--insisted on their publication."</p>
<p>'We descendants of Ts'ui P&ecirc;n," I replied, "continue to curse that monk.
Their publication was senseless. The book is an indeterminate heap of
contradictory drafts. I examined it once: in the third chapter the hero dies, in
the fourth he is alive. As for the other undertaking of Ts'ui P&ecirc;n, his
labyrinth . . ."</p>
<p>"Here is Ts'ui P&ecirc;n's labyrinth," he said, indicating a tall lacquered desk.
"An ivory labyrinth!" I exclaimed. "A minimum labyrinth."</p>
<p>"A labyrinth of symbols," he corrected. "An invisible labyrinth of time.
To me, a barbarous Englishman, has been entrusted the revelation of this
diaphanous mystery. After more than a hundred years, the details are
irretrievable; but it is not hard to conjecture what happened. Ts'ui Pe must
have said once: <i>I am withdrawing to write a book. And another time: I am withdrawing
to construct a labyrinth.</i> Every one imagined two works; to no one did it occur
that the book and the maze were one and the same thing. The Pavilion of the
Limpid Solitude stood in the center of a garden that was perhaps intricate;
that circumstance could have suggested to the heirs a physical labyrinth. Ts'ui P&ecirc;n died; no one in the vast territories that were his came upon the labyrinth;
the confusion of the novel suggested to me that it was the maze. Two
circumstances gave me the correct solution of the problem. One: the curious
legend that Ts'ui P&ecirc;n had planned to create a labyrinth which would be
strictly infinite. The other: a fragment of a letter I discovered."</p>
<p>Albert rose. He turned his back on me for a moment; he opened a
drawer of the black and gold desk. He faced me and in his hands he held a
sheet of paper that had once been crimson, but was now pink and tenuous
and cross-sectioned. The fame of Ts'ui P&ecirc;n as a calligrapher had been justly
won. I read, uncomprehendingly and with fervor, these words written with a
minute brush by a man of my blood: <i>I leave to the various futures (not to all) my
garden of forking paths.</i> Wordlessly, I returned the sheet. Albert continued:</p>
<p>"Before unearthing this letter, I had questioned myself about the ways in
which a book can be infinite. I could think of nothing other than a cyclic
volume, a circular one. A book whose last page was identical with the first, a
book which had the possibility of continuing indefinitely. I remembered too
that night which is at the middle of the <i>Thousand and One Nights</i> when
Scheherazade (through a magical oversight of the copyist) begins to relate
word for word the story of the Thousand and One Nights, establishing the
risk of coming once again to the night when she must repeat it, and thus on
to infinity. I imagined as well a Platonic. hereditary work. transmitted from
father to son, in which each new individual adds a chapter or corrects with
pious care the pages of his elders. These conjectures diverted me; but none
seemed to correspond, not even remotely, to the contradictory chapters of
Ts'ui P&ecirc;n. In the midst of this perplexity, I received from Oxford the
manuscript you have examined. I lingered, naturally, on the sentence: <i>I leave to
the various futures (not to all) my garden of forking paths.</i> Almost instantly, I
understood: 'the garden of forking paths' was the chaotic novel; the phrase
'the various futures (not to all)' suggested to me the forking in time, not in
space. A broad rereading of the work confirmed the theory. In all fictional
works, each time a man is confronted with several alternatives, he chooses
one and eliminates the others; in the fiction of Ts'ui P&ecirc;n, he chooses--
simultaneously--all of them. <i>He creates,</i> in this way, diverse futures, diverse
times which themselves also proliferate and fork. Here, then, is the
explanation of the novel's contradictions. Fang, let us say, has a secret; a
stranger calls at his door; Fang resolves to kill him. Naturally, there are
several possible outcomes: Fang can kill the intruder, the intruder can kill
Fang, they both can escape, they both can die, and so forth. In the work of
Ts'ui P&ecirc;n, all possible outcomes occur; each one is the point of departure for
other forkings. Sometimes, the paths of this labyrinth converge: for example,
you arrive at this house, but in one of the possible pasts you are my enemy, in
another, my friend. If you will resign yourself to my incurable pronunciation,
we shall read a few pages."</p>
<p>His face, within the vivid circle of the lamplight, was unquestionably that
of an old man, but with something unalterable about it, even immortal. He
read with slow precision two versions of the same epic chapter. In the first,
an army marches to a battle across a lonely mountain; the horror of the rocks
and shadows makes the men undervalue their lives and they gain an easy
victory. In the second, the same army traverses a palace where a great festival
is taking place; the resplendent battle seems to them a continuation of the
celebration and they win the victory. I listened with proper veneration to
these ancient narratives, perhaps less admirable in themselves than the fact
that they had been created by my blood and were being restored to me by a
man of a remote empire, in the course of a desperate adventure, on a
Western isle. I remember the last words, repeated in each version like a secret
commandment: <i>Thus fought the heroes, tranquil their admirable hearts, violent their
swords, resigned to kill and to die.</i></p>
<p>From that moment on, I felt about me and within my dark body an
invisible, intangible swarming. Not the swarming of the divergent, parallel
and finally coalescent armies, but a more inaccessible, more intimate agitation
that they in some manner prefigured. Stephen Albert continued:</p>
<p>"I don't believe that your illustrious ancestor played idly with these
variations. I don't consider it credible that he would sacrifice thirteen years to
the infinite execution of a rhetorical experiment. In your country, the novel is
a subsidiary form of literature; in Ts'ui P&ecirc;n's time it was a despicable form.
Ts'ui P&ecirc;n was a brilliant novelist, but he was also a man of letters who
doubtless did not consider himself a mere novelist. The testimony of his
contemporaries proclaims--and his life fully confirms--his metaphysical and mystical interests. Philosophic controversy usurps a good part of the novel. I
know that of all problems, none disturbed him so greatly nor worked upon
him so much as the abysmal problem of time. Now then, the latter is the only
problem that does not figure in the pages of the <i>Garden</i>. He does not even
use the word that signifies <i>time</i>. How do you explain this voluntary omission?</p>
<p>I proposed several solutions--all unsatisfactory. We discussed them.
Finally, Stephen Albert said to me:</p>
<p>"In a riddle whose answer is chess, what is the only prohibited word?"</p>
<p>I thought a moment and replied, "The word chess."</p>
<p>"Precisely," said Albert. "<i>The Garden of Forking Paths</i> is an enormous
riddle, or parable, whose theme is time; this recondite cause prohibits its
mention. To omit a word always, to resort to inept metaphors and obvious
periphrases, is perhaps the most emphatic way of stressing it. That is the
tortuous method preferred, in each of the meanderings of his indefatigable
novel, by the oblique Ts'ui P&ecirc;n. I have compared hundreds of manuscripts, I
have corrected the errors that the negligence of the copyists has introduced, I
have guessed the plan of this chaos, I have re-established--I believe I have reestablished--
the primordial organization, I have translated the entire work: it
is clear to me that not once does he employ the word 'time.' The explanation
is obvious: <i>The Garden of Forking Paths</i> is an incomplete, but not false, image
of the universe as Ts'ui P&ecirc;n conceived it. In contrast to Newton and
Schopenhauer, your ancestor did not believe in a uniform, absolute time. He
believed in an infinite series of times, in a growing, dizzying net of divergent,
convergent and parallel times. This network of times which approached one
another, forked, broke off, or were unaware of one another for centuries,
embraces all possibilities of time. We do not exist in the majority of these
times; in some you exist, and not I; in others I, and not you; in others, both
of us. In the present one, which a favorable fate has granted me, you have
arrived at my house; in another, while crossing the garden, you found me
dead; in still another, I utter these same words, but I am a mistake, a ghost."</p>
<p>"In every one," I pronounced, not without a tremble to my voice, "I am
grateful to you and revere you for your re-creation of the garden of Ts'ui
P&ecirc;n."</p>
<p>"Not in all," he murmured with a smile. "Time forks perpetually toward
innumerable futures. In one of them I am your enemy."</p>
<p>Once again I felt the swarming sensation of which I have spoken. It
seemed to me that the humid garden that surrounded the house was infinitely
saturated with invisible persons. Those persons were Albert and I, secret,
busy and multiform in other dimensions of time. I raised my eyes and the
tenuous nightmare dissolved. In the yellow and black garden there was only
one man; but this man was as strong as a statue . . . this man was approaching
along the path and he was Captain Richard Madden.</p>
<p>"The future already exists," I replied, "but I am your friend. Could I see
the letter again?"</p>
<p>Albert rose. Standing tall, he opened the drawer of the tall desk; for the
moment his back was to me. I had readied the revolver. I fired with extreme
caution. Albert fell uncomplainingly, immediately. I swear his death was
instantaneous--a lightning stroke.</p>
<p>The rest is unreal, insignificant. Madden broke in, arrested me. I have
been condemned to the gallows. I have won out abominably; I have
communicated to Berlin the secret name of the city they must attack. They
bombed it yesterday; I read it in the same papers that offered to England the
mystery of the learned Sinologist Stephen Albert who was murdered by a
stranger, one Yu Tsun. The Chief had deciphered this mystery. He knew my
problem was to indicate (through the uproar of the war) the city called
Albert, and that I had found no other means to do so than to kill a man of
that name. He does not know (no one can know) my innumerable contrition
and weariness.</p>


<p class="footnote"><a name="1"/><sup>1</sup> An hypothesis both hateful and odd. The Prussian spy Hans Rabener, alias Viktor
Runeberg, attacked with drawn automatic the bearer of the warrant for his arrest,
Captain Richard Madden. The latter, in self-defense, inflicted the wound which
brought about Runeberg's death. (Editor's note.)</p>


<p><b>Excerpted from <i>Labyrinths: Selected Stories and Other Writings</i> by Jorge Luis Borges</b></p>
<p><tt>Reproduced without permission of the author (who's dead) or publisher. It's a really good book. Go <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0811200124/103-3118395-9031843">buy a copy</a>.</tt></P>

<p class="footer">
8/2/2006</p>
        ]]>
        </description>
        <author>borges@pitt.edu</author>
			<pubDate>Wed, 2 Aug 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/borges-garden.html</guid>
    </item>








 
 <item>
        <title>Three Versions of Judas by Jorge Luis Borges</title>
        <link>http://www.hccp.org/borges-judas.html</link>
        <description>
        <![CDATA[
    

<h2>Three Versions of Judas</h2>
<h3>by Jorge Luis Borges</h3>


<p>"There seemed a certainty in degradation."
- T. E. Lawrence, <i>Seven Pillars of Wisdom</i></p>


<p>In Asia Minor or in Alexandria, in the second century of our faith (when
Basilides was announcing that the cosmos was a rash and malevolent improvisation
engineered by defective angels), Nils Runeberg might have directed, with a
singular intellectual passion, one of the Gnostic conventicles. Dante would have
destined him, perhaps, for a fiery sepulcher; his name might have augmented the
catalogues of heresiarchs, between Satornibus and Carpocrates; some fragment of
his preaching, embellished with invective, might have been preserved in the
apocryphal Liber adversus omnes haereses or might have perished when the firing
of a monastic library consumed the last example of the Syntagma. Instead, God
assigned him to the twentieth century, and to the university city of Lund.
There, in 1904, he published the first edition of <i>Kristus och Judas</i>; there, in
1909, his masterpiece <i>Dem hemlige Fr&#228;lsaren</i> appeared. (Of this last mentioned
work there exists a German version, called <i>Der heimliche Heiland</i>, executed in
1912 by Emil Schering.)</p>

<p>Before undertaking an examination of the foregoing works, it is necessary to
repeat that Nils Runeberg, a member of the National Evangelical Union, was
deeply religious. In some salon in Paris, or even in Buenos Aires, a literary
person might well rediscover Runeberg's theses; but these arguments, presented
in such a setting, would seem like frivolous and idle exercises in irrelevance
or blasphemy. To Runeberg they were the key with which to decipher a central
mystery of theology; they were a matter of meditation and analysis, of historic
and philologic controversy, of loftiness, of jubilation, and of terror. They
justified, and destroyed, his life. Whoever peruses this essay should know that
it states only Runeberg's conclusions, not his dialectic or his proof. Someone
may observe that no doubt the conclusion preceded the "proofs" For who gives
himself up to looking for proofs of something he does not believe in or the
predication of which he does not care about?</p>

<p>The first edition of <i>Kristus och Judas</i> bears the following categorical epigraph,
whose meaning, some years later, Nils Runeberg himself would monstrously dilate:
Not one thing, but everything tradition attributes to Judas Iscariot is false.
(De Quincey, 1857.) Preceded in his speculation by some German thinker, De
Quincey opined that Judas had betrayed Jesus Christ in order to force him to
declare his divinity and thus set off a vast rebellion against the yoke of Rome;
Runeberg offers a metaphysical vindication. Skillfully, he begins by pointing
out how superfluous was the act of Judas. He observes (as did Robertson) that in
order to identify a master who daily preached in the synagogue and who performed
miracles before gatherings of thousands, the treachery of an apostle is not
necessary. This, nevertheless, occurred. To suppose an error in Scripture is
intolerable; no less intolerable is it to admit that there was a single
haphazard act in the most precious drama in the history of the world. Ergo, the
treachery of Judas was not accidental; it was a predestined deed which has its
mysterious place in the economy of the Redemption. Runeberg continues: The Word,
when It was made flesh, passed from ubiquity into space, from eternity into
history, from blessedness without limit to mutation and death; in order to
correspond to such a sacrifice it was necessary that a man, as representative of
all men, make a suitable sacrifice. Judas Iscariot was that man. Judas, alone
among the apostles, intuited the secret divinity and the terrible purpose of
Jesus. The Word had lowered Himself to be mortal; Judas, the disciple of the
Word, could lower himself to the role of informer (the worst transgression
dishonor abides), and welcome the fire which can not be extinguished. The lower
order is a mirror of the superior order, the forms of the earth correspond to
the forms of the heavens; the stains on the skin are a map of the incorruptible
constellations; Judas in some way reflects Jesus. Thus the thirty pieces of
silver and the kiss; thus deliberate self-destruction, in order to deserve
damnation all the more. In this manner did Nils Runeberg elucidate the enigma of
Judas.</p>

<p>The theologians of all the confessions refuted him. Lars Peter Engstr&#246;m accused
him of ignoring, or of confining to the past, the hypostatic union of the Divine
Trinity; Axel Borelius charged him with renewing the heresy of the Docetists,
who denied the humanity of Jesus; the sharpedged bishop of Lund denounced him
for contradicting the third verse of chapter twenty-two of the Gospel of St.
Luke.</p>

<p>These various anathemas influenced Runeberg, who partially rewrote the
disapproved book and modified his doctrine. He abandoned the terrain of theology
to his adversaries and postulated oblique arguments of a moral order. He
admitted that Jesus, "who could count on the considerable resources which
Omnipotence offers," did not need to make use of a man to redeem all men. Later,
he refuted those who affirm that we know nothing of the inexplicable traitor; we
know, he said, that he was one of the apostles, one of those chosen to announce
the Kingdom of Heaven, to cure the sick, to cleanse the leprous, to resurrect
the dead, and to cast out demons (Matthew 10:7-8; Luke 9:1). A man whom the
Redeemer has thus distinguished deserves from us the best interpretations of his
deeds. To impute his crime to cupidity (as some have done, citing John 12:6) is
to resign oneself to the most torpid motive force. Nils Runeberg proposes an
opposite moving force: an extravagant and even limitless asceticism. The
ascetic, for the greater glory of God, degrades and mortifies the flesh; Judas
did the same with the spirit. He renounced honor, good, peace, the Kingdom of
Heaven, as others, less heroically, renounced pleasure.<sup><a href="#1">1</a></sup> With a terrible
lucidity he premeditated his offense.</p>

<p>In adultery, there is usually tenderness and self-sacrifice; in murder, courage;
in profanation and blasphemy, a certain satanic splendor. Judas elected those
offenses unvisited by any virtues: abuse of confidence (John 12 :6) and
informing. He labored with gigantic humility; he thought himself unworthy to be
good. Paul has written: Whoever glorifieth himself, let him glorify himself in
God (I Corinthians 1:31); Judas sought Hell because the felicity of the Lord
sufficed him. He thought that happiness, like good, is a divine attribute and
not to be usurped by men.<sup><a href="#2">2</a></sup></p>

<p>Many have discovered post factum that in the justifiable beginnings of Runeberg
lies his extravagant end and that <i>Dem hemlige Fr&#228;lsaren</i> is a mere perversion or
exacerbation of Kristus och Judas. Toward the end of 1907, Runeberg finished and
revised the manuscript text; almost two years passed without his handing it to
the printer. In October of 1909, the book appeared with a prologue (tepid to the
point of being enigmatic) by the Danish Hebraist Erik Erfjord and bearing this
perfidious epigraph: In the world he was, and the world was made by him, and the
world knew him not (John 1:10). The general argument is not complex, even if the
conclusion is monstrous. God, argues Nils Runeberg, lowered himself to be a man
for the redemption of the human race; it is reasonable to assume that the
sacrifice offered by him was perfect, not invalidated or attenuated by any
omission. To limit all that happened to the agony of one afternoon on the cross
is blasphemous.<sup><a href="#3">3</a></sup> To affirm that he was a man and that he was incapable of sin
contains a contradiction; the attributes of impeccabilitas and of humanitas are
not compatible. Kemnitz admits that the Redeemer could feel fatigue, cold,
confusion, hunger and thirst; it is reasonable to admit that he could also sin
and be damned. The famous text "He will sprout like a root in a dry soil; there
is not good mien to him, nor beauty; despised of men and the least of them; a
man of sorrow, and experienced in heartbreaks" (Isaiah 53:2-3) is for many people
a forecast of the Crucified in the hour of his death; for some (as for instance,
Hans Lassen Martensen), it is a refutation of the beauty which the vulgar
consensus attributes to Christ; for Runeberg, it is a precise prophecy, not of
one moment, but of all the atrocious future, in time and eternity, of the Word
made flesh. God became a man completely, a man to the point of infamy, a man to
the point of being reprehensible - all the way to the abyss. In order to save
us, He could have chosen any of the destinies which together weave the uncertain
web of history; He could have been Alexander, or Pythagoras, or Rurik, or Jesus;
He chose an infamous destiny: He was Judas.</p>

<p>In vain did the bookstores of Stockholm and Lund offer this revelation. The
incredulous considered it, a priori, an insipid and laborious theological game;
the theologians disdained it. Runeberg intuited from this universal indifference
an almost miraculous confirmation. God had commanded this indifference; God did
not wish His terrible secret propagated in the world. Runeberg understood that
the hour had not yet come. He sensed ancient and divine curses converging upon
him, he remembered Elijah and Moses, who covered their faces on the mountain top
so as not to see God; he remembered Isaiah, who prostrated himself when his eyes
saw That One whose glory fills the earth; Saul who was blinded on the road to
Damascus; the rabbi Simon ben Azai, who saw Paradise and died; the famous
soothsayer John of Viterbo, who went mad when he was able to see the Trinity;
the Midrashim, abominating the impious who pronounce the Shem Hamephorash, the
secret name of God. Wasn't he, perchance, guilty of this dark crime? Might not
this be the blasphemy against the Spirit, the sin which will not be pardoned
(Matthew 12:3)? Valerius Soranus died for having revealed the occult name of
Rome; what infinite punishment would be his for having discovered and divulged
the terrible name of God?</p>

<p>Intoxicated with insomnia and with vertiginous dialectic, Nils Runeberg wandered
through the streets of Malm&#246;, praying aloud that he be given the grace to share
Hell with the Redeemer.</p>

<p>He died of the rupture of an aneurysm, the first day of March 1912. The writers
on heresy, the heresiologists, will no doubt remember him; he added to the
concept of the Son, which seemed exhausted, the complexities of calamity and
evil.<p>

<p class="footnote"><a name="1"/><sup>1</sup> Borelius mockingly interrogates: Why did he not renounce to renounce? Why
not renounce renouncing?</p>

<p class="footnote"><a name="2"/><sup>2</sup> Euclydes da Cunha, in a book ignored by Runeberg, notes that for the
heresiarch of Canudos, Antonio Conselheiro, virtue was "a kind of impiety
almost." An Argentine reader could recall analogous passages in the work of
Almafuerte. Runeberg published, in the symbolist sheet <i>Sju insegel</i>, an
assiduously descriptive poem, "The Secret Water": the first stanzas narrate the
events of one tumultuous day; the last, the finding of a glacial pool; the poet
suggests that the eternalness of this silent water checks our useless violence,
and in some way allows and absolves it. The poem concludes in this way: <i>The water of the forest is still and felicitous, And we, we can be vicious and
full of pain.</i>
</p>
<p class="footnote"><a name="3"/><sup>3</sup> Maurice Abramowicz observes: "Jesus, d'apres ce scandinave, a toujours le
beau role; ses deboires, grace a la science des typographes, jouissent d'une
reputation polyglotte; sa residence de trente-trois ans parmis les humains ne
fut, en somne, qu'une villegiature." Erfjord, in the third appendix to the
Christelige Dogmatik, refutes this passage. He writes that the crucifying of God
has not ceased, for anything which has happened once in time is repeated
ceaselessly through all eternity. Judas, now, continues to receive the pieces of
silver; he continues to hurl the pieces of silver in the temple; he continues to
knot the hangman's noose on the field of blood. (Erfjord, to justify this
affirmation, invokes the last chapter of the first volume of the <i>Vindication of
Eternity</i>, by Jaromir Hladlk.)</p>
<p><b>Excerpted from <i>Labyrinths: Selected Stories and Other Writings</i> by Jorge Luis Borges</b></p>
<p><tt>Reproduced without permission of the author (who's dead) or publisher. It's a really good book. Go <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0811200124/103-3118395-9031843">buy a copy</a>.</tt></P>

<p class="footer">
5/30/2006</p>
        ]]>
        </description>
         <author>borges@pitt.edu</author>
			<pubDate>Tue, 30 May 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/borges-judas.html</guid>
    </item>




  
 
 <item>
        <title>Deming/Shewhart PDSA Loop</title>
        <link>http://www.hccp.org/pdsa.html</link>
        <description>
        <![CDATA[
    
<h3>Deming/Shewhart PDSA Loop</h3>
<p>The PDSA loop of <a href="http://en.wikipedia.org/wiki/W._Edwards_Deming">W. Edwards Deming</a> and <a href="http://en.wikipedia.org/wiki/Walter_A._Shewhart">Walter Shewhart</a>.</p>
<ol class="cycle">
<li><p class="part"><b>Plan:</b> determine scope of project as well as interval of initial iteration</p></li>
<li><p class="part"><b>Do:</b> execute - small steps in controlled circumstances</b></li>
<li><p class="part"><b>Study:</b> gather empirical evidence, involve the customer if possible</li>
<li><p class="part"><b>Act:</b> take action to improve or standardize the plan or process</p></li>

</ol>
Rinse and repeat until complete. It's very <a href="http://en.wikipedia.org/wiki/Scrum_%28management%29">Scrum</a>.
<p class="footer">
3/26/2006</p>
        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Sun, 26 Mar 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/pdsa.html</guid>
    </item>
   
  
  
   
    <item>
        <title>HOW-TO: OpenLDAP on OS X (Tiger)</title>
        <link>http://www.hccp.org/osx-ldap-tiger.html</link>
        <description>
        <![CDATA[
    
<h3>HOW-TO: OpenLDAP on OS X (Tiger)</h3>
<p>OpenLDAP is installed by default on Tiger (and earlier versions of OS X).
In order to get it into a useful state, however, you will need to make a few changes:
<ol>
<li><p>Locate the OpenLDAP configuration files in <i>/etc/openldap/</i></p></li>
<li><p><i>cp slapd.conf.default slapd.conf</i></p></li>
<li><p>Edit <i>slapd.conf</i>:
    <ul><li>Remove the folowing lines:
<pre><s>database        netinfo
suffix          ""
flags           DSENGINE_FLAGS_NATIVE_AUTHORIZATION
datasource      /var/db/netinfo/network.nidb
include         /etc/openldap/schema/netinfo.schema</s>
</pre></p>
</li>
<li><p>And add the following:<pre>
database        bdb
directory      /var/db/openldap/openldap-data/
suffix          "dc=hccp,dc=org"
rootdn          "cn=Directory Manager,dc=hccp,dc=org"
rootpw          secret
</pre>
</ul>
</p>
<p>(optionally use <i>slappasswd</i> to avoid plaintext password in <i>slapd.conf</i>)</p>
<li>
<p>Make sure that <i>/var/db/openldap/openldap-data/</i> exists, creating it if it does not.</p></li>
<li><p>Run slapd: <i>sudo /usr/libexec/slapd</p></li>
</ol>
<p class="footer">
3/18/2006</p>
 
        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Sat, 18 Mar 2006 15:00:00 PST</pubDate>
			<guid>http://www.hccp.org/osx-ldap-tiger.html</guid>
    </item>
   
   
   
  
  
  
   
   
   
    <item>
        <title>2 Letter Scrabble Words.</title>
        <link>http://www.hccp.org/scrabble-two-letters.html</link>
        <description>
        <![CDATA[
            A simple set of flashcards for two-letter Scrabble words.
        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Sat, 18 Mar 2006 12:00:00 PST</pubDate>
			<guid>http://www.hccp.org/scrabble-two-letters.html</guid>
        
    </item>
   
   
   
   
   
   
    <item>
        <title>HOW-TO: Building and configuring mod_jk on OS X (Tiger)</title>
        <link>http://www.hccp.org/mod_jk-how-to.html</link>
        <description>
        <![CDATA[
    
<h3>HOW-TO: Building and configuring mod_jk on OS X (Tiger)</h3>
<p>Brief HOW-TO building and configuring mod_jk on OS X (Tiger)</p>
<ol>
<li><p>Download the mod_jk source: <a href="http://www.apache.org/dist/tomcat/tomcat-connectors/jk/source/jk-1.2.15/jakarta-tomcat-connectors-1.2.15-src.tar.gz">http://www.apache.org/dist/tomcat/tomcat-connectors/jk/source/jk-1.2.15/jakarta-tomcat-connectors-1.2.15-src.tar.gz</a></p></li>
<li><p>Expand and cd to <i>jakarta-tomcat-connectors-1.2.15-src/jk/native</i></p></li>
<li><p class="command">./configure --with-apxs=/usr/sbin/apxs</p></li>
<li><p class="command"> cd apache-1.3/</p></li>
<li><p class="command">make -f Makefile.apxs</p></li>
<li><p class="command">sudo cp mod_jk.so /usr/libexec/httpd/</p></li>
<li><p class="command">sudo chmod ugo+x /usr/libexec/httpd/mod_jk.so</p></li>
<li><p>
Create a workers prop file:
<pre class="doc">
workers.tomcat_home=/usr/local/tomcat
workers.java_home=/Library/Java/Home

worker.list=myworker

worker.myworker.type=ajp13
worker.myworker.host=localhost
worker.myworker.port=8009
worker.myworker.socket_keepalive=1
</pre>
This file will be referenced by the mod_jk configuration section in <i>/etc/httpd/httpd.conf</i>, so it can be placed anywhere, as long as subsequent references have the correct path. By convention it is usually placed in the Tomcat server's <i>conf</i> dir (<i>e.g. /usr/local/tomcat/conf/worker.properties</i>).
</p>
</li>
<li><p>Add the following to the end of /etc/httpd/httpd.conf:

<pre class="doc">
LoadModule jk_module libexec/httpd/mod_jk.so

JkWorkersFile /usr/local/tomcat/conf/worker.properties
JkLogFile /private/var/log/httpd/mod_jk.log
JkLogLevel trace

JkMount /* myworker
</pre>
</p>
</li>
<li><p class="command">sudo apachectl restart</p></li>

</ol>
<p>All requests sent to the Apache host will now be forwarded on to the Tomcat server.</p>
<p class="footer">
12/11/2005</p> 
        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Sun, 11 Dec 2005 12:00:00 PST</pubDate>
			<guid>http://www.hccp.org/mod_jk-how-to.html</guid>
        
    </item>
   
   
   
   
    <item>
        <title>Snowman and Crake</title>
        <link>http://www.hccp.org/oryx.html</link>
        <description>
        <![CDATA[
    <h3>Snowman and Crake</h3>
<p>"Let's suppose for the sake of argument," said Crake one evening, "that civilization as we know it get's destroyed. Want some popcorn?"</p>
<p>"Is that real butter?" said Jimmy.</p>
<p>"Nothing but the best at Watson-Crick," said Crake. "Once it's flattened, it could never be rebuilt."</p>
<p>"Because why? Got any salt?"</p>
<p>"Because all available surface metals have already been mined," said Crake. "Without which, no iron age, no bronze age, no age of steel, and all the rest of it. There's metals farther down, but the advanced technology we need for extracting those would have been obliterated."</p>
<p>"It could be put back together," said Jimmy, chewing. It was so long since he'd tasted popcorn this good. "They'd still have the instructions."</p>
<p>"Actually not," said Crake. "It's not like the wheel, it's too complex now. Suppose the instructions survived, suppose there were any people left with the knowledge to read them. Those people would be few and far between, and they wouldn't have the tools. Remember, no electricity. Then once those people died, that would be it. They'd have no apprentices, they'd have no successors. Want a beer?"</p>
<p>"Is it cold?"</p>
<p>"All it takes," said Crake, "is the elimination of one generation. One generation of anything. Beetles, trees, microbes, scientists, speakers of French, whatever. Break the link in time between one generation and the next, and it's game over forever."</p>
<br/>
<p><b>Excerpted from <i>Oryx and Crake</i> by Margaret Atwood</b></p>
<p><tt>Reproduced without permission of the author or publisher. It's a really good book. Go <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0385721676/002-1534138-9629629">buy a copy</a>.</tt></P>
<p class="footer">
11/12/2005</p>
        
        ]]>
        </description>
			<pubDate>Sun, 11 Dec 2005 12:00:00 PST</pubDate>
			<guid>http://www.hccp.org/oryx.html</guid>
    </item>
   
   
   
    <item>
        <title>Legitimate Spiritual Discovery</title>
        <link>http://www.hccp.org/legit-spiritual-disco.html</link>
        <description>
        <![CDATA[
    <h3>Legitimate Spiritual Discovery</h3>
<p>
<a href="http://www.projectzero.com/">Jason</a>, who shares an office with the <a href="http://www.sxip.com">Sxip U.S.</a> crew, was experiencing significant web lag. As far as we could tell, it was  Akami having problems, and sites like <a href="http://sfgate.com">SF Gate</a> were serving up images rather slowly. So, HTML loads, and ALT tags are exposed for all the world to see, as we wait for Akamai to deliver the image, and we are treated to this bit of web developer wit on an article about the Grateful Dead: 
</p>
<img border=1 src="images/dead.gif"/>
<p>
<code>
&lt;A HREF="http://www.sfgate.com/cgi-bin/article.cgi?f=/c/a/2005/11/08/DDGDCFJDAJ1.DTL">&lt;IMG SRC="/chronicle/pictures/2005/11/08/dd-220x314-dead.jpg"
WIDTH="220" HEIGHT="314" BORDER="0" VSPACE=3 ALT=<b>"Q. What did the Deadhead say when his pot ran out? A. Dude, this band sucks!"</b>>&lt;/A>&lt;BR>
&lt;/td>&lt;/tr>&lt;tr>&lt;td align="left" valign="top">
&lt;font size="1" face="geneva,arial,sans-serif">
</code>
</p>
<p>
Nice. But -1 for not using CSS. Really, still using the <b>&lt;font></b> tag?!?!
</p>
</code>
</p>
<p class="footer">
11/08/2005</p>
        
        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Tue, 8 Nov 2005 12:00:00 PST</pubDate>
			<guid>http://www.hccp.org/legit-spiritual-disco.html</guid>
    </item>
   
   
   
    <item>
        <title>Is Apple censoring podcast feed descriptions?</title>
        <link>http://www.hccp.org/itunes-censorship.html</link>
        <description>
        <![CDATA[
        <h3>Is Apple censoring podcast feed descriptions?</h3>
<p>
The title element, viewed in the raw feed, as linked from iTunes:
<div class="feed">
<pre>&lt;item>
    &lt;title>Dick Hardt on Identity 2.0 at Supernova 2005.&lt;/title>
	&lt;description> 
	. . . </pre>
</div>	
	</p>	
<p>But when rendered in iTunes, it seems like some offensive words get blocked:
<p>
<img border="1" src="images/itunes-censorship.gif"/>
</p>
</p>
<p>Maybe it's just the inadvertent innuendo of D**k's name triggering a family-safe filter? It is difficult to believe that every time a certain word appears it is automatically censored (For instance, will we always see "<i>D**k</i> Cheney" in titles on news and political podcast feeds?).
</p>
<p> In any case, it's disappointing to see yet another example of Apple <a href="http://phobos.apple.com/static/iTunesRSS.html">f***ing up</a> podcasting and RSS.</p>
</p>

<p class="footer">
7/30/2005</p>

        
        ]]>
        </description>
        <author>igb@hccp.org</author>
			<pubDate>Sat, 30 Jul 2005 12:00:00 PST</pubDate>
			<guid>http://www.hccp.org/itunes-censorship.html</guid>
    </item>
    <item>
        <title>Setting a global HTTP proxy in C# and .NET client classes.</title>
        <link>http://www.hccp.org/csharp-http-proxy.html</link>
        <description>
        &lt;h3>Setting a global HTTP proxy in C# and .NET client classes.&lt;/h3>&lt;p>To configure HTTP client classes (&lt;tt>System.Net.WebClient, System.Xml.XmlTextReader)&lt;/tt> to use an HTTP proxy use the &lt;tt>System.Net.GlobalProxySelection&lt;/tt> class.&lt;/p>
&lt;p class="code">
&lt;b>Example code:&lt;/b>
&lt;br/>
&lt;br/>&lt;code>System.Net.Uri proxyURI = new System.Net.Uri("http://64.202.165.130:3128");&lt;br/>
System.Net.GlobalProxySelection.Select = new System.Net.WebProxy(proxyURI);
&lt;/code>
&lt;/p>
&lt;p>Subsequent invocations of methods that directly or indirectly make HTTP requests will route the request through the declared proxy.&lt;/p>

        </description>
        <author>igb@hccp.org</author>
			<pubDate>Sat, 30 Jul 2005 12:00:00 PST</pubDate>
			<guid>http://www.hccp.org/csharp-http-proxy.html</guid>
        </item>
    <item>
        <title>Amazon, ASIN, and ISBN</title>
        <link>http://www.hccp.org/amazon-asin-isbn.html</link>
        <description>
 &lt;h1>Amazon.com, ASIN, and ISBN.&lt;/h1>
&lt;p>The other day I wanted to use Amazon's web services to get book info using ISBNs, but couldn't seem to find a method in the e-Commerce API that took an ISBN as a parameter. After some searching&lt;a href="#search">*&lt;/a>, I discovered the following information: &lt;blockquote>Every unique product in Amazon.com's catalog has an "ASIN", which is short for "Amazon Standard Item Number". (For our books category, a book's ASIN is the same as its "International Standard Book Number", or "ISBN").&lt;/blockquote>
Very useful information, indeed. It should have been alot easier to find, but I'm glad that this particular search (looking up a book by ISBN) is available via AWS.
&lt;/p>
&lt;p>
It's also interesting to note that if you enter an ISBN number as a parameter in a &lt;a href="http://www.google.com/search?rls=en&amp;q=0385495323&amp;ie=UTF-8&amp;oe=UTF-8">Google search&lt;/a>, you get an advertisement from Amazon, linking to that book's page on Amazon.com. Looks like it might be time to take a look at Google's AdWords API. 
&lt;/p>
&lt;p class="footnote">&lt;a name="search">*&lt;/a>In order to arrive at this information, I ended up doing a search on amazon.com for books about AWS, and then used Amazon's "Search Inside This Book" feature to get to a page in &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0782143075">Mining Amazon Web Services: Building Applications with the Amazon API&lt;/a>, that in turn referenced a page in the AWS guide (&lt;i>AmazonWebServices/API Guide/search_asin_isbn.htm&lt;/i>) that I'd downloaded previously from amazon, and was sitting on my hard drive. Man, I can't wait for &lt;a href="http://www.apple.com/macosx/features/spotlight/">Spotlight&lt;/a>.&lt;/p>
        
</description>

        <author>igb@hccp.org</author>
			<pubDate>Sat, 30 Jul 2005 12:00:00 PST</pubDate>
			<guid>http://www.hccp.org/amazon-asin-isbn.html</guid>
    </item>
    
    
    
    
    
    <item>
        <title>HOW-TO: Trace logging in WSE 2.0</title>
        <link>http://www.hccp.org/wse-trace-info.html</link>
        <description>
 &lt;h2>HOW-TO: Adding debug or trace information to a WSE service. &lt;/h2>
 &lt;p>The examples in the  &lt;i>Web.config &lt;/i> snippet below show how to add trace logging to SOAP requests and responses: &lt;/p>
 &lt;table cellpadding=8 cellspacing=1 bgcolor="000000">
 &lt;tr>
 &lt;td bgcolor="eeeeee">
 &lt;pre>
 &lt;b>
&amp;lt;configuration>

...

 &amp;lt;configSections>
  &amp;lt;section name="microsoft.web.services2"
           type="Microsoft.Web.Services2.Configuration.WebServicesConfiguration, Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral,  PublicKeyToken=31bf3856ad364e35" />
 &amp;lt;/configSections>

 &amp;lt;microsoft.web.services2>
  &amp;lt;diagnostics> 
   &amp;lt;trace enabled="true" 
          input="inputTrace.webinfo" 
          output="outputTrace.webinfo"/>
  &amp;lt;/diagnostics>
 &amp;lt;/microsoft.web.services2>

...

&amp;lt;/configuration>
 &lt;/b>
 &lt;/pre>
 &lt;/td>
 &lt;/tr>
 &lt;/table>
 &lt;p>This particular configuration will put the specified output files in the configured IIS  &lt;i>wwwroot &lt;/i> directory. So the files might respectively be found, for example, at the following locations:  &lt;tt> &lt;b>C:\Inetpub\wwwroot\ &lt;i>inputTrace.webinfo &lt;/i> &lt;/b> &lt;/tt> or  &lt;tt> &lt;b>C:\Inetpub\wwwroot\ &lt;i>outputTrace.webinfo &lt;/i> &lt;/b> &lt;/tt> &lt;/p>


        
</description>
<author>igb@hccp.org</author>
			<pubDate>Sat, 30 Jul 2005 12:00:00 PST</pubDate>
			<guid>http://www.hccp.org/wse-trace-info.html</guid>
    </item>
    <item>
        <title>Adding 'pushd' invocation to a 'cd' command.</title>
        <link>http://www.hccp.org/modding-cd.html</link>
        <description>&lt;h2&gt;Adding &lt;tt&gt;pushd&lt;/tt&gt; invocation to a &lt;tt&gt;cd&lt;/tt&gt; command.&lt;/h2&gt;
&lt;p&gt;A coworker of mine recently introduced me to the &lt;tt&gt;pushd&lt;/tt&gt; and &lt;tt&gt;popd&lt;/tt&gt; commands in Unix. It's nice to be able to push a location onto a stack, and pop it off later to jump back. It almost gives you a web browser-like history or back button for command line navigation. Almost.&lt;/p&gt;

&lt;p&gt;Where the usability starts to bend is the requirement that one needs know, ahead of time, that one will want to jump back to the current location at some point in the future. Ideally, the push of the current directory would be implicit as one moves around the filesystem. So rather than invoke &lt;tt&gt;popd .&lt;/tt&gt; before every &lt;tt&gt;cd&lt;/tt&gt;, I did a little shell hack and &lt;tt&gt;alias&lt;/tt&gt;'ed &lt;tt&gt;cd&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Here's what the line in my &lt;tt&gt;bash_profile&lt;/tt&gt; looks like:&lt;br/&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;table cellpadding="8" cellspacing="1" bgcolor="000000"&gt;
&lt;tr&gt;
&lt;td bgcolor="eeeeee"&gt;
&lt;tt&gt;&lt;b&gt;.bash_profile&lt;/b&gt;&lt;/tt&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td bgcolor="eeeeee"&gt;
&lt;pre&gt;
alias cd="pushd . &gt; /dev/null; cd"
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;
 . . . now any time I want to go back to where I've been, my directory history is stored in a stack, accessible by &lt;tt&gt;popd&lt;/tt&gt; invocations.
&lt;/p&gt;

</description>
<author>igb@hccp.org</author>
			<pubDate>Sat, 30 Jul 2005 12:00:00 PST</pubDate>
			<guid>http://www.hccp.org/modding-cd.html</guid>
    </item>
    <item>
        <title>Invoking OS X apps from the command line.</title>
        <link>http://www.hccp.org/command-line-os-x.html</link>
        <description>Often I've been working inside the shell, and have wanted to edit or view a file in some non-terminal based application. I recently came across the  "open" command, which allows the terminal to invoke OS X Finder Open commands.</description>
        <author>igb@hccp.org</author>
			<pubDate>Sat, 30 Jul 2005 12:00:00 PST</pubDate>
			<guid>http://www.hccp.org/command-line-os-x.html</guid>
    </item>
    <item>
        <title>Persisting ifconfig changes in Mandrake Linux.</title>
        <link>http://www.hccp.org/misc-mandrake-info.html</link>
        <description>After running in to issues with reboots reverting eth0 settings, despite multiple changes using ifconfig, I tracked down the location of the settings used by Mandrake during startup.</description>
        <author>igb@hccp.org</author>
			<pubDate>Sat, 30 Jul 2005 12:00:00 PST</pubDate>
					<guid>http://www.hccp.org/misc-mandrake-info.html</guid>
    </item>
    <item>
        <title>Getting command line arguments from .BAT scripts.</title>
        <link>http://www.hccp.org/bat-cmd-line-args.html</link>
        <description>When wrapping commands with BAT scripts in DOS, I've often found it useful to allow for any number of arguments to be passed in to the wrapped command. Here's a quick hack to do just that.</description>
        <author>igb@hccp.org</author>
			<pubDate>Sat, 30 Jul 2005 12:00:00 PST</pubDate>
			<guid>http://www.hccp.org/bat-cmd-line-args.html</guid>
    </item>
 </channel>
</rss>
