feedjira 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +8 -0
  5. data/CHANGELOG.md +162 -0
  6. data/Gemfile +17 -0
  7. data/Guardfile +5 -0
  8. data/README.md +242 -0
  9. data/Rakefile +6 -0
  10. data/benchmarks/README.md +90 -0
  11. data/benchmarks/basic.rb +31 -0
  12. data/benchmarks/feed_list.txt +10 -0
  13. data/benchmarks/feed_xml/apple.xml +149 -0
  14. data/benchmarks/feed_xml/cnn.xml +278 -0
  15. data/benchmarks/feed_xml/daring_fireball.xml +1697 -0
  16. data/benchmarks/feed_xml/engadget.xml +604 -0
  17. data/benchmarks/feed_xml/feedjira_commits.xml +370 -0
  18. data/benchmarks/feed_xml/gizmodo.xml +2 -0
  19. data/benchmarks/feed_xml/loop.xml +441 -0
  20. data/benchmarks/feed_xml/rails.xml +1938 -0
  21. data/benchmarks/feed_xml/white_house.xml +951 -0
  22. data/benchmarks/feed_xml/xkcd.xml +2 -0
  23. data/benchmarks/fetching_systems.rb +23 -0
  24. data/benchmarks/other_libraries.rb +73 -0
  25. data/feedjira.gemspec +27 -0
  26. data/lib/feedjira.rb +16 -0
  27. data/lib/feedjira/core_ext.rb +3 -0
  28. data/lib/feedjira/core_ext/date.rb +19 -0
  29. data/lib/feedjira/core_ext/string.rb +9 -0
  30. data/lib/feedjira/core_ext/time.rb +31 -0
  31. data/lib/feedjira/feed.rb +459 -0
  32. data/lib/feedjira/feed_entry_utilities.rb +66 -0
  33. data/lib/feedjira/feed_utilities.rb +103 -0
  34. data/lib/feedjira/parser.rb +20 -0
  35. data/lib/feedjira/parser/atom.rb +61 -0
  36. data/lib/feedjira/parser/atom_entry.rb +34 -0
  37. data/lib/feedjira/parser/atom_feed_burner.rb +22 -0
  38. data/lib/feedjira/parser/atom_feed_burner_entry.rb +35 -0
  39. data/lib/feedjira/parser/google_docs_atom.rb +28 -0
  40. data/lib/feedjira/parser/google_docs_atom_entry.rb +29 -0
  41. data/lib/feedjira/parser/itunes_rss.rb +50 -0
  42. data/lib/feedjira/parser/itunes_rss_item.rb +41 -0
  43. data/lib/feedjira/parser/itunes_rss_owner.rb +12 -0
  44. data/lib/feedjira/parser/rss.rb +24 -0
  45. data/lib/feedjira/parser/rss_entry.rb +37 -0
  46. data/lib/feedjira/parser/rss_feed_burner.rb +23 -0
  47. data/lib/feedjira/parser/rss_feed_burner_entry.rb +43 -0
  48. data/lib/feedjira/version.rb +3 -0
  49. data/spec/feedjira/feed_entry_utilities_spec.rb +62 -0
  50. data/spec/feedjira/feed_spec.rb +762 -0
  51. data/spec/feedjira/feed_utilities_spec.rb +273 -0
  52. data/spec/feedjira/parser/atom_entry_spec.rb +86 -0
  53. data/spec/feedjira/parser/atom_feed_burner_entry_spec.rb +47 -0
  54. data/spec/feedjira/parser/atom_feed_burner_spec.rb +56 -0
  55. data/spec/feedjira/parser/atom_spec.rb +76 -0
  56. data/spec/feedjira/parser/google_docs_atom_entry_spec.rb +22 -0
  57. data/spec/feedjira/parser/google_docs_atom_spec.rb +31 -0
  58. data/spec/feedjira/parser/itunes_rss_item_spec.rb +63 -0
  59. data/spec/feedjira/parser/itunes_rss_owner_spec.rb +18 -0
  60. data/spec/feedjira/parser/itunes_rss_spec.rb +58 -0
  61. data/spec/feedjira/parser/rss_entry_spec.rb +85 -0
  62. data/spec/feedjira/parser/rss_feed_burner_entry_spec.rb +85 -0
  63. data/spec/feedjira/parser/rss_feed_burner_spec.rb +57 -0
  64. data/spec/feedjira/parser/rss_spec.rb +57 -0
  65. data/spec/sample_feeds/AmazonWebServicesBlog.xml +797 -0
  66. data/spec/sample_feeds/AmazonWebServicesBlogFirstEntryContent.xml +63 -0
  67. data/spec/sample_feeds/AtomFeedWithSpacesAroundEquals.xml +61 -0
  68. data/spec/sample_feeds/FeedBurnerUrlNoAlternate.xml +28 -0
  69. data/spec/sample_feeds/GoogleDocsList.xml +188 -0
  70. data/spec/sample_feeds/HREFConsideredHarmful.xml +314 -0
  71. data/spec/sample_feeds/HREFConsideredHarmfulFirstEntry.xml +22 -0
  72. data/spec/sample_feeds/ITunesWithSpacesInAttributes.xml +63 -0
  73. data/spec/sample_feeds/PaulDixExplainsNothing.xml +175 -0
  74. data/spec/sample_feeds/PaulDixExplainsNothingAlternate.xml +175 -0
  75. data/spec/sample_feeds/PaulDixExplainsNothingFirstEntryContent.xml +19 -0
  76. data/spec/sample_feeds/PaulDixExplainsNothingWFW.xml +174 -0
  77. data/spec/sample_feeds/SamRuby.xml +583 -0
  78. data/spec/sample_feeds/TechCrunch.xml +1515 -0
  79. data/spec/sample_feeds/TechCrunchFirstEntry.xml +9 -0
  80. data/spec/sample_feeds/TechCrunchFirstEntryDescription.xml +3 -0
  81. data/spec/sample_feeds/TenderLovemaking.xml +516 -0
  82. data/spec/sample_feeds/TenderLovemakingFirstEntry.xml +66 -0
  83. data/spec/sample_feeds/TrotterCashionHome.xml +611 -0
  84. data/spec/sample_feeds/TypePadNews.xml +368 -0
  85. data/spec/sample_feeds/atom_with_link_tag_for_url_unmarked.xml +31 -0
  86. data/spec/sample_feeds/itunes.xml +67 -0
  87. data/spec/sample_feeds/pet_atom.xml +497 -0
  88. data/spec/spec_helper.rb +88 -0
  89. metadata +229 -0
@@ -0,0 +1,174 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/atom10full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
3
+ <title>Paul Dix Explains Nothing</title>
4
+
5
+ <link rel="alternate" type="text/html" href="http://www.pauldix.net/" />
6
+ <id>tag:typepad.com,2003:weblog-108605</id>
7
+ <updated>2009-01-22T10:50:22-05:00</updated>
8
+ <subtitle>Entrepreneurship, programming, software development, politics, NYC, and random thoughts.</subtitle>
9
+ <generator uri="http://www.typepad.com/">TypePad</generator>
10
+ <link rel="self" href="http://feeds.feedburner.com/PaulDixExplainsNothing" type="application/atom+xml" /><entry>
11
+ <title>Making a Ruby C library even faster</title>
12
+ <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~3/519925023/making-a-ruby-c-library-even-faster.html" />
13
+ <link rel="replies" type="text/html" href="http://www.pauldix.net/2009/01/making-a-ruby-c-library-even-faster.html" thr:count="1" thr:updated="2009-01-22T16:30:53-05:00" />
14
+ <id>tag:typepad.com,2003:post-61753462</id>
15
+ <published>2009-01-22T10:50:22-05:00</published>
16
+ <updated>2009-01-22T16:30:53-05:00</updated>
17
+ <summary>Last week I released the first version of a SAX based XML parsing library called SAX-Machine. It uses Nokogiri, which uses libxml, so it's pretty fast. However, I felt that it could be even faster. The only question was how...</summary>
18
+ <author>
19
+ <name>Paul Dix</name>
20
+ </author>
21
+ <category scheme="http://www.sixapart.com/ns/types#category" term="Ruby" />
22
+ <category scheme="http://www.sixapart.com/ns/types#category" term="Another Category" />
23
+
24
+
25
+ <content type="html" xml:lang="en-US" xml:base="http://www.pauldix.net/">&lt;p&gt;Last week I released the first version of a &lt;a href="http://www.pauldix.net/2009/01/sax-machine-sax-parsing-made-easy.html"&gt;SAX based XML parsing library called SAX-Machine&lt;/a&gt;. It uses Nokogiri, which uses libxml, so it's pretty fast. However, I felt that it could be even faster. The only question was how to make a ruby library that is already using c underneath perform better. Since I've never written a Ruby C extension and it's been a few years since I've touched C, I decided it would be a good educational experience to give it a try.&lt;/p&gt;&#xD;
26
+ &#xD;
27
+ &lt;p&gt;First, let's look into how Nokogiri and SAX-Machine perform a parse. The syntax for SAX-Machine builds up a set of class variables (actually, instance variables on a class object) that describe what you're interested in parsing. So when you see something like this:&#xD;
28
+ &lt;/p&gt;&lt;script src="http://gist.github.com/50549.js"&gt;&lt;/script&gt;&lt;p&gt;&#xD;
29
+ It calls the 'element' and 'elements' methods inserted by the SAXMachine module that build up ruby objects that describe what XML tags we're interested in for the Entry class. That's all pretty straight forward and not really the source of any slowdown in the parsing process. These calls only happen once, when you first load the class.&#xD;
30
+ &#xD;
31
+ &lt;/p&gt;&lt;p&gt;Things get interesting when you run a parse. So you run Entry.parse(some_xml). That makes the call to Nokogiri, which in turn makes a call to libxml. Libxml then parses over the stream (or string) and makes calls to C methods (in Nokogiri) on certain events. For our purposes, the most interesting are start_element, end_element, and characters_func. The C code in Nokogiri for these is basic. It simply converts those C variables into Ruby ones and then makes calls to whatever instance of Nokogiri::XML:SAX::Document (a Ruby object) is associated with this parse. This is where SAXMachine comes back in. It has handlers for these events that match up the tags with the previously defined SAXMachine objects attached to the Entry class. It ignores the events that don't match a tag (however, it still needs to determine if the tag should be ignored).&lt;/p&gt;&#xD;
32
+ &#xD;
33
+ &lt;p&gt;The only possible place I saw to speed things up was to push more of SAX event handling down into the C code. Unfortunately, the only way to do this was to abandon Nokogiri and write my own code to interface with libxml. I used the xml_sax_parser.c from Nokogiri as a base and added to it. I changed it so the SAXMachine definitions of what was interesting would be stored in C. I then changed the SAX handling code to capture the events in C and determine if a tag was of interest there before sending it off to the Ruby objects. The end result is that calls are only made to Ruby when there is an actual event of interest. Thus, I avoid doing any comparisons in Ruby and those classes are simply wrappers that call out to the correct value setters.&lt;/p&gt;&#xD;
34
+ &#xD;
35
+ &lt;p&gt;Here are the results of a quick speed comparison against the Nokogiri SAXMachine, parsing my atom feed using &lt;a href="http://gist.github.com/47938"&gt;code from my last post&lt;/a&gt;.&lt;/p&gt;&#xD;
36
+ &lt;pre&gt; user system total real&lt;br&gt;sax c 0.060000 0.000000 0.060000 ( 0.069990)&lt;br&gt;sax nokogiri 0.500000 0.010000 0.510000 ( 0.520278)&lt;br&gt;&lt;/pre&gt;&lt;p&gt;&#xD;
37
+ The SAX C is 7.4 times faster than SAX Nokogiri. Now, that doesn't seem like a whole lot, but I think it's quite good considering it was against a library that was already half in C. It's even more punctuated when you look at the comparison of these two against rfeedparser.&#xD;
38
+ &lt;/p&gt;&lt;pre&gt; user system total real&lt;br&gt;sax c 0.060000 0.000000 0.060000 ( 0.069990)&lt;br&gt;sax nokogiri 0.500000 0.010000 0.510000 ( 0.520278)&lt;br&gt;rfeedparser 13.770000 1.730000 15.500000 ( 15.690309)&lt;br&gt;&lt;/pre&gt;&#xD;
39
+ &lt;p&gt;The SAX C version is 224 times faster than rfeedparser! The 7 times multiple from the Nokogiri version of SAXMachine really makes a difference. Unfortunately, I really only wrote this code as a test. It's not even close to something I would use for real. It has memory leaks, isn't thread safe, is completely unreadable, and has hidden bugs that I know about. You can take a look at it in all its misery on the &lt;a href="http://github.com/pauldix/sax-machine/tree/c-refactor"&gt;c-rafactor branch of SAXMachine on github&lt;/a&gt;. Even though the code is awful, I think it's interesting that there can be this much variability in performance on Ruby libraries that are using C.&lt;/p&gt;&#xD;
40
+ &#xD;
41
+ &lt;p&gt;I could actually turn this into a legitimate working version, but it would take more work than I think it's worth at this point. Also, I'm not excited about the idea of dealing with C issues in SAXMachine. I would be more excited for it if I could get this type of SAX parsing thing into Nokogiri (in addition to the one that is there now). For now, I'll move on to using the Nokogiri version of SAXMachine to create a feed parsing library.&lt;/p&gt;&lt;div class="feedflare"&gt;
42
+ &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=9Q8qfQ.P"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=9Q8qfQ.P" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=rLK96Z.p"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=rLK96Z.p" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=B95sFg.p"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=B95sFg.p" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
43
+ &lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~4/519925023" height="1" width="1"/&gt;</content>
44
+
45
+ <wfw:commentRss>this is the new val</wfw:commentRss>
46
+ <feedburner:origLink>http://www.pauldix.net/2009/01/making-a-ruby-c-library-even-faster.html</feedburner:origLink></entry>
47
+ <entry>
48
+ <title>SAX Machine - SAX Parsing made easy</title>
49
+ <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~3/514044516/sax-machine-sax-parsing-made-easy.html" />
50
+ <link rel="replies" type="text/html" href="http://www.pauldix.net/2009/01/sax-machine-sax-parsing-made-easy.html" thr:count="4" thr:updated="2009-01-21T23:16:44-05:00" />
51
+ <id>tag:typepad.com,2003:post-61473064</id>
52
+ <published>2009-01-16T09:47:32-05:00</published>
53
+ <updated>2009-01-21T23:16:44-05:00</updated>
54
+ <summary>For a while now I've been wanting to create a ruby library for feed (Atom, RSS) parsing. I know there are already some out there, but for one reason or another each of them falls short for my needs. The...</summary>
55
+ <author>
56
+ <name>Paul Dix</name>
57
+ </author>
58
+ <category scheme="http://www.sixapart.com/ns/types#category" term="Ruby" />
59
+
60
+
61
+ <content type="html" xml:lang="en-US" xml:base="http://www.pauldix.net/">&lt;p&gt;For a while now I've been wanting to create a ruby library for feed (Atom, RSS) parsing. I know there are already some out there, but for one reason or another each of them falls short for my needs. The first part of this effort requires me to decide how I want to go about parsing the feeds. One of the primary goals is speed. I want this thing to be fast. So I decided to look into SAX parsing. Further, I wanted to use Nokogiri because I'm going to be doing a few other things with the posts like pulling out links and tags, and sanitizing entries.&lt;/p&gt;&lt;p&gt;SAX parsing is an event based parsing model. It fires events during parsing for things like start_tag, end_tag, start_document, end_document, and characters. Nokogiri contains a very light weight wrapper around libxml's SAX parsing. Using this I started creating a basic declarative syntax for registering parsing events and mapping them into objects and values. The end result is &lt;a href="http://github.com/pauldix/sax-machine"&gt;SAX Machine, a declarative SAX parser for parsing xml into ruby objects&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Some of the syntax was inspired by &lt;a href="http://github.com/jnunemaker/happymapper"&gt;John Nunemaker's Happy Mapper&lt;/a&gt;. However, the behavior is a bit different. There are probably many more features I am going to add in as I use it to create my feed parsing library, but the basic stuff is there right now.&lt;/p&gt;&lt;p&gt;Here's an example that uses SAX Machine to parse a FeedBurner atom feed into ruby objects.&lt;/p&gt;&lt;script src="http://gist.github.com/47938.js"&gt;&lt;/script&gt;&lt;p&gt;&#xD;
62
+ &#xD;
63
+ So in a few short lines of code this parses feedburner feeds exactly how I want them. It's also pretty fast. Here's a benchmark against rfeedparser running against the atom feed from this blog 100 times.&#xD;
64
+ &lt;/p&gt;&lt;pre&gt;feedzirra 1.430000 0.020000 1.450000 ( 1.472081)&lt;br&gt;rfeedparser 15.780000 0.580000 16.360000 ( 16.768889)&lt;br&gt;&lt;/pre&gt;&lt;p&gt;&#xD;
65
+ It's about 11 times faster in this test. I have to do more tests before I feel comfortable with that figure, but it's a promising start. More importantly this will enable me to make a feed parser that's flexible, extensible, and readable.&lt;/p&gt;&lt;p&gt;SAX Machine is available as a gem as long as you have github added as a gem source. Just do gem install pauldix-sax-machine to get the party started (&lt;strong&gt;UPDATE:&lt;/strong&gt; for some reason it's not built yet. looking into it. &lt;strong&gt;UPDATE 2: &lt;/strong&gt;it's built and ready to go. thanks to nakajima). Also, special thanks to &lt;a href="http://www.brynary.com/"&gt;Bryan Helmkamp&lt;/a&gt; for helping me turn my initial spike into a decently tested and refactored version (even if it did slow my benchmark down by a factor of 4).&lt;/p&gt;&lt;div class="feedflare"&gt;
66
+ &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=2VN4Om.P"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=2VN4Om.P" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=5MHPvx.p"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=5MHPvx.p" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=nMpoB4.p"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=nMpoB4.p" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
67
+ &lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~4/514044516" height="1" width="1"/&gt;</content>
68
+
69
+
70
+ <feedburner:origLink>http://www.pauldix.net/2009/01/sax-machine-sax-parsing-made-easy.html</feedburner:origLink></entry>
71
+ <entry>
72
+ <title>Professional Goals for 2009</title>
73
+ <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~3/499546917/professional-goals-for-2009.html" />
74
+ <link rel="replies" type="text/html" href="http://www.pauldix.net/2008/12/professional-goals-for-2009.html" thr:count="3" thr:updated="2009-01-01T10:17:04-05:00" />
75
+ <id>tag:typepad.com,2003:post-60634768</id>
76
+ <published>2008-12-31T10:55:02-05:00</published>
77
+ <updated>2009-01-01T10:17:05-05:00</updated>
78
+ <summary>In two weeks I'll be making the transition from full time student to full time worker. Instead of worrying about grades and papers I'll have to get real work done. For the last four years I've set a lot of...</summary>
79
+ <author>
80
+ <name>Paul Dix</name>
81
+ </author>
82
+
83
+
84
+ <content type="html" xml:lang="en-US" xml:base="http://www.pauldix.net/">&lt;p&gt;In two weeks I'll be making the transition from full time student to full time worker. Instead of worrying about grades and papers I'll have to get real work done. For the last four years I've set a lot of goals for myself, but I've mainly been focused on the single goal of finishing school. Now that I've accomplished that it's time to figure out what the next steps are. Being that it's the eve of a new year, I thought a good way to start would be to outline exactly what I'd like to accomplish professionally in 2009. So here are some goals in no particular order:&#xD;
85
+ &lt;/p&gt;&lt;ul&gt;&#xD;
86
+ &lt;li&gt;Write 48 well thought out blog posts (once a week for 48 weeks of the year)&lt;/li&gt;&#xD;
87
+ &lt;li&gt;Write an open source library that at least 2 people/organizations use in production&lt;/li&gt;&#xD;
88
+ &lt;li&gt;Contribute to a popular open source library/project&lt;/li&gt;&#xD;
89
+ &lt;li&gt;Finish a working version of &lt;a href="http://www.pauldix.net/tahiti/index.html"&gt;Filterly&lt;/a&gt; and use it daily&lt;/li&gt;&#xD;
90
+ &lt;li&gt;Learn a new programming language&lt;/li&gt;&#xD;
91
+ &lt;li&gt;Finish reading &lt;a href="http://www.amazon.com/Introduction-Machine-Learning-Adaptive-Computation/dp/0262012111/ref=sr_1_3?ie=UTF8&amp;amp;s=books&amp;amp;qid=1230736254&amp;amp;sr=1-3"&gt;this book on machine learning&lt;/a&gt;&lt;/li&gt;&#xD;
92
+ &lt;li&gt;Read &lt;a href="http://www.amazon.com/Learning-Kernels-Regularization-Optimization-Computation/dp/0262194759/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1230736307&amp;amp;sr=1-1"&gt;Learning With Kernels by Schlkopf and Smola&lt;/a&gt;&lt;/li&gt;&#xD;
93
+ &lt;li&gt;Be a contributing author to a book or shortcut&lt;/li&gt;&#xD;
94
+ &lt;li&gt;Present at a conference&lt;/li&gt;&#xD;
95
+ &lt;li&gt;Present at a users group&lt;/li&gt;&#xD;
96
+ &lt;li&gt;Help create a site that gets decent traffic (kind of non-specific, I know)&#xD;
97
+ &lt;/li&gt;&#xD;
98
+ &lt;li&gt;Attend two conferences&lt;/li&gt;&#xD;
99
+ &lt;li&gt;Attend at least 8 &lt;a href="http://nycruby.org/wiki/"&gt;nyc.rb (NYC Ruby) meetings&lt;/a&gt;&lt;/li&gt;&#xD;
100
+ &lt;li&gt;Attend at least 6 &lt;a href="http://www.meetup.com/ny-tech/"&gt;NY Tech Meetups&lt;/a&gt;&lt;/li&gt;&#xD;
101
+ &lt;li&gt;Attend at least 4 &lt;a href="http://www.meetup.com/BlueVC/"&gt;Columbia Blue Venture Community events&lt;/a&gt; (hard because it conflicts with nyc.rb)&lt;/li&gt;&#xD;
102
+ &lt;li&gt;Attend at least 4 &lt;a href="http://nextny.org/"&gt;NextNY&lt;/a&gt; events&lt;/li&gt;&#xD;
103
+ &lt;li&gt;Do all the &lt;a href="http://codekata.pragprog.com/"&gt;Code Katas&lt;/a&gt; at least once (any language)&lt;/li&gt;&#xD;
104
+ &lt;/ul&gt;&#xD;
105
+ &lt;p&gt;That's all I've come up with so far. I probably won't be able to get everything on the list, but if I get most of the way there I'll be happy. A year may be too long of a development cycle for professional goals. It would be much more agile if I broke these down into two week sprints, but this will do for now. It gives me specific areas to focus my efforts over the next 12 months. What goals do you have for 2009?&lt;/p&gt;&lt;div class="feedflare"&gt;
106
+ &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=IP49Wo.O"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=IP49Wo.O" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=4Azfxm.o"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=4Azfxm.o" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=iwU8iG.o"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=iwU8iG.o" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
107
+ &lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~4/499546917" height="1" width="1"/&gt;</content>
108
+
109
+
110
+ <feedburner:origLink>http://www.pauldix.net/2008/12/professional-goals-for-2009.html</feedburner:origLink></entry>
111
+ <entry>
112
+ <title>Marshal data too short error with ActiveRecord</title>
113
+ <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~3/383536354/marshal-data-to.html" />
114
+ <link rel="replies" type="text/html" href="http://www.pauldix.net/2008/09/marshal-data-to.html" thr:count="2" thr:updated="2008-11-17T14:40:06-05:00" />
115
+ <id>tag:typepad.com,2003:post-55147740</id>
116
+ <published>2008-09-04T16:07:19-04:00</published>
117
+ <updated>2008-11-17T14:40:06-05:00</updated>
118
+ <summary>In my previous post about the speed of serializing data, I concluded that Marshal was the quickest way to get things done. So I set about using Marshal to store some data in an ActiveRecord object. Things worked great at...</summary>
119
+ <author>
120
+ <name>Paul Dix</name>
121
+ </author>
122
+ <category scheme="http://www.sixapart.com/ns/types#category" term="Tahiti" />
123
+
124
+
125
+ <content type="html" xml:lang="en-US" xml:base="http://www.pauldix.net/">
126
+ &lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;p&gt;In my previous &lt;a href="http://www.pauldix.net/2008/08/serializing-dat.html"&gt;post about the speed of serializing data&lt;/a&gt;, I concluded that Marshal was the quickest way to get things done. So I set about using Marshal to store some data in an ActiveRecord object. Things worked great at first, but on some test data I got this error: marshal data too short. Luckily, &lt;a href="http://www.brynary.com/"&gt;Bryan Helmkamp&lt;/a&gt; had helpfully pointed out that there were sometimes problems with storing marshaled data in the database. He said it was best to base64 encode the marshal dump before storing.&lt;/p&gt;
127
+
128
+ &lt;p&gt;I was curious why it was working on some things and not others. It turns out that some types of data being marshaled were causing the error to pop up. Here's the test data I used in my specs:&lt;/p&gt;
129
+ &lt;pre&gt;{ :foo =&amp;gt; 3, :bar =&amp;gt; 2 } # hash with symbols for keys and integer values&lt;br /&gt;[3, 2.1, 4, 8]&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; # array with integer and float values&lt;/pre&gt;
130
+ &lt;p&gt;Everything worked when I switched the array values to all integers so it seems that floats were causing the problem. However, in the interest of keeping everything working regardless of data types, I base64 encoded before going into the database and decoded on the way out.&lt;/p&gt;
131
+
132
+ &lt;p&gt;I also ran the benchmarks again to determine what impact this would have on speed. Here are the results for 100 iterations on a 10k element array and a 10k element hash with and without base64 encode/decode:&lt;/p&gt;
133
+ &lt;pre&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; user&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; system&amp;nbsp; &amp;nbsp;&amp;nbsp; total&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; real&lt;br /&gt;array marshal&amp;nbsp; 0.200000&amp;nbsp; &amp;nbsp;0.010000&amp;nbsp; &amp;nbsp;0.210000 (&amp;nbsp; 0.214018) (without Base64)&lt;br /&gt;array marshal&amp;nbsp; 0.220000&amp;nbsp; &amp;nbsp;0.010000&amp;nbsp; &amp;nbsp;0.230000 (&amp;nbsp; 0.250260)&lt;br /&gt;&lt;br /&gt;hash marshal&amp;nbsp; &amp;nbsp;1.830000&amp;nbsp; &amp;nbsp;0.040000&amp;nbsp; &amp;nbsp;1.870000 (&amp;nbsp; 1.892874) (without Base64)&lt;br /&gt;hash marshal&amp;nbsp; &amp;nbsp;2.040000&amp;nbsp; &amp;nbsp;0.100000&amp;nbsp; &amp;nbsp;2.140000 (&amp;nbsp; 2.170405)&lt;/pre&gt;
134
+ &lt;p&gt;As you can see the difference in speed is pretty negligible. I assume that the error has to do with AR cleaning the stuff that gets inserted into the database, but I'm not really sure. In the end it's just easier to use Base64.encode64 when serializing data into a text field in ActiveRecord using Marshal.&lt;/p&gt;
135
+
136
+ &lt;p&gt;I've also read people posting about this error when using the database session store. I can only assume that it's because they were trying to store either way too much data in their session (too much for a regular text field) or they were storing float values or some other data type that would cause this to pop up. Hopefully this helps.&lt;/p&gt;&lt;/div&gt;
137
+ &lt;div class="feedflare"&gt;
138
+ &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=SX7veW.P"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=SX7veW.P" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=9RuRMG.p"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=9RuRMG.p" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=3a9dsf.p"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=3a9dsf.p" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
139
+ &lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~4/383536354" height="1" width="1"/&gt;</content>
140
+
141
+
142
+ <feedburner:origLink>http://www.pauldix.net/2008/09/marshal-data-to.html</feedburner:origLink></entry>
143
+ <entry>
144
+ <title>Serializing data speed comparison: Marshal vs. JSON vs. Eval vs. YAML</title>
145
+ <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~3/376401099/serializing-dat.html" />
146
+ <link rel="replies" type="text/html" href="http://www.pauldix.net/2008/08/serializing-dat.html" thr:count="5" thr:updated="2008-10-14T01:26:31-04:00" />
147
+ <id>tag:typepad.com,2003:post-54766774</id>
148
+ <published>2008-08-27T14:31:41-04:00</published>
149
+ <updated>2008-10-14T01:26:31-04:00</updated>
150
+ <summary>Last night at the NYC Ruby hackfest, I got into a discussion about serializing data. Brian mentioned the Marshal library to me, which for some reason had completely escaped my attention until last night. He said it was wicked fast...</summary>
151
+ <author>
152
+ <name>Paul Dix</name>
153
+ </author>
154
+ <category scheme="http://www.sixapart.com/ns/types#category" term="Tahiti" />
155
+
156
+
157
+ <content type="html" xml:lang="en-US" xml:base="http://www.pauldix.net/">
158
+ &lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;p&gt;Last night at the &lt;a href="http://nycruby.org"&gt;NYC Ruby hackfest&lt;/a&gt;, I got into a discussion about serializing data. Brian mentioned the Marshal library to me, which for some reason had completely escaped my attention until last night. He said it was wicked fast so we decided to run a quick benchmark comparison.&lt;/p&gt;
159
+ &lt;p&gt;The test data is designed to roughly approximate what my &lt;a href="http://www.pauldix.net/2008/08/storing-many-cl.html"&gt;stored classifier data&lt;/a&gt; will look like. The different methods we decided to benchmark were Marshal, json, eval, and yaml. With each one we took the in-memory object and serialized it and then read it back in. With eval we had to convert the object to ruby code to serialize it then run eval against that. Here are the results for 100 iterations on a 10k element array and a hash with 10k key/value pairs run on my Macbook Pro 2.4 GHz Core 2 Duo:&lt;/p&gt;
160
+ &lt;pre&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; user&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;system&amp;nbsp; &amp;nbsp;&amp;nbsp; total&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; real&lt;br /&gt;array marshal&amp;nbsp; 0.210000&amp;nbsp; &amp;nbsp;0.010000&amp;nbsp; &amp;nbsp;0.220000 (&amp;nbsp; 0.220701)&lt;br /&gt;array json&amp;nbsp; &amp;nbsp;&amp;nbsp; 2.180000&amp;nbsp; &amp;nbsp;0.050000&amp;nbsp; &amp;nbsp;2.230000 (&amp;nbsp; 2.288489)&lt;br /&gt;array eval&amp;nbsp; &amp;nbsp;&amp;nbsp; 2.090000&amp;nbsp; &amp;nbsp;0.060000&amp;nbsp; &amp;nbsp;2.150000 (&amp;nbsp; 2.240443)&lt;br /&gt;array yaml&amp;nbsp; &amp;nbsp; 26.650000&amp;nbsp; &amp;nbsp;0.350000&amp;nbsp; 27.000000 ( 27.810609)&lt;br /&gt;&lt;br /&gt;hash marshal&amp;nbsp; &amp;nbsp;2.000000&amp;nbsp; &amp;nbsp;0.050000&amp;nbsp; &amp;nbsp;2.050000 (&amp;nbsp; 2.114950)&lt;br /&gt;hash json&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;3.700000&amp;nbsp; &amp;nbsp;0.060000&amp;nbsp; &amp;nbsp;3.760000 (&amp;nbsp; 3.881716)&lt;br /&gt;hash eval&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;5.370000&amp;nbsp; &amp;nbsp;0.140000&amp;nbsp; &amp;nbsp;5.510000 (&amp;nbsp; 6.117947)&lt;br /&gt;hash yaml&amp;nbsp; &amp;nbsp;&amp;nbsp; 68.220000&amp;nbsp; &amp;nbsp;0.870000&amp;nbsp; 69.090000 ( 72.370784)&lt;/pre&gt;
161
+ &lt;p&gt;The order in which I tested them is pretty much the order in which they ranked for speed. Marshal was amazingly fast. JSON and eval came out roughly equal on the array with eval trailing quite a bit for the hash. Yaml was just slow as all hell. A note on the json: I used the 1.1.3 library which uses c to parse. I assume it would be quite a bit slower if I used the pure ruby implementation. Here's &lt;a href="http://gist.github.com/7549"&gt;a gist of the benchmark code&lt;/a&gt; if you're curious and want to run it yourself.&lt;/p&gt;
162
+
163
+
164
+
165
+ &lt;p&gt;If you're serializing user data, be super careful about using eval. It's probably best to avoid it completely. Finally, just for fun I took yaml out (it was too slow) and ran the benchmark again with 1k iterations:&lt;/p&gt;
166
+ &lt;pre&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; user&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;system&amp;nbsp; &amp;nbsp;&amp;nbsp; total&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; real&lt;br /&gt;array marshal&amp;nbsp; 2.080000&amp;nbsp; &amp;nbsp;0.110000&amp;nbsp; &amp;nbsp;2.190000 (&amp;nbsp; 2.242235)&lt;br /&gt;array json&amp;nbsp; &amp;nbsp; 21.860000&amp;nbsp; &amp;nbsp;0.500000&amp;nbsp; 22.360000 ( 23.052403)&lt;br /&gt;array eval&amp;nbsp; &amp;nbsp; 20.730000&amp;nbsp; &amp;nbsp;0.570000&amp;nbsp; 21.300000 ( 21.992454)&lt;br /&gt;&lt;br /&gt;hash marshal&amp;nbsp; 19.510000&amp;nbsp; &amp;nbsp;0.500000&amp;nbsp; 20.010000 ( 20.794111)&lt;br /&gt;hash json&amp;nbsp; &amp;nbsp;&amp;nbsp; 39.770000&amp;nbsp; &amp;nbsp;0.670000&amp;nbsp; 40.440000 ( 41.689297)&lt;br /&gt;hash eval&amp;nbsp; &amp;nbsp;&amp;nbsp; 51.410000&amp;nbsp; &amp;nbsp;1.290000&amp;nbsp; 52.700000 ( 54.155711)&lt;/pre&gt;&lt;/div&gt;
167
+ &lt;div class="feedflare"&gt;
168
+ &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=a3KCSc.P"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=a3KCSc.P" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=zhI5zo.p"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=zhI5zo.p" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?a=u7DqIA.p"&gt;&lt;img src="http://feeds.feedburner.com/~f/PaulDixExplainsNothing?i=u7DqIA.p" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
169
+ &lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~4/376401099" height="1" width="1"/&gt;</content>
170
+
171
+
172
+ <feedburner:origLink>http://www.pauldix.net/2008/08/serializing-dat.html</feedburner:origLink></entry>
173
+
174
+ </feed>
@@ -0,0 +1,583 @@
1
+
2
+ <?xml version="1.0" encoding="utf-8"?>
3
+ <feed xmlns="http://www.w3.org/2005/Atom"
4
+ xmlns:thr="http://purl.org/syndication/thread/1.0">
5
+ <link rel="self" href="http://intertwingly.net/blog/index.atom"/>
6
+ <link rel="hub" href="http://pubsubhubbub.appspot.com/"/>
7
+ <id>http://intertwingly.net/blog/index.atom</id>
8
+ <icon>../favicon.ico</icon>
9
+
10
+ <title>Sam Ruby</title>
11
+ <subtitle>It’s just data</subtitle>
12
+ <author>
13
+ <name>Sam Ruby</name>
14
+ <email>rubys@intertwingly.net</email>
15
+ <uri>/blog/</uri>
16
+ </author>
17
+ <updated>2013-02-23T18:33:07-08:00</updated>
18
+ <link href="/blog/"/>
19
+ <link rel="license" href="http://creativecommons.org/licenses/BSD/"/>
20
+
21
+ <entry>
22
+ <id>tag:intertwingly.net,2004:3308</id>
23
+ <link href="/blog/2013/01/30/Plex"/>
24
+ <link rel="replies" href="3308.atom" thr:count="2" thr:updated="2013-01-30T13:58:47-08:00"/>
25
+ <title>Plex</title>
26
+ <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p><a href="http://www.hanselman.com/blog/PlexIsTheMediaCenterSoftwareEcosystemIveBeenWaitingFor.aspx">Scott Hanselman</a>: <em>Plex is the media center software ecosystem I’ve been waiting for</em></p>
27
+ <p>Unhappy with <a href="http://intertwingly.net/blog/2012/12/05/Time-Warner-Cables-idea-of-service">Time Warner Cable</a>, I’ve been exploring <a href="http://movies.netflix.com/WiHome">netflix</a>, <a href="http://www.dish.com/">dish</a>, <a href="http://www.slingbox.com/">sling</a>, <a href="http://www.roku.com/">roku</a>, <a href="http://www.samsung.com/smarttv">samsung</a>, <a href="http://fmpeg.org/">ffmpeg</a>, <a href="http://handbrake.fr/">handbrake</a>, and <a href="http://cclive.sourceforge.net/">cclive</a>.  Next up, some form of <a href="http://www.linuxtv.org/wiki/index.php/ATSC_USB_Devices">video capture device</a>... at the moment I’m leaning towards <a href="http://www.tigerdirect.com/applications/SearchTools/item-details.asp?EdpNo=4146195&amp;CatId=4546">Hauppauge</a>.</p>
28
+ <p>I’m not quite prepared to declare Plex as the centerpiece of my home media center, but it certainly has become a key component.</p></div></summary>
29
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
30
+ <defs>
31
+ <radialGradient id="plex1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
32
+ <stop offset="0%" stop-color="#f8ce22" stop-opacity="0.9" ></stop>
33
+ <stop offset="100%" stop-color="rgb(0,0,0)" stop-opacity="0" ></stop>
34
+ </radialGradient>
35
+ </defs>
36
+ <rect width="100" height="100" rx="10"></rect>
37
+ <ellipse cx="54" cy="50" rx="38" ry="60" fill="url(#plex1)" ></ellipse>
38
+ <path d="M28,7h31l28,43l-28,43h-31l28-43Z" fill="#ff8e00" stroke="#f8ce22" stroke-width="2"></path>
39
+ </svg>
40
+ <p><a href="http://www.hanselman.com/blog/PlexIsTheMediaCenterSoftwareEcosystemIveBeenWaitingFor.aspx"><cite>Scott Hanselman</cite></a>: <em>Plex is the media center software ecosystem I’ve been waiting for</em></p>
41
+ <p>Unhappy with <a href="http://intertwingly.net/blog/2012/12/05/Time-Warner-Cables-idea-of-service">Time Warner Cable</a>, I’ve been exploring <a href="http://movies.netflix.com/WiHome">netflix</a>, <a href="http://www.dish.com/">dish</a>, <a href="http://www.slingbox.com/">sling</a>, <a href="http://www.roku.com/">roku</a>, <a href="http://www.samsung.com/smarttv">samsung</a>, <a href="http://fmpeg.org/">ffmpeg</a>, <a href="http://handbrake.fr/">handbrake</a>, and <a href="http://cclive.sourceforge.net/">cclive</a>.  Next up, some form of <a href="http://www.linuxtv.org/wiki/index.php/ATSC_USB_Devices">video capture device</a>... at the moment I’m leaning towards <a href="http://www.tigerdirect.com/applications/SearchTools/item-details.asp?EdpNo=4146195&amp;CatId=4546">Hauppauge</a>.</p>
42
+ <p>I’m not quite prepared to declare Plex as the centerpiece of my home media center, but it certainly has become a key component.</p>
43
+ <p>Unlike Scott, I didn’t go with a dedicated NAS box.  Installation of a <a href="https://apps.ubuntu.com/cat/applications/precise/plexmediaserver/">Plex Media Server</a> on Ubuntu is a snap (though a <a href="https://bugs.launchpad.net/ubuntu/+source/software-center/+bug/647212">workaround</a> is needed if you happen to make use of an <a href="http://linuxexpresso.wordpress.com/2011/02/13/howto-apt-cacher-ng-on-ubuntu/">apt cacher</a>).</p>
44
+ <p>Obligatory <a href="http://i.imgur.com/VCTCAS7.png">Cable Guy</a> reference.</p></div></content>
45
+ <updated>2013-01-30T10:12:03-08:00</updated>
46
+ </entry>
47
+
48
+ <entry>
49
+ <id>tag:intertwingly.net,2004:3307</id>
50
+ <link href="/blog/2012/12/22/RESTful-Web-APIs"/>
51
+ <link rel="replies" href="3307.atom" thr:count="0"/>
52
+ <title>RESTful Web APIs</title>
53
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
54
+ <path d="M10,90.1v-2h80V90.1zM10,70.1v-2h80V70.1zM10,50.1v-2h80V50.1zM10,30.1v-2h80V30.1zM10,10.1v-2h80V10.1z"></path>
55
+ <path d="M44.4,20.8c1.5,1.6,13,15.7,13,15.7s-6.4,6.1-6.4,12.5c0,7.5,8.6,14.3,8.6,14.3l-0.9,1.1c-3.3-1.9-8.9-2.1-11.4,0.8c-3.1,3.6,3.9,9.1,3.9,9.1l-0.8,1.1c-2.4-1.8-12.6-11.4-8.3-16.1c2.6-2.9,5.8-3.8,10.3-1.4l-12.1-12.5c7-8.6,8.2-11.1,8.2-13.4c0-4.8-3.4-8.2-5.1-10.4c-0.6-0.9-1.7-1.6-1-2.2C43.1,18.9,43.5,19.7,44.4,20.8z" fill="#F33"></path>
56
+ </svg>
57
+ <p><a href="http://amundsen.com/blog/archives/1139"><cite>Mike Amundsen</cite></a>: <em>I have the even greater privilege of working with Leonard and Sam on a new book - “RESTful Web APIs”. It’s scheduled for completion by the end of Q1 2013 and should be available soon after.</em></p>
58
+ <p>While I’m formally on this project, I’m not planning on doing any writing beyond possibly an introduction.  As Mike put it, this book isn’t merely a 2nd edition, but rather <em>more of a “follow-up” seven years on.</em>  I’m very much looking forward to seeing where Mike can help Leonard take this work.</p></div></content>
59
+ <updated>2012-12-22T05:47:48-08:00</updated>
60
+ </entry>
61
+
62
+ <entry>
63
+ <id>tag:intertwingly.net,2004:3306</id>
64
+ <link href="/blog/2012/12/19/Feedvalidator-org-Hacked"/>
65
+ <link rel="replies" href="3306.atom" thr:count="5" thr:updated="2013-01-07T12:31:41-08:00"/>
66
+ <title>Feedvalidator.org Hacked?</title>
67
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" stroke="#000" width="100" height="100" viewBox="0 0 100 100">
68
+ <path d="M8,80s-5,8,5,9l78,0s9,0,5-9l-40-71s-4-6-8,0z" stroke-width="2" fill="#fff"></path>
69
+ <path d="M52,10 L10,85 L93,85z" stroke-width="2" stroke-linejoin="round" fill="#fc0"></path>
70
+ <path d="M52,32l0,26" stroke-width="9" stroke-linecap="round"></path>
71
+ <circle r="6" cx="52" cy="73"></circle>
72
+ </svg>
73
+ <p>Google has reported <a href="http://feedvalidator.org/">feedvalidator.org</a> as being <a href="http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=Firefox&amp;hl=en-US&amp;site=http://feedvalidator.org/">hacked</a>, and people are tweeting and emailing me.</p>
74
+ <p>I’ve looked at the markup being returned and it looks clean to me.  The <a href="https://raw.github.com/rubys/feedvalidator/master/.htaccess">.htaccess</a> file looks fine.  A <code>git status</code> command shows that none of the files on the server have been modified.</p>
75
+ <p>Can somebody identify what is causing Google to be concerned?</p></div></content>
76
+ <updated>2012-12-19T03:33:01-08:00</updated>
77
+ </entry>
78
+
79
+ <entry>
80
+ <id>tag:intertwingly.net,2004:3305</id>
81
+ <link href="/blog/2012/12/13/Changing-the-TAG"/>
82
+ <link rel="replies" href="3305.atom" thr:count="4" thr:updated="2012-12-14T09:16:37-08:00"/>
83
+ <title>Changing the TAG</title>
84
+ <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p><a href="https://blog.linss.com/2012/12/12/changing-the-tag-an-unexpected-opportunity/">Peter Linss</a>: <em>I really want to see the TAG be more involved with the rest of the working groups at the W3C</em></p>
85
+ <p>I’ll come out and say it.  I’m a skeptic.  I’ll note that the three out of the four of the “TAG reformists” statements do NOT list getting involved with the rest of the working groups at the W3C as a goal.  What am I missing?</p></div></summary>
86
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="131" height="76" viewBox="0 0 131 76">
87
+ <path d="M36,5l12,41l12-41h33v4l-13,21c30,10,2,69-21,28l7-2c15,27,33,-22,3,-19v-4l12-20h-15l-17,59h-1l-13-42l-12,42h-1l-20-67h9l12,41l8-28l-4-13h9" fill='#005A9C'></path>
88
+ <path d="M94,53c15,32,30,14,35,7l-1-7c-16,26-32,3-34,0M122,16c-10-21-34,0-21,30c-5-30 16,-38 23,-21l5-10l-2-9"></path>
89
+ </svg>
90
+ <p><a href="https://blog.linss.com/2012/12/12/changing-the-tag-an-unexpected-opportunity/"><cite>Peter Linss</cite></a>: <em>I really want to see the TAG be more involved with the rest of the working groups at the W3C</em></p>
91
+ <p>I’ll come out and say it.  I’m a skeptic.  Each of the <a href="http://www.w3.org/2012/12/03-tag-nominations">nominees</a> are good people.</p>
92
+ <p>I’ll note that the three out of the four of the “TAG reformists” statements do NOT list getting involved with the rest of the working groups at the W3C as a goal: <a href="http://infrequently.org/2012/12/reforming-the-w3c-tag/">Alex Russell</a>, <a href="http://marcosc.com/2012/12/w3c-tag-elections/">Marcos Cáceres</a>, <a href="http://annevankesteren.nl/2012/12/w3c-tag">Anne van Kesteren</a>, and <a href="http://yehudakatz.com/2012/12/07/im-running-to-reform-the-w3cs-tag/">Yehuda Katz</a>.</p>
93
+ <p>And outside of Anne, none of them have significantly been involved in the <a href="http://www.w3.org/html/wg/">HTML WG</a>.  As to Anne, I don’t see being on the TAG as resolving his <a href="http://annevankesteren.nl/2012/11/copyright">concern</a>.</p>
94
+ <p>What am I missing?</p></div></content>
95
+ <updated>2012-12-13T07:54:49-08:00</updated>
96
+ </entry>
97
+
98
+ <entry>
99
+ <id>tag:intertwingly.net,2004:3304</id>
100
+ <link href="/blog/2012/12/05/Time-Warner-Cables-idea-of-service"/>
101
+ <link rel="replies" href="3304.atom" thr:count="15" thr:updated="2012-12-20T14:47:52-08:00"/>
102
+ <title>Time Warner Cable’s idea of “service”</title>
103
+ <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>It started with two notifications we received via postal mail.  First Time Warner was going to start charging us rent for an outdated cable modem.  Second they were going to drop a number of cable channels, but if I acted now, I could request a digital adapter which would allow me to watch these channels on exactly one TV.</p>
104
+ <p>This process has turned a fairly complacent Time Warner customer into one that is actively seeking alternatives.  In looking around, I see plenty of promo offers of more service than I have (basic cable and basic internet) for considerably less than I am currently paying.  I am OK with waiting an hour or more for an answer, but I am not OK with having to be on hold for that entire time.  And I’m definitely not OK with renting a separate box per device simply to get access.</p>
105
+ <p>This process has turned a fairly complacent Time Warner customer into one that is actively seeking alternatives.  So I am beginning my research: starting with looking for alternatives to cable TV.  What I want is a single plan that allows me to watch whatever I want wherever I want.  I am OK with upgrading my devices as long as we are talking about a purchase not a lease.</p>
106
+ <p>Any pointers people might leave in comments would be appreciated.</p></div></summary>
107
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="108" height="93" viewBox="0 0 108 93">
108
+ <path d='M17,27c-3,3-5,6-10,11c-2,1-3,1-5,0c-4-4-2-7,8-17c11-11,24-19,36-20c13-2,30,1,43,11c7,6,15,14,19,21c-4,7-9,13-14,17c-5,5-11,8-16,10c-13,4-28,3-36-10c-2-4-2-8,0-12c2-5,8-9,13-9c4,0,9,2,11,7c1,2,1,6-1,8c-1,1-6,2-7-2c0-2-0-4-2-4c-4,0-7,3-6,8c1,3,4,6,11,7c3,0,7-1,11-6c3-4,3-11,0-15c-4-7-10-10-18-10c-9,0-17,5-21,14c-3,7-5,17,0,28c4,8,11,13,17,16c5,3,16,4,17,8c0,3-2,5-4,5c-17-3-31-11-37-25c-7-13-6-30,2-41c5-7,13-12,20-13c19-5,38,9,35,28c-1,3-2,6-4,8c0,1,0,1-1,1l2-1c7-4,13-10,17-17c-10-18-32-27-49-24c-14,2-23,10-31,18' fill='#0056a2'></path>
109
+ </svg>
110
+ <p>It started with two notifications we received via postal mail.  First Time Warner was going to start charging us rent for an outdated cable modem.  Second they were going to drop a number of cable channels, but if I acted now, I could request a digital adapter which would allow me to watch these channels on exactly one TV.</p>
111
+ <p>So I did some research and purchased a DOCSIS 3.0 compatible modem that can do IP V6, figuring that would future proof me for a while, and connected it up.  I actually managed to get an IP address assigned, but everything I tried after that was redirected to a site saying that I needed to be “provisioned” and to call a number.  Upon calling that number, I got connected with a person whose sole purpose seemed to be to upsell me to a higher plan.  After I politely but firmly refused, I was transferred and placed on hold for about 30 minutes.  The woman that tried to help me get connected couldn’t get it to work so she transferred me to level 3.  Another 5 minutes later, a gentleman picked up and also had trouble.  It took him about 30 minutes to get it to work — apparently they didn’t give him instructions on how to deal with DOCSIS 3.0 modems despite my picking one of the options on the list they provided to me.  But he was pleasant and apologetic throughout, and eventually did manage to get it working.</p>
112
+ <p>The next day I drove 15 minutes to stand in a 20 minute line to do what amounted to a 60 second transaction: here’s a box, here’s a receipt.  Thank you and goodbye.</p>
113
+ <p>As to the dropped channels... I dutifully filled out an online form requesting a digital adapter, and got first a confirmation and subsequently a notification that the order was “complete”... where the latter merely indicated that something would be shipping in 3-5 business days, giving me a confirmation number.  That was 18 November.</p>
114
+ <p>The box never showed up.</p>
115
+ <p>Yesterday, the channels went dark, and I went online.  After using Chrome to override my User Agent so that I could make use of their chat system, I waited over 20 minutes for a representative.  After checking, he said that there was nothing he could do for me, and gave me a number I could call.  I called that number and was told that the wait time would be more than 30 minutes.  As the chat window was still open, I asked if there was anything else I could do.  He said call back late in the evening when the wait times would be less.  I was not happy and closed the chat window.  I was then presented with a survey, in which I responded that the person was not able to solve my problem and that I was not happy.</p>
116
+ <p>I <a href="https://twitter.com/samruby">tweeted to TWCableHelp</a> and got <strike>no response</strike> a DM five hours later asking me for my phone number.  Before I went to bed, I sent an email.  When I woke up I got a response indicating that the email had been forwarded to “our regional contacts”, who would be contacting me.  They have not.</p>
117
+ <p>I called again, and was told that there would be a 20 to 25 minute wait time.  It was closer to 30.  I was told that another digital adapter had been placed on order.  I asked for a confirmation number, and was told that she didn’t have one.  I asked for an email, and she said that one would be sent within 48 hours.  I was given a case number.  And that was all she could do for me.</p>
118
+ <p>At this point, I have nobody I can contact, no tracking number, and no confidence that this time will turn out any different.  And a number of black channels.</p>
119
+ <p>This process has turned a fairly complacent Time Warner customer into one that is actively seeking alternatives.  In looking around, I see plenty of promo offers of more service than I have (basic cable and basic internet) for considerably less than I am currently paying.  I am OK with waiting an hour or more for an answer, but I am not OK with having to be on hold for that entire time.  And I’m definitely not OK with renting a separate box per device simply to get access.</p>
120
+ <p>So I am beginning my research: starting with looking for alternatives to cable TV.  What I want is a single plan that allows me to watch whatever I want wherever I want.  I am OK with upgrading my devices as long as we are talking about a purchase not a lease.</p>
121
+ <p>Any pointers people might leave in comments would be appreciated.</p></div></content>
122
+ <updated>2012-12-05T08:54:58-08:00</updated>
123
+ </entry>
124
+
125
+ <entry>
126
+ <id>tag:intertwingly.net,2004:3303</id>
127
+ <link href="/blog/2012/11/09/In-defence-of-Polyglot"/>
128
+ <link rel="replies" href="3303.atom" thr:count="21" thr:updated="2012-12-10T20:19:45-08:00"/>
129
+ <title>In defence of Polyglot</title>
130
+ <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I see that <a href="http://hsivonen.iki.fi/author/">Henri Sivonen</a> is once again <a href="https://twitter.com/hsivonen/status/266535784050458624">being snarky</a> without <a href="https://twitter.com/hsivonen/status/266565956585795585">backing his position</a>.  I’ll state my position, namely that something like the <a href="http://dev.w3.org/html5/html-xhtml-author-guide/html-xhtml-authoring-guide.html">polyglot specification</a> needs to exist, and why I believe that to be the case.</p>
131
+ <p>It makes sense for authors who may produce a handful of pages to be processed by an uncountable number of imperfect tools to agree on restrictions that may go well behond the <a href="http://lists.w3.org/Archives/Public/public-html/2012Nov/0006.html">minimal logical consequences from normative text elsewhere</a> if those restrictions increase the odds of the document produced being correctly processed.</p>
132
+ <p>Such restrictions are not a bad thing.  In fact, such restrictions are very much a good thing.</p></div></summary>
133
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="86" height="116" viewBox="0 0 86 116">
134
+ <path d='M70,70c0,20-15,37-34,37c-18,0-33-17-32-37c0-21,14-54,33-55c18,0,34,34,33,55' fill='#0C0'></path>
135
+ <path d='M27,48a1,2,170,1,1-12,0a1,2,170,1,1,12,0M30,48a1,2,10,1,1,12,1a1,2,10,1,1-12-1M46,66l-5,4c-2,2-5,3-9,4c-4,1-8,1-12,0h-1c0,2,1,3,2,5c-1,0,4,5,7,5c4,0,6,0,10-1c2,0,5,1,7-1c1-1,1-8,1-10v-6' fill='#fff' stroke="#0A0"></path>
136
+ <path d='M30,25l13,4l-1,3l-12-5zM24,25l-12,4l2,3l11-5zM26,52a2,3,170,1,1-7,0a2,3,170,1,1,7,0M37,52a2,3,10,1,1-7,0a2,3,10,1,1,7,0'></path>
137
+ <path d='M34,48a1,1,0,1,1-1,0M23,48a1,1,0,1,1-1,0' fill='#999'></path>
138
+ <path stroke='#000' d='M31,20c-1,0-2-2-3-3c-1-1,2-3,3-3c3-6-2-9-7-6' fill='none'></path>
139
+ </svg>
140
+ <p>I see that <a href="http://hsivonen.iki.fi/author/">Henri Sivonen</a> is once again <a href="https://twitter.com/hsivonen/status/266535784050458624">being snarky</a> without <a href="https://twitter.com/hsivonen/status/266565956585795585">backing his position</a>.  I’ll state my position, namely that something like the <a href="http://dev.w3.org/html5/html-xhtml-author-guide/html-xhtml-authoring-guide.html">polyglot specification</a> needs to exist, and why I believe that to be the case.</p>
141
+ <p>The short version is that I have developed a <a href="https://github.com/rubys/wunderbar">library</a> that I believe to be polyglot compatible, and by that I mean that if there are differences between what this library does and what polyglot specifies that one or both should be corrected to bring them into compliance.</p>
142
+ <p>I didn’t write this library simply because I am loonie, but very much to solve a real problem.</p>
143
+ <p>The problem is that HTML source files <a href="http://svn.whatwg.org/webapps/complete.html">exist</a> that contain artifacts like consecutive &lt;td&gt; elements; people process such documents using tools such as <a href="http://anolis.gsnedders.com/">anolis</a>; and such libraries often depend on — for good reasons — libraries such as <a href="http://www.xmlsoft.org/">libxml2</a> which do an imperfect job of parsing HTML correctly.  The output produced by such tools when combined with such libraries are incorrect.</p>
144
+ <p>Note that I stop well short of recommending that others serve their content as <a href="http://www.w3.org/TR/xhtml-media-types/">application/xhtml+xml</a>.  Or that tools should <a href="http://docs.activestate.com/activepython/3.1/diveintopython3/html/xml.html#xml-custom-parser">halt and catch fire</a> if they are presented with incorrect input.  In fact, I would even be willing to say that in general people <a href="http://www.ietf.org/rfc/rfc2119.txt">SHOULD NOT</a> do either of these things.</p>
145
+ <p>Now that I have provided instance proofs of the problem and the solution, I’ll proceed with the longer answer.  I will start by noting that <a href="http://en.wikipedia.org/wiki/Robustness_principle">Postel’s law</a> has two halves, and while the HTML WG has focused heavily on the second half of that law, the story should not stop there.</p>
146
+ <p>To get HTML right involves a number of details that people often get wrong.  Details such as encoding and escaping.  Details that have consequences such as <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS vulnerabilities</a> when the scenario involves integrating content from untrusted sources.  Scenarios which include comments on blogs or feed aggregators.  Scenarios that lead people to write sanitizers and employ the use of imperfect HTML parsers.</p>
147
+ <p>It is well and good that Henri maintains — on a best effort basis only — a <a href="http://about.validator.nu/htmlparser/">superior parser</a> for exactly one programming language.  <a href="https://twitter.com/hsivonen/status/263696331141431296">Advertising</a> this library more won’t solve the problem for people who code in languages such as C#, Perl, PHP, Python, or Ruby.  Fundamentally, a <a href="http://www.xml.com/pub/a/2004/07/21/dive.html">tools will save us</a> response is not an adequate response when the problem is imperfect tools.</p>
148
+ <p>This problem that needs to be addressed is very much the flip side, and complement to, the parsing problem that HTML5 has competently solved.  Given a handful of browser vendors and an uncountable number of imperfect documents, it very much make sense for the browser vendors to get together and agree on how to handle error recovery.  By the very same token, it makes sense for authors who may produce a handful of pages to be processed by an uncountable number of imperfect tools to agree on restrictions that may go well beyond the <a href="http://lists.w3.org/Archives/Public/public-html/2012Nov/0006.html">minimal logical consequences from normative text elsewhere</a> if those restrictions increase the odds of the document produced being correctly processed.</p>
149
+ <p>Yes, it would be great if this weren’t necessary and all tools were perfect.  Similarly, it would be great if browser vendors didn’t have to agree on error recovery as this makes the creation of streaming parsers more difficult.  The point is that while both would be great, neither will happen, at least not any time soon.</p>
150
+ <p>These restrictions may indeed go beyond “always explicitly close all elements” and “always quote all attribute values”.  It may include such statements as “always use UTF-8”.</p>
151
+ <p>Such restrictions are not a bad thing.  In fact, such restrictions are very much a good thing.</p></div></content>
152
+ <updated>2012-11-09T03:58:21-08:00</updated>
153
+ </entry>
154
+
155
+ <entry>
156
+ <id>tag:intertwingly.net,2004:3302</id>
157
+ <link href="/blog/2012/10/09/Web-Platform-Docs"/>
158
+ <link rel="replies" href="3302.atom" thr:count="0"/>
159
+ <title>Web Platform Docs</title>
160
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="100" height="100" viewBox="0 0 100 100">
161
+ <path d='M73,55v-40c0-8,4-13,12-13c7,0,13,4,13,12v68c-7-10-25-27-25-27M85,10c-3,0-5,2-5,5c0,3,2,5,5,5c3,0,5-2,5-6c0-2-2-4-5-4' fill='#31B0BC'></path>
162
+ <path d='M2,77v-61c0-9,6-14,14-14c7,0,12,5,11,14v40l-25,24M15,9c-3,0-5,2-5,5c0,3,2,5,5,5c3,0,5-2,5-6c0-2-2-4-5-4' fill='#F19620'></path>
163
+ <path d='M4,77l23-21v35c-4,6-10,10-17,7c-8-3-11-16-6-21M15,91c3,0,5-2,5-5c0-3-2-5-5-5c-4,0-6,2-6,5c0,3,3,5,6,5' fill='#CC2D28'></path>
164
+ <path d='M73,55c0,0,23,22,25,27c1,7-1,13-8,16c-7,3-13,0-17-6v-37M90,86c0-3-2-5-5-5c-3,0-5,2-5,5c0,3,2,5,5,5c3,0,5-2,5-5' fill='#273C7D'></path>
165
+ <path d='M73,92l-24-22v-2l14-22l10,9l0,37' fill='#654D97'></path>
166
+ <path d='M50,67l-12-22l-11,11v1v34l22-21' fill='#D24839'></path>
167
+ <path d='M49,70c-7-8-14-14-12-24c9-12,17-11,26,0c1,11-7,17-14,24M50,55c3,0,5-2,5-5c0-3-2-5-5-5c-4,0-6,2-6,5c0,3,3,5,6,5' fill='#59152B'></path>
168
+ </svg>
169
+ <p><a href="http://blog.webplatform.org/2012/10/one-small-step/"><cite>Doug Sheppers</cite></a>: <em><a href="http://docs.webplatform.org/">WebPlatform.org</a> will have accurate, up-to-date, comprehensive references and tutorials for every part of client-side development and design, with quirks and bugs revealed and explained. It will have in-depth indicators of browser support and interoperability, with links to tests for specific features. It will feature discussions and script libraries for cutting-edge features at various states of implementation or standardization, with the opportunity to give feedback into the process before the features are locked down. It will have features to let you experiment with and share code snippets, examples, and solutions. It will have an API to access the structured information for easy reuse. It will have resources for teachers to help them train their students with critical skills. It will have information you just can’t get anywhere else, and it will have it all in one place.</em></p>
170
+ <p><em>But it doesn’t. Not yet.</em></p></div></content>
171
+ <updated>2012-10-09T11:35:17-07:00</updated>
172
+ </entry>
173
+
174
+ <entry>
175
+ <id>tag:intertwingly.net,2004:3301</id>
176
+ <link href="/blog/2012/09/04/The-Flowing-Standard"/>
177
+ <link rel="replies" href="3301.atom" thr:count="1" thr:updated="2013-01-03T17:32:29-08:00"/>
178
+ <title>The Flowing Standard</title>
179
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="131" height="76" viewBox="0 0 131 76">
180
+ <path d="M36,5l12,41l12-41h33v4l-13,21c30,10,2,69-21,28l7-2c15,27,33,-22,3,-19v-4l12-20h-15l-17,59h-1l-13-42l-12,42h-1l-20-67h9l12,41l8-28l-4-13h9" fill='#005A9C'></path>
181
+ <path d="M94,53c15,32,30,14,35,7l-1-7c-16,26-32,3-34,0M122,16c-10-21-34,0-21,30c-5-30 16,-38 23,-21l5-10l-2-9"></path>
182
+ </svg>
183
+ <a href="http://www.w3.org/QA/2012/09/the_flowing_standard.html"><cite>Robin Berjon</cite></a>: <em>Looking at it in terms of rebounds, plot twists, nurtured healing and abandonment, love and betrayal, strife, toil, stunning victories, dispersions and last minute rallies the only thing that distinguishes HTML’s history from a charts-topping teenage fantasy saga seems to be the lack of vampires. And even then, were vampires around I’m not sure we’d notice them for all the action.</em></div></content>
184
+ <updated>2012-09-04T16:10:12-07:00</updated>
185
+ </entry>
186
+
187
+ <entry>
188
+ <id>tag:intertwingly.net,2004:3300</id>
189
+ <link href="/blog/2012/08/25/Taming-the-wild-wild-web"/>
190
+ <link rel="replies" href="3300.atom" thr:count="3" thr:updated="2012-10-18T03:54:07-07:00"/>
191
+ <title>Taming the wild, wild web</title>
192
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="100" height="100" viewBox="0 0 100 100">
193
+ <path fill='#85B916' d='M50,82l-31-31l31-31l10,10l-20,21l10,10l31-31l-27-27c-2-2-6-2-8,0l-43,44c-2,2-2,6,0,8l43,43c2,2,6,2,8,0l43-43c2-2,2-6,0-8l-6-7z'></path>
194
+ </svg>
195
+ <a href="http://toc.oreilly.com/2012/08/portable-documents-for-the-open-web-part-3.html"><cite>Bill McCoy</cite></a>: <em>EPUB in effect takes the Wild, Wild Web and tames it. EPUB for example requires use of the XML serialization of HTML5 (XHTML5), rather than “Tag Soup” aka “Street” HTML. This means that EPUB content, unlike arbitrary web pages, can be reliably created and manipulated with XML tool chains. EPUB defined Reading System conformance more tightly than HTML5 defines for browser User Agents, pinning down things that are under-specified in the union of W3C standards.</em> [via <a href="https://twitter.com/pmuellr/status/238664881308565504"><cite>Patrick Mueller</cite></a>]</div></content>
196
+ <updated>2012-08-25T12:32:40-07:00</updated>
197
+ </entry>
198
+
199
+ <entry>
200
+ <id>tag:intertwingly.net,2004:3299</id>
201
+ <link href="/blog/2012/07/16/Inhibiting-Suspend"/>
202
+ <link rel="replies" href="3299.atom" thr:count="1" thr:updated="2012-07-17T08:34:14-07:00"/>
203
+ <title>Inhibiting Suspend</title>
204
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="109" height="92" viewBox="0 0 109 92">
205
+ <g style='fill:#FFFFFF;stroke:#3B80AE;stroke-width:3'>
206
+ <path d='M107,51c3,10-3,20-13,23l-60,15c-10,3-20-3-23-13l-9-36c-2-10,3-20,13-22l60-16c10-2,20,3,23,13z' style='stroke:#BABABA'></path>
207
+ <path d='M101,50c2,10-2,17-12,19l-53,14c-9,3-18-1-20-11l-8-30c-2-11,1-17,12-20l53-14c10-2,18,2,20,11z' style='fill:#3B80AE;stroke:none'></path>
208
+ <path d='M57,65l-27-26l48-5z' style='opacity:0.5;fill:none;stroke:#FFFFFF'></path>
209
+ <path d='M91,36c0,2-1,4-3,5l-15,4c-2,0-4-1-5-3l-3-11c0-2,1-4,3-5l15-4c2,0,4,1,5,3z'></path>
210
+ <path d='M46,42c0,3-1,5-3,6l-19,5c-3,0-5-1-6-4l-3-13c-1-3,0-5,3-6l19-5c2,0,5,1,5,4z'></path>
211
+ <path d='M66,67c0,1-1,3-2,3l-11,3c-1,0-2-1-3-2l-2-8c0-1,1-2,2-3l11-3c1,0,3,1,3,2z'></path>
212
+ </g>
213
+ </svg>
214
+ <p>The <a href="http://people.gnome.org/~mccann/gnome-session/docs/gnome-session.html#org.gnome.SessionManager.Inhibit">interface</a> is a bit low level, but workable:</p>
215
+ <pre class="code">require 'dbus' # gem install ruby-dbus
216
+ bus = DBus::SessionBus.instance
217
+ sm = bus.service('org.gnome.SessionManager').object('/org/gnome/SessionManager')
218
+ sm.introspect
219
+ sm.default_iface = 'org.gnome.SessionManager'
220
+ cookie = sm.Inhibit($0, 0, 'inhibiting', 4).first
221
+ at_exit { cookie = sm.Uninhibit(cookie) if sm.IsInhibited(4).first }</pre>
222
+ <p>Note: the call to <code>Uninhibit</code> is optional — it will occur on process exit anyway.</p>
223
+ <p>Hat tip to <a href="http://www.lucidelectricdreams.com/2011/06/disabling-screensaverlock-screen-on.html">JanuZ</a>.</p></div></content>
224
+ <updated>2012-07-16T08:48:01-07:00</updated>
225
+ </entry>
226
+
227
+ <entry>
228
+ <id>tag:intertwingly.net,2004:3298</id>
229
+ <link href="/blog/2012/07/10/utf8mb4"/>
230
+ <link rel="replies" href="3298.atom" thr:count="7" thr:updated="2012-10-15T14:45:05-07:00"/>
231
+ <title>utf8mb4</title>
232
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="115" height="87" viewBox="0 0 115 87">
233
+ <path d="M0,1v83h26c-10,0-22-11-22-21v-62zM22,1v53c0,16,22,16,22,0v-53zM41,84c10,0,22-11,22-21v-22l27,43zM60,1h30v20h19v-20h5v84h-5v-56h-19v18z" fill="#C60025"></path>
234
+ </svg>
235
+ <p><a href="http://golem.ph.utexas.edu/~distler/blog/archives/002539.html"><cite>Jacques Distler</cite></a>: <em>Remarkably, even after a decade of such pain, Unicode is, in 2012, still “cutting edge.”</em></p>
236
+ <p>Ouch.</p></div></content>
237
+ <updated>2012-07-10T10:55:32-07:00</updated>
238
+ </entry>
239
+
240
+ <entry>
241
+ <id>tag:intertwingly.net,2004:3297</id>
242
+ <link href="/blog/2012/06/23/Ubuntu-12-04-and-Ruby-1-9-3"/>
243
+ <link rel="replies" href="3297.atom" thr:count="0"/>
244
+ <title>Ubuntu 12.04 and Ruby 1.9.3</title>
245
+ <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I previously had installed Ubuntu 12.04 on a NetBook, and my overall impression was simply that it was more stable than its predecessor — particularly for Unity.</p>
246
+ <p>For the first time I tried it on a desktop, and to my surprise the following worked:</p>
247
+ <pre class="code">sudo apt-get install ruby1.9.3</pre>
248
+ <p>And by worked, I mean not only did it install Ruby 1.9.3, but it made it (and gem, and irc) the default ruby.</p>
249
+ <p>For those that still use <a href="https://rvm.io//">rvm</a>, (many of the ‘cool kids’ have moved on to <a href="https://github.com/sstephenson/rbenv/">rbenv</a>, I noticed a few niggles</p></div></summary>
250
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="140" height="140" viewBox="-70 -70 140 140">
251
+
252
+ <defs>
253
+ <path id="b" d="M 23,-20 A32,32 0,0,0 -23,-20 L -40,-30 A42,42 0,0,1 -14,-47 A17,17 0,0,0 14,-47 A42,42 0,0,1 40,-30 Z"></path>
254
+ <circle id="h" cx="0" cy="-57" r="12"></circle>
255
+ </defs>
256
+
257
+ <g transform="translate(5,5)" opacity="0.125">
258
+ <use xlink:href="#h" transform="rotate(30)"></use>
259
+ <use xlink:href="#b" transform="rotate(30)"></use>
260
+ <use xlink:href="#h" transform="rotate(150)"></use>
261
+ <use xlink:href="#b" transform="rotate(150)"></use>
262
+ <use xlink:href="#h" transform="rotate(-90)"></use>
263
+ <use xlink:href="#b" transform="rotate(-90)"></use>
264
+ </g>
265
+
266
+ <a xlink:href="http://www.ubuntu.com/">
267
+ <use xlink:href="#h" fill="#d00" transform="rotate(30)"></use>
268
+ <use xlink:href="#b" fill="#f40" transform="rotate(30)"></use>
269
+ <use xlink:href="#h" fill="#f80" transform="rotate(150)"></use>
270
+ <use xlink:href="#b" fill="#d00" transform="rotate(150)"></use>
271
+ <use xlink:href="#h" fill="#f40" transform="rotate(-90)"></use>
272
+ <use xlink:href="#b" fill="#f80" transform="rotate(-90)"></use>
273
+ </a>
274
+
275
+ </svg>
276
+ <p>I previously had installed Ubuntu 12.04 on a NetBook, and my overall impression was simply that it was more stable than its predecessor — particularly for Unity.</p>
277
+ <p>For the first time I tried it on a desktop, and to my surprise the following worked:</p>
278
+ <pre class="code">sudo apt-get install ruby1.9.3</pre>
279
+ <p>And by worked, I mean not only did it install Ruby 1.9.3, but it made it (and gem, and irc) the default ruby.</p>
280
+ <p>For those that still use <a href="https://rvm.io//">rvm</a>, (many of the ‘cool kids’ have moved on to <a href="https://github.com/sstephenson/rbenv/">rbenv</a>, I noticed a few niggles:</p>
281
+ <ul>
282
+ <li>Don’t follow the <a href="https://rvm.io//rvm/install/installation">instructions</a> and specify <code>--ruby</code> or <code>--rails</code>. You will get a version of Ruby that can’t install gems. Simply omit that parameter.</li>
283
+ <li>Next set the <a href="https://rvm.io/integration/gnome-terminal/">‘Run command as login shell’</a> checkbox.</li>
284
+ <li>Then run <code>rvm requirements</code> and install what it tells you to install.</li>
285
+ <li>Finally, run <code>rvm install 1.9.3</code> to build the latest.</li>
286
+ </ul>
287
+
288
+ <p>Personally, I follow that up with <code>rvm --default system</code>.  That means that while I have other Rubies available at my finger-tips, the one I generally use is the one provided with Ubuntu.</p></div></content>
289
+ <updated>2012-06-23T15:45:50-07:00</updated>
290
+ </entry>
291
+
292
+ <entry>
293
+ <id>tag:intertwingly.net,2004:3296</id>
294
+ <link href="/blog/2012/06/07/Prefixed-no-more"/>
295
+ <link rel="replies" href="3296.atom" thr:count="0"/>
296
+ <title>Prefixed no more</title>
297
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="133" height="78" viewBox="0 0 133 78">
298
+ <path d="M23,72c-2,0-3,2-5,2c-1-2,2-4,2-7c-3,0-4,4-6,4c1-6,9-12,4-12c0,0-10,7-11,6c2-2,10-14,7-14c-1,0-7,4-9,4c0-2,9-10,10-11c2,0,3-2,2-3c-5,0-11,8-15,6l2-2c1-1,16-14,16-16c-3-2-13,6-18,6c22-24,38-33,47-35c7,0,14,2,21,3c0,3,12-1,13-1c5,0,9,4,11,8c0,1,0,2,0,4c3,11,31,7,35,19c0,5,1,9,2,14c-2,4-2,12-6,13c-4,1-4,1-4,1c-3,2-7,5-10,6c0,0-16-6-20-3c-12,4-16,8-19,20l-49-3"></path>
299
+ <path fill="#FFF" d="M86,22l-1-2h3v2h-2M83,19l-2,1l-1-2h2l1,1M122,57l-1-2c-1,0-1,1-3,1c0-1,0-3,0-4h2l1,2c1-1,2-1,3-1c1,1,1,2,0,3l-2,1M113,56c0-1,0-2,0-3c0-1,1-2,3-2c0,4,0,4-3,5M109,55c0-1-1-3,0-4h2c1,2,0,4-2,4M106,54l-2-2c-1,0-2,1-3,0c-1,0-1-2,0-4c1,0,2,0,3,1v2c1,0,2-1,3-1c1,0,0,2,0,3l-1,1M96,50c-2-1-1-2-1-4c2,0,3,0,4,2c-1,1-2,2-3,2"></path>
300
+ <path fill="#ED1C24" d="M40,75v-2c-2,0-9,2-9-2c0-2,5-8,3-8c-3-6-7-11-10-17c2-1,0-3,2-6c3-1,2,4,5,3c-4-17,5-22,5-22c-3,0-4,0-6,1c1-7,11-14,17-15c5-1,15-3,18,2c0,1-1,2-1,3c4,0,10-4,15-5c2-1,4-1,7,0l1,2c-7-3-17,3-23,6c-1,0-2,1-3,1l1,1c3,1,4,2,8,2c1,1,2,2,3,3c1,1,2,2,3,2c0-2,0-2-1-4c1-2-1-3,2-5c2,0,2,1,3,1c-4,4-2,8,10,9c1,0,3,1,3-2c-2,0-2-2-2-3l2,1c1,3,27,7,31,12c1,2,0,3-4,5c0,2,2,5,3,6l2-2l1,1c0,2,0,3,0,5v1c-1,0-2,0-3,0c-4-1-9-1-13-1c-11-5-25-16-36-20c-2-1-1-1-4-1c0,2,1,2,3,3c3,4,6,6,5,11l-1,2c-4,0-1-8-4-9c-10,8,5,25,13,20c-4-2-4-4-4-5c10,5,31,10,33,11c0,1-4,1-4,2c-5,1-13-2-17-4c-5-1-11,7-22,4c-2-1-13-8-15-8c0,4,9,12,11,13l0,2c-2,2-5,5-5,7"></path>
301
+ <path d="M80,24c3,1,11,4,9,5c-3,0-8,0-9-3v-2m-36-4l-2,2c0-1,1-3,1-3c3-6,9-8,14-7l0,1c-8,2-6,12-7,12c-2-1-3-5-6-5m0,34c0-6-8-17,3-22c1,0-2,15,7,19v2c-2,0-3,0-5,0c-1-2-1-1-2-1c0,2,1,5,1,7c-1-1-3-3-4-5m14-26c0-2-2-3,0-4c2,0,3-2,3-4c2,0,5,2,6,3c0,2-1,2-2,4c1,2,1,2,1,4h-1c-2,0-8-1-8,1c-2,0-3,0-5,0c-1-1,1-2,1-3c2,0,3-1,5-1"></path>
302
+ </svg>
303
+ <p>Firefox 13 for developers: <em>Support for <a href="https://developer.mozilla.org/en/CSS/border-radius"><code>-moz-border-radius*</code></a>  and <a href="https://developer.mozilla.org/en/CSS/box-shadow"><code>-moz-box-shadow</code></a> has been removed. Authors should use unprefixed <code>border-radius</code> or <code>box-shadow</code> instead. See <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=693510">bug 693510</a></em></p>
304
+ <p>+1</p></div></content>
305
+ <updated>2012-06-07T05:33:07-07:00</updated>
306
+ </entry>
307
+
308
+ <entry>
309
+ <id>tag:intertwingly.net,2004:3295</id>
310
+ <link href="/blog/2012/05/29/Twitter"/>
311
+ <link rel="replies" href="3295.atom" thr:count="0"/>
312
+ <title>Twitter -= #!</title>
313
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" fill='black' xmlns='http://www.w3.org/2000/svg' width="95" height="105" viewBox="0 0 95 105">
314
+ <path d='M75,75h-21l-6,28h-10l6-28h-21l-6,28h-10l6-28h-11v-10h13l5-25h-18v-10h20l6-28h10l-6,28h21l6-28h10l-6,28h12v10h-14l-5,25h19zM51,40h-21l-5,25h21z'></path>
315
+ <path d='M93,25l-3,52h-8l-4-52v-22h15zM93,101h-14v-13h14z'></path>
316
+ </svg>
317
+ <a href="http://engineering.twitter.com/2012/05/improving-performance-on-twittercom.html"><cite>Dan Webb</cite></a>: <em>The first thing that you might notice is that permalink URLs are now simpler: they no longer use the hashbang (#!). While hashbang-style URLs have a <a href="http://danwebb.net/2011/5/28/it-is-about-the-hashbangs">handful of limitations</a>, our primary reason for this change is to improve initial page-load performance.</em></div></content>
318
+ <updated>2012-05-29T14:50:26-07:00</updated>
319
+ </entry>
320
+
321
+ <entry>
322
+ <id>tag:intertwingly.net,2004:3294</id>
323
+ <link href="/blog/2012/04/29/WebSocket-Demos"/>
324
+ <link rel="replies" href="3294.atom" thr:count="0"/>
325
+ <title>WebSocket Demos</title>
326
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
327
+ <path d="M4,14h92" stroke="#4682b4" stroke-width="5"></path>
328
+ <text x="50" y="90" font-size="90" fill="#5f9ea0" font-family="serif" text-anchor="middle"><![CDATA[W]]></text>
329
+ </svg>
330
+ <p><a href="https://github.com/rubys/wunderbar/blob/master/demo/chat.rb">chat</a> implements a shared textarea field across multiple clients.  Demonstrates bi-directional communication.</p>
331
+ <p><a href="https://github.com/rubys/wunderbar/blob/master/demo/diskusage.rb">diskusage</a> is more typical of my usage.  The <code>du</code> command produces tabular output that the user may want to sort different ways and yet is may take considerable time to complete.</p></div></content>
332
+ <updated>2012-04-29T18:33:49-07:00</updated>
333
+ </entry>
334
+
335
+ <entry>
336
+ <id>tag:intertwingly.net,2004:3293</id>
337
+ <link href="/blog/2012/04/24/Wunderbar-on-Rails"/>
338
+ <link rel="replies" href="3293.atom" thr:count="0"/>
339
+ <title>Wunderbar on Rails</title>
340
+ <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>Usage: add <code>wunderbar</code> and <code>nokogiri</code> to your <code>Gemfile</code> and run <code>bundle install</code>.  Template extensions supported are <code>_html</code> and <code>_json</code>.  Examples: <a href="https://github.com/rubys/wunderbar/blob/master/test/views/rails_test/index.html._html">view</a>, <a href="https://github.com/rubys/wunderbar/blob/master/test/views/layouts/application.html._html">layout</a>, <a href="https://github.com/rubys/wunderbar/blob/master/test/views/rails_test/index.json._json">json</a>.</p>
341
+ <p>Note that as Rails layouts and views are predicated on the assumption that output is produced by concatenating text, one must use <code>_ yield</code> instead of simply <code>yield</code>.  On the plus side, Wunderbar will note when the first argument to a call which creates an element is <code>html_safe?</code> and will treat it as markup.</p></div></summary>
342
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
343
+ <path d="M4,14h92" stroke="#4682b4" stroke-width="5"></path>
344
+ <text x="50" y="90" font-size="90" fill="#5f9ea0" font-family="serif" text-anchor="middle"><![CDATA[W]]></text>
345
+ </svg>
346
+ <p>Usage: add <code>wunderbar</code> and <code>nokogiri</code> to your <code>Gemfile</code> and run <code>bundle install</code>.  Template extensions supported are <code>_html</code> and <code>_json</code>.  Examples: <a href="https://github.com/rubys/wunderbar/blob/master/test/views/rails_test/index.html._html">view</a>, <a href="https://github.com/rubys/wunderbar/blob/master/test/views/layouts/application.html._html">layout</a>, <a href="https://github.com/rubys/wunderbar/blob/master/test/views/rails_test/index.json._json">json</a>.</p>
347
+ <p>Note that as Rails layouts and views are predicated on the assumption that output is produced by concatenating text, one must use <code>_ yield</code> instead of simply <code>yield</code>.  I have noticed that this may lose blank lines in the process, which apparently is a <a href="http://groups.google.com/group/nokogiri-talk/browse_thread/thread/d332456737253631?pli=1">known</a> <a href="https://github.com/tenderlove/nokogiri/issues/575">issue</a> with Nokogiri.  Not a problem if the layout is erb, but then you lose the unified indentation that you get if you have a layout using <code>_html</code>.</p>
348
+ <p>On the plus side, Wunderbar will note when the first argument to a call which creates an element is <code>html_safe?</code> and will treat it as markup.  An example of where this is useful would be in the <code>_td link_to</code> calls below. </p>
349
+ <pre class="code">_h1_ 'Listing products'
350
+
351
+ _table do
352
+ _tr do
353
+ _th 'Title'
354
+ _th
355
+ _th
356
+ _th
357
+ end
358
+
359
+ @products.each do |product|
360
+ _tr_ do
361
+ _td product.title
362
+ _td link_to 'Show', product
363
+ _td link_to 'Edit', edit_product_path(product)
364
+ _td link_to 'Destroy', product, confirm: 'Are you sure?', method: :delete
365
+ end
366
+ end
367
+ end
368
+
369
+ _br_
370
+
371
+ _ link_to 'New Product', new_product_path</pre></div></content>
372
+ <updated>2012-04-24T14:12:59-07:00</updated>
373
+ </entry>
374
+
375
+ <entry>
376
+ <id>tag:intertwingly.net,2004:3292</id>
377
+ <link href="/blog/2012/04/12/Wunderbar-now-does-Sinatra"/>
378
+ <link rel="replies" href="3292.atom" thr:count="2" thr:updated="2012-04-22T09:44:27-07:00"/>
379
+ <title>Wunderbar now does Sinatra</title>
380
+ <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p><a href="https://github.com/rubys/wunderbar/blob/master/demo/hellosinatra.rb">Demo</a></p>
381
+ <p>The result is a lot like <a href="http://markaby.rubyforge.org/">Markaby</a>, except you get to be/have to be explicit when you are creating a tag.  In this demo, there is no logic, so the benefits of doing so are less clear, but include you being able to use tags that aren’t known to Markaby, like the ones that were <a href="http://www.w3.org/TR/html5-diff/#new-elements">added in HTML5</a>.  Both inline and views are supported, but support for layouts has yet to be added.</p>
382
+ <p>Future plans include <a href="http://rubyonrails.org/">Rails</a>.</p></div></summary>
383
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
384
+ <path d="M4,14h92" stroke="#4682b4" stroke-width="5"></path>
385
+ <text x="50" y="90" font-size="90" fill="#5f9ea0" font-family="serif" text-anchor="middle"><![CDATA[W]]></text>
386
+ </svg>
387
+ <p><a href="https://github.com/rubys/wunderbar/blob/master/demo/hellosinatra.rb">Demo</a></p>
388
+ <p>The result is a lot like <a href="http://markaby.rubyforge.org/">Markaby</a>, except you get to be/have to be explicit when you are creating a tag.  In this demo, there is no logic, so the benefits of doing so are less clear, but include you being able to use tags that aren’t known to Markaby, like the ones that were <a href="http://www.w3.org/TR/html5-diff/#new-elements">added in HTML5</a>.  Both inline and views are supported, but support for layouts has yet to be added.</p>
389
+ <p>While the demos require Ruby 1.9.2+ (the Hash syntax is nicer), the library works equally well with Ruby 1.8.7.</p>
390
+ <p>The progression is that you start from <a href="https://github.com/rubys/wunderbar/blob/master/demo/helloworld.rb">scripts</a> that you can run from the command line:</p>
391
+ <pre class="code">ruby helloworld.rb</pre>
392
+ <p>...can pass arguments to:</p>
393
+ <pre class="code">ruby helloword.rb name=Sam</pre>
394
+ <p>...can run as a standalone server:</p>
395
+ <pre class="code">ruby helloworld.rb --port=3004</pre>
396
+ <p>...can install as a CGI:</p>
397
+ <pre class="code">ruby helloworld.rb --install="/Library/WebServer/Documents/helloworld.cgi"</pre>
398
+ <p>.,. and can now run under Sinatra.  Future plans include <a href="http://rubyonrails.org/">Rails</a>.</p>
399
+ <p>There even is a <a href="https://github.com/rubys/wunderbar/blob/master/tools/web2script.rb">tool</a> that will reverse engineer an existing web page into a script.</p></div></content>
400
+ <updated>2012-04-12T17:12:31-07:00</updated>
401
+ </entry>
402
+
403
+ <entry>
404
+ <id>tag:intertwingly.net,2004:3291</id>
405
+ <link href="/blog/2012/04/02/Hacked"/>
406
+ <link rel="replies" href="3291.atom" thr:count="5" thr:updated="2012-05-20T03:28:03-07:00"/>
407
+ <title>Hacked</title>
408
+ <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>This site was hacked.  A reader of the site noted that Google’s <a href="https://www.google.com/search?q=site%3Aintertwingly.net">index of this site</a> had been co-opted by dubious pharmaceutical offerings.  I’ll gladly thank that individual publicly if they give me permission to do so; but my email reply got bounced as spam.</p>
409
+ <p>The immediate culprit was the addition of the following lines to a number of <code>.htaccess</code> files</p></div></summary>
410
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
411
+ <g stroke="#000" stroke-linejoin="round">
412
+ <path fill="#DDD" d="M27,42c-8-53,55-53,47,0h-8 c10-41-40-41-30,0h-9z"></path>
413
+ <path fill="#CB9" d="M23,91v-50c18-3,36-2,55,0v50c-19,3-37,2-55,0z"></path>
414
+ <path fill="#EDA" d="M23,91v-50c18-3,36-2,55,0z"></path>
415
+ <path fill="#A87" d="M78,41v50c-19,3-37,2-55,0z"></path>
416
+ </g>
417
+ <path fill="#EEE" d="M30,21c5-10,7-17,23-16c-10,0-18,14-23,16"></path>
418
+ <path fill="#CB9" d="M78,41c-50,4-50,0-55,50c50-5,50,0,55-50z"></path>
419
+ <path fill="#000" d="M46,77h10l-3-11a6,6,0,1,0-5,0z"></path>
420
+ </svg>
421
+ <p>This site was hacked.  A reader of the site noted that Google’s <a href="https://www.google.com/search?q=site%3Aintertwingly.net">index of this site</a> had been co-opted by dubious pharmaceutical offerings.  I’ll gladly thank that individual publicly if they give me permission to do so; but my email reply got bounced as spam.</p>
422
+ <p>The immediate culprit was the addition of the following lines to a number of <code>.htaccess</code> files:</p>
423
+ <pre class="code">&lt;IfModule mod_rewrite.c&gt;
424
+ RewriteEngine On
425
+ RewriteCond %{HTTP_USER_AGENT} (google|yahoo) [OR]
426
+ RewriteCond %{HTTP_REFERER} (google|aol|yahoo)
427
+ RewriteCond %{REQUEST_URI} /$ [OR]
428
+ RewriteCond %{REQUEST_FILENAME} (html|htm|php)$ [NC]
429
+ RewriteCond %{REQUEST_FILENAME} !common.php
430
+ RewriteRule ^.*$ /common.php [L]
431
+ &lt;/IfModule&gt;</pre>
432
+ <p>I removed those lines, as well as the <code>common.php</code> file, and scanned any and all php files on my site.  I saw the addition of lines such as the following:</p>
433
+ <pre class="code">$FYAqxDo='p'.'r'. 'eg_repl'. 'ace';...
434
+ $IHxWfs=str_rot13('cert_ercynpr');...
435
+ $DcNZVHCi="eW6DLAlbeAki"^"...
436
+ $LYDmvYopCKSSSGcfCVNpsskU='ba'.'se64_'.'deco'.'de'...</pre>
437
+ <p>I had old (vintage 2006) installations of PHP-openid-1.2.1 and PHP-yadis-1.0.2 that I am tentatively assuming were the ports of initial entry.</p>
438
+ <p>I also wiped my .ssh directory.  It has a private key there that was generated for this site that presumably was legitimate, but unused by me and now presumed compromised.  I never initiate sessions from this host, nor do I have any passwords saved there, so any damage caused was isolated.</p>
439
+ <p>I do daily backups of my site, which I keep for a week; as well as monthly backups that I basically keep forever.  In addition, as I recently <a href="http://intertwingly.net/blog/2012/02/13/On-The-Move">migrated hosts</a>, I have a hot backup.</p>
440
+ <p>The PHP hacks were done after I migrated but before March 1st.  The htaccess hacks were done over a week ago, but after March 1st.</p>
441
+ <p>Over the next few days, I’ll be looking at diffs of different snapshots of my site contents to see if there is anything else I missed.</p></div></content>
442
+ <updated>2012-04-02T04:16:43-07:00</updated>
443
+ </entry>
444
+
445
+ <entry>
446
+ <id>tag:intertwingly.net,2004:3290</id>
447
+ <link href="/blog/2012/04/01/Improved-Wunderbar-JSON-support"/>
448
+ <link rel="replies" href="3290.atom" thr:count="0"/>
449
+ <title>Improved Wunderbar JSON support</title>
450
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
451
+ <path d="M4,14h92" stroke="#4682b4" stroke-width="5"></path>
452
+ <text x="50" y="90" font-size="90" fill="#5f9ea0" font-family="serif" text-anchor="middle"><![CDATA[W]]></text>
453
+ </svg>
454
+ <p>I’ve integrated <a href="https://github.com/rails/jbuilder">jbuilder</a> like functionality into <a href="https://github.com/rubys/wunderbar#readme">Wunderbar</a>.  Key differences?  A DSL that doesn’t suck, and output that isn’t ugly.</p>
455
+ <p>To harsh?  You be the judge.  Compare <a href="https://github.com/rails/jbuilder/blob/master/test/jbuilder_test.rb#L176">jbuilder</a> ("json dot bar json bar json dot child bang") vs <a href="https://github.com/rubys/wunderbar/blob/master/test/test_jbuilder.rb#L154">Wunderbar</a> ("underbar underbar underbar underbar").</p>
456
+ <p>As to the output?  Don’t be fooled by the jbuilder <a href="https://github.com/rails/jbuilder#readme">readme</a>.  In actuality is no unnecessary whitespace in the output.  That’s good if you are bandwidth limited.  Not so good when viewing the XHR traffic via firebug...</p></div></content>
457
+ <updated>2012-04-01T05:57:41-07:00</updated>
458
+ </entry>
459
+
460
+ <entry>
461
+ <id>tag:intertwingly.net,2004:3289</id>
462
+ <link href="/blog/2012/03/28/Keeping-it-on-the-Rails"/>
463
+ <link rel="replies" href="3289.atom" thr:count="0"/>
464
+ <title>Keeping it on the Rails</title>
465
+ <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>It is increasingly becoming the case that <a href="http://pragprog.com/book/rails4/agile-web-development-with-rails">Agile Web Development with Rails</a> is being actively co-developed with <a href="http://rubyonrails.org/">Rails</a> itself.</p>
466
+ <p>While <a href="http://intertwingly.net/projects/dashboard.html">my tests</a> have been an <a href="https://github.com/rails/rails/blob/master/RELEASING_RAILS.rdoc">official part of the release process</a> for a long time now, yesterday’s release of <a href="http://weblog.rubyonrails.org/2012/3/27/ann-rails-3-2-3-rc1-has-been-released/">3.2.3RC1</a> provides a number of examples that illustrate this.</p>
467
+ <p>The intent is to prove an updated to the eBook free of charge which incorporates the necessary changes, either concurrent with the final release of 3.2.3 or shortly thereafter.</p></div></summary>
468
+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="100" height="100" viewBox="0 0 1000 1000">
469
+
470
+ <!-- 5 -->
471
+ <path d='M160,560c2-6-2-13-6-17l-6-9c-104-164,58-356,234-305c59,18,119,63,158,116c33,45,49,95,53,140c8,87-16,169-62,219c0,0-22,24,8,42c28,16,112-18,152-163c37-132-50-403-312-455c-190-37-302,124-304,268c0,58,30,125,63,159c14,14,21,11,22,5' fill='#17733B'></path>
472
+ <radialGradient cx='651' cy='363' id='r5g1' r='257' gradientUnits='userSpaceOnUse'>
473
+ <stop offset='0' style='stop-color:#E0EECF'></stop>
474
+ <stop offset='1' style='stop-color:#17753C'></stop>
475
+ </radialGradient>
476
+ <path d='M581,733c-20,9-31-2-31-2c107-75,132-334-31-471c-159-133-277-83-327-52c0,0,36-73,145-76c61-2,229,40,314,213c99,202-1,327-22,352c-13,17-37,31-48,36' fill='url(#r5g1)'></path>
477
+ <radialGradient cx='477' cy='494' id='r5g2' r='247' gradientUnits='userSpaceOnUse'>
478
+ <stop offset='0' style='stop-color:#DAECCE'></stop>
479
+ <stop offset='1' style='stop-color:#17733B'></stop>
480
+ </radialGradient>
481
+ <path d='M562,675c44-90,66-232-27-346c-93-114-198-113-198-113s156-14,250,175c73,147-25,284-25,284' fill='url(#r5g2)'></path>
482
+
483
+ <!-- 1 -->
484
+ <path d='M593,219c4,5,12,4,18,4c3-1,7-1,11-1c194-9,279,228,147,354c-45,43-115,72-180,80c-55,6-106-6-147-25c-79-36-139-97-159-163c0,0-10-31-40-14c-29,16-41,106,64,213c96,98,375,159,551-42c127-146,44-324-80-397c-51-30-123-37-169-25c-20,5-21,12-16,16' fill='#821C35'></path>
485
+ <radialGradient cx='518' cy='742' id='r1g1' r='257' gradientUnits='userSpaceOnUse'>
486
+ <stop offset='0' style='stop-color:#F7A8A9'></stop>
487
+ <stop offset='0.7178' style='stop-color:#821C35'></stop>
488
+ </radialGradient>
489
+ <path d='M232,497c3-22,18-25,18-25c12,129,224,280,424,208c195-71,210-198,208-257c0,0,45,67-7,164c-29,53-149,177-342,164c-223-14-282-164-294-194c-7-20-8-48-7-60' fill='url(#r1g1)'></path>
490
+ <radialGradient cx='492' cy='526' id='r1g2' r='247' gradientUnits='userSpaceOnUse'>
491
+ <stop offset='0' style='stop-color:#F2A5B7'></stop>
492
+ <stop offset='1' style='stop-color:#821C35'></stop>
493
+ </radialGradient>
494
+ <path d='M293,510c55,83,167,173,312,149c146-24,197-115,197-115s-66,143-276,130c-164-11-233-164-233-164' fill='url(#r1g2)'></path>
495
+
496
+ <!-- 3 -->
497
+ <clipPath id="r3c">
498
+ <path d="M999,999 L558,370 c-30-50-40-50-70-84h-400v700z" opacity="0"></path>
499
+ </clipPath>
500
+ <g clip-path="url(#r3c)">
501
+ <path d='M677,766c-6,2-10,9-11,14c-2,3-4,7-5,11c-90,172-338,127-381-51c-14-60-5-135,21-195c23-51,58-89,95-115c71-50,154-71,220-56c0,0,32,7,33-28c0-33-71-88-217-51c-133,34-324,245-238,498c62,183,258,200,383,129c51-28,94-88,107-134c5-19-1-23-7-22' fill='#3564AF'></path>
502
+ <radialGradient cx='262' cy='440' id='r3g1' r='364' gradientUnits='userSpaceOnUse'>
503
+ <stop offset='0' style='stop-color:#EFF1F6'></stop>
504
+ <stop offset='1' style='stop-color:#3564AF'></stop>
505
+ </radialGradient>
506
+ <path d='M617,315c18,14,13,28,13,28c-118-54-355,54-392,263c-36,205,66,281,118,309c0,0-81,6-138-88c-32-51-79-217,28-378c125-186,283-162,316-157c21,3,45,16,55,23' fill='url(#r3g1)'></path>
507
+ <radialGradient cx='462' cy='525' id='r3g2' r='350' gradientUnits='userSpaceOnUse'>
508
+ <stop offset='0' style='stop-color:#EFF1F6'></stop>
509
+ <stop offset='1' style='stop-color:#3564AF'></stop>
510
+ </radialGradient>
511
+ <path d='M576,362c-100,6-234,58-286,195s1,228,1,228s-90-128,26-304c91-136,259-119,259-119' fill='url(#r3g2)'></path>
512
+ </g>
513
+
514
+ <!-- 6 -->
515
+ <radialGradient cx='528' cy='251' id='r6g1' r='277' gradientUnits='userSpaceOnUse'>
516
+ <stop offset='0' style='stop-color:#E2EFCF'></stop>
517
+ <stop offset='1' style='stop-color:#14743B'></stop>
518
+ </radialGradient>
519
+ <path d='M804,494c-16,4-38-12-43-43c-17-99-90-288-283-364c-176-69-252-6-252-6c-10,4-6-12,2-18c7-7,105-112,334-13c217,94,278,309,272,383c0,10-3,24-4,29c-5,21-15,28-26,32' fill='url(#r6g1)'></path>
520
+ <radialGradient cx='748' cy='240' id='r6g2' r='312' gradientUnits='userSpaceOnUse'>
521
+ <stop offset='0' style='stop-color:#E2EFCF'></stop>
522
+ <stop offset='1' style='stop-color:#14743B'></stop>
523
+ </radialGradient>
524
+ <path d='M800,488c-1-132-88-337-289-418c-193-78-256-19-256-19s73-91,293-4c208,82,265,267,278,321c12,52,4,94-4,108c-9,16-22,12-22,12' fill='url(#r6g2)'></path>
525
+ <radialGradient cx='634' cy='302' id='r6g3' r='185' gradientUnits='userSpaceOnUse'>
526
+ <stop offset='0' style='stop-color:#E2EFCF'></stop>
527
+ <stop offset='1' style='stop-color:#14743B'></stop>
528
+ </radialGradient>
529
+ <path d='M767,457c-16-90-50-158-87-212c-45-66-103-114-191-158c0,0,112,25,198,148c73,106,80,222,80,222' fill='url(#r6g3)'></path>
530
+
531
+ <!-- 4 -->
532
+ <path d='M298,243c12,11,9,38-15,58c-78,64-204,222-174,427c28,187,121,221,121,221c8,6-8,11-17,8s-150-35-178-283c-27-235,128-396,195-428c9-4,22-9,27-10c21-6,32-2,41,7' fill='#3564AF'></path>
533
+ <radialGradient cx='107' cy='418' id='r4g1' r='441' gradientUnits='userSpaceOnUse'>
534
+ <stop offset='0' style='stop-color:#D3DCE8'></stop>
535
+ <stop offset='1' style='stop-color:#3564AF'></stop>
536
+ </radialGradient>
537
+ <path d='M295,248c-114,68-248,245-217,459c29,207,111,232,111,232s-115-18-150-251c-33-221,99-364,140-402c38-36,78-50,95-50c18,0,21,12,21,12' fill='url(#r4g1)'></path>
538
+ <radialGradient cx='217' cy='485' id='r4g2' r='261' gradientUnits='userSpaceOnUse'>
539
+ <stop offset='0' style='stop-color:#F0F1F9'></stop>
540
+ <stop offset='1' style='stop-color:#3564AF'></stop>
541
+ </radialGradient>
542
+ <path d='M285,293c-70,59-112,121-141,182c-34,71-47,145-41,243c0,0-34-109,29-244c55-117,153-181,153-181' fill='url(#r4g2)'></path>
543
+
544
+ <!-- 2 -->
545
+ <radialGradient cx='661' cy='712' id='r2g1' r='275' gradientUnits='userSpaceOnUse'>
546
+ <stop offset='0' style='stop-color:#E89EB0'></stop>
547
+ <stop offset='1' style='stop-color:#821C35'></stop>
548
+ </radialGradient>
549
+ <path d='M329,810c4-16,28-27,58-16c94,35,294,66,457-63c147-118,131-216,131-216c1-10,13,2,15,11c2,10,44,147-156,296c-190,141-407,87-468,45l-23-18c-15-16-17-27-14-39' fill='url(#r2g1)'></path>
550
+ <radialGradient cx='576' cy='888' id='r2g2' r='312' gradientUnits='userSpaceOnUse'>
551
+ <stop offset='0' style='stop-color:#CFA2AD'></stop>
552
+ <stop offset='1' style='stop-color:#821C35'></stop>
553
+ </radialGradient>
554
+ <path d='M335,810c116,64,336,92,506-42c164-128,145-212,145-212s43,108-142,255c-175,139-365,96-418,80c-50-15-83-42-91-57c-9-16,0-24,0-24' fill='url(#r2g2)'></path>
555
+ <radialGradient cx='579' cy='758' id='r2g3' r='185' gradientUnits='userSpaceOnUse'>
556
+ <stop offset='0' style='stop-color:#DE95A7'></stop>
557
+ <stop offset='1' style='stop-color:#821C35'></stop>
558
+ </radialGradient>
559
+ <path d='M379,796c86,31,161,36,227,31c79-6,150-32,232-87c0,0-78,85-226,98c-129,11-233-42-233-42' fill='url(#r2g3)'></path>
560
+
561
+ </svg>
562
+ <p>It is increasingly becoming the case that <a href="http://pragprog.com/book/rails4/agile-web-development-with-rails">Agile Web Development with Rails</a> is being actively co-developed with <a href="http://rubyonrails.org/">Rails</a> itself.</p>
563
+ <p>While <a href="http://intertwingly.net/projects/dashboard.html">my tests</a> have been an <a href="https://github.com/rails/rails/blob/master/RELEASING_RAILS.rdoc">official part of the release process</a> for a long time now, yesterday’s release of <a href="http://weblog.rubyonrails.org/2012/3/27/ann-rails-3-2-3-rc1-has-been-released/">3.2.3RC1</a> provides a number of examples that illustrate this.</p>
564
+ <p>Within hours after the release, I got an excited IM from Santiago Pastorino that my tests were failing.  In particular, the failure was thus:</p>
565
+ <pre class="code">rake db:migrate
566
+ rake aborted!
567
+ An error has occurred, this and all later migrations canceled:
568
+ uninitialized constant Arel::Relation
569
+ Tasks: TOP =&gt; db:migrate
570
+ (See full trace by running task with --trace)</pre>
571
+ <p>The root cause was quickly determined to be a recent change to <a href="https://github.com/rails/arel/commit/9978fc40a8a5a262670279129a335845ad647f48">arel</a>, and a number of corrective actions were promptly taken: first, <a href="https://github.com/rails/arel/commit/6e8d1587091e00a84ea24ab92d9e836c3c38bcb8">the change was backed out</a>, then <a href="https://github.com/rails/rails/commit/2fa7ccf7aee3696e99f1b528db848aff5a671f77">Rails 4.0 was updated</a> and <a href="https://github.com/rails/rails/commit/24208d9a8662e2e35afc9c64695c600b2e960418">Rails 3.2 was changed to point to a branch of arel</a>, and finally, the <a href="https://github.com/rails/arel/commit/d43ae586aab7092c6bf742609ff1dc3ebf6aff6a">original change was reapplied</a>.</p>
572
+ <p>The previous error that was caught was <a href="https://github.com/rails/rails/commit/b700153507b7d539a57a6e3bcf03c84776795051"> connection pool of new applications have size 1</a>.  This demonstrates the unique value that my tests bring to the table.  Outside of my tests, the bulk of the test of Rails is an impressive array of unit tests (which verify that the connection pool setting does what it is supposed to do), and real world testing (using applications with highly tuned configurations), and my tests.  Only the latter is effectively testing that the defaults provided actually work together to provide a viable configuration to use as a starter set for new applications.</p>
573
+ <p>One last example, this one shows the level cooperation involved.  The underlying security changes that were the raison d'être for the 3.2.3 release caused the following scenario to fail:</p>
574
+ <pre class="code">rails generate scaffold Product title:string
575
+ rake db:migrate
576
+ rake test</pre>
577
+ <p>The root cause was that the code generated as scaffolding used the very feature which is now being discouraged as it creates a security issue. The fix required both changes to Rails itself (to change the scaffolding generated) and to the scenario provided in the book (both in identifying the code that needs to be changed, and in the changes that need to be made).</p>
578
+ <p>The intent is to prove an updated to the eBook free of charge which incorporates the necessary changes, either concurrent with the final release of 3.2.3 or shortly thereafter.</p></div></content>
579
+ <updated>2012-03-28T13:44:13-07:00</updated>
580
+ </entry>
581
+
582
+ </feed>
583
+