<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <title>Neil Ang</title>
  
  <link href="http://neilang.com/" />
  <updated>2011-12-31T22:18:07-08:00</updated>
  <id>http://neilang.com/</id>
  <author>
    <name>Neil Ang</name>
    <email>neil@neilang.com</email>
  </author>
  
  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/neilang" /><feedburner:info uri="neilang" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title>Using EventKit in iOS</title>
    <link href="http://feedproxy.google.com/~r/neilang/~3/9_hMdvXTAdg/using-eventkit-in-ios" />
    <updated>2011-09-28T00:00:00-07:00</updated>
    <id>http://neilang.com/entries/using-eventkit-in-ios</id>
    <content type="html">&lt;p&gt;I presented a talk at /dev/world/2011 on using EventKit and EventKitUI in iOS 4. Below is a summary of the talk, the slides and links to the sample code I used.&lt;/p&gt;


&lt;h3&gt;What's EventKit?&lt;/h3&gt;

&lt;p&gt;It is a framework provided by Apple in iOS 4+ for integrating your iOS app with the built in calendar app (iCal). You are able to retrieve events from the calendar, as well as create, update and delete events.&lt;/p&gt;

&lt;h3&gt;The Simulator&lt;/h3&gt;

&lt;p&gt;Although there is no calendar application in the iOS simulator, you can still use it for EventKit development. For my talk, I created an application that could retrieve events stored in the simulator, and insert sample ones if the calendar was empty. The code for this sample application is &lt;a href="http://github.com/neilang/Countdown"&gt;available on github&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Fetching Events&lt;/h3&gt;

&lt;p&gt;Retrieving stored events from a users calendar is super simple. The only parameters you need to specify is a date range and the calendar you want to query. &lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="objc"&gt;&lt;span class="n"&gt;EKEventStore&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;EKEventStore&lt;/span&gt; &lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="n"&gt;NSDate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;startDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NSDate&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;NSDate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;endDate&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NSDate&lt;/span&gt; &lt;span class="n"&gt;distantFuture&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="n"&gt;NSPredicate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;predicate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt; &lt;span class="nl"&gt;predicateForEventsWithStartDate:&lt;/span&gt;&lt;span class="n"&gt;startDate&lt;/span&gt;
                                                             &lt;span class="nl"&gt;endDate:&lt;/span&gt;&lt;span class="n"&gt;endDate&lt;/span&gt;
                                                           &lt;span class="nl"&gt;calendars:&lt;/span&gt;&lt;span class="nb"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
                                                           
&lt;span class="n"&gt;NSArray&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt; &lt;span class="nl"&gt;eventsMatchingPredicate:&lt;/span&gt;&lt;span class="n"&gt;predicate&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;h3&gt;Calendars within the Calendar app&lt;/h3&gt;

&lt;p&gt;The calendar app is made up of many calendars, e.g. Home calendar, Work calendar, Birthday calendar etc. Every event created must belong to a calendar, however some calendars are read-only.&lt;/p&gt;

&lt;p&gt;You can retrieve the following calendar information in iOS 4:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="objc"&gt;&lt;span class="n"&gt;EKEventStore&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;EKEventStore&lt;/span&gt; &lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Get all calendars&lt;/span&gt;
&lt;span class="n"&gt;NSArray&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;calendars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt; &lt;span class="n"&gt;calendars&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Get the default calendar&lt;/span&gt;
&lt;span class="n"&gt;EKCalendar&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;calendar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt; &lt;span class="n"&gt;defaultCalendarForNewEvents&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Test if calendar is read-­‐only&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;calendar&lt;/span&gt; &lt;span class="n"&gt;allowsContentModifications&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Get the associated colour of a calendar&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UIColor&lt;/span&gt; &lt;span class="nl"&gt;colorWithCGColor:&lt;/span&gt;&lt;span class="n"&gt;calendar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CGColor&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h3&gt;Inserting Events&lt;/h3&gt;

&lt;p&gt;As the following code illustrates, inserting an event to a users calendar is also fairly simple.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="objc"&gt;&lt;span class="n"&gt;EKEventStore&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;EKEventStore&lt;/span&gt; &lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="n"&gt;EKEvent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;EKEvent&lt;/span&gt; &lt;span class="nl"&gt;eventWithEventStore:&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;calendar&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt; &lt;span class="n"&gt;defaultCalendarForNewEvents&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;@&amp;quot;/dev/world/2011&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;@&amp;quot;Melbourne&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notes&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;@&amp;quot;AUC Developer Conference&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;startDate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endDate&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;endDate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allDay&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt; &lt;span class="nl"&gt;saveEvent:&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="nl"&gt;span:&lt;/span&gt;&lt;span class="n"&gt;EKSpanThisEvent&lt;/span&gt; &lt;span class="nl"&gt;error:&lt;/span&gt;&lt;span class="nb"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;h3&gt;Inserting Events with EventKitUI&lt;/h3&gt;

&lt;p&gt;Instead of saving the created event directly into the event store, a better approach is to use EventKitUI which will allow the user visually check/modify an event before it is inserted.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="objc"&gt;&lt;span class="n"&gt;EKEventStore&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;eventStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;EKEventStore&lt;/span&gt; &lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="n"&gt;EKEvent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;EKEvent&lt;/span&gt; &lt;span class="nl"&gt;eventWithEventStore:&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;startDate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endDate&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;endDate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notes&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;EKEventEditViewController&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;EKEventEditViewController&lt;/span&gt; &lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;eventStore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;editViewDelegate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt; &lt;span class="nl"&gt;presentModalViewController:&lt;/span&gt;&lt;span class="n"&gt;controller&lt;/span&gt; &lt;span class="nl"&gt;animated:&lt;/span&gt;&lt;span class="n"&gt;YES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;controller&lt;/span&gt; &lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;eventStore&lt;/span&gt; &lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If you use EventKitUI, remember to always set the &lt;kbd&gt;editViewDelegate&lt;/kbd&gt; delegate, and implement a delegate method to handle the dismissal of the view controller window.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="objc"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nl"&gt;eventEditViewController:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EKEventEditViewController&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;controller&lt;/span&gt;
         &lt;span class="nl"&gt;didCompleteWithAction:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EKEventEditViewAction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;EKEventEditViewActionCanceled:&lt;/span&gt;
           &lt;span class="c1"&gt;// User tapped &amp;quot;cancel&amp;quot;&lt;/span&gt;
           &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;EKEventEditViewActionSaved:&lt;/span&gt;
           &lt;span class="c1"&gt;// User tapped &amp;quot;save&amp;quot;&lt;/span&gt;
           &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;EKEventEditViewActionDeleted:&lt;/span&gt;
           &lt;span class="c1"&gt;// User tapped &amp;quot;delete&amp;quot;&lt;/span&gt;
           &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt; &lt;span class="nl"&gt;dismissModalViewControllerAnimated:&lt;/span&gt;&lt;span class="n"&gt;YES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h3&gt;Resources&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="/resources/downloads/dw11.pdf"&gt;My /dev/world/2011 slides&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/neilang/Countdown"&gt;Sample iOS app for viewing stored events&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/neilang/EventKit-demo"&gt;Sample iOS app for retrieving/inserting events&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/neilang/EventsFeed"&gt;Sample rails app for creating an event feed&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/EventKitProgGuide/"&gt;EventKit programming guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/sVNa1xI3chCtQ_4KHOCl3vdFzpQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sVNa1xI3chCtQ_4KHOCl3vdFzpQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/sVNa1xI3chCtQ_4KHOCl3vdFzpQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sVNa1xI3chCtQ_4KHOCl3vdFzpQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/neilang?a=9_hMdvXTAdg:9SM4HESpaTU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=9_hMdvXTAdg:9SM4HESpaTU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=9_hMdvXTAdg:9SM4HESpaTU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=9_hMdvXTAdg:9SM4HESpaTU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=9_hMdvXTAdg:9SM4HESpaTU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=9_hMdvXTAdg:9SM4HESpaTU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=9_hMdvXTAdg:9SM4HESpaTU:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://neilang.com/entries/using-eventkit-in-ios</feedburner:origLink></entry>
  
  <entry>
    <title>How to install APC on OS X (10.6)</title>
    <link href="http://feedproxy.google.com/~r/neilang/~3/XJYSuvk3nHk/install-apc-on-osx" />
    <updated>2011-05-29T00:00:00-07:00</updated>
    <id>http://neilang.com/entries/install-apc-on-osx</id>
    <content type="html">&lt;p&gt;There are two ways to install APC on OS X 10.6 (Snow Leopard). The &lt;em&gt;easy&lt;/em&gt; way, and the &lt;em&gt;manual&lt;/em&gt; way. Thanks goes to &lt;a href="http://twitter.com/j_cartledge"&gt;@j_cartledge&lt;/a&gt; for the tipoff on the how to do it the easy way.&lt;/p&gt;

&lt;h3&gt;Easy Install&lt;/h3&gt;

&lt;p&gt;The easiest way to get running with APC is to use &lt;a href="https://github.com/mxcl/homebrew"&gt;homebrew&lt;/a&gt;. If you already have this installed, just type: &lt;/p&gt;

&lt;p&gt;
  &lt;code&gt;brew install apc&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;The brew formula may ask you to do some additional steps like update your php.ini and restart apache. Otherwise that's it.&lt;/p&gt;


&lt;h3&gt;Manual Install&lt;/h3&gt;

&lt;p&gt;Here are the steps I took to compile and install APC on my machine running OS X 10.6 (Snow Leopard). I found a lot of inconsistent information on how to install APC manually, so hopefully this will work for you.&lt;/p&gt;

&lt;p&gt;Step 1, install &lt;a href="http://developer.apple.com/xcode/"&gt;Xcode&lt;/a&gt; if it's not already installed.&lt;/p&gt;

&lt;p&gt;Step 2, PCRE is is a prerequisite for installing APC, so it needs to be installed next:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Download the latest version of &lt;a href="http://www.pcre.org/"&gt;PCRE&lt;/a&gt;, and unpack it somewhere handy.&lt;/li&gt;
  &lt;li&gt;Using terminal, &lt;kbd&gt;cd&lt;/kbd&gt; to the unpacked PCRE directory.&lt;/li&gt;
  &lt;li&gt;Run: &lt;kbd&gt;./configure --prefix=/usr/local&lt;/kbd&gt;&lt;/li&gt;
  &lt;li&gt;Run: &lt;kbd&gt;make&lt;/kbd&gt;&lt;/li&gt;
  &lt;li&gt;Run: &lt;kbd&gt;sudo make install&lt;/kbd&gt;&lt;/li&gt;
  
&lt;/ol&gt;

&lt;p&gt;Step 3, install APC:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Download the latest copy of &lt;a href="http://pecl.php.net/package/APC"&gt;APC&lt;/a&gt;, and unpack it somewhere handy.&lt;/li&gt;
  &lt;li&gt;Using terminal, &lt;kbd&gt;cd&lt;/kbd&gt; to the unpacked APC directory.&lt;/li&gt;
  &lt;li&gt;Run: &lt;kbd&gt;/usr/bin/phpize&lt;/kbd&gt;&lt;/li&gt;
  &lt;li&gt;Run: &lt;kbd&gt;MACOSX_DEPLOYMENT_TARGET=10.6 CFLAGS="-arch x86_64 -g -Os -pipe -no-cpp-precomp" CCFLAGS="-arch x86_64 -g -Os -pipe" CXXFLAGS="-arch x86_64 -g -Os -pipe" LDFLAGS="-arch x86_64 -bind_at_load" ./configure --enable-apc-spinlocks&lt;/kbd&gt;&lt;/li&gt;
  &lt;li&gt;Run: &lt;kbd&gt;make&lt;/kbd&gt;&lt;/li&gt;
  &lt;li&gt;Run: &lt;kbd&gt;sudo make install&lt;/kbd&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step 4, update your settings:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open (or create) your &lt;kbd&gt;/etc/php.ini&lt;/kbd&gt; file in a text editor and add a reference to APC: &lt;kbd&gt;extension=/usr/lib/php/extensions/no-debug-non-zts-20090626/apc.so&lt;/kbd&gt;&lt;/li&gt;
  &lt;li&gt;Restart apache: &lt;kbd&gt;sudo httpd -k restart&lt;/kbd&gt;&lt;/li&gt;
  &lt;li&gt;Test APC is installed: &lt;kbd&gt;php -i | grep "APC"&lt;/kbd&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Was this helpful? Please leave a comment if these instructions worked for you. If you needed to take alternate steps to get this installed, please leave a comment on what you did differently and what issue it resolved. Thanks!&lt;/p&gt;


&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/uG1yeUaISFzdk-iw8j585PwYaAI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uG1yeUaISFzdk-iw8j585PwYaAI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/uG1yeUaISFzdk-iw8j585PwYaAI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uG1yeUaISFzdk-iw8j585PwYaAI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/neilang?a=XJYSuvk3nHk:rjm_qMSJm4g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=XJYSuvk3nHk:rjm_qMSJm4g:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=XJYSuvk3nHk:rjm_qMSJm4g:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=XJYSuvk3nHk:rjm_qMSJm4g:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=XJYSuvk3nHk:rjm_qMSJm4g:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=XJYSuvk3nHk:rjm_qMSJm4g:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=XJYSuvk3nHk:rjm_qMSJm4g:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://neilang.com/entries/install-apc-on-osx</feedburner:origLink></entry>
  
  <entry>
    <title>Stop safari's toolbar being hidden</title>
    <link href="http://feedproxy.google.com/~r/neilang/~3/Oc_ePhm0ci0/stop-safaris-toolbar-being-hidden" />
    <updated>2011-04-30T00:00:00-07:00</updated>
    <id>http://neilang.com/entries/stop-safaris-toolbar-being-hidden</id>
    <content type="html">&lt;p&gt;It really annoys me when a site forces you to open a web page in a new window. It &lt;strong&gt;really really really really really&lt;/strong&gt; annoys me when that new window has no toolbar, status bar, bookmarks bar, scroll bars, has been moved, resized or stops you from resizing it.&lt;/p&gt;

&lt;p&gt;That is why I've put together an &lt;a href="https://github.com/neilang/WindowControl"&gt;open source&lt;/a&gt; safari 5 extension called "WindowControl", that disables web pages from doing this.&lt;/p&gt;

&lt;p&gt;WindowControl gives users back the power to control how their browser windows look and behave. New windows will still open, only the child windows will look like their parent windows. No alterations.&lt;/p&gt;

&lt;p&gt;You can download the FREE safari extension &lt;a href="https://github.com/downloads/neilang/WindowControl/WindowControl.safariextz"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I've added toggable settings to the extension, so you can choose which parts of your browser window scripts can alter.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5o-4Sdry3qBD59qPr1kjQsWjT5I/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5o-4Sdry3qBD59qPr1kjQsWjT5I/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5o-4Sdry3qBD59qPr1kjQsWjT5I/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5o-4Sdry3qBD59qPr1kjQsWjT5I/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/neilang?a=Oc_ePhm0ci0:Xtolm77lQMg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=Oc_ePhm0ci0:Xtolm77lQMg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=Oc_ePhm0ci0:Xtolm77lQMg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=Oc_ePhm0ci0:Xtolm77lQMg:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=Oc_ePhm0ci0:Xtolm77lQMg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=Oc_ePhm0ci0:Xtolm77lQMg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=Oc_ePhm0ci0:Xtolm77lQMg:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://neilang.com/entries/stop-safaris-toolbar-being-hidden</feedburner:origLink></entry>
  
  <entry>
    <title>Scheduled Shutdown on OS X</title>
    <link href="http://feedproxy.google.com/~r/neilang/~3/PL3nOG5ZOm8/scheduled-shutdown-app" />
    <updated>2011-02-24T00:00:00-08:00</updated>
    <id>http://neilang.com/entries/scheduled-shutdown-app</id>
    <content type="html">&lt;p&gt;I found a mac app (actually two) on the App Store, that allow you to set a timer for when you want your mac to shutdown, restart, sleep or logout. I thought this would be an easy app to build so I attempted my own.&lt;/p&gt;

&lt;p style="text-align:center"&gt;&lt;img src="/resources/images/scheduled-shutdown.png" alt="Interface for scheduled shutdown" /&gt;&lt;/p&gt;

&lt;p&gt;I considered posting the instructions on how to write this app, but it is really simple to implement. In fact, Apple provide you with the &lt;a href="http://developer.apple.com/library/mac/#qa/qa2001/qa1134.html"&gt;most important part of the code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So instead I am just going to open source &lt;a href="https://github.com/neilang/Scheduled-Shutdown"&gt;the code&lt;/a&gt; for this app, and let you lol at the simplicity.&lt;/p&gt; 

&lt;p&gt;If you are a good (or just better then me) interface designer, feel free to modify the interface into something nicer and get it onto the App Store as a free download.&lt;/p&gt;

&lt;p&gt;I've also made available an &lt;a href="https://github.com/downloads/neilang/Scheduled-Shutdown/Scheduled%20Shutdown.app.zip"&gt;universal binary&lt;/a&gt; of the app. Enjoy.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mIPL6t9SA5sOeqHPu7r9wGA1WwY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mIPL6t9SA5sOeqHPu7r9wGA1WwY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mIPL6t9SA5sOeqHPu7r9wGA1WwY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mIPL6t9SA5sOeqHPu7r9wGA1WwY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/neilang?a=PL3nOG5ZOm8:0i3hZaaCSVY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=PL3nOG5ZOm8:0i3hZaaCSVY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=PL3nOG5ZOm8:0i3hZaaCSVY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=PL3nOG5ZOm8:0i3hZaaCSVY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=PL3nOG5ZOm8:0i3hZaaCSVY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=PL3nOG5ZOm8:0i3hZaaCSVY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=PL3nOG5ZOm8:0i3hZaaCSVY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://neilang.com/entries/scheduled-shutdown-app</feedburner:origLink></entry>
  
  <entry>
    <title>How to write a password generator</title>
    <link href="http://feedproxy.google.com/~r/neilang/~3/EwRUNv2IjnM/how-to-write-a-password-generator" />
    <updated>2011-02-22T00:00:00-08:00</updated>
    <id>http://neilang.com/entries/how-to-write-a-password-generator</id>
    <content type="html">&lt;p&gt;I noticed on the recently released mac app store, there are some very simple apps which are being sold for $1 or more. So I thought I would write my own version of these apps and explain how they work.&lt;/p&gt;

&lt;p&gt;Let's take a look at how to write a simple password generator. The source for this project can be found on &lt;a href="https://github.com/neilang/Password-Generator"&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;p style="text-align:center"&gt;&lt;img src="/resources/images/password-gen.png" alt="Picture of final product" /&gt;&lt;/p&gt;

&lt;h3&gt;Password generator&lt;/h3&gt;

&lt;p&gt;For this project I wanted the user to be able to select the types of symbols that will appear in the password. I'm going to assume you are already familiar with setting up interfaces and connecting them with IBOutlets and IBActions (if not, examine the provided source code).&lt;/p&gt;

&lt;p&gt;NB: Although this is an objective-c project, I've dropped back to C to do do most of the work. Manipulating characters in c-strings is very efficient and simple.&lt;/p&gt;


&lt;p&gt;The first step is to determine how long the password will be, and what characters it will be built from:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;letters&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt; &lt;span class="c1"&gt;// set these values from your input controls&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;capitals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;digits&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;letters&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;capitals&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;digits&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;lettersAlphabet&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;abcdefghijklmnopqrstuvwxyz&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;capitalsAlphabet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;digitsAlphabet&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;0123456789&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;symbolsAlphabet&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;!@#$%*[];?()&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Then declare an empty string of the right length which we will fill with these random characters. We will also need a second char pointer that points to this string:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="c1"&gt;// Build the password using C strings - for speed&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cPassword&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;cPassword&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// terminate the c-string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now for each alphabet set, we will need to add the required amount of symbols. I've used a helper function to reduce duplication:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;appendRandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lettersAlphabet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;letters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;appendRandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capitalsAlphabet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capitals&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;appendRandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;digitsAlphabet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;appendRandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbolsAlphabet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is what the helper function looks like:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;appendRandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;alphabet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arc4random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alphabet&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;alphabet&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Notice how it advances the string pointer after it appends each character? This is why we needed to create the second char pointer.&lt;/p&gt;

&lt;p&gt;Next, we rearrange the symbols in the string so the different alphabet types aren't grouped together:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt;  &lt;span class="n"&gt;r&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arc4random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cPassword&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="n"&gt;cPassword&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cPassword&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="n"&gt;cPassword&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Finally, convert the c-string back into an objective-c string, and don't forget to free any allocated memory. &lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="objc"&gt;&lt;span class="n"&gt;NSString&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;thePassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NSString&lt;/span&gt; &lt;span class="nl"&gt;stringWithCString:&lt;/span&gt;&lt;span class="n"&gt;cPassword&lt;/span&gt; &lt;span class="nl"&gt;encoding:&lt;/span&gt;&lt;span class="n"&gt;NSUTF8StringEncoding&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cPassword&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;See! I told you it was simple, and you've saved yourself a dollar.&lt;/p&gt;

&lt;p&gt;Download the full code for this project from &lt;a href="https://github.com/neilang/Password-Generator"&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/WvefKWKdFVAV6DRpzIia_32i0RI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WvefKWKdFVAV6DRpzIia_32i0RI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/WvefKWKdFVAV6DRpzIia_32i0RI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WvefKWKdFVAV6DRpzIia_32i0RI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/neilang?a=EwRUNv2IjnM:zbqNvSHmSG8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=EwRUNv2IjnM:zbqNvSHmSG8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=EwRUNv2IjnM:zbqNvSHmSG8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=EwRUNv2IjnM:zbqNvSHmSG8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=EwRUNv2IjnM:zbqNvSHmSG8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=EwRUNv2IjnM:zbqNvSHmSG8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=EwRUNv2IjnM:zbqNvSHmSG8:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://neilang.com/entries/how-to-write-a-password-generator</feedburner:origLink></entry>
  
  <entry>
    <title>A new design</title>
    <link href="http://feedproxy.google.com/~r/neilang/~3/S1lPk3Pqy40/a-new-design" />
    <updated>2011-01-25T00:00:00-08:00</updated>
    <id>http://neilang.com/entries/a-new-design</id>
    <content type="html">&lt;p&gt;Don't adjust your computer screens, this is still &lt;a href="http://neilang.com/"&gt;neilang.com&lt;/a&gt;. For the fourth time I've rebuilt my blog (or should I say "Plog"). Now with even less features!&lt;/p&gt;

&lt;p&gt;Notable changes include: &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Less navigation&lt;/li&gt;
  &lt;li&gt;Less content&lt;/li&gt;
  &lt;li&gt;New HTML5 layout&lt;/li&gt;
  &lt;li&gt;Running on Jekyll (previously Symphony)&lt;/li&gt;
  &lt;li&gt;Hosted on &lt;a href="http://github.com"&gt;github.com&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Comments by &lt;a href="http://disqus.com"&gt;Disqus&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Dropped support for IE6, IE7 and FF2.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/WHMzGbyiGI5Ji0CVqvIxC1f_LUs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WHMzGbyiGI5Ji0CVqvIxC1f_LUs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/WHMzGbyiGI5Ji0CVqvIxC1f_LUs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WHMzGbyiGI5Ji0CVqvIxC1f_LUs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/neilang?a=S1lPk3Pqy40:iK76rhR4F74:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=S1lPk3Pqy40:iK76rhR4F74:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=S1lPk3Pqy40:iK76rhR4F74:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=S1lPk3Pqy40:iK76rhR4F74:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=S1lPk3Pqy40:iK76rhR4F74:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=S1lPk3Pqy40:iK76rhR4F74:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=S1lPk3Pqy40:iK76rhR4F74:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://neilang.com/entries/a-new-design</feedburner:origLink></entry>
  
  <entry>
    <title>Redirect to iPhone site with htaccess</title>
    <link href="http://feedproxy.google.com/~r/neilang/~3/2dLahfX6kSw/redirect-to-iphone-site-with-htaccess" />
    <updated>2010-02-06T00:00:00-08:00</updated>
    <id>http://neilang.com/entries/redirect-to-iphone-site-with-htaccess</id>
    <content type="html">&lt;p&gt;This is my implementation of how to redirect to an iPhone optimised website using Apache rewrite rules and cookies. Although this redirect can be achieved easily through server-side scripting, websites that implement heavy page caching need to redirect at the request level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The interaction:&lt;/strong&gt; If the user is using an iPhone to view the site, I wanted to automatically redirect them to the iphone site, however I also wanted to allow the user to switch between the two versions of the website freely - and to remember their preference for which version of the site they wanted to view when they returned. I also didn't want to embed absolute URLs into links or append parameters to the end of urls.&lt;/p&gt;

&lt;p&gt;So these are the rules I came up with to redirect an iphone visiting &lt;kbd&gt;www.example.com&lt;/kbd&gt; to &lt;kbd&gt;i.example.com&lt;/kbd&gt;. On each page of the site I include a link to switch between the two sites. Example. If the user is viewing &lt;kbd&gt;i.example.com/about.html&lt;/kbd&gt; there would be a server relative link to "/noiphone/about.html" and on the normal site there would be a link to "/iphone/about.html" etc.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="apache"&gt;&lt;span class="c"&gt;# Always redirect to the iphone site (unless there is a cookie)&lt;/span&gt;
&lt;span class="nb"&gt;RewriteCond&lt;/span&gt; %{HTTP_USER_AGENT} iPhone 
&lt;span class="nb"&gt;RewriteCond&lt;/span&gt; %{HTTP_HOST} !^i.example.com 
&lt;span class="nb"&gt;RewriteCond&lt;/span&gt; %{HTTP_COOKIE} !^.*no_iphone=yes.*$ [NC] 
&lt;span class="nb"&gt;RewriteRule&lt;/span&gt; ^/(.*)$ http://i.example.com/$1 [R,L] 

&lt;span class="c"&gt;# User requested normal site (sets cookie) &lt;/span&gt;
&lt;span class="nb"&gt;RewriteCond&lt;/span&gt; %{REQUEST_URI} ^/noiphone/.*$ 
&lt;span class="nb"&gt;RewriteRule&lt;/span&gt; ^/noiphone/(.*)$ http://www.example.com/$1 [R,L,CO=no_iphone:yes:.example.com:10080] 

&lt;span class="c"&gt;# User requested iphone site (removes cookie) &lt;/span&gt;
&lt;span class="nb"&gt;RewriteCond&lt;/span&gt; %{REQUEST_URI} ^/iphone/.*$ 
&lt;span class="nb"&gt;RewriteRule&lt;/span&gt; ^/iphone/(.*)$ http://i.example.com/$1 [R,L,CO=no_iphone:0:.example.com:-1]
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;You may notice that the cookie expire time to remember their preference is set to 10080 minutes (1 week), you may want to adjust this if you don't want their preference to expire.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QEDsfCyIER7-qGSpNQpWqciBVlk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QEDsfCyIER7-qGSpNQpWqciBVlk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QEDsfCyIER7-qGSpNQpWqciBVlk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QEDsfCyIER7-qGSpNQpWqciBVlk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/neilang?a=2dLahfX6kSw:Pg5anDYxoBw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=2dLahfX6kSw:Pg5anDYxoBw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=2dLahfX6kSw:Pg5anDYxoBw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=2dLahfX6kSw:Pg5anDYxoBw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=2dLahfX6kSw:Pg5anDYxoBw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=2dLahfX6kSw:Pg5anDYxoBw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=2dLahfX6kSw:Pg5anDYxoBw:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://neilang.com/entries/redirect-to-iphone-site-with-htaccess</feedburner:origLink></entry>
  
  <entry>
    <title>How to create a spell checking web spider</title>
    <link href="http://feedproxy.google.com/~r/neilang/~3/xKfh7RqghjQ/how-to-create-a-spell-checking-web-spider" />
    <updated>2009-08-24T00:00:00-07:00</updated>
    <id>http://neilang.com/entries/how-to-create-a-spell-checking-web-spider</id>
    <content type="html">&lt;p&gt;Recently I found out my employer was paying a third-party company to regularly check the spelling on their website and send them a monthly report. So I thought I would write a simple spider that could to do the same thing and save them money.&lt;/p&gt;

&lt;h3&gt;The setup&lt;/h3&gt;
&lt;p&gt;My solution uses ruby (plus some gems) and the awesome &lt;a href="http://aspell.net/"&gt;Aspell&lt;/a&gt; (an open source spell checker).&lt;/p&gt;

&lt;p&gt;First of all you will need to download and install &lt;a href="http://aspell.net/"&gt;Aspell&lt;/a&gt;, and an Aspell dictionary for the language you want to use. In this example I will be using the English dictionary.&lt;/p&gt;


&lt;p&gt;To install Aspell on OS X, download and unpack the latest version, and then using terminal:&lt;/p&gt;

&lt;p&gt;
  &lt;code&gt;cd path/to/aspell &lt;br /&gt; ./configure &lt;br /&gt; make &lt;br /&gt; sudo make install&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;To install a dictionary, repeat the steps above with a downloaded dictionary.&lt;/p&gt;

&lt;p&gt;You can verify that Aspell installed correctly and that the dictionaries are loaded by typing these commands in terminal: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;aspell -v&lt;br /&gt;aspell dicts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next you will need to install &lt;em&gt;raspell&lt;/em&gt;, which is a gem used to interact with Aspell. You will also need another gem called &lt;em&gt;spider&lt;/em&gt;, which will take care of the web crawling work for us. And finally, &lt;em&gt;hpricot&lt;/em&gt; or &lt;em&gt;nokogiri&lt;/em&gt; to handle the HTML.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo gem install raspell &lt;br /&gt;sudo gem install spider&lt;br /&gt;sudo gem install hpricot&lt;/code&gt;&lt;/p&gt;


&lt;h3&gt;The script&lt;/h3&gt;
&lt;p&gt;With that done, you can use the spider gem to crawl all the html pages on a website, then use hpricot to extract the relevant words from the page and check each one with raspell. E.g.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby &lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt; 
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;spider&amp;#39;&lt;/span&gt; 
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;raspell&amp;#39;&lt;/span&gt; 
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;hpricot&amp;#39;&lt;/span&gt; 

&lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;http://www.example.com/&amp;#39;&lt;/span&gt; 

&lt;span class="n"&gt;speller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Aspell&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;en_GB&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="no"&gt;Spider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 

  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_url_check&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;a_url&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 
    &lt;span class="n"&gt;a_url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;^&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
  &lt;span class="k"&gt;end&lt;/span&gt; 

  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="ss"&gt;:success&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;a_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prior_url&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 
    &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;content-type&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;text/html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Skipping &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;a_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; 
      &lt;span class="k"&gt;next&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt; 
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;On page &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;a_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; 
     
    &lt;span class="n"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hpricot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;head&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt; 
    &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;script&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt; 
    &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;link&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt; 
    &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;meta&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt; 
    &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;style&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt; 
    &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inner_text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/\s+/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/\s/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
     
    &lt;span class="n"&gt;speller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_misspelled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;mistake&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; * Found mistake &lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;mistake&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt; perhaps you meant &lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;speller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;suggest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mistake&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt; 
  &lt;span class="k"&gt;end&lt;/span&gt; 

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;A few things to note about this script:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I have set the spider to use the "en_GB" dictionary (as this is what we use in Australia), but you can set it to any dictionary you installed (e.g. "en_US").&lt;/li&gt;
  &lt;li&gt;If you wanted to use nokogiri instead of hpricot, simply replace the Hpricot declaration with &lt;kbd&gt;document = Nokogiri(resp.body)&lt;/kbd&gt; and &lt;kbd&gt;require&lt;/kbd&gt; it at the start of the script.&lt;/li&gt;
  &lt;li&gt;Hpricot is used to strip out typically non-visible sections of the page, so that we only spellcheck the displayed words.&lt;/li&gt;
  &lt;li&gt;The spider won't search outside of the set domain.&lt;/li&gt;
  &lt;li&gt;The spider is also capable of performing a link check as it crawls.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can see this is only a very basic implementation, but demonstrates how easily you can create your own spelling spider!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/POXUykWX-WNjXymUEBgzNELRw6I/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/POXUykWX-WNjXymUEBgzNELRw6I/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/POXUykWX-WNjXymUEBgzNELRw6I/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/POXUykWX-WNjXymUEBgzNELRw6I/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/neilang?a=xKfh7RqghjQ:3au2jnQqQdw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=xKfh7RqghjQ:3au2jnQqQdw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=xKfh7RqghjQ:3au2jnQqQdw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=xKfh7RqghjQ:3au2jnQqQdw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=xKfh7RqghjQ:3au2jnQqQdw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=xKfh7RqghjQ:3au2jnQqQdw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=xKfh7RqghjQ:3au2jnQqQdw:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://neilang.com/entries/how-to-create-a-spell-checking-web-spider</feedburner:origLink></entry>
  
  <entry>
    <title>Validate an ISSN using Perl</title>
    <link href="http://feedproxy.google.com/~r/neilang/~3/CaBIZnya_wI/validate-an-issn-using-perl" />
    <updated>2009-06-12T00:00:00-07:00</updated>
    <id>http://neilang.com/entries/validate-an-issn-using-perl</id>
    <content type="html">&lt;p&gt;Last week I wrote about validating an ISBN, so this week I thought I would post the code to validate an ISSN.&lt;/p&gt;

&lt;p&gt;There are only a few minor differences between validating an ISSN and ISBN.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="perl"&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;valid_issn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$issn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; 
     &lt;span class="nv"&gt;$issn&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/[^\dX]//gi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$issn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@chars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$issn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="nv"&gt;$chars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;uc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$chars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="ow"&gt;eq&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;X&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$char&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$char&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;@chars&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$char&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nv"&gt;$sum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;$char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$chars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$char&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt; 
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;$sum&lt;/span&gt; &lt;span class="nv"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ZfdjjlJUzD0J2g9tZQotR8flXW4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZfdjjlJUzD0J2g9tZQotR8flXW4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ZfdjjlJUzD0J2g9tZQotR8flXW4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZfdjjlJUzD0J2g9tZQotR8flXW4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/neilang?a=CaBIZnya_wI:b3Ydsrl0wac:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=CaBIZnya_wI:b3Ydsrl0wac:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=CaBIZnya_wI:b3Ydsrl0wac:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=CaBIZnya_wI:b3Ydsrl0wac:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=CaBIZnya_wI:b3Ydsrl0wac:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=CaBIZnya_wI:b3Ydsrl0wac:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=CaBIZnya_wI:b3Ydsrl0wac:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://neilang.com/entries/validate-an-issn-using-perl</feedburner:origLink></entry>
  
  <entry>
    <title>Validate an ISSN using JavaScript</title>
    <link href="http://feedproxy.google.com/~r/neilang/~3/QjYOixF3jhs/validate-an-issn-using-javascript" />
    <updated>2009-06-12T00:00:00-07:00</updated>
    <id>http://neilang.com/entries/validate-an-issn-using-javascript</id>
    <content type="html">&lt;p&gt;Last week I wrote about validating an ISBN, so this week I thought I would post the code to validate an ISSN.&lt;/p&gt;

&lt;p&gt;There are only a few minor differences between validating an ISSN and ISBN.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isValidISSN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;issn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nx"&gt;issn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;issn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/[^\dX]/gi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;issn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt; 
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;chars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;issn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;X&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt; 
    &lt;span class="nx"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt; 
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt; 
  &lt;span class="p"&gt;};&lt;/span&gt; 
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/NTjsR2qd-XzAb-dM05pFaJOFecc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NTjsR2qd-XzAb-dM05pFaJOFecc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/NTjsR2qd-XzAb-dM05pFaJOFecc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NTjsR2qd-XzAb-dM05pFaJOFecc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/neilang?a=QjYOixF3jhs:ZMaWk9MH1Hs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=QjYOixF3jhs:ZMaWk9MH1Hs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=QjYOixF3jhs:ZMaWk9MH1Hs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=QjYOixF3jhs:ZMaWk9MH1Hs:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=QjYOixF3jhs:ZMaWk9MH1Hs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?i=QjYOixF3jhs:ZMaWk9MH1Hs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/neilang?a=QjYOixF3jhs:ZMaWk9MH1Hs:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/neilang?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://neilang.com/entries/validate-an-issn-using-javascript</feedburner:origLink></entry>
  
</feed>

