Comfortably Codinghttp://www.mathew.com.au/blogMathew Rodley's BlogPyRSS2Gen-1.0.0http://blogs.law.harvard.edu/tech/rssThe Analysis & Fix of an annoying MythTV Bughttp://www.mathew.com.au/blog/2010/01/16/the-analysis-fix-of-an-annoying-mythtv-bug/<div class="post-content"> <p>A couple of days ago, I upgraded my MythTV frontend to use an SSD drive. It&#8217;s been great, it&#8217;s very quiet and prodeces a low amount of heat. I also used this as an opportunity to refresh the system by rebuilding it anew. I backed up /etc/ and ~&#8217;s and went about rebuilding the system.</p> <p>Unfortunatly, once I finished and tried the new system, things were not quite smooth and I was hitting a really annoying bug with my infrared remote used to control the system. <b>The remote would only work in MythTV 2 minutes after startup</b>. Wow, how annoying&#8230; A few quick commands showed me that this was nothing wrong with the drivers (which I had to patch myself), or lirc as <i>irw</i> reported the button presses coming through just fine. So my conclusion was that MythFrontend was doing something odd.</p> <h3>Beginning the Investigation</h3> <p>I was running mythtv&#8211;0-22-fixes, so I fired up SVN and checked out the source for that release</p> <pre class="syntax-highlight:php"> svn co http://svn.mythtv.org/svn/branches/release-0-22-fixes/ mythtv-0-22 </pre> <p> Armed with the fantastic power of x-ray-googles, I began looking at how MythFrontend picks up LIRC events. A lot of this magic is in the sources in mythtv/libs/libmythui/*.<br /> In mythmainwindow.cpp, Myth initialises a thread which reads from LIRCD on whichever UNIX socket or tcp/ip socket you have it setup from (this is in MythMainWindow::StartLIRC())</p> <p>This begins a thread which has a its runloop defined as LIRC::run() in lirc.cpp. However, before this is called, LIRC is initialised by LIRC::Init(). Needless to say, all of this was performing successfully and Myth, for all intents and purposes was reading my keypresses from /dev/lircd which were picked up from my remote by LIRCD just fine (irw prooved this).</p> <p>At this point I moved further down the stack. When a code is received from LIRCD, the LIRC thread calls LIRC::Process(data), passing it that keypress information. This method will do some logic and then send a KeyPress and a KeyRelease to the MythFrontend main window</p> <pre class="syntax-highlight:php"> QApplication::postEvent( m_mainWindow, new LircKeycodeEvent( QEvent::KeyPress, keycode, mod, text, lirctext)); QApplication::postEvent( m_mainWindow, new LircKeycodeEvent( QEvent::KeyPress, keycode, mod, text, lirctext)); </pre> <p>and later</p> <pre class="syntax-highlight:php"> for (int i = (int)keyReleases.size() - 1; i&gt;=0; i--) { QApplication::postEvent(m_mainWindow, keyReleases[i]); } </pre> <p>Some quick working with a debugger told me that these functions were being called. At this point I began to wonder if the mainWindow was receiving these events. I tracked the callback handler for these events to libs/libmythui/mythmainwindow.cpp, to the customEvent method.</p> <pre class="syntax-highlight:php"> void MythMainWindow::customEvent(QEvent *ce) </pre> <p>Now, this is where it gets interesting. This customEvent method was being called for all Keypresses, HOWEVER it was ignoring some! - Aha, my problem was here somewhere (or so I thought…).</p> <p>Inside this customEvent method, there is a large conditional to deal with a number of cases, one of which deals with LIRC keycode events:</p> <pre class="syntax-highlight:php"> else if (ce-&gt;type() == (QEvent::Type) LircKeycodeEvent::kLIRCKeycodeEventType &amp;&amp; !d-&gt;ignore_lirc_keys) { </pre> <p>It turns out that this was not being called, which was why I was experiencing my problem (but not the root cause). Now, the smart readers here will notice the !d->ignore_lirc_keys condition. This was causing the problem. For some reason ignoe_lirc_keys was true for the first 2 minutes after starting up… What… why would this be? Well, to find out I had to figure out how ignore_lirc_keys could be set to true. </p> <h3>Setting ignore_lirc_keys to true</h3> <p>Some plodding around in the source code revealed that there is an LircEventLock::Lock() method in lircevent.cpp. This was being called by someone, causing mythfrontend to ignore LIRC keypresses. To get a simple backtrace at this point, I modified the code to include </p> <pre class="syntax-highlight:php"> #include &lt;execinfo.h&gt; </pre> <p>so that I can call backtrace() and backtrace_symbols(). This allowed me to get a stack trace at the point the Lock was set, and see who might be calling Lock, and annoying the hell out of me. Here is the result of that stack trace:</p> <pre class="syntax-highlight:php"> Obtained 10 stack frames. /home/user/sandbox/my-myth-build/lib/libmythui-0.22.so.0(_Z11print_tracev+0x26) [0x5f7796] /home/user/sandbox/my-myth-build/lib/libmythui-0.22.so.0(_ZN13LircEventLock4lockEv+0x1f3) [0x5f7a03] /home/user/sandbox/my-myth-build/lib/libmythui-0.22.so.0(_ZN13LircEventLockC1Eb+0x25) [0x5f7bf5] /home/user/sandbox/my-myth-build/lib/libmythui-0.22.so.0(_Z11myth_systemRK7QStringi+0x48) [0x5a9198] /home/user/sandbox/my-myth-build/lib/libmyth-0.22.so.0(_ZN15MythMediaDevice15performMountCmdEb+0x58e) [0x669807e] /home/user/sandbox/my-myth-build/lib/libmyth-0.22.so.0(_ZN7MythHDD10checkMediaEv+0x98) [0x67623e8] /home/user/sandbox/my-myth-build/lib/libmyth-0.22.so.0(_ZN12MediaMonitor12CheckDevicesEv+0x5e) [0x669a66e] /home/user/sandbox/my-myth-build/lib/libmyth-0.22.so.0(_ZN13MonitorThread3runEv+0x38) [0x669a708] /usr/lib/libQtCore.so.4 [0x59cce32] /lib/tls/i686/cmov/libpthread.so.0 [0x64e80e] </pre> <p> As you can see, Lock() is called by myth_system, which is called by MythMediaDevice::performMountCmd, called by MythHDD::checkMedia etc…</p> <h3>BINGO</h3> <p>Armed with this knowledge, I knew exactly what was happening. The myth_system() is used to execute commands, however when these commands execute, sometimes we want mythfrontend to ignore LIRC commands sent to it. For example, if myth_system executes mplayer, which is now in-front of mythfrontend, we should ignore LIRC keypresses on Myth. However, the mount command also caused mythfrontend to Ignore Keypresses while mount was being run.</p> <p><b>But why two minutes?</b> Because I have a cardreader which registers 4 SCSI devices which cannot be mounted without cards in them. if you try and mount them, the mount command waits an amount of time (sometimes up to 30 seconds, it seems for me) then gives up.</p> <p><b>The sdb, sdc, sdd and sde devices in /dev</b></p> <pre class="syntax-highlight:php"> user@kmedia2:~/sandbox/my-myth-build$ ls /dev | grep -e &quot;^sd&quot; sda sda1 sda2 sda5 sdb sdc sdd sde user@kmedia2:~/sandbox/my-myth-build$ </pre> <p><b>dmesg</b></p> <pre class="syntax-highlight:php"> [ 7.064559] usb-storage: device scan complete [ 7.101340] scsi 8:0:0:0: Direct-Access Generic STORAGE DEVICE 9602 PQ: 0 ANSI: 0 [ 7.107230] scsi 8:0:0:1: Direct-Access Generic STORAGE DEVICE 9602 PQ: 0 ANSI: 0 [ 7.120038] scsi 8:0:0:2: Direct-Access Generic STORAGE DEVICE 9602 PQ: 0 ANSI: 0 [ 7.148029] scsi 8:0:0:3: Direct-Access Generic STORAGE DEVICE 9602 PQ: 0 ANSI: 0 [ 7.148391] sd 8:0:0:0: Attached scsi generic sg2 type 0 [ 7.148466] sd 8:0:0:1: Attached scsi generic sg3 type 0 [ 7.148544] sd 8:0:0:2: Attached scsi generic sg4 type 0 [ 7.148619] sd 8:0:0:3: Attached scsi generic sg5 type 0 [ 7.447250] sd 8:0:0:1: [sdc] Attached SCSI removable disk [ 7.458246] sd 8:0:0:3: [sde] Attached SCSI removable disk [ 7.469466] sd 8:0:0:0: [sdb] Attached SCSI removable disk [ 7.491250] sd 8:0:0:2: [sdd] Attached SCSI removable disk </pre> <p><b>the mount command</b></p> <pre class="syntax-highlight:php"> root@kmedia2:/mnt# time mount /dev/sdb trash mount: /dev/sdb: unknown device real 0m18.158s user 0m0.004s sys 0m0.000s </pre> <p>By the way, if I rmmod -f usb-storage, which removes these devices in /dev, mythtv starts fine.</p> <h3>The Simple Fix</h3> <p>So, armed with the known cause of the issue, and the fact that myth_system accepts a flag called MYTH_SYSTEM_DONT_BLOCK_LIRC, which causes the system() command not to block LIRC keypresses on the front end, I added a small patch.</p> <p>I changed line 124 of libs/libmyth/mythmedia.cpp from</p> <pre class="syntax-highlight:php"> if (0 == myth_system(MountCommand)) </pre> <p>to</p> <pre class="syntax-highlight:php"> if (0 == myth_system(MountCommand, MYTH_SYSTEM_DONT_BLOCK_LIRC)) </pre> <p>I compiled the libmyth library, and everything was OK… the bug was gone!</p> </div>adminhttp://www.mathew.com.au/blog/2010/01/16/the-analysis-fix-of-an-annoying-mythtv-bug/Sat, 16 Jan 2010 01:07:21 GMTToday… I played with Codilityhttp://www.mathew.com.au/blog/2010/01/13/today-i-played-with-codility/<div class="post-content"> <p>Well this seems pretty cool, http://codility.com</p> <p>Although, it seems to just quiz you about basic asymptotic growth and does not seem to look at things like programming style etc. Still, I&#8217;m please my Ruby answer for the demo test got 100%, which, as the histogram shows&#8230; Not many people get. I suspect that the reason is, many people probably submit an O(n^2) answer, which fails for very large data sets. Here is what I submitted</p> <p>And here is what I submitted:</p> <pre class="syntax-highlight:php"> def equi(arr) lhs = 0 tmp = 0 rhs = arr.inject(0) { |a,b| a + b } arr.each_index do |i| lhs += tmp rhs -= arr[i] tmp = arr[i] return i if lhs == rhs end return -1 end </pre> <p> And Here&#8217;s the analysis it gave back to me:</p> <table class="tab"> <thead> <tr> <th>test</th> <th>time</th> <th>result</th> </tr> </thead> <tbody> <tr> <td> example <p></p> <p> <small>Test from the task description</small></p> </td> <td align="right">0.012&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> extreme_empty <p> <small>Empty array</small></p> </td> <td align="right">0.020&nbsp;s.</td> <td> <p> <b>OK</b></p> </td> </tr> <tr> <td> extreme_first </td> <td align="right">0.008&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> extreme_large_numbers <p> <small>Sequence with extremly large numbers testing arithmetic overflow.</small></p> </td> <td align="right">0.020&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> extreme_last </td> <td align="right">0.012&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> extreme_single_zero </td> <td align="right">0.020&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> extreme_sum_0 <p> <small>sequence with sum=0</small></p> </td> <td align="right">0.020&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> simple </td> <td align="right">0.016&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> single_non_zero </td> <td align="right">0.012&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> combinations_of_two <p> <small>multiple runs, all combinations of {-1,0,1}^2</small></p> </td> <td align="right">0.008&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> combinations_of_three <p> <small>multiple runs, all combinations of {-1,0,1}^3</small></p> </td> <td align="right">0.012&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> small_pyramid </td> <td align="right">0.072&nbsp;s.</td> <td> <p> <b>OK</b></p> </td> </tr> <tr> <td> large_long_sequence_of_ones </td> <td align="right">13.349&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> large_long_sequence_of_minus_ones </td> <td align="right">10.781&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> medium_pyramid </td> <td align="right">4.336&nbsp;s.</td> <td> <b>OK</b> </td> </tr> <tr> <td> large_pyramid <p> <small>Large performance test, O(n^2) solutions should fail.</small></p> </td> <td align="right">21.369&nbsp;s.</td> <td> <b>OK</b> </td> </tr> </tbody> </table> </div>adminhttp://www.mathew.com.au/blog/2010/01/13/today-i-played-with-codility/Wed, 13 Jan 2010 11:55:47 GMTDynamic Image Reflectionhttp://www.mathew.com.au/blog/2009/02/08/dynamic-image-reflection/<div class="post-content"> <p>Todays post is about creating a mirrored effect on images appearing on a website. Looking around, there are already a few people who have attempted to do this, however, I would like to tackle the problem myself and provide an in depth post about how to actually do it. At the end of this post we should have a fully functioning jQuery plugin which allows us to mirror images. We can approach this two ways, using Canvas or SVG. I have opted to use Canvas, however I did create a neat SVG file which is able to mirror arbitrary images, passed in by a query parameter. The first part if this post will address creating a reflection of an image. Once we have the ability to do this, we can roll it into a jQuery plugin to provide reflections for images which we specify.<span id="more-13"></span></p> <p><strong>Creating a Reflection</strong><br /> The approach I have taken for reflection uses the HTML canvas element. The Canvas element was originally introduced by Apple into their WebKit component and allows for a drawable region in HTML. The Canvas element exposes a full set of drawing functions to the developer to draw inside of it. We can utilise these functions to mirror an image, complete with a &#8216;fading&#8217; effect. Assuming we already have a canvas DOM element, we can retrieve the 2d drawing context with a call to <em>getContext(&#8217;2d&#8217;)</em> on the DOM element. This can then be used to draw to the canvas via a published API. If you wish to know more the Mozilla Developer Center has published some <a href="https://developer.mozilla.org/en/Drawing_Graphics_with_Canvas">tutorials on using Canvas</a>.</p> <p>In order to achieve our mirror effect, we must &#8216;flip&#8217; the vertical of the image. We can achieve this using the scale function exposed to us in the canvas API, <em>context.scale(1, -1)</em>. This will effectively &#8216;flip&#8217; what we draw, or, more technically add a &#8216;flip&#8217; transform to the translation matrix of our canvas element. The Mozilla Developer Center again provides some useful resources <a href="https://developer.mozilla.org/en/Canvas_tutorial/Transformations#Scaling">regarding the use of scale</a>. However, this documentation states that <em>scale()</em> may only take positive arguments.</p> <p>With a little experimentation however, I revealed that it actually works as expected for negative augments. Quite naturally I followed this up with some source code digging.<br /> For WebKit, in<a href="http://trac.webkit.org/browser/trunk/WebCore/html/CanvasRenderingContext2D.cpp"> CanvasRenderingContext2D.cpp</a> line 326 we see the definition for the scale function, as provided to us by the 2d drawing context in WebKit. All this does is add a scale transformation to the current transformation matrix of the canvas. If this is negative, it will cause a &#8216;flip&#8217; of the image.<br /> In Firefox we find in <a href="http://mxr.mozilla.org/firefox/source/content/canvas/src/nsCanvasRenderingContext2D.cpp">nsCanvasRenderingContext2D.cpp</a> on line 877 the definition for scale. This simply calls cairo_scale, with the supplied parameters. Cairo is the Firefox graphics backend, so it makes quite a bit of sense that this actually happens and <a href="http://www.cairographics.org/manual/cairo-transformations.html#cairo-scale">cairo_scale</a> accepts negative parameters as well.</p> <p>But I digress. We may achieve a reflected image with the following code (assuming we have the 2d context from the canvas (canvas) and an image we want to mirror (image)):</p> <pre class="syntax-highlight:javascript"> canvas.translate(0, image_height);canvas.scale(1, -1); canvas.drawImage(image, 0, 0, image_width, image_height); canvas.restore(); </pre> <p>This will render a mirrored form of the image, flipped on the horizontal axis. However, many mirror effects also feature a gradual fading of the mirrored image. In order to add this we add a mask on top of our flipped image, using the &#8216;destination-in&#8217; globalCompositeOperation:</p> <pre class="syntax-highlight:javascript"> canvas.globalCompositeOperation = &quot;destination-in&quot;; var gradient = canvas.createLinearGradient(0, 0, 0, height); gradient.addColorStop(1, &quot;rgba(255, 255, 255, 1.0)&quot;); gradient.addColorStop(0, &quot;rgba(255, 255, 255, 0.0)&quot;); canvas.fillStyle = gradient; canvas.rect(0, 0, width, height); canvas.fill(); </pre> <p>This now completes our mirror image effect, fading out to black as the distance from the horizontal flip axis increases. In order to make this functionality, cleaner, more modular &amp; reusable and thus more useful to us, we make this functionality available as a jQuery plugin. The goal should be that one only needs to call <em>$(&#8217;.mirror&#8217;).mirror()</em> to mirror all images selected by the selector (in this case, all images with a class of &#8216;mirror&#8217;).  In order to achieve this, we turn our approach into a jQuery extension, and add the function mirror(). As I have explained the general method, I will provide a simple example for a jQuery plugin:</p> <pre class="syntax-highlight:javascript"> jQuery.fn.mirror = function() { /* * jQuery functions should return &#039;this&#039;, to conform to the fluent interface. * We also iterate through all img elements. */ return this.find(&quot;img&quot;).each(function(i, e) { /* Our jQuery Element */ var je = jQuery(e); /* For a number of calculations, we require the width and the height of the image */ var width = je.attr(&#039;width&#039;); var height = je.attr(&#039;height&#039;); /* * Create a div to contain our original image * and its reflection. */ var div = jQuery(&quot;&lt;div&gt;&lt;/div&gt;&quot;) .css(&#039;position&#039;, &#039;relative&#039;) .css(&#039;width&#039;, width) .css(&#039;height&#039;, height * 2); /* create a canvas for our relection */ var canvas = jQuery(&quot;&lt;canvas&gt;&lt;/canvas&gt;&quot;) .attr(&#039;width&#039;, width) .attr(&#039;height&#039;, height) .css(&#039;width&#039;, width) .css(&#039;height&#039;, height) .css(&#039;position&#039;, &#039;absolute&#039;) .css(&#039;left&#039;, 0) .css(&#039;top&#039;, height); /* * Replace the image with our div. * This line is magic for taking the image out * putting the image &amp; canvas in the div, * then putting the div in the images place. */ div.append(je.replaceWith(div)).append(canvas); /* * Now we must do our voodo with canvas to make a * reflection of the image */ canvas = canvas.get(0).getContext(&#039;2d&#039;); je.load(function() { canvas.translate(0, height); canvas.scale(1, -1); canvas.drawImage(e, 0, 0, width, height); canvas.restore(); canvas.globalCompositeOperation = &quot;destination-in&quot;; var gradient = canvas.createLinearGradient(0, 0, 0, height); gradient.addColorStop(1, &quot;rgba(255, 255, 255, 1.0)&quot;); gradient.addColorStop(0, &quot;rgba(255, 255, 255, 0.0)&quot;); canvas.fillStyle = gradient; canvas.rect(0, 0, width, height); canvas.fill(); }); }); } </pre> </div>adminhttp://www.mathew.com.au/blog/2009/02/08/dynamic-image-reflection/Sun, 08 Feb 2009 07:26:00 GMTRuby inside .NET and Javahttp://www.mathew.com.au/blog/2009/01/27/ruby-inside-net-and-java/<div class="post-content"> <p> In the past I have played around with JRuby and accessing some of the Java framework from Ruby. Its fantastic and I have raved about it infront of my friends in the past.  Microsoft as well now have a product called IronRuby which runs Ruby inside Microsofts Dynamic Language Runtime (DLR). IronRuby is a Ruby interpereter which runs in the DLR and as a byproduct gives Ruby access to the .NET framework (yay, power to the programmer!). <span id="more-17"></span></p> <p>I just thought I would blog about this little code snippet I put together on the weekend for some fun. It retrives the IP addresses for the interfaces on the machine it is run on.  If it is run in JRuby (inside the JVM) it uses the Java framework to retrieve the interfaces and print them. If it is running in IronRuby (inside the DLR) it uses the .NET framework to retreive the IP addresses. Finally, if it is not running in either of those it reports that we are not running in either the JVM or the DLR and exits.</p> <p>I suspect this may be a handy thing to do if you have common tasks which you perform accross the two different environments (Java and .NET) as you dont have to expose functionality from inside your environment, you can intergrate directly into it using the same language (with a bit of added abstraction on your part)</p> <pre class="syntax-highlight:ruby">path = { :DotNet =&gt; lambda { require &#039;System.Management, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&#039; mc = System::Management::ManagementClass.new(&quot;Win32_NetworkAdapterConfiguration&quot;) moc = mc.GetInstances() moc.each { |v| p v.GetPropertyValue(&quot;ipAddress&quot;) if v.GetPropertyValue(&quot;ipEnabled&quot;) } }, :Java =&gt; lambda { java.net.NetworkInterface.networkInterfaces.each { |v| puts v } }, :None =&gt; lambda { puts &quot;Sorry, you are not running in the JVM or DLR&quot; } } begin # If we are in IronRuby we have access to the .NET classes require &#039;mscorlib&#039; call = :DotNet rescue Exception =&gt; e begin include Java call = :Java rescue Exception =&gt; e call = :None end end path[call].call() </pre> </div>adminhttp://www.mathew.com.au/blog/2009/01/27/ruby-inside-net-and-java/Tue, 27 Jan 2009 03:07:57 GMTMail Server with Dovecot and Exim4http://www.mathew.com.au/blog/2009/01/19/mail-server-with-dovecot-and-exim4/<div class="post-content"> <p>I am changing my hosting around at the moment and have a new server, that is completely managed by myself. One of my first requirements is to setup up mail hosting for my domains. Since I am not using any sort of control panel or packaged software, I have to configure this by hand. My needs are simple: virtual users, TLS/SSL security and to run with a small footprint. Further down the track, I also plan on adding virus and spam filtering. <span id="more-16"></span></p> <p><strong>Software</strong><br /> First off, I had to choose the software I would use. I elected t use <a href="http://www.dovecot.org/">Dovecot</a> for my IMAP server and <a href="http://www.exim.org/">Exim4</a> for my MTA. Dovecot is an excellent choice for an IMAP server as it is designed with security in mind, is simple to configure has a low memory footprint, performs excellently and supports the Maildir format which I intended to use. Exim4 is a good MTA, with a simple and clean configuration (relative to Sendmail!) and is designed with consideration to security.</p> <p>My server is running Debian Etch, so installation of these packages through apt is easy. However, I had to install Exim4 from Backports as version 6.64 and later include an authentication driver for dovecot that allowing Exim4 to authenticate SMTP sessions against the Dovecot user database. The version of Exim4 that ships with Etch is 6.63, which means I either had to compile a new version from source or use Exim4 from Backports. I elected to use Backports. Installing the required software is easy, once you have the etch-backports repository (note, exim4-daemon-heavy has the extra Dovecot authentication driver):</p> <pre class="syntax-highlight:bash"> sudo apt-get -t etch-backports install exim4-daemon-heavy sudo apt-get install dovecot-imapd </pre> <p><strong>Configuration</strong><br /> I started by configuring Dovecot so I could access a users Maildir through IMAPS. Because all users would be virtual, the Maildir&#8217;s would be stored in /home/vmail/$user@$domain/Maildir/ and owned by vmail:vmail. It should be noted here that the Maildir&#8217;s have the executable permission set on them so that Exim4 can validate that the user exists. Failure to do so will cause Exim4 to report an Unroutable Address error.</p> <p>The contents of my /etc/dovecot/dovecot.conf contains a line by line description in comments, and is more or less pretty painless:</p> <pre class="syntax-highlight:php"> # Protocols (others available imap, pop3, pop3s) protocols = imaps # Log files for Dovecot log_path = /var/log/dovecot/main.log info_log_path = /var/log/dovecot/info.log # SSL settings (I already generated my certificate, if you don&#039;t know how visit http://letmegooglethatforyou.com/?q=openssl%20generate%20certificate). ssl_listen = * ssl_disable = no ssl_cert_file = /etc/ssl/certs/example.crt ssl_key_file = /etc/ssl/private/exmaple.key # Auth Settings (do not allow plaintext auth (except when under SSL/TLS) disable_plaintext_auth = yes # We are not really a very busy imap server, so we dont need a large number of processes waiting for logon login_processes_count = 1 # So we get information about processes (in ps). verbose_proctitle = yes # Login process can auth multiple connections (less secure then yes, but I&#039;m aiming for less overall processes) login_process_per_connection = no # We&#039;re using Maildir format mail_location = maildir:~/Maildir # we want group xwrx--x-- so exim can validate the addresses (it does a stat on /home/vmail/local_part@domain_part/ umask = 0066 # Not required for me, but in there in case I ever want to support pop3. # Outlook 2003 has problems with the default, while %08Xu%08Xv is regarded as more or less safe. pop3_uidl_format = %08Xu%08Xv # 108 is my vmail user id. If this is too high, Dovecot will not allow the user to read/write the Maildir&#039;s first_valid_uid = 108 # Optimizations maildir_copy_with_hardlinks=yes # Authentication Config auth_verbose = yes auth default { mechanisms = plain login passdb passwd-file { args = /etc/dovecot/passwd } userdb static { args = uid=vmail gid=vmail home=/home/vmail/%u } socket listen { # This allows authentication to take place between lda (the dovecot deliver) and dovecot master { path = /var/run/dovecot/auth-master mode = 0600 user = vmail group = vmail } # This allows Exim4 to authenticate against Dovecot&#039;s user database client { path = /var/run/dovecot/auth-client mode = 0666 user = vmail group = vmail } } } # deliver Configuration protocol lda { postmaster_address = postmaster@example.org log_path = /var/log/dovecot/deliver.log info_log_path = /var/log/dovecot/deliver.log auth_socket_path = /var/run/dovecot/auth-master } </pre> <p>This then leaves my user configuration in /etc/dovecot/passwd formatted as follows:</p> <pre class="syntax-highlight:php"> # # Example.org # user1@example.org:{PLAIN}plaintxtpass user2@example.org:{SSHA}mp9sL0Xl1kqi2N/3g/E6qU/PTtV/+qEx </pre> <p>To generate passwords other then plain, use the dovecotpw program, e.g. dovecotpw -s SSHA</p> <p>Configuring Exim4 is slightly tricker, also note that I am using the Debian split configuration here, so if you are using the monolithic single file configuration, you will have to figure out where things go yourself.</p> <p>First either update your update-exim4.conf.conf by hand and issue the `update-exim4.conf` command or use `dpkg-reconfigure exim4-config` to configure your install as a Internet mail server listening on a public interface and to accept email for the domains you plan to host email for. Once this was done I began to configure Exim4 to work the way I wanted. In order to do this I had to do a few things.</p> <p><strong>Configuring TLS</strong><br /> If you do not already have a certificate you may use `/usr/share/doc/exim4-base/examples/exim-gencert` to generate the exim.crt and exim.key files which are placed in /etc/exim4. Once I had my certificates I set the MAIN_TLS_ENABLE macro to true. I did this by creating the file /etc/exim4/conf.3/main/00_local containing:</p> <pre class="syntax-highlight:php"> MAIN_TLS_ENABLE = true </pre> <p><strong>Configuring Authentication with Dovecot</strong><br /> As I said before, Exim4 can be used to authenticate against Dovecot. In order do do this I created the file /etc/exim4/conf.d/auth/20_dovecot and inside placed:</p> <pre class="syntax-highlight:php"> dovecot_login: driver = dovecot public_name = LOGIN server_socket = /var/run/dovecot/auth-client server_set_id = $auth1 dovecot_plain: driver = dovecot public_name = PLAIN server_socket = /var/run/dovecot/auth-client server_set_id = $auth1 </pre> <p>You should notice that the server_socket corresponds to my configuration in the Dovecot config file.</p> <p><strong>Alias &amp; Virtual Emails Routing</strong><br /> My actual email accounts do not correspond to system users and as such Exim4 needs a mechanism to know if an email is valid (and how to deliver it, however I deal with that in the next section). As well as this, I wanted to allow aliases to be created, for example alias@example.org is an alias for user1@example.org. In order to do this I created both an alias router and a router to my virtual mailbox&#8217;s (my Dovecot configuration expects the mailboxes to be in /home/vmail/user@domain/Mailbox).</p> <p>I first created a router for Dovecot in /etc/exim4/conf.d/router/880_dovecot_router. It must be noted that this sends it to a transport called dovecot_transport. This is not yet created, however I will create one shortly. Also, we allow the local part to have a suffix, this allows us to route emails such as user1+emailsuffix@example.org which you may wish to mark certain subscriptions with.</p> <pre class="syntax-highlight:php"> dovecot_router: driver = accept local_part_suffix = +* local_part_suffix_optional require_files = +/home/vmail/${local_part}@${domain}/Maildir transport = dovecot_transport </pre> <p>I also created a virtual alias router to allow me to specify mappings, such as a catchall for a domain *@example.org -&gt; user1@example.org or aliases such as alias@example.org -&gt; user1@example.org. To do this I created the file /etc/exim4/conf.d/router/870_virtual_aliases</p> <pre class="syntax-highlight:php"> virtual: driver = redirect allow_defer allow_fail data = ${lookup{$local_part@$domain}lsearch*@{/etc/exim4/virtual.users}} domains = partial-lsearch;/etc/exim4/virtual.domains retry_use_local_part </pre> <p>Along with this, I also maintain two files /etc/exim4/virtual.users that specifies my aliases:</p> <pre class="syntax-highlight:php"> # # Example.org # alias@example.org : user1@example.org *@example2.org : user2@example.org </pre> <p>And /etc/exim4/virtual.domains which specifies any domain with a virtual alias:</p> <pre class="syntax-highlight:php"> example.org example2.org </pre> <p><strong>Virtual Email Delivery</strong><br /> In order to deliver mail to my virtual user&#8217;s Maildir, which will allow Dovecot to read them I had to create my own transport. There are two ways to accomplish this. I could deliver to the Maildir directly or use Dovecot&#8217;s deliver binary. Dovecot&#8217;s deliver will do magical things such as update Dovecot&#8217;s transparent indexes, so this is the approach I took, and would recommend. I will however also provide the Maildir transport but commented out. I defined my dovecot_transport in /etc/exim4/conf.d/transport/36_dovecot_transport:</p> <pre class="syntax-highlight:php"> #dovecot_transport: # driver = appendfile # user = vmail # group = vmail # mode = 0600 # directory=/home/vmail/${lc:$local_part}@${lc:$domain}/Maildir/ # maildir_format = true # mode_fail_narrower = false # envelope_to_add = true # return_path_add = true dovecot_transport: driver = pipe command = /usr/lib/dovecot/deliver -d $local_part@$domain message_prefix = message_suffix = log_output = delivery_date_add envelope_to_add return_path_add group = vmail user = vmail </pre> <p><strong>Rebuilding Configuration&amp; Restarting</strong><br /> With all this done, I rebuilt the exim4 configuration file with `update-exim4.conf.template` and restarted both Dovecot and Exim4. They should be now configured to process and serve Email together:</p> <pre class="syntax-highlight:bash"> sudo update-exim4.conf.template -r sudo /etc/init.d/dovecot restart sudo /etc/init.d/exim4 restart </pre> <p><strong>Testing</strong><br /> You may also test your configuration with a few commands in order to work out how and where email is being delivered to, I recommend you try this on an alias. You should see it map to a virtual address.</p> <p>To run exim in address testing mode (pass the -d flag for debugging information)</p> <pre class="syntax-highlight:bash"> exim -bt &#039;user1@example.org&#039; </pre> <p>To run exim in address verification mode (pass the -d flag for debugging information)</p> <pre class="syntax-highlight:bash"> exim -bv &#039;user1@example.org&#039; </pre> <p>And lastly, you are able to use SMTP directly by starting a telnet session to port 25 and testing things out. It should appear something like this (the lines without the prefixed numbers are what I type):</p> <pre class="syntax-highlight:bash"> khaless@galactica:~$ telnet localhost 25 Trying 127.0.0.1... Connected to localhost.localdomain. Escape character is &#039;^]&#039;. 220 galactica ESMTP Exim 4.69 Mon, 19 Jan 2009 01:38:29 -0500 EHLO example.org 250-galactica Hello localhost.localdomain [127.0.0.1] 250-SIZE 52428800 250-PIPELINING 250-AUTH LOGIN PLAIN 250-STARTTLS 250 HELP MAIL FROM: user1@example.org 250 OK RCPT TO: user2@example.org 250 Accepted DATA 354 Enter message, ending with &quot;.&quot; on a line by itself Subject: My Test Email Hello, I am a test email. . 250 OK id=1LOnmh-0006Hx-Vt quit 221 galactica closing connection Connection closed by foreign host. khaless@galactica:~$ </pre> </div>adminhttp://www.mathew.com.au/blog/2009/01/19/mail-server-with-dovecot-and-exim4/Mon, 19 Jan 2009 06:43:52 GMTTsukasa’s PyGolf Challengehttp://www.mathew.com.au/blog/2008/12/06/tsukasas-pygolf-challenge/<div class="post-content"> <p>Greg recently offered a challenge: <a href="http://blag.tsukasa.net.au/2008/11/23/python-golf-competition/">Python Golf</a>. The idea, to create a parser for Apache&#8217;s Common Log Format, to aggregate the amount of data sent to each IP address. The challenge being to do it with the least amount of characters. Soon after this challenge was issued, <a href="http://moofco.com/blog/">Sam</a> and <a href="http://blag.tsukasa.net.au">Greg</a> were both convinced (before even talking to me) that I would attempt a Ruby solution. How could I dissapoint them? :).</p> <p>I tried a number of things, however I eventually settled on this solution (63 chars):</p> <pre class="syntax-highlight:ruby"> m=Hash.new(0);STDIN.map{|l|m[l[/^\S+/]]+=l[/\d+\s+$/].to_i};p m </pre> <p>A slightly longer version, with a slightly prettier printing can be accomplished with inject (78 chars):</p> <pre class="syntax-highlight:ruby"> STDIN.inject(Hash.new(0)){|m,l|m[l[/^\S+/]]+=l[/\d+\s+$/].to_i;m}.each{|v|p v} </pre> <p>Not to brag, but the <a href="http://blag.tsukasa.net.au/2008/11/29/pygolf-winner-of-competition-1/">winning Python entry</a> was 121 characters. So the Ruby solution managed to be almost half this count!</p> </div>adminhttp://www.mathew.com.au/blog/2008/12/06/tsukasas-pygolf-challenge/Sat, 06 Dec 2008 00:53:16 GMTSome things for the debugging toolboxhttp://www.mathew.com.au/blog/2008/10/10/some-things-for-the-debugging-toolbox/<div class="post-content"> <p>Reading Steve&#8217;s blog today I saw his post on <a href="http://www.shuningbian.net/2008/10/some-people-are-going-to-hate-me-for.php">accessing the current functions name in python</a>. This could end up being a useful thing to know if you are  playing with some unfamiliar code and need this sort of information, or are doing something nasty. So without anymore fuss here&#8217;s how to do the same thing in Ruby and JavaScript! <span id="more-12"></span></p> <p><strong>JavaScript</strong></p> <p>We can access the current functions name through arguments.callee.name, in fact to take this a bit further, arguments.callee is the function actually being called (so we can recurse in anonymous functions!</p> <pre class="syntax-highlight:javascript"> function NamedFunction() { console.log(arguments.callee.name); } var fn = NamedFunction; fn(); </pre> <p>Outputs: &#8220;NamedFunction&#8221;</p> <p><strong>Ruby</strong></p> <p>In Ruby you can use the caller method of the Kernel module (all objects have this). caller returns an array of strings representing the stack and we can use this (as <a href="http://facets.rubyforge.org/">Ruby Facets </a>does) to find out the current functions name. Ruby Facets extend the Kernel module with `called`:</p> <pre class="syntax-highlight:ruby"> module Kernel def called /`([^&#039;]+)&#039;/.match(caller(1).first)[1].to_sym end end </pre> <p>and one can now write</p> <pre class="syntax-highlight:ruby"> def namedFunction puts called end namedFunction() </pre> <p>Outputs &#8220;namedFunction&#8221;</p> <p><strong>JavaScript Stack trace</strong></p> <p>Getting  a stack trace in JavaScript is a fun task, because browsers are not the same, but here are some quick tips. When Firefox throws an exception, that exception has a &#8217;stack&#8217; member which contains a stack trace. For example:</p> <pre class="syntax-highlight:javascript"> try { var x = nil; x.x; } catch(e) {console.log(e.stack); } </pre> <p>Opera&#8217;s exceptions contain the &#8216;message&#8217; member which contains stack information. And finally IE and Safari don&#8217;t provide anything, but we can roll our own using arguments.callee.caller, which is as you guessed it the function which has called the current function. So we can roll our own!</p> <pre class="syntax-highlight:javascript"> function stack() { var fn = arguments.callee; while(fn = fn.caller) { console.log(fn.name || &quot;Anonymous&quot;); } } function a() { stack() } function b() { a() } function c() { b() } c(); </pre> <p>Outputs: &#8220;a b c&#8221;</p> <p><strong>JavaScript &amp; recursing anonymous functions</strong></p> <p>And just a little icing on the cake for the end of this post. Take some time and run this in a JavaScript Shell <img src="http://www.mathew.com.au/blog/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /> </p> <pre class="syntax-highlight:javascript"> var x = 0; (function() { console.log(x++); if(x &lt; 10) arguments.callee(); })(); </pre> </div>adminhttp://www.mathew.com.au/blog/?p=12Fri, 10 Oct 2008 04:39:56 GMTAvoiding Bad Email Communicationhttp://www.mathew.com.au/blog/2008/10/03/avoiding-bad-email-communication/<div class="post-content"> <p>It often occurs that once I subscribe to a website, they wants to communicate with me via email. This may be information about my account, confirmation of some process or an occasional  email promoting some new feature or deal. In many of these cases websites may choose to send an email in which the content is presented in HTML. HTML may appear like a good choice to someone who only thinks about bells and whistles, however in reality there are a number of issues. Off the top of my head, here is a list:<span id="more-11"></span></p> <p><strong>Problem 1 - Not everyone can read HTML</strong></p> <p>There is a portion of your subscribers who will receive emails that are unable to render the HTML. In this case, if all they see is HTML it is probably safe to assume they cannot read it, and to them this email is worthless.</p> <p><strong>Problem 2 - HTML typically uses more bandwidth &amp; CPU</strong></p> <p>Remember that users are becoming increasingly mobile. I really don&#8217;t want to be waiting 30 seconds to download the larger email, possibly with images, and wasting my battery life on my mobile device just because you want HTML, consider this growing portion of users and provide an alternative for them.</p> <p><strong>Problem 3 -  It is hard to create good HTML Emails</strong></p> <p>Most email clients use old rendering engines which don&#8217;t support many new features. Adding to this the variation in so many of these clients, to write a HTML email that will even display the same in most mail clients is a challenge. Restrict yourself mostly to older flavours of HTML, if you do need to use CSS, use inline styles and keep everything simple.</p> <p><strong>Problem 4 - Developers struggle with Mime Types</strong></p> <p>All to often I have received a simple communication, provided to me only in HTML. Please, if you insist on a HTML communication  provide a text only alternative for people who cannot read HTML emails. Its not hard, emails can be sent containing two forms, HTML and Plain Text and the reader can choose which one they want to view.</p> <p><strong>Problem 5 - Sloppy HTML &amp; big images appears like spam</strong></p> <p>Many email communications are put together by someone with little to no experience in HTML. They often use a WYSIWYG editor to generate formatted content, which will be placed in a template and then sent. However some of these WYSIWYG editors are known for producing sloppy HTML which can be a flag to a spam filter. Compounding this issue further is that HTML email&#8217;s with many images, or a single large image are bound to be classed as spam!</p> <h3>Mathews Rule of Thumb</h3> <p>I understand that companies like the idea of a HTML email as it allows them to effectively brand their communication by including elements such as their colours, styles and logo. But it may also exclude a large number of recipients from reading their email. So with this in mind, the general advice I give is:</p> <p>If the email is a result of the user interacting with the website i.e. signing up, receiving a message, submitting a form, use Plain Text as this is most likely an important email which must be readable by the recipient. However, if the email is a form of passive communication, where the user may have opted in, but it is not the direct result of some action or important process then you may choose to use HTML to present your email. However please,<strong> in all cases provide a text only alternative</strong>. If you choose to have a HTML communication <strong>design simple</strong> (and do not forget about mobile readers) and <strong>test, test, test </strong>as Email clients are all different. Make  sure you test on all the majority desktop clients as well as Yahoo, Gmail, Hotmail  etc.</p> <p>Remember nothing looks more unprofessional then a sloppy communication, and when it comes down to it many companies choose to spend $1000&#8217;s of dollars on pamphlets while paying next to nothing for an email communication that ends up looking unprofessional and amateurish.</p> </div>adminhttp://www.mathew.com.au/blog/?p=11Fri, 03 Oct 2008 05:25:12 GMTRuby & the Hex value of a numberhttp://www.mathew.com.au/blog/2008/10/01/ruby-the-hex-value-of-a-number/<div class="post-content"> <p>Sure you could use</p> <pre class="syntax-highlight:ruby"> sprintf &quot;0x%X&quot; % v </pre> <p>but isnt this snippet I put together more fun?</p> <pre class="syntax-highlight:ruby"> (-7..0).inject(&quot;0x&quot;){|h,i|h&lt;&lt;&quot;0123456789ABCDEF&quot;[(v&gt;&gt;(i.abs*4))&amp;0x0F].chr} </pre> <p>Something to note here is that Ruby&#8217;s range Object does not support a range going backwards i.e. from 7 to 0, so I use a range from -7 to 0 and take the abs value of those numbers.</p> </div>adminhttp://www.mathew.com.au/blog/?p=10Wed, 01 Oct 2008 10:28:05 GMTModular Exponentiation and a lesson in Rubyhttp://www.mathew.com.au/blog/2008/10/01/modular-exponentiation-and-a-lesson-in-ruby/<div class="post-content"> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">Today someone asked me if I knew of a large number class in C++. Specifically they wanted to be able to hold the value 5<sup>58</sup> in a variable. I was suspicious of why they would want to do this and asked what their ultimate goal was. It turned out they wanted to calculate n<sup>x</sup> mod p for arbitrary values of n,x and p, their ultimate goal being an implementation of Diffie Hellman key exchange.</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">Now, Calculating n<sup>x</sup> then taking the modulus p of it is a valid way of solving the problem, but it has a few nagging problems. The first is that you must be able to handle large numbers in whatever environment you are doing these calculations in, and the second is that you must be able to calculate these large numbers and take them modulo some value. To begin with,  I remembered back to my early days at University when we covered something called Modular Arithmetic. Consider this example:<span id="more-9"></span></p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">We have a clock face which has 12 hours on it and we want to find where the clock hand will be pointing to in 7 hours (If we are already at 12 o&#8217;clock). Easy, it will be pointing to 7. Now extending this, where will it be pointing in 14 hours? Well the answer is 14 mod 12 or 2.</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">Further extending this, if we want to know where the hand will be in 2 * 14 hours = 28 hours we can do 28mod12 = 4 or (2mod12 * 14)mod12 = 4.</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">Now, what if we want to know 14<sup>4</sup> mod 12? Well we know 14<sup>4</sup> is 14 * 14 * 14 * 14 so we can apply what we have just realised above and</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">14<sup>4</sup>mod12 = ((((14mod12) * 14)mod12 * 14)mod12 * 14)mod12</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">And we can do the same with 5<sup>58</sup> mod 97 and we can do all this without requiring  a large exponent and modular operation.</p> <h3>A quick implementation in Ruby</h3> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">Taking what we have learn, we know that we can now efficiently calculate a modular exponentiation without using large numbers. Implementing this in Ruby works as follows:</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">&gt;&gt; def modpow(base, pow, mod)</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">&gt;&gt;    (1..pow).inject(1) { |mult,x| (mult * base) % mod }</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">&gt;&gt; end</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">(1..pow) is shorthand for creating a Range object (Range.new(1, pow)) and it represents the set of whole integers between 1 and pow as an enumerable object. Please note, it does not create an array of numbers [1,2,3,&#8230;,10].</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">inject is a method which can be called on an enumerable object which is similar to reduce. Here is how it works for summing a collection:</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">[1,2,3,4,5].inject(0) { | a, b| a + b }</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">inject() operates over the collection and we pass the block a + b into it, which take two parameters a and b. a is the value last returned by the last call to the block and b is the current value we are enumerating over. In this example, the first call to block provided to inject will yield a = 0 and b = 1. it will return a + b = 1.</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">The second call will then yield a = 1 and b = 2 and will return a + b = 3 and so on.</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">This gives us a mechanism to iterate over everything in a collection and reduce the result to one variable, in this case it will be the sum of all integers in the collection.</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">Looking back at our original code, our block { (mult * base) % mod } will be called pow times by the inject function, and mult will be the result of all previous calls. This is exactly what we want so that line of code effectively does</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal">(((((1*5)%97)*5)%97)*5)%97 &#8230; 55 more times.</p> <p style="margin: 0px; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; min-height: 14px">&nbsp;</p> </div>adminhttp://www.mathew.com.au/blog/?p=9Wed, 01 Oct 2008 10:24:44 GMT