<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Aymeric on Software</title>
  <link href="https://blog.barthe.ph/index.xml" rel="self"/>
  <link href="https://blog.barthe.ph/"/>
  <updated>2026-03-17T00:00:00+00:00</updated>
  <id>https://blog.barthe.ph/</id>
  <author>
    <name>Aymeric Barthe</name>
    <email>aymeric@barthe.ph</email>
  </author>
  <generator>Hugo -- gohugo.io</generator>  
  <entry>
    <title type="html"><![CDATA[The End of an Era]]></title>
    <link href="https://blog.barthe.ph/2026/03/17/the-end-of-an-era/"/>
    <id>https://blog.barthe.ph/2026/03/17/the-end-of-an-era/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2026-03-17T00:00:00+00:00</published>
    <updated>2026-03-17T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>Today marks the first time <strong>everything</strong> I host on the Internet has moved away from a dedicated Linux VPS.</p>
<p>This blog had moved to <a href="https://pages.cloudflare.com/">Cloudflare Pages</a> in 2022, and previously it had been hosted on a dedicated server provided by <a href="/2014/09/17/kimsufi-migration/">Kimsufi</a> and, before that, <a href="/2014/09/17/kimsufi-migration/">Dedibox</a>.</p>
<p>However, half a dozen sites and applications remained on that server. It ultimately took about four years to complete the transition. 😱</p>
<h2 id="why-not-a-vps">Why Not a VPS?</h2>
<p>Renting a dedicated server simply stopped making any economic sense. The underpowered machine that previously hosted this site cost €15 a month; a price point that had long ceased to be competitive.</p>
<p>You can host a collection of static HTML/CSS files at zero or near zero cost on either <strong>Cloudflare Pages</strong> or <strong>AWS Cloudfront/S3</strong>.</p>
<p>While SQL databases, PHP, docker images have their use, they always felt like an overkill for a simple blog or the kind of simple sites I was hosting. This blog, for instance, is just a collection of static files generated by the <a href="https://gohugo.io">Hugo</a> template generator.</p>
<h2 id="where-are-things-hosted-now">Where Are Things Hosted Now?</h2>
<p>It depends:</p>
<ul>
<li>
<p>Simple sites like this one are hosted on either Cloudflare Pages or AWS Cloudfront.</p>
</li>
<li>
<p>For public-facing sites, I converted some simple PHP or Ruby scripts to run on Cloudflare Workers/Pages and store their data in a <a href="https://developers.cloudflare.com/d1">D1 database</a> instead of self-hosting PostgreSQL. My usage is small enough to fit comfortably within the free tier.</p>
</li>
<li>
<p>Finally, I have run a few servers at home for over a decade. Some sites that were previously hosted on the VPS are now are served from home and put behind a <a href="https://developers.cloudflare.com/tunnel/">Cloudflare Tunnel</a>. A few are additionally gated behind <a href="https://developers.cloudflare.com/cloudflare-one/access-controls/policies/">Cloudflare Access</a>. Faster internet connections with Gigabit upload now makes this a viable option, at a fraction of the cost of a VPS.</p>
</li>
<li>
<p>The home sites all run in Docker containers, so moving or migrating them in the future should be easier. This also helps with the security aspect, as you would need to break out of containment to compromise the host.</p>
</li>
</ul>
<h2 id="why-did-it-take-so-long">Why Did It Take So Long?</h2>
<p>I made an historical mistake when I set up my first Linux servers. Initially, I set them up with little to no documentation&hellip; making migrating and rebuilding them a challenge.</p>
<p>Having learned from my mistakes, everything I host at home now follows the tenets of <a href="https://en.wikipedia.org/wiki/Infrastructure_as_code">infrastructure as code</a> religiously. The base system is installed automatically via Ansible, and every web application or site runs on top as low-privilege Docker containers. Installation, deployment, and updates are largely automated, and all changes are tracked in Git, which serves as both documentation and historical record.</p>
<p>In addition, recent advances in AI have made this setup even more useful: agentic LLMs do a reasonable job of maintaining the repository. They can also explain how things work when you invariably forget a decade later.</p>
<p>In fact, with Claude&rsquo;s help I was able to move the remaining sites that had been hosted on the Kimsufi VPS. For some of these, Claude also assisted with the conversion from Ruby/PHP-FPM/PostgreSQL to Cloudflare Workers and the D1 Database. All in all, four years of procrastinated drudge work and technical debt disappeared over the course of a couple of long evenings.</p>
<p>I may use a VPS again someday if the free or near-free services I rely on disappear, but I will make sure to have a clear exit plan in place.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Things I Learned in 2020]]></title>
    <link href="https://blog.barthe.ph/2021/01/09/year-2020-retrospective/"/>
    <id>https://blog.barthe.ph/2021/01/09/year-2020-retrospective/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2021-01-09T00:00:00+00:00</published>
    <updated>2021-01-09T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>Let&rsquo;s get the elephant out of the room: 2020 has been a very different kind of year because of the COVID-19 crisis. I am very fortunate that myself, my wife, our family and close friends have not been – so far – impacted in any meaningful way.</p>
<p>However, this blog post is not about COVID-19. In fact, I have been thinking of doing some kind of the yearly retrospective for the last couple of years. So here I am, starting one now, and trying to leave the COVID topic aside.</p>
<p>I do read a lot of development blogs. My interests in programming languages and technologies are varied and somewhat eclectic. The blogs I read range from the serious and in-depth analyses to more light-weight off the cough testimonies. Oftentimes, this is how I stumble on some interesting tool or a piece of technology which I may end up using months or years later. I am writing this blog post with the hope that it may be useful to someone else in the same manner.</p>
<h2 id="tldr">TL;DR</h2>
<p>So here are three things I have learned in 2020: <em><a href="https://www.terraform.io/">Terraform</a></em>, <em><a href="https://www.notion.so/">Notion</a></em> and I <em>somewhat improved my writing skills</em>.</p>
<h2 id="terraform">Terraform</h2>
<p>I had been aware of <a href="https://www.terraform.io/">Terraform</a> for some time. It is a tool born of the <em>infrastructure as code</em> methodology from DevOps. Unlike older solutions, which were historically rooted in <em>imperative</em> scripts such as <em>Chef</em> or <em>Puppet,</em> Terraform only supports the <em>declarative</em> approach. In other words, you describe the end state of the cloud infrastructure you want, and Terraform figures out <strong>which</strong> steps are necessary, if any, to bring the system in line with expectations.</p>
<p>Terraform is a cloud agnostic tool. I did not need a multi-cloud tool, so I had reservations in adopting Terraform over a first party solution like CloudFormation for AWS. Both tools play the same role and are declarative, but CloudFormation being a first party product, it has the advantage that it integrates better with the AWS stack. The reasoning is correct, but what I failed to appreciate is how poor and painful it was to use CloudFormation in practice. Terraform provides a much better experience:</p>
<ul>
<li>The description language of Terraform is less verbose and better designed than CloudFormation&rsquo;s. It feels like Terraform was designed to be read and written by humans, whereas CloudFormation looks like a <em>memory dump</em> transcribed into YAML or JSON.</li>
<li>The documentation of Terraform is excellent despite being a third party provider. Not that the AWS documentation is bad either.</li>
<li>The killer feature of Terraform is the ability to <em>refactor</em> re-usable code into modules. This is a very straightforward and <a href="https://www.terraform.io/docs/modules/index.html">well-documented</a> process. It compares infinitely better to the kind of hacks one would have to do with CloudFormation to achieve similar results.</li>
</ul>
<p>One of the drawbacks of Terraform is that the current state of the infrastructure is stored on a file locally, whereas a first party solution like CloudFormation can store the state in the cloud. Personally, I like having the state in a GIT repository and I find it somewhat reassuring.</p>
<p>I currently use Terraform to use all my AWS resources: Route 53 DNS entries, EKR Docker Registries and a handful of Amazon S3 buckets.</p>
<h2 id="notion">Notion</h2>
<p>I have been looking for a tool to take and organize notes. One of the many requirements was that the tool needed to be truly cross platform with support for macOS, Windows and iOS and features cloud syncing. In addition, I wanted a tool which can integrate very well with Markdown.</p>
<p>I essentially use Notion to collect links and information when I research a topic and to write design documents. I also adopted the practice of scientists who keep logs about their work. The draft of this blog post was also written in Notion first, before being exported as Markdown and published via Hugo.</p>
<p>I have been looking for a good note taking tool since 2019. I have looked at many and tried a handful. Even though I was aware of Notion for a long time, I was somewhat put off by it. I understood it could be used to publish things on the Internet and it had some kind of database features. Those features are not exactly something I cared for, so they acted as repulsive force, because I was worried about feature creep and unnecessary complexity. These thoughts were echoed by <em>CGP Grey</em> from <a href="https://www.relay.fm/cortex">Cortex</a>; so Notion was put to the back of the pile. How wrong was I!</p>
<p>The truth is that <a href="https://www.notion.so/">Notion</a> is still a pretty good way to take and organize textual notes. All the normal features from a Markdown editor are well supported, including syntax highlighting for code snippets, even though it uses a WYSIWYG editor. There are some useful additional features like the ability to use Callouts, Emojis or insert LaTeX formulas. The import and export of Markdown is not perfect but it is usable. I have used some of the advanced features like tables, databases and calendars and they are fine. The ability to publish a note as a public webpage on the Internet in one click has turned out to be surprisingly useful, especially since that page automatically updates when the source document in Notion is updated. And to top it all, it looks like my usage of the tool would fit in the <em>free tier</em> forever.</p>
<p>Although I am overall satisfied, Notion has some usability annoyances. Non standard key bindings and mouse control for text selection drive me mad. Occasionally, the WYSIWYG editor will require some non obvious combination of key strokes. But the main downside, by far, is that I am not in control of the data. The way information is stored on the file system or on Notion&rsquo;s servers is completely undocumented. The Notion API was <a href="https://github.com/kjk/notionapi">successfully reversed engineered</a>, but an <a href="https://www.notion.so/Does-Notion-have-an-API-I-can-use-4541b07a5caa46dba0026624646118c0">official Content API should be launching in 2021</a>. Until then, it seems like the official way to backup data is to <a href="https://www.notion.so/Back-up-your-data-1a8eb5bdfce34d19a6360fd015c0075f">Export the Workspace</a> as HTML or Markdown, but it is a lossy export. I am currently relying on exports but I hope to start using the upcoming Content API when it becomes available.</p>
<h3 id="notions-alternatives">Notion&rsquo;s Alternatives</h3>
<p>While researching a note taking tool, I stumbled on <a href="https://bear.app/">Bear</a>. It provides a native editing experience that I like more, but fewer features than Notion overall. The downside is that it is only supported on iOS and macOS (no Windows / no Web). But if that&rsquo;s not a deal breaker, it is an excellent tool. I also stumbled on <a href="https://typora.io/">Typora</a> which is a very good Markdown Editor, that I use regularly with the <a href="https://theme.typora.io/theme/Ursine/">Ursine theme</a>. I don&rsquo;t use Notion&rsquo;s project management features very much. For very simple lists of things to do, I tend to rely on the much simpler <a href="https://to-do.microsoft.com/tasks/">Microsoft To Do</a>.</p>
<h2 id="improved-written-communication">Improved Written Communication</h2>
<p>I have worked from home for most of the year. Even though there are some obvious advantages like avoiding the daily commute grind, the lack of face to face communication has many drawbacks that cannot be fixed by video conferencing.</p>
<p>One of the obvious consequences is that all but trivial communications (which can be done via instant messaging with tools like Slack) must be formalized into a meeting or an exchange of e-mails. Consequently, I have found myself reading and writing more prose than ever before.</p>
<p>The trick with written communication is that you need to be as clear and non-ambiguous as possible while remaining concise. Clarity is very important. If one of your colleagues were to misinterpret one of your ideas, you an easily end up exchanging a few e-mails just to clear things out. This translates into wasted time, and some frustration, for everybody involved. If you had been in the same room, you would have been able to intervene sooner and save that time. Making things clear can involve some amount of repetition or rephrasing, or showing examples. Whenever possible I try to show a diagram or a table instead of prose.</p>
<p>The goal of clarity needs to counter-balanced by the necessity to be short and concise. Long and winding emails are boring to read, so people will just skim them or put them off until the last minute. I know, I am guilty of the same thing. For communication to have an impact, it needs to be read, therefore it needs to be short.</p>
<p>Through repetition, I would like to believe that I have somewhat achieved a basic level of competency at written communication. I am better at it than last year, and definitely better than ten years ago, as plainly demonstrated by the earliest – cringeworthy – posts on this very blog.</p>
<p>As an aside, I would like to recommend &ldquo;<a href="https://www.amazon.co.uk/Have-Eaten-Grandma-Gyles-Brandreth/dp/0241352630">Have You Eaten Grandma?</a>&rdquo;, a book which is very humorous way to review the basic rules of grammar and punctuation in British English. (Yes this blog is written in American English except for rule about <a href="https://proofreadmyessay.co.uk/writing-tips/differences-british-american-punctuation/">punctuation within quotes or brackets</a>.)</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[My Firefox Setup]]></title>
    <link href="https://blog.barthe.ph/2020/11/06/firefox-setup/"/>
    <id>https://blog.barthe.ph/2020/11/06/firefox-setup/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2020-11-06T00:00:00+00:00</published>
    <updated>2020-11-06T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<h2 id="why-i-use-firefox">Why I Use Firefox</h2>
<p>I have used Firefox since the very beginning on Windows. I stuck with it even in the early 2010s, when it clearly lagged behind Chrome, because of a profound distaste for Chrome&rsquo;s GUI and Google&rsquo;s business practices. In my opinion, Firefox Quantum released in 2017, has addressed most of the performance gap between Chrome and Firefox. In many cases, Firefox feels even snappier than Chrome. I still use Chrome every day, but mostly as my &ldquo;debugging&rdquo; browser for web development, my &ldquo;translator&rdquo; and, very rarely, my &ldquo;Flash player&rdquo;.</p>
<p>On macOS, I have used Safari since the beginning. However, as of macOS 10.15, I was forced to switch to Firefox when Apple decided to disable the <a href="https://developer.apple.com/documentation/safariextensions">legacy JavaScript API</a> for extensions. The new extension model involves installing an App from the App Store. The &ldquo;container&rdquo; App provides an <a href="https://developer.apple.com/documentation/safariservices/safari_app_extensions">XPC extension</a> which runs inside the Safari browser. This is arguably more efficient than JavaScript extensions, but this choice makes it very difficult for developers to port existing extensions to Safari. The &ldquo;container&rdquo; app also provides a much greater attack surface than a mere JavaScript extension.</p>
<h2 id="content-blocking-extensions">Content Blocking Extensions</h2>
<p>The move to the new extension API in Safari <a href="https://github.com/el1t/uBlock-Safari/issues/158">killed support</a> for my favorite extension: <a href="https://en.wikipedia.org/wiki/UBlock_Origin">uBlock Origin</a>.</p>
<p>For performance and security reasons, Apple decided to no longer let extensions intercept HTTP requests in Safari. Instead, extensions had to migrate to the newer <a href="https://developer.apple.com/documentation/safariservices/creating_a_content_blocker">content blocking API</a> introduced in 2015, as part of <a href="https://www.macworld.com/article/2986298/how-to-enable-safari-ad-blockers-in-ios-9.html">iOS 9</a>. This API requires extensions to provide a fixed list of blocking rules, identical for all sites. This is nowhere near as effective as uBlock Origin&rsquo;s dynamic rules. However, the privacy advantage is undeniable, since extension no longer have access to the sensitive information that can be inferred from intercepting all HTTP requests.</p>
<p>This debate about content blocking extensions was recently revived by the upcoming transition to <a href="https://www.theregister.com/2020/10/15/microsoft_adopting_google_chromes_controversial/">Manifest v3 for Google Chrome extensions</a>. Google is pushing for a similar approach to Apple&rsquo;s with their new <a href="https://developer.chrome.com/extensions/declarativeWebRequest">declarativeWebRequest API</a>. They also argue that their new API would be <a href="https://blog.chromium.org/2019/06/web-request-and-declarative-net-request.html">more efficient and safer</a>. However, I am somewhat skeptical, since the old <a href="https://developer.chrome.com/extensions/webRequest">webRequest API</a> will be kept as part of manifest v3 <em>minus</em> the ability to block requests. In other words, Google plans to cripple content blocking extensions <a href="https://github.com/uBlockOrigin/uBlock-issues/issues/338">like uBLock Origin</a> but other extensions would still be able to spy on users by sniffing requests. The old webRequest blocking API will also be kept for their &ldquo;Enterprise customers&rdquo;, which I interpret as Google&rsquo;s partial acknowledgement that their new API does… indeed… suck.</p>
<h2 id="my-firefox-extensions">My Firefox Extensions</h2>
<p>This is the list of my Firefox Extensions:</p>
<ul>
<li>
<p><strong><a href="https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/">uBlock Origin</a></strong>. As previously mentioned, I ditched Safari in favor of Firefox because of this extension. It is the best and fastest ad blocker. It can also be configured to block any kind of content on the spot. Content blocking extensions not only make web pages render better and faster, but also more <a href="https://www.malwarebytes.com/malvertising/">securely</a> since legitimate ad networks have been tricked many times in the past into distributing malware.</p>
</li>
<li>
<p><strong><a href="https://www.eff.org/https-everywhere">HTTPS Everywhere</a></strong>. This extension ensures that you always use <code>HTTPS</code> for a site that support it, even though you may be following an <code>HTTP</code> link. It is becoming less of an issue, but still worth having.</p>
</li>
<li>
<p><strong><a href="https://addons.mozilla.org/en-US/firefox/addon/cookie-autodelete/#:~:text=%20Cookie%20AutoDelete%20by%20CAD%20Team%20%201,Watch%20those%20unused%20cookies%20disappear%20%3A%29%20More%20">Cookie AutoDelete</a></strong>. This extension can be configured to delete cookies and local storage data for all visited sites, except for a short list of exceptions. This is more aggressive than the built-in <em>delete cookies when Firefox is closed option</em> since the extension will activity attempt to delete cookies while Firefox is running. I would recommend turning off notifications, since this extension is a bit too proud of itself for deleting cookies.</p>
</li>
<li>
<p><strong><a href="https://www.i-dont-care-about-cookies.eu/">I don&rsquo;t care about cookies</a></strong>. This extension automatically discards the <a href="https://techcrunch.com/2019/08/10/most-eu-cookie-consent-notices-are-meaningless-or-manipulative-study-finds/">annoying EU Cookie Banners</a> that seem to spread around the Internet like the plague. I really do not need know about your cookies, nor care, since they will soon be deleted (see above). The only downside of this extension is that it does occasionally break sites. When this occurs, disable the extension for the site, click on the banner, and move on.</p>
</li>
<li>
<p><strong><a href="https://addons.mozilla.org/en-US/firefox/addon/darkreader/">Dark Reader</a></strong>. I use macOS built-in feature to automatically switch to <a href="https://support.apple.com/en-gb/HT208976">dark mode</a> at night. The problem is that many web pages do not implement dark mode and carry on using very light backgrounds. Dark Reader attempts to automatically switch the pages to have <em>light text on dark background</em>. It usually does a decent job and it can be tweaked for more challenging sites. The only downside is that it seems unable to detect sites that natively support dark mode via the <code>prefers-color-scheme</code> media query.</p>
</li>
<li>
<p><strong><a href="https://addons.mozilla.org/en-US/firefox/addon/multi-account-containers/">Firefox Multi-Account Containers</a></strong>. This extension creates boundaries for cookies and local storage data. It is conceptually similar to running different tabs in the browser under different user profiles. I use this extension to segment sites where I need to remember cookies. For personal use the obvious example is social media. I also use the extension to keep multiple Google Classroom accounts simultaneously opened, to track the progress of my children&rsquo;s online learning. I also use dedicated containers for work.</p>
</li>
<li>
<p><strong><a href="https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/">Tampermonkey</a></strong>. This extension allows you to run a custom scripts to modify the appearance and functionality of any sites. I use it to improve some internal web applications we use at work. I also use it to make Google search results look <a href="https://greasyfork.org/en/scripts/395257-better-google">the same as before</a>. It is also trivial to <a href="https://greasyfork.org/en/scripts/2686-remove-ads-from-google-search/code">remove ads from Google search results</a>.</p>
</li>
<li>
<p><strong><a href="https://www.instapaper.com/">Instapaper</a></strong>. I use Instaper to quickly save interesting web pages I do not have the time to read <em>right away</em>. I can go back to them <em>later</em> in the evening and read them on my phone.</p>
</li>
<li>
<p><strong><a href="https://www.lastpass.com/">Lastpass</a></strong> is my password manager. It works and it is cross-platform. I am very convinced one needs to use a password manager, but there are many things in Lastpass that annoy me. I may change in the future.</p>
</li>
</ul>
<h2 id="configuration-tweaks">Configuration Tweaks</h2>
<p>I use the following configuration tweaks to improve privacy without resorting to a VPN:</p>
<ul>
<li>
<p><strong><a href="https://support.mozilla.org/en-US/kb/firefox-dns-over-https">Enable DNS over HTTPS</a></strong> (aka DoH). This feature is normally turned on by default, except if you <a href="https://www.theregister.com/2019/09/24/mozilla_backtracks_doh_for_uk_users/">live in the UK</a> as it frustrates the government surveillance efforts (see <a href="https://en.wikipedia.org/wiki/Draft_Communications_Data_Bill">Snoopers&rsquo; Charter</a>) and the &ldquo;voluntary&rdquo; porn filters run by ISPs. The UK Internet Service Providers Association has named Firefox an <a href="https://www.ispreview.co.uk/index.php/2019/07/ispa-pulls-uk-internet-villain-category-over-mozilla-doh-fallout.html">Internet Villain</a> over the issue.</p>
</li>
<li>
<p><strong><a href="https://blog.cloudflare.com/encrypt-that-sni-firefox-edition/">Turn on Encrypted SNI support</a></strong> (aka eSNI). This ensures that Firefox does not leak the name of the visited sites in the clear, when doing a TLS handshake. By default, over <em>plain old SNI</em>, the domain name is sent in plain text <em>before</em> the encrypted connection is established.</p>
</li>
</ul>
<p>You can verify the state of DoH and eSNI using this convenient <a href="https://www.cloudflare.com/ssl/encrypted-sni/">Test Page from Cloudflare</a>.</p>
<p>Alternatively, if you live in the UK, you could also try to visit the <a href="https://en.wikipedia.org/wiki/List_of_websites_blocked_in_the_United_Kingdom#Court_ordered_implementations_targeting_copyright_and_trademark_infringement">top banned site</a> which cannot effectively be blocked by ISPs when using DoH and eSNI. Since the site is hosted by CLoudFlare, IP blocking would result in massive over blocking of thousands of legitimate sites.</p>
<h2 id="the-future-is-uncertain">The Future is Uncertain</h2>
<p>Unfortunately, it looks like my current set up is living on borrowed times. Mozilla laid off the majority of the Servo team <a href="https://www.zdnet.com/article/mozilla-lays-off-250-employees-while-it-refocuses-on-commercial-products/">last August</a>, which begs the question about the future of the Firefox, since Servo backported a lot of their <a href="https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-engine-quantum-css-aka-stylo/">technologies</a> to make Firefox Quantum possible. The <a href="https://github.com/servo/servo">Servo project on Github</a> is now essentially <a href="https://github.com/servo/servo/pulse/monthly">dead</a>. I am somewhat less worried about the <a href="https://www.rust-lang.org/">Rust language</a> itself, since it is now large and useful enough to survive on its on merits.</p>
<p>Instead, Mozilla seems to be focusing their energy on their <a href="https://vpn.mozilla.org">VPN offer</a> and their <a href="https://monitor.firefox.com/">clone</a> of <a href="https://haveibeenpwned.com/">Have I been pwned?</a>. Obviously these services have a clear monetization strategy compared to a free web browser, but it&rsquo;s hard to imagine how Mozilla intends to fulfill their self professed goal of providing a <em>better Internet for People</em> with these niche and unambitious projects. If the Firefox browser is unable to keep pace with its commercial competitors, it will fail to attract new users.</p>
<p>In any case, I may transition back to Safari on the Mac. The upcoming version of Safari will <a href="https://developer.apple.com/documentation/safariservices/safari_web_extensions">support manifest v2 JavaScript extensions</a> as announced at <a href="https://developer.apple.com/videos/play/wwdc2020/10665/">WWDC</a>. This appears to support webRequest, so a port of uBlock Origin may be theoretically possible.</p>
<p>Another alternative would be to consider using <a href="https://brave.com/">Brave</a>, which is yet another Chromium based browser with a focus on privacy. However, the browser has made some <a href="https://www.theverge.com/2020/6/8/21283769/brave-browser-affiliate-links-crypto-privacy-ceo-apology">controversial moves</a> in the past.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Powered by Hugo]]></title>
    <link href="https://blog.barthe.ph/2020/10/10/powered-by-hugo/"/>
    <id>https://blog.barthe.ph/2020/10/10/powered-by-hugo/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2020-10-10T00:00:00+00:00</published>
    <updated>2020-10-10T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>This blog is now powered by <a href="https://gohugo.io/">Hugo</a>, a static page generator, and features a refreshed look. This is hopefully the first of many posts after a years long hiatus.</p>
<h2 id="old-setup">Old Setup</h2>
<p>When I started the blog in 2009, it was powered by a self-hosted <a href="https://wordpress.com/">Wordpress</a> instance. Since I was getting frustrated with maintaining PHP, MySQL and Wordpress up to date, I <a href="/2013/04/10/octopress-migration/">decided to switch to Octopress</a>, a statically generated site, in 2013.</p>
<p>Overall, I have been satisfied with <a href="http://octopress.org/">Octopress</a>, a somewhat abandoned setup for <a href="https://jekyllrb.com/">Jekyll</a>, the static site generator written in Ruby that powers <a href="https://pages.github.com/">Github Pages</a>.</p>
<p>The setup enabled me to write blog posts in <a href="https://en.wikipedia.org/wiki/Markdown">Markdown</a> rather than plain HTML. The beginning of each markdown file contained a small <a href="https://jekyllrb.com/docs/front-matter/">front matter</a> header to describe the post&rsquo;s meta data such as titles and publication dates. These files were then fed into the Jekyll machinery that generated this complex web site, including an <a href="/atom.xml">Atom feed</a> and a <a href="/sitemap.xml">sitemap</a>.</p>
<p>This setup served me well for many years but I had two growing sources of annoyances. First, the <a href="https://github.com/amelandri/darkstripes">theme</a> I was using, looked incredibly dated and was overdue for a refresh. Second, the Ruby stack that powers Jekyll can be very finicky:  I had to install a very specific version of Ruby (via <em>rvm</em> or <em>rbenv</em>) to make things work.</p>
<h2 id="new-setup">New Setup</h2>
<p>For the new setup, I have decided to use <a href="https://gohugo.io/">Hugo</a>, another static site generator, written in Go. Hugo is very similar to Jekyll, as it also uses <a href="https://gohugo.io/getting-started/configuration-markup/">Markdown</a> and <a href="https://gohugo.io/content-management/front-matter#readout">Front Matter</a>. This made the transition easier. For the most part, I was able to re-use my existing markdown source files unchanged.</p>
<p>The motivation to choose Hugo over Jekyll is that Hugo is a batteries included solution, which covers all the needs of this blog. I did not have to worry about Ruby and Gem dependencies. My Hugo setup is as simple as <code>sudo port install hugo</code>. Moreover, I have found that Hugo&rsquo;s <a href="https://gohugo.io/documentation/">documentation</a> is really excellent: every time I wondered <em>how</em> to do something, I was able to figure it out rapidly.</p>
<p>This blog now features a modern theme, with a refined minimalist layout, that let readers concentrate on the content. The garish gradients and drop shadows of the previous theme are gone. I have also re-introduced color on this site, by using slightly different shades of blue as accent or background colors. A <em>dark mode</em> color scheme is also supported and displayed when <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">requested by the browser</a>.</p>
<p>For the first time, I made my own theme, rather than use one readily available on the Internet, as I now know enough CSS and SASS to be dangerous. However, my work was loosely based on the <a href="https://github.com/alanorth/hugo-theme-bootstrap4-blog">Hugo Bootstrap v4 Blog theme</a>. It uses <a href="https://getbootstrap.com/">Bootstrap 4</a> for the layout, <a href="https://fortawesome.com/">Fortawesome</a> for the symbols, and <a href="https://fonts.google.com/specimen/Lato">Lato</a> as the main font.</p>
<p>Another change is the lack of Google Analytics, as I have grown incredibly frustrated with Google’s approach to privacy, and their lack of innovation. In addition, many laws require to show cookie banners to end users, which is hardly conducive to a good user experience. I am currently pondering relying solely on the NGINX access logs and running either a self hosted <a href="https://matomo.org/">Matomo</a> or <a href="https://github.com/plausible/analytics/">Plausible</a>, but currently I have no analytics.</p>
<h2 id="whats-next">What’s Next?</h2>
<p>Obviously, I intend to blog a lot more in 2020 than I did I the past few years.</p>
<p>Aside from inevitable tweaks and fixes, I don&rsquo;t have any major plans for this blog with the exception of search.</p>
<p>Another change in the pipeline is to complete review the hosting which has been on <a href="2014/09/17/kimsufi-migration/">Kimsufi since 2014</a>.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[The .NET Core Zoo]]></title>
    <link href="https://blog.barthe.ph/2017/11/18/dotnetcore-zoo/"/>
    <id>https://blog.barthe.ph/2017/11/18/dotnetcore-zoo/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2017-11-18T07:55:00+00:00</published>
    <updated>2017-11-18T07:55:00+00:00</updated>
    <content type="html"><![CDATA[<p>Unless you have been living under a rock, you may have noticed that Microsoft has been iterating at a furious pace on their <a href="https://www.microsoft.com/net/learn/get-started/macos">.NET Core initiative</a> for the past two years.</p>
<p>It is a clean reboot of the .NET Framework that is both open-source and cross-platform, targeting Windows, macOS and Linux.</p>
<p>For a company that has historically been an enemy of open-source software, it is difficult not to be amazed at the amount of openness that Microsoft is demonstrating with .NET Core. Not only have they released the entire stack as open source software but the development is also being done in the open on <a href="https://github.com/dotnet/core">Github</a>.</p>
<p>The issue with .NET Core is that it can easily be confused with older closed source products that Microsoft has released for the past 15 years. The problem is compounded by Microsoft&rsquo;s willingness to re-use similar names to designate radically different underlying technologies.</p>
<p>In this post, I will provide you with an overview of .NET Core, ASP.NET Core and Visual Studio, and I will explain how the open-source flavors differ from their closed source relatives.</p>
<h2 id="the-different-flavors-of-net-framework">The Different Flavors of .NET Framework</h2>
<p>Different flavors of the .NET framework have coexisted for some time. Typically each flavor combines a different runtime and a different set of standard libraries.</p>
<ul>
<li>
<p>The <strong>.NET framework</strong> denotes the classical Windows-only .NET framework. This is the oldest flavor of .NET which shipped with Windows XP.</p>
</li>
<li>
<p>The <strong>.NET Core</strong> framework is the new open-source framework released in 2016. It works on Linux, macOS and Windows. Generally speaking, it can be considered as a subset of the older .NET Framework.</p>
</li>
<li>
<p><strong>Xamarin Mono</strong> is a third party framework developed by open source Linux developers. It predates .NET Core by more than 10 years. It is also considered a subset of .NET Framework, because the Xamarin developers have never managed to quite catch up with Microsoft. However Mono also features special support for iOS, Android, Game Consoles, and Linux UI frameworks, which is entirely absent from Microsoft&rsquo;s flavors.</p>
</li>
<li>
<p><strong>.NET Standard</strong> is a recent initiative from Microsoft which formalizes the APIs shared by the different flavors of .NET. If your code targets .NET Standard, it should be able to run without recompiling on all flavors of .NET runtimes: .NET, .NET Core and Xamarin Mono.</p>
</li>
</ul>
<h2 id="the-different-versions-of-net-core">The Different Versions of .NET Core</h2>
<p>Microsoft&rsquo;s download page for <a href="https://www.microsoft.com/net/download/">.NET Core</a> shows many different options:</p>
<ul>
<li>
<p>Microsoft offers both a <em>Long Time Support</em> (LTS) version and a <em>regular</em> version. The LTS version is older but Microsoft promises to support it for about <a href="https://docs.microsoft.com/en-us/dotnet/core/versions/lts-current#what-causes-updates-in-lts-and-current-trains">3 years</a>. The downside is that it lags behind in terms of features.</p>
</li>
<li>
<p>A <em>runtime</em> and <em>SDK</em> versions. The <em>SDK</em> includes the <em>runtime</em> necessary for running .NET Core executables, but also all the development tools (i.e. the compiler and <code>dotnet</code> command line tool). Thus you only need to install one of them.</p>
</li>
<li>
<p>The <em>Windows Server Hosting</em> includes the <em>runtime</em>, but also a special module necessary to run ASP.NET Core sites within IIS. Since IIS is only available on Windows the <em>Windows Server Hosting</em> is not available on Linux nor macOS.</p>
</li>
</ul>
<h2 id="the-different-versions-of-visual-studio">The Different Versions of Visual Studio</h2>
<p>You can develop for .NET Core by using the text editor of your choice and the command line <code>dotnet</code> tool. However, I would highly recommend that you have a look at the different versions of <a href="https://www.visualstudio.com/downloads/">Visual Studio</a> that Microsoft provides.</p>
<ul>
<li>
<p><strong>Visual Studio 2017 for Windows</strong>. This is the traditional version of Visual Studio. The <em>Community</em> edition is free and fully featured when it comes to .NET and .NET Core development. The only downside is that you will probably have to use the paid-for <em>Professional</em> or <em>Enterprise</em> editions in a commercial setting.</p>
</li>
<li>
<p><strong>Visual Studio Code</strong> is an open-source text editor based on <a href="https://atom.io/">Atom</a>. It is a very capable text editor which also provides advanced IDE features, such as refactoring tools, compiler and debugger support for common languages including C#. It competes against <a href="https://atom.io/">Atom</a> and <a href="https://www.sublimetext.com">Sublime Text</a>.</p>
</li>
<li>
<p><strong>Visual Studio 2017 for Mac</strong>. Although it shares the same name as the Windows version, it is a radically different piece of software based on <a href="http://www.monodevelop.com">Mono Develop</a>. It is a bit rough and has definitely not achieved the level of maturity as the Windows counterpart. That being said, <em>Visual Studio Code</em> was in a similar state when it was introduced in 2015, and I am confident that Microsoft will iterate and make Visual Studio for Mac a lot better soon.</p>
</li>
</ul>
<h2 id="the-different-versions-of-aspnet">The Different Versions of ASP.NET</h2>
<p>This the area where the marketing at Microsoft has gone wrong. The name <em>ASP.NET Core</em> refers to old technologies which gives this very <em>modern</em> and <em>compelling</em> framework a very bad press, in my opinion.</p>
<ul>
<li>
<p><strong><a href="https://en.wikipedia.org/wiki/Active_Server_Pages">ASP</a></strong>, <em>Active Server Pages</em> is a very old technology released in the late 1990s. Think of it as a clone of PHP but using Visual Basic instead. It is also similar to what <a href="https://en.wikipedia.org/wiki/JavaServer_Pages">JSP</a> for Java used to be. It was abandoned long ago and is not suitable for modern web application development.</p>
</li>
<li>
<p><strong>ASP.NET</strong> superceded ASP in the early 2000s, and development shifted from Visual Basic to C#. It is a framework based on <em>Web Forms</em>, with a page template system powered by XML and uses the <code>*.aspx</code> file extension. The framework was invented before AJAX became mainstream, and a lot of effort seems to be devoted to make sure developers never write any JavaScript. It also integrates with the <code>System.Web</code> pipeline of IIS which, even though is a step up from CGI, makes use of <em>global variables</em> to represent the state of <em>requests</em> and <em>responses</em>. Even though it is still maintained, it is a technology that is clearly showing its age.</p>
</li>
<li>
<p><strong>ASP.NET MVC</strong> is a modern framework that Microsoft introduced in 2009. It is inspired by the successful <em>Ruby on Rails</em> framework, and as the name indicates, features a clear separation between <em>Models</em>, <em>Views</em> and <em>Controllers</em>. It also introduced a better view template system named <em>Razor</em> and improved routing. Even though it is still integrated with the same <code>System.Web</code> IIS centric pipeline, it goes out of its way to hide that fact from developers, and wrap HTTP requests and responses into non-global variables, which can be <em>mocked</em> for the purpose of unit testing.</p>
</li>
<li>
<p><strong>ASP.NET Web API</strong> is another framework Microsoft introduced in 2012. It is <em>very</em> similar to ASP.NET MVC, to the point that entire class hierarchies between the two frameworks share identical names and functions. But unlike ASP.NET MVC which focuses on generating dynamic HTML pages, ASP.NET Web API as the name indicates, targets the creation of Web APIs. It is a pretty good framework to write JSON RESTful APIs for instance.</p>
</li>
<li>
<p>Finally <strong>ASP.NET Core</strong> is a complete rewrite and a merge of both <strong>ASP.NET MVC</strong> and <strong>ASP.NET Web API</strong>. It was released in 2016 and is developed in the open on <a href="https://github.com/aspnet/Home">Github</a>. It makes great use of dependency injection and provides support for writing middleware. ASP.NET Core web applications can be deployed to Linux servers or Docker containers.</p>
</li>
</ul>
<h2 id="the-different-versions-of-aspnet-core">The Different Versions of ASP.NET Core</h2>
<p>As I indicated in the previous section, <em>ASP.NET Core</em> is a complete reboot of the Microsoft framework for writing web application software.</p>
<p>But the moniker <em>ASP.NET Core</em> denotes some radically different realities:</p>
<ul>
<li>
<p><strong>The version of ASP.NET Core which targets Kestrel</strong>. This is the main version that Microsoft is promoting. <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/aspnet-core-module?tabs=aspnetcore2x">Kestrel</a> is an open-source asynchronous HTTP server with very good performance characteristic. If you target <em>.NET Core</em> as your runtime, this is the only available option. Kestrel and .NET Core can be deployed to Linux (possibly using nginx or Apache as a reverse proxy). You can also target .NET Standard or .NET 4.7 for Windows. In this flavor of ASP.NET Core, the entire HTTP pipeline has been rewritten from scratch, and you can inject your own middleware, as in any modern web application framework.</p>
</li>
<li>
<p><strong>The version of ASP.NET Core which integrates with the IIS pipeline</strong>. This flavor of ASP.NET Core integrates with the classic IIS pipeline introduced for <code>ASP.NET</code> and it relies on the <code>System.Web</code> classes and their global variables. If you adopt this flavor of ASP.NET Core you have to target .NET 4.7 and run the web application on IIS on a Windows Server. In addition some features, such as writing your own custom middleware, are not available. The advantage of this flavor of ASP.NET Core, is that it can be viewed as an incremental update from the old <em>ASP.NET MVC</em> and <em>ASP.NET Web API</em> frameworks. Unless you have some existing ASP.NET code, you should probably stay away from this configuration for new projects.</p>
</li>
<li>
<p><strong>Finally you can use ASP.NET Core with Kestrel inside IIS</strong>. So this is the option where you are essentially using IIS as a reverse proxy for the Kestrel server. In this version you sort of get the best of both worlds: your Windows centric IT team can continue managing IIS sites as before, and you get all the features and performance improvements available to the Kestrel stack. This is achieved by installing a custom IIS module provided by Microsoft, which is called the <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/aspnet-core-module?tabs=aspnetcore2x">ASP.NET Core Module</a>. This is the recommended way to deploy ASP.NET Core on Windows servers. On Linux Microsoft recommends using nginx or Apache in similar reverse proxy configurations.</p>
</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>.NET Core and ASP.NET Core are very compelling open source technologies promoted by Microsoft. The frameworks, libraries, compilers and runtime are published on Github. You can use Visual Studio Code, another open-source piece of software to write C# code and deploy it to Linux, possibly via docker containers.</p>
<p>But make no mistake, Microsoft still has ways to make money:</p>
<ul>
<li>
<p>Microsoft sells access to <a href="https://azure.microsoft.com/en-us/">Azure</a>, their own cloud computing platform which competes with the likes of AWS and Google Cloud. Naturally Azure integrates very well with ASP.NET Core.</p>
</li>
<li>
<p>Microsoft also sells Visual Studio 2017, which unlike Visual Studio Code is closed source software. Although it may be used for free under some circumstances, for most commercial settings you will have to pay a subscription to use it.</p>
</li>
<li>
<p>Microsoft is also strongly pushing <a href="https://www.microsoft.com/en-us/sql-server/default.aspx">SQL Server</a>, their closed source relational database server. It has better integration than any other SQL databases with the .NET Core stack. Traditionally SQL Server used to run on Windows Servers only, but since the last release of <em>SQL Server 2017</em> last October, the software can now be deployed to Linux servers as well.</p>
</li>
</ul>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Let&#39;s Encrypt with Nginx]]></title>
    <link href="https://blog.barthe.ph/2015/12/09/lets-encrypt-with-nginx/"/>
    <id>https://blog.barthe.ph/2015/12/09/lets-encrypt-with-nginx/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2015-12-09T22:30:32+00:00</published>
    <updated>2015-12-09T22:30:32+00:00</updated>
    <content type="html"><![CDATA[<h2 id="the-objectives">The Objectives</h2>
<p>One of the major hurdles hampering the deployment of HTTPS on smaller websites like this one, has always been the price of certificates. As much I would have liked to get one, I could hardly justify the cost. That&rsquo;s why a year ago, when the <a href="https://letsencrypt.org">Let&rsquo;s Encrypt project</a> was announced, with the promise of free domain certificates, I was particularly excited. I decided to migrate my websites as soon as the project reached the public beta phase, last week.</p>
<p>Even if your site does not require HTTPS for security reasons, it is worth considering:</p>
<ul>
<li>
<p><strong>to provide additional privacy</strong> to your users. Unscrupulous ISPs have started to inject <a href="http://arstechnica.com/tech-policy/2014/09/why-comcasts-javascript-ad-injections-threaten-security-net-neutrality">javascript</a> or <a href="https://www.eff.org/en-gb/deeplinks/2014/11/verizon-x-uidh">cookies</a> into third party HTTP pages. They cannot do this with HTTPS pages.</p>
</li>
<li>
<p><strong>to benefit from the performance improvements of HTTP/2</strong>. Even though in theory HTTP/2 does not require TLS, all major browsers have decided to boycott the &ldquo;plaintext&rdquo; version of the protocol.</p>
</li>
</ul>
<p>In this blog post, I intend to explain how I migrated this Octopress blog hosted with <a href="https://www.nginx.com">nginx</a> from HTTP to HTTPS and obtained an <a href="https://www.ssllabs.com/ssltest/analyze.html?d=blog.barthe.ph">A+ Grade</a> from <a href="https://www.ssllabs.com">SSL Labs</a>.</p>
<h2 id="intall-lets-encrypt">Intall Let&rsquo;s Encrypt</h2>
<p>This part of the process is very well covered by the <a href="http://letsencrypt.readthedocs.org/en/latest/using.html">Let&rsquo;s Encrypt documentation</a>. Since there are no packages for Ubuntu Server LTS at the moment, I used the source code approach. In this case, we end up using the <code>letsencrypt-auto</code> command instead of <code>letsencrypt</code> directly. <code>letsencrypt-auto</code> is a wrapper script that ensures that the tool and its dependencies are up to date, prior to running any <code>letsencrypt</code> commands.</p>
<pre tabindex="0"><code># Optionally install git
sudo apt-get install git-core

# Checkout the let&#39;s encrypt git repository into /srv/letsencrypt
git clone https://github.com/letsencrypt/letsencrypt /srv/letsencrypt

# Run the tool at least once
cd /srv/letsencrypt
./letsencrypt-auto --help
</code></pre><p>When I did this, I happened to have some kind of <em>InsecurePlatform</em> Python warning.</p>
<pre tabindex="0"><code>Creating virtual environment...
Updating letsencrypt and virtual environment dependencies...../home/aymericb/.local/share/letsencrypt/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
  InsecurePlatformWarning
./home/aymericb/.local/share/letsencrypt/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
  InsecurePlatformWarning
</code></pre><p>This warning comes from <a href="https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning">urllib3</a>. I ignored it and everything was fine!</p>
<h2 id="getting-the-certificate">Getting the Certificate</h2>
<p>At this stage you are ready to request a certificate for the website. Let&rsquo;s Encrypt uses the ACME protocol, which requires serving a bespoke generated file on the web server to confirm ownership of a domain. The <code>letsencrypt</code> tool aims to automate the whole setup, so that writing <code>./letsencrypt-auto --apache -d blog.barthe.ph</code> should be sufficient to get the entire web server up and running, if you happen to use <em>Apache</em>.</p>
<p>Unfortunately, the plugin for <em>nginx</em> is not stable yet and cannot be used. The setup will be slightly more complicated. We will use the <code>--webroot</code> switch, telling <code>letsencrypt</code> where to find our web server files, and afterwards, we will have to modify the nginx configuration files ourselves.</p>
<p>Getting the Let&rsquo;s Encrypt certificate is the easy part:</p>
<pre tabindex="0"><code>./letsencrypt-auto certonly --webroot -w /srv/blog.barthe.ph/www -d blog.barthe.ph
</code></pre><p>You are asked to provide an email address (used to warn you when your certificate is about to expire), and agree to the terms and conditions.</p>
<p>Afterwards, you need to manually edit the nginx configuration files using your favorite editor (e.g. <code>nano -w /etc/nginx/sites-available/blog.barthe.ph</code>). The TLS certificate and the private keys are located in <code>/etc/letsencrypt/live/blog.barthe.ph</code>.</p>
<pre tabindex="0"><code># Add the following to redirect HTTP requests to HTTPS
server {
        server_name blog.barthe.ph;
        listen 80;
        return 301 https://$server_name$request_uri;
}
# Modify the existing HTTP setup to use HTTPS
server {
        server_name blog.barthe.ph;
        listen 443 ssl;

        # Basic TLS setup
        ssl_certificate /etc/letsencrypt/live/blog.barthe.ph/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/blog.barthe.ph/privkey.pem;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

        # keep the rest of the site configuration unchanged
        # [...]
 }
</code></pre><p>You&rsquo;ll notice that in the configuration, I chose to support TLS 1.0 and greater. I wanted to be more aggressive but TLS 1.1 is not that well supported. It does not work on OS X 10.8 for instance. However, I did drop support for the older SSLv3 protocol (which preceded TLS 1.0) and is still supported by most websites. The consequence is that my site is no longer compatible with older versions of Internet Explorer (IE6 to IE8). Supporting SSLv3 without weakening the security of modern TLS 1.2 browsers is becoming increasingly difficult because of downgrade attacks such as <a href="https://blog.mozilla.org/security/2014/10/14/the-poodle-attack-and-the-end-of-ssl-3-0/">POODLE</a>.</p>
<p>In order for the changes to take effect you should invoke <code>sudo service nginx reload</code>. If you botched the configuration file, the site will continue running with the existing configuration and you should get an error in <code>/var/log/nginx/error.log</code>.</p>
<p>Once that&rsquo;s done, you should have a web server running with HTTPS, and that redirects older HTTP URLs to their HTTPS equivalents. <strong>W00t!</strong></p>
<h2 id="a-grade-security">A+ Grade Security</h2>
<p>When testing the Octopress server on different browsers, I got some warnings about mixed content. It means that although my website was configured to serve its content through HTTPS, it still referenced URLs that used HTTP, either for internal URLs or externals URLs (such as Google Fonts, etc&hellip;). Chrome in particular was the most strict of all the browsers about this. After spending some time searching and replacing all references to HTTP URLs, I managed to fix all the warnings.</p>
<p>The next step was to edit <code>/etc/nginx/sites-available/blog.barthe.ph</code> to improve performance, by enabling TLS session caching:</p>
<pre tabindex="0"><code>ssl_session_cache shared:SSL:10m;
ssl_session_timeout 20m;
</code></pre><p>Let&rsquo;s now focus on improving security and get an <em>A+ grade</em> on SSL Labs.</p>
<p>Let&rsquo;s start by overriding the default prime used for Diffie Hellman. The default prime is usually too small, and also since it is a shared prime, some pre-computed attacks like <a href="https://en.wikipedia.org/wiki/Logjam_%28computer_security%29">Logjam</a> are possible. Beware, the <code>openssl</code> command will take <strong>a long time</strong>; from 20 minutes to a few hours.</p>
<pre tabindex="0"><code># Be patient…
openssl dhparam -out /etc/ssl/private/dhparams_4096.pem 4096

# Add &#34;ssl_dhparam /etc/ssl/private/dhparams_4096.pem;&#34; to nginx config
</code></pre><p>Now, let&rsquo;s add support for OCSP stapling. <a href="https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol">OCSP</a> is a mechanism that can be used by the browser to confirm that a certificate has not been revoked. This normally involves an extra connection to the certificate authority, <em>unless</em> the website uses stapling.</p>
<pre tabindex="0"><code>ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/blog.barthe.ph/fullchain.pem;
</code></pre><p>Let&rsquo;s enable <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security">HSTS</a>. This prevents a browser that connected to the website at least once before, from ever accepting an HTTP connection from the same domain.</p>
<pre tabindex="0"><code>add_header Strict-Transport-Security max-age=31536000;  # Valid for 1 year
</code></pre><p>Finally let&rsquo;s massage the cipher suite to only use safe and secure ciphers.</p>
<pre tabindex="0"><code>ssl_prefer_server_ciphers on;
ssl_ciphers &#39;ECDHE-ECDSA-AES256-GCM-SHA384:... SEE BELOW&#39;;
</code></pre><p>In order to obtain the list of ciphers separated by <code>:</code>, use <code>openssl ciphers -V</code> to dump all available ciphers. Then do as follow:</p>
<ul>
<li>
<p>Delete all references to <code>DES</code>, <code>3DES</code> and <code>RC4</code>, and just keep <code>AES</code> ciphers.</p>
</li>
<li>
<p>Delete all references to <code>MD5</code>.</p>
</li>
<li>
<p>Put all ciphers that use SHA1, whose name ends with <code>_SHA</code> and are <code>SSLv3</code> at the bottom.</p>
</li>
<li>
<p>Put ciphers with larger key lengths on top.</p>
</li>
<li>
<p>Put ciphers with <a href="https://en.wikipedia.org/wiki/Forward_secrecy">forward secrecy</a> on top. That would be <code>ECDHE</code> or <code>DHE</code>, the <em>DH</em> stands for <a href="https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange">Diffie-Hellman</a>, and the <em>E</em> for <em>Ephemeral</em>, which means a new key is negotiated for each connection. Stealing the private key will not allow an attacked to decrypt <strong>past</strong> TLS sessions.</p>
</li>
<li>
<p>Favor <code>GCM</code> over <code>CBC</code> as a <a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation">mode of operation</a>. This is faster, and CBC brought security issues like <a href="https://en.wikipedia.org/wiki/POODLE">POODLE</a> in the past.</p>
</li>
<li>
<p>Favor Elleptic Curves (anything with <code>EC</code>) over plain <code>RSA</code>, <code>DSA</code>, or <code>DHE</code>. Elliptic curves are faster because they require smaller primes than <em>traditional</em> crypto, and as far as we know the security behind the maths is solid.</p>
</li>
</ul>
<p>Here&rsquo;s my list:</p>
<pre tabindex="0"><code>0xC0,0x2C - ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(256) Mac=AEAD
0xC0,0x30 - ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AESGCM(256) Mac=AEAD
0xC0,0x24 - ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA384
0xC0,0x28 - ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA384
0x00,0xA3 - DHE-DSS-AES256-GCM-SHA384 TLSv1.2 Kx=DH       Au=DSS  Enc=AESGCM(256) Mac=AEAD
0x00,0x9F - DHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH       Au=RSA  Enc=AESGCM(256) Mac=AEAD
0x00,0x6B - DHE-RSA-AES256-SHA256   TLSv1.2 Kx=DH       Au=RSA  Enc=AES(256)  Mac=SHA256
0x00,0x6A - DHE-DSS-AES256-SHA256   TLSv1.2 Kx=DH       Au=DSS  Enc=AES(256)  Mac=SHA256
0xC0,0x2B - ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(128) Mac=AEAD
0xC0,0x2F - ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AESGCM(128) Mac=AEAD
0xC0,0x23 - ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AES(128)  Mac=SHA256
0xC0,0x27 - ECDHE-RSA-AES128-SHA256 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AES(128)  Mac=SHA256
0x00,0xA2 - DHE-DSS-AES128-GCM-SHA256 TLSv1.2 Kx=DH       Au=DSS  Enc=AESGCM(128) Mac=AEAD
0x00,0x9E - DHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=DH       Au=RSA  Enc=AESGCM(128) Mac=AEAD
0x00,0x67 - DHE-RSA-AES128-SHA256   TLSv1.2 Kx=DH       Au=RSA  Enc=AES(128)  Mac=SHA256
0x00,0x40 - DHE-DSS-AES128-SHA256   TLSv1.2 Kx=DH       Au=DSS  Enc=AES(128)  Mac=SHA256          
0xC0,0x2E - ECDH-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AESGCM(256) Mac=AEAD
0xC0,0x32 - ECDH-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AESGCM(256) Mac=AEAD
0xC0,0x26 - ECDH-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AES(256)  Mac=SHA384
0xC0,0x2A - ECDH-RSA-AES256-SHA384  TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AES(256)  Mac=SHA384
0xC0,0x31 - ECDH-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AESGCM(128) Mac=AEAD
0xC0,0x2D - ECDH-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AESGCM(128) Mac=AEAD
0xC0,0x29 - ECDH-RSA-AES128-SHA256  TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AES(128)  Mac=SHA256
0xC0,0x25 - ECDH-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AES(128)  Mac=SHA256
0x00,0x3D - AES256-SHA256           TLSv1.2 Kx=RSA      Au=RSA  Enc=AES(256)  Mac=SHA256
0x00,0x9C - AES128-GCM-SHA256       TLSv1.2 Kx=RSA      Au=RSA  Enc=AESGCM(128) Mac=AEAD
0x00,0x3C - AES128-SHA256           TLSv1.2 Kx=RSA      Au=RSA  Enc=AES(128)  Mac=SHA256
0xC0,0x0A - ECDHE-ECDSA-AES256-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA1
0xC0,0x14 - ECDHE-RSA-AES256-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA1
0xC0,0x09 - ECDHE-ECDSA-AES128-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(128)  Mac=SHA
0xC0,0x13 - ECDHE-RSA-AES128-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(128)  Mac=SHA1
0x00,0x39 - DHE-RSA-AES256-SHA      SSLv3 Kx=DH       Au=RSA  Enc=AES(256)  Mac=SHA1
0x00,0x38 - DHE-DSS-AES256-SHA      SSLv3 Kx=DH       Au=DSS  Enc=AES(256)  Mac=SHA1          
0x00,0x33 - DHE-RSA-AES128-SHA      SSLv3 Kx=DH       Au=RSA  Enc=AES(128)  Mac=SHA1
0x00,0x32 - DHE-DSS-AES128-SHA      SSLv3 Kx=DH       Au=DSS  Enc=AES(128)  Mac=SHA1          
0xC0,0x22 - SRP-DSS-AES-256-CBC-SHA SSLv3 Kx=SRP      Au=DSS  Enc=AES(256)  Mac=SHA1
0xC0,0x21 - SRP-RSA-AES-256-CBC-SHA SSLv3 Kx=SRP      Au=RSA  Enc=AES(256)  Mac=SHA1
0xC0,0x20 - SRP-AES-256-CBC-SHA     SSLv3 Kx=SRP      Au=SRP  Enc=AES(256)  Mac=SHA1
0xC0,0x1F - SRP-DSS-AES-128-CBC-SHA SSLv3 Kx=SRP      Au=DSS  Enc=AES(128)  Mac=SHA1
0xC0,0x1E - SRP-RSA-AES-128-CBC-SHA SSLv3 Kx=SRP      Au=RSA  Enc=AES(128)  Mac=SHA1          
0xC0,0x1D - SRP-AES-128-CBC-SHA     SSLv3 Kx=SRP      Au=SRP  Enc=AES(128)  Mac=SHA1
0xC0,0x05 - ECDH-ECDSA-AES256-SHA   SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=AES(256)  Mac=SHA1
0xC0,0x0F - ECDH-RSA-AES256-SHA     SSLv3 Kx=ECDH/RSA Au=ECDH Enc=AES(256)  Mac=SHA1
0xC0,0x0E - ECDH-RSA-AES128-SHA     SSLv3 Kx=ECDH/RSA Au=ECDH Enc=AES(128)  Mac=SHA1
0xC0,0x04 - ECDH-ECDSA-AES128-SHA   SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=AES(128)  Mac=SHA1
0x00,0x35 - AES256-SHA              SSLv3 Kx=RSA      Au=RSA  Enc=AES(256)  Mac=SHA1
0x00,0x2F - AES128-SHA              SSLv3 Kx=RSA      Au=RSA  Enc=AES(128)  Mac=SHA1	
</code></pre><h2 id="automatic-updates-of-the-certificate">Automatic Updates of the Certificate</h2>
<p>As a matter of policy the certificates emitted by Let&rsquo;s Encrypt are only valid for a short period of 90 days. This explains why the project focuses so much on automation.</p>
<p>It is possible to renew the certificate by executing the following commands, which I added to a <code>/srv/letsencrypt/cron-update.sh</code> script</p>
<pre tabindex="0"><code>#!/bin/sh
/srv/letsencrypt/letsencrypt-auto certonly --webroot -w /srv/blog.barthe.ph/www -d blog.barthe.ph --renew-by-default  --agree-tos
service nginx reload
</code></pre><p>Unfortunately, you&rsquo;ll find out that the <code>letsencrypt-auto</code> command fails with the following error:</p>
<pre tabindex="0"><code>Failed authorization procedure. blog.barthe.ph (http-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Error parsing key authorization file: Invalid key authorization: 231 parts
</code></pre><p>I found out that the ACME protocol attempts to validate the ownership using HTTP and is unable to follow the HTTP to HTTPS 301 redirection we set up at the beginning. So I had to slightly change my setup in <code>/etc/nginx/sites-available/blog.barthe.ph</code>.</p>
<pre tabindex="0"><code># The following lines prevent Let&#39;s Encrypt ACME protocol from working 
#server {
#        server_name blog.barthe.ph;
#        listen 80;
#        return 301 https://$server_name$request_uri;
#}
#
# Replace by these lines, to continue serving /.well-known/ files on port 80
server {
        server_name blog.barthe.ph;
        listen 80;
        location /.well-known/ {
                root /srv/blog.barthe.ph/www;
                try_files $uri $uri/ =404;
        }
        location / {
                return 301 https://$server_name$request_uri;
        }
}
</code></pre><p>The new version let all ACME requests to <code>/.well-known/</code> be served normally over HTTP by nginx, but redirects all the others to HTTPS. Once that change is done and nginx reloaded, executing the <code>letsencrypt-auto</code> successfully updates the certificate.</p>
<p>The next is to add a CRON job, by typing <code>crontab -e</code> (as <code>root</code>). I set up mine to update the certificate once a month, as follow:</p>
<pre tabindex="0"><code># contrab -e
# m h  dom mon dow   command
0 11 7 * * /srv/letsencrypt/cron-update.sh
</code></pre><h2 id="conclusion">Conclusion</h2>
<p>So far I&rsquo;m relatively happy with Let&rsquo;s Encrypt. I have chosen to run the <code>letsencrypt-auto</code> run with <code>root</code> privileges, but if that bothers you, there is a project named <a href="https://github.com/diafygi/letsencrypt-nosudo">Let&rsquo;s Encrypt no sudo</a> which aims to prevent that.</p>
<p>For websites with more traffic, you could delay the HTTP to HTTPS redirection until you have fully tested the HTTPS version of the site. This is a good opportunity to fix all mixed URL scheme content issues.</p>
<p>Finally, I published my final <code>/etc/nginx/sites-available/blog.barthe.ph</code> config file as a <a href="https://gist.github.com/aymericb/b1a6e889fcca07058bc7">Gist</a>.</p>
<p><strong>Edit</strong>. I initially made a mistake and wrote <code>return 301 https://blog.barthe.ph</code> instead of <code>return 301 https://$server_name$request_uri</code> in the nginx configuration. The consequence is that URLs starting with <code>http</code> would be redirected to the home page of the blog, instead of the <code>https</code> counterpart page. This defect was somehow masked by HSTS, because after browsing once to the site, the browser would redirect to the correct pages.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Migrated to Kimsufi]]></title>
    <link href="https://blog.barthe.ph/2014/09/17/kimsufi-migration/"/>
    <id>https://blog.barthe.ph/2014/09/17/kimsufi-migration/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2014-09-17T08:12:55+01:00</published>
    <updated>2014-09-17T08:12:55+01:00</updated>
    <content type="html"><![CDATA[<p>Originally, this website was powered by a shared hosting plan on <a href="http://www.dreamhost.com">Dreamhost</a>, but I migrated to a fully hosted solution <a href="/2013/04/10/octopress-migration/">over a year ago</a>.</p>
<p>After considering many options, I chose a <a href="http://www.online.net/en/dedicated-server/dedibox-scg2">Dedibox SC gen 2</a>, a dedicated server solution from <a href="http://www.online.net/en">Online.net</a> a French server manged hosting provider. The machine features a fairly low spec CPU, a 500GB hybrid SSD-HDD disk, 2GB of RAM and unlimited bandwidth with guaranteed throughput.</p>
<p>All that for €12 a month! It is much cheaper that all other hardware of VPS solutions I could find, and in fact about the same price as the Dreamhost hosting plan it replaced.</p>
<p>France seems to have two companies (<a href="http://www.online.net/en">Online</a> with Dedibox and <a href="https://www.kimsufi.com/">OVH</a> with Kimsufi) dedicated to offer very low cost hosting solutions. The prices can be low thanks to custom dedicated hardware that is both small and power efficient. As you can see below, a Dedibox SC is barely larger than a 3.5 inch HDD. My gut feeling is that the emergence of these offers in France is linked to the <a href="http://en.wikipedia.org/wiki/HADOPI_law">three strike piracy law</a> and the disappearance of <a href="http://en.wikipedia.org/wiki/Megaupload">Megaupload</a>. A lot of these servers were used as <a href="http://en.wikipedia.org/wiki/Seedbox">seed boxes</a>, at least in the beginning…</p>
<p><img src="/assets/2014/dedibox_sc.jpg" alt="Comparison of a Dedibox SC and a 3.5 inch Hard Disk"></p>
<p>The hosting on Dedibox turned out to be very good and sufficient for my needs. A properly configured nginx server, that serves mostly static pages, has no problem serving the 20,000 hits per month my sites require. I initially hesitated using Amazon S3 for some of the most popular pages, but dropped the plan entirely. I also have a few dynamic pages, but these are mostly for personal use. The PHP code of <a href="https://github.com/aymericb/exposition">Exposition</a>, my unfinished photo gallery software, works a lot faster than on Dreamhost.</p>
<p>The support on Dedibox is not great though. I had some billing issue at the beginning and it took forever for it to be resolved. I&rsquo;m not sure I would trust them for something critical, like a business.</p>
<p>In the past few days, I made the switch to their competitor Kimsufi. I was running out of space on the 500GB disk of the Dedibox, because of my large photo collection. I opted for a KS-2, which is the exact same price price as the Dedibox SC Gen 2. It is normally fitted with a 1TB disk, but I got 2TB disk instead (surprise!). The KS-2 is also fitted with 4GB of RAM instead of the 2GB of the Dedibox.</p>
<p>The rest is worse though. On Dedibox, the bandwidth is guaranteed, whereas on Kimsufi it&rsquo;s best effort. In practice, I have not noticed any differences. The disk on the Dedibox is a hybrid SDD; Kimsufi uses a traditional slower spinning disk. Dedibox offers free monitoring services, like email notifications when the machine is turned on or off. Kimsufi offers nothing. OVH has a full featured iOS app that used to support Kimsufi users, but is now restricted to the pro tier of OVH hosting. Shame on you OVH! So I ended up configuring a free <a href="https://www.pingdom.com">pingdom.com</a> account for basic monitoring.</p>
<p>In the end, it&rsquo;s a pretty good deal if you need the storage or the RAM. 2TB of &ldquo;Cloud Storage&rdquo; (it should be 1TB) for €12 month and similar fees with no limits in bandwidth is pretty good. It&rsquo;s more than what you would get from Amazon S3 or Dropbox for the same price. But if you&rsquo;re fine with 500GB or only 2GB of RAM, I would recommend the Dedibox offer instead.</p>
<p>Let&rsquo;s hope the new hosting is as reliable as the previous one…</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Compute the Balance of a Bitcoin Wallet with node.js and blockchain.info]]></title>
    <link href="https://blog.barthe.ph/2014/07/23/compute-bitcoin-balance-nodejs/"/>
    <id>https://blog.barthe.ph/2014/07/23/compute-bitcoin-balance-nodejs/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2014-07-23T21:23:24+01:00</published>
    <updated>2014-07-23T21:23:24+01:00</updated>
    <content type="html"><![CDATA[<h2 id="the-problem">The Problem</h2>
<p>As I have explained in great details <a href="/2014/04/03/bitcoin-balance-differs">in a previous post</a>, the balance of a Bitcoin wallet differs from the balance that can be computed by looking at the blockchain. That&rsquo;s because every time you make a transaction, the Bitcoin software sends back to you, the fraction of the funds that were not sent. These funds are sent back to a new address, invisible to the end users. These addresses are pre-allocated and constitute the <strong>key pool</strong>.</p>
<p>In this article, I explain <em>how</em> you can compute the balance of a BitcoinQt <code>wallet.dat</code> file using <a href="http://nodejs.org">node.js</a> and the <a href="https://www.blockchain.com/api/blockchain_api">JSON API of blockchain.info</a>. I also show how to extract the public addresses contained in the wallet, whether encrypted or not, and demonstrate how to use the blockchain.info API efficiently.</p>
<h2 id="extracting-the-keys">Extracting the Keys</h2>
<p>Bitcoin relies on public/private key cryptography. The public key is what is turned into a public address through hashing (detailed below) and the private key is the one used to sign the transactions. In order to compute the balance of a wallet, we need to extract all the public keys from the <em>key pool</em>.</p>
<p>The <code>wallet.dat</code> is a <a href="http://en.wikipedia.org/wiki/Berkeley_DB">Berkley DB</a> database. This is an old NoSQL embedded database from long before the term was coined. Unlike relational databases, such as SQLite, it is not possible to make complicated queries in SQL. The wallet uses a single key/value dictionary to store all public and private keys, the last transactions, and all other account informations.</p>
<p>The keys from the <em>key pool</em> are stored directly into the database as individual records. The database keys are split into two parts. The first part of the DB key is some kind of identifier, that describes the type of record. Non encrypted Bitcoin keys are identified with <code>key</code> while encrypted keys are identified with <code>ckey</code>. The second part of the DB key is the Bitcoin public key itself, preceded by a single byte that indicates the length in bytes of the public key. The database record associated to the DB key is the private Bitcoin key, which may or may not be encrypted. This splitting of the DB key into two parts may sound odd, you have to remember that the DB keys must be unique to identify a record.</p>
<p>Here&rsquo;s a drawing, in case you&rsquo;re starting to be confused between the DB keys and the Bitcoin public and private keys.</p>
<img src="/assets/2014/btc_keypool_wallet.png" alt="Bitcoin wallet key pool storage" class="dark-inverted-img"/>
<p>You can see details about the key loarding algorithm in <a href="https://github.com/bitcoin/bitcoin/tree/v0.8.6/src/walletdb.cpp">walletdb.cpp</a> from the source code of Bitcoin. Look at the <code>CWalletDB::ReadKeyValue()</code> method.</p>
<p>I had no luck using <a href="https://github.com/mcavage/node-bdb">node-bdb</a> for reading the wallet with node.js, because <em>cursors</em> are not supported. Instead, I used a crude algorithm looking for the <code>ckey</code> and <code>key</code> strings within the wallet. This works because BerkeleyDB does not use any compression, but that&rsquo;s not ideal.</p>
<h2 id="computing-bitcoin-public-addresses">Computing Bitcoin Public Addresses</h2>
<p>Once you have obtained the Bitcoin public keys from the pool, you can turn them into a Bitcoin addresses through a complicated process of hashing, <a href="https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses">which is well documented</a>.</p>
<p>However, I found a discrepancy with the documentation. The length of the keys I read from my wallet were all 33 bytes instead of the expected 65 bytes. Bitcoin uses ECDSA, a variant of elliptic curve cryptography. Both public and private keys are points on a specific elliptic curve (<a href="https://en.bitcoin.it/wiki/Secp256k1">Secp256k1</a>) whose equation is \( y^2 = x^3 + 7 \). The keys are the \(x\) and \(y\) coordinates stored as 32 bit integers preceded by one extra header byte that OpenSSL uses to store format information. Since \(x\) and \(y\) satisfy the known equation of the curve, you can store a single coordinate and a sign to compute the other coordinate with \(y = \pm\sqrt{x^3 + 7}\). This is what is called a <strong>compressed key</strong>, and it is 33 bytes long.</p>
<p>I initially thought that I would have to decompress the key, and convert it to the 65 bytes format in order to compute the address. But it turns out that Bitcoin hashes the OpenSSL ECDSA public key as it is. I suspect that means you could have multiple public addresses associated to the same public key: one public address for uncompressed 65 bytes key, and one public address for compressed 33 bytes keys&hellip;</p>
<p>You can simply hash the public keys with with the <code>ripemd160</code> and <code>sha256</code> algorithms as documented. The details of the hashing are strangely complicated, but easy to follow, and you end up with a 25 bytes binary address. This binary address is then converted into an ASCII string using the <a href="https://en.bitcoin.it/wiki/Base58Check_encoding">Base58 Check</a> encoding. As explained in the source code and the docs, this encoding is used instead of the easier to calculate and more base64 encoding, to avoid confusion between similar characters like <code>0OIl</code>.</p>
<p>Implementation with node.js is relatively straightforward using the <a href="https://www.npmjs.org/package/crypto">crypto</a> and <a href="https://www.npmjs.org/package/bs58">bs58</a> modules</p>
<h2 id="computing-the-balance-with-blockchaininfo">Computing the Balance with Blockchain.info</h2>
<p>You can use the <a href="https://www.blockchain.com/api/blockchain_api">JSON API from blockchain.info</a> to compute the balance of each address in the key pool, and sum them up to obtain the final balance. These APIs are public and can be used without authentication, but they are rate limited. This can be a problem if you use naively the single address API. Instead you should use the multi address API or alternatively the unspent outputs API.</p>
<h2 id="source-code">Source Code</h2>
<p>I wrote a quick and dirty sample using <a href="http://nodejs.org">node.js</a> and published it on <a href="https://github.com/aymericb/Sample-BitcoinWalletBalance/blob/master/wallet.js">Github</a>.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[HFS&#43; Bit Rot]]></title>
    <link href="https://blog.barthe.ph/2014/06/10/hfs-plus-bit-rot/"/>
    <id>https://blog.barthe.ph/2014/06/10/hfs-plus-bit-rot/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2014-06-10T09:13:12+01:00</published>
    <updated>2014-06-10T09:13:12+01:00</updated>
    <content type="html"><![CDATA[<p>HFS+ is a terribly old filesystem with serious flaws. I sincerely hope that Apple comes with an update of the filesystem for WWDC 2015. After all they have been working on <a href="https://developer.apple.com/swift/">Swift</a> for the past 4 years and we have just learned about it last week.</p>
<h2 id="hfs-is-seriously-old">HFS+ is seriously old</h2>
<p><a href="http://en.wikipedia.org/wiki/HFS%2B">HFS+</a> was released in 1998, in the era of Mac OS Classic. It predates the current Unix based version of OS X by at least three years. It was created in a period where Apple&rsquo;s business was in such a dire situation that Michael Dell&rsquo;s uttered this <a href="http://news.cnet.com/2100-1001-203937.html">now infamous quote</a> &ldquo;What would I do? I&rsquo;d shut it down and give the money back to the shareholders&rdquo;.</p>
<p>Technically HFS+ is small evolution of its predecessor <a href="http://en.wikipedia.org/wiki/Hierarchical_File_System">HFS</a> which dates back to 1985. The major change from HFS to HFS+ is the transition of block addresses from 16 bits to 32 bits. This change was really needed, as hard drives capacity exploded in the late 90s. On a 16 bit addressing scheme, a file containing a single byte would use 16KB on a 1GB hard drive, and around 16MB on a 1TB hard drive. The other changes included the transition to longer filenames (from 31 to 255 characters) and a switch to <a href="https://developer.apple.com/library/mac/documentation/macosx/conceptual/bpinternational/Articles/FileEncodings.html">Unicode encoding</a>.</p>
<p>By and large the rest of the design of HFS+ has remained unchanged since 1985.</p>
<h2 id="hfs-has-serious-limitations-and-flaws">HFS+ has serious limitations and flaws</h2>
<p>When it was first released, HFS+ did not support <a href="http://en.wikipedia.org/wiki/Hard_links">hard links</a>, <a href="http://en.wikipedia.org/wiki/Journaling_file_system">journaling</a>, <a href="http://en.wikipedia.org/wiki/Extended_attributes">extended attributes</a>, <a href="http://dubeiko.com/development/FileSystems/HFSPLUS/tn1150.html#HotFile">hot files</a>, and online <a href="http://en.wikipedia.org/wiki/Defragmentation">defragmentation</a>. These features were gradually added with subsequent releases of Mac OS X. But they are basically hacked to death, which leads to a complicated, slow and not so reliable implementation.</p>
<p>In the early days, the system had a hard limit to the number of files that could be written and deleted over the lifetime of the volume. It was 2,147,483,648 (i.e. 2^31). After that, the volume would stop being able to add any more files or directories. On HFS+, every entry in the filesystem is associated to a CNID (Catalog Number ID). The early implementations used a simple a global counter <code>nextCatalogID</code> stored in a volume header, that could only be incremented by one until the maximum value was reached. More recent versions of Mac OS X can now recycle old unused CNIDs, but this gives you an idea of the types of considerations that went into the design of HFS+.</p>
<p>More recently Apple added support for <a href="http://en.wikipedia.org/wiki/Disk_encryption">full disk encryption</a> with FileVault 2 and <a href="http://en.wikipedia.org/wiki/Fusion_Drive">Fusion Drive</a>. But these features are implemented in a layer underneath the file system, by Core Storage, a logical volume manager. Additional features like <a href="http://en.wikipedia.org/wiki/Snapshot_%28computer_storage%29">Snapshotting</a> and <a href="http://en.wikipedia.org/wiki/Versioning_file_system">Versioning</a> would probably require much tighter integration to the file system&hellip; and they would also make <a href="http://en.wikipedia.org/wiki/Time_Machine_%28OS_X%29">TimeMachine</a> extremely efficient and reliable. Currently TimeMachine is built on top of the file system and relies on capturing I/O events, which adds overhead and complexity. Another hack.</p>
<p>Finally there is <a href="http://en.wikipedia.org/wiki/Data_degradation">Bit Rot</a>. Over time data stored on spinning hard disks or SSDs degrade and become incorrect. Modern file systems like <a href="http://en.wikipedia.org/wiki/ZFS">ZFS</a>, which Apple considered but abandoned as a replacement, include checksums of all <del>meta data structures</del> content <a href="#erratum">[1]</a>. That means that when the file is accessed, the filesystem detects the corruption and throws an error. This prevents incorrect data from propagating to backups. With ZFS, you can also scrub your disk on a regular basis and verify if existing files have been corrupted preemptively.</p>
<h2 id="a-concrete-example-of-bit-rot">A concrete example of Bit Rot</h2>
<p>I have a large collection of photos, which starts around 2006. Most of these files have been kept on HFS+ volumes since their existence.</p>
<p>In addition to TimeMachine backups, I also use two other backup solutions that I described in a <a href="http://blog.barthe.ph/2013/10/16/how-store-bytes/">previous blog post</a>. I keep a copy of the photos on a Linux microserver using ext3, which I checksum and verify regularly using <a href="http://snapraid.sourceforge.net">snapraid</a>. I also keep off-site backups using <a href="http://www.haystacksoftware.com">ARQ</a> and <a href="https://aws.amazon.com/glacier/">Amazon Glaciers</a>.</p>
<p>Before I acquired the Linux Microserver, I used to keep a copy of all my photos on a Dreamhost account. I recently compared these photos against their current versions on the iMac and was a bit shocked by the results.</p>
<p>The photos were taken between 2006 and 2011, most of them after 2008. There are 15264 files, which represent a total of 105 GiB. 70% of these photos are CR2 raw files from my old <a href="http://en.wikipedia.org/wiki/Canon_EOS_350D">EOS 350D</a> camera. The other photos are regular JPEGs which come from the cameras of friends and relatives.</p>
<p><strong>HFS+ lost a total of 28 files over the course of 6 years</strong>.</p>
<p>Most of the corrupted files are completely unreadable. The JPEGs typically decode partially, up to the point of failure. So if you&rsquo;re lucky, you may get most of the image except the bottom part. The raw .CR2 files usually turn out to be totally unreadable: either completely black or having a large color overlay on significant portions of the photo. Most of these shots are not so important, but a handful of them are. One of the CR2 files in particular, is a very good picture of my son when he was a baby. I printed and framed that photo, so I am glad that I did not lose the original.</p>
<p><strong>If you&rsquo;re keeping all your files and backups on HFS+ volumes, you&rsquo;re doing it wrong.</strong></p>
<h2 id="how-to-check-for-file-corruptions">How to check for file corruptions</h2>
<p>I used the following technique to compare the photos from the Dreamhost backup against my main HFS+ volume.</p>
<p>I ran the <code>shasum</code> commmand line tool to compute SHA1 hashes of every single file in the backup folder, except <code>.DS_Store</code> files. Then, I ran <code>shasum</code> in <em>verify mode</em> to check the files on my main volume against the hashes. Differences either indicate voluntary modifications (which did not apply in my case), or corruptions courtesy of HFS+ (which was my case).</p>
<pre tabindex="0"><code># Compute checksums
find . -type f -a ! -name &#34;.DS_Store&#34; -exec  shasum &#39;{}&#39; \; &gt; shasums.txt
# Check against checksums
shasum -c &lt; shasums.txt  &gt; check.txt
# Filter out differences
cat check.txt | fgrep -v OK
</code></pre><p>You can use the same technique to check for corruptions on a single volume. You need to compute checksums and verify against them from time to time. If you use clone backups, it is probably a good idea to check for corruptions before doing the clone.</p>
<h2 id="addendum---june-11th-2014">Addendum - June 11th, 2014</h2>
<p>Thanks to everyone who spent the time to send feedback. There are a few things I would like to add:</p>
<ul>
<li><a name="erratum">[1]</a> Erratum. ZFS uses checksums for everything, not just the meta-data.</li>
<li>I understand the corruptions were caused by hardware issues. My complain is that the lack of checksums in HFS+ makes it a silent error when a corrupted file is accessed.</li>
<li>This not an issue specific to HFS+. Most filesystems do not include checksums either. Sadly&hellip;</li>
<li>Other people have written articles on similar topics. <a href="http://arstechnica.com/information-technology/2014/01/bitrot-and-atomic-cows-inside-next-gen-filesystems/#image-3">Jim Salter</a> and <a href="http://arstechnica.com/apple/2011/07/mac-os-x-10-7/12/">John Siracusa</a> for Ars Technica in particular.</li>
</ul>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Why the Blockchain and the Bitcoin Wallet Balances Differ]]></title>
    <link href="https://blog.barthe.ph/2014/04/03/bitcoin-balance-differs/"/>
    <id>https://blog.barthe.ph/2014/04/03/bitcoin-balance-differs/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2014-04-03T21:28:18+01:00</published>
    <updated>2014-04-03T21:28:18+01:00</updated>
    <content type="html"><![CDATA[<p>If you look at a website like <a href="https://blockchain.info">blockchain.info</a> or <a href="http://blockexplorer.com">blockexplorer.com</a>, you may notice it is possible to find out the details about a particular bitcoin address, such as the last transactions and of course the balance.</p>
<p>If you try this on a Bitcoin address that belongs to you, and fire up the Bitcoin Qt client (aka <a href="https://bitcoin.org/bin/0.9.0/README.txt">Bitcoin Core</a>), you may have noticed a discrepancy. It&rsquo;s very likely for the balance displayed on the website to be less than the one displayed by the software wallet.</p>
<p>The discrepancy is caused by the nature of bitcoin. Instead of storing actual coins, the bitcoin protocol should be seen as a distributed public database of <em>transactions</em> which together form the <em>blockchain</em>. You &ldquo;receive&rdquo; bitcoins when another party decides to use their private key to sign a transaction and send some amount of bitcoins to your public address. Bitcoins only <em>exist</em> in the sense that you can trace the chain of valid transactions until you reach special <em>coinbase transaction</em>, i.e. some <em>mined</em> bitcoins. You can almost think of all the transactions forming a <a href="http://en.wikipedia.org/wiki/Linked_list">singly linked list</a>, that stops at one end with mined bitcoins, and on the other end with unspent bitcoins&hellip; except for the fact that each transaction can have multiple inputs or outputs. (Please keep in mind this is voluntarily simplified, if you wish to know more check <a href="https://en.bitcoin.it/wiki/Protocol_specification#tx">the protocol documentation</a>)</p>
<p>One of the quirks of the protocol, is that the amount of the inputs and outputs in the transaction must match (in reality, the output can be less than the input, and the remainder then constitutes the optional <em>transaction fee</em>). That rule greatly simplifies the validation of transactions, since there is no need to extract the entire history of transactions to figure out how much funds are spent or unspent for a given transaction: it&rsquo;s either all or nothing.</p>
<p>The drawback of this solution arises when you need to spend only a fraction of the amount received in a previous transaction. In that case, the wallet software automatically creates two outputs to the transaction: one output is used to send money to the intended recipient, one output is used to send the remainder to the sender.</p>
<p>At this stage, it&rsquo;s probably simpler to reason with an example. Let&rsquo;s imagine <em>Alice</em> wants to sent 1.2 BTC to <em>Bob</em>. Alice previously received 1 BTC from <em>Chip</em> and 0.5 BTC from <em>Dale</em>. The new transaction she makes has to reference both previous unspent transactions as inputs, since neither of these transactions taken individually have enough funds. One of the outputs of the transaction must be the 1.2 BTC that are sent to Bob. But Alice also need to add a 0.3 BTC output that are sent back to herself. In the future, if she could use these 0.3 BTC coins that remain in her wallet, by referencing this 0.3 BTC output as an input for a new transaction.</p>
<img src="/assets/2014/btc_transaction.png" alt="Example of transaction" class="dark-inverted-img"/>
<p>It would be possible to use the same public address to send the money back to the sender, but the Bitcoin Qt software sends it to a new address instead, for privacy reasons. A bitcoin wallet contains at least a hundred of such addresses which constitute the <em>key pool</em>. The key pool is pre-allocated (therefore many addresses will have a balance of zero) so that slightly out of date backups of wallet files result in no loss of bitcoins. Every time a transaction that requires return funds is made, these returned funds seem to &ldquo;disappear&rdquo; from the balance of the wallet&rsquo;s public address. It&rsquo;s possible to reach a balance of <em>zero</em> on your public address in that way.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[How I Store my Bytes]]></title>
    <link href="https://blog.barthe.ph/2013/10/16/how-store-bytes/"/>
    <id>https://blog.barthe.ph/2013/10/16/how-store-bytes/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2013-10-16T09:33:00+00:00</published>
    <updated>2013-10-16T09:33:00+00:00</updated>
    <content type="html"><![CDATA[<p>Over a year ago, I read <a href="https://web.archive.org/web/20130615160313/https://mocko.org.uk/b/2012/06/17/how-i-store-my-1s-and-0s-zfs-bargain-hp-microserver-joy/">an article on Mockyblog</a> about storing your personal data on a HP ProLiant MicroServer. After juggling with no less than 4 external hard drives, to palliate the the lack of space on my iMac, I ended up buying this machine and turning it into a Linux powered NAS. After listening to a <a href="http://atp.fm/episodes/29-computerized-garden-gnome">recent episode of Accidental Tech Podcast</a>, where the host chose a more expensive and convenient approach, I decided to share my experience.</p>
<ul>
<li>
<p><strong>The HP microserver is cheaper than a real NAS</strong>. HP regularly operates a cashback offer on this hardware (which I used). You could acquire an <a href="https://web.archive.org/web/20130827232408/http://www.ebuyer.com/430446-proliant-microserver-turion-2-2-2gb-250gb-nhpl-sata-lff-in-704941-421">HP ProLiant G7 N54L 2.2GHz</a> for roughly £150 with a cashback offer last month. The cashback and the price varies but regularly comes back. The hardware is comparable to a NAS: it is small, fitted with a 4 HD bay, it has a CD-ROM bay that can be used for an additional disk, and it has E-SATA ports for adding external disks. In comparison, Synology hardware is usually <a href="http://www.amazon.co.uk/s/ref=nb_sb_noss_1?url=search-alias%3Daps&amp;field-keywords=synology+4+bay">north of £400</a> and DROBO is <a href="http://www.amazon.co.uk/s/ref=nb_sb_noss?url=search-alias%3Daps&amp;field-keywords=drobo+4+bay&amp;rh=i%3Aaps%2Ck%3Adrobo+4+bay">north of £300</a>. The cheapest 4 day NAS I found is the <a href="">Synology DS413j</a> which currently <a href="http://www.amazon.co.uk/Synology-DS413j-DiskStation-Diskless-Desktop/dp/B0095RYB36">retails at £265</a>. But the hardware is pale in comparison of my HP microserver: single core CPU, no E-SATA and only 512MB of RAM.</p>
</li>
<li>
<p><strong>Booting from the internal USB connector</strong>. There is a connector fitted on the motherboard, and this is where I plug my USB thumbdrive (a SanDisk Cruzer Blade). Since the microserver is not connected to any screen nor keyboard, having it boot from a thumbdrive is an advantage. In case of troubles, I can take the drive, plug it to the iMac and boot using VMWare. I also regularly clone it to another thumbdrive for backup purposes. Using the USB drive as a boot disk also means that all my hard drives are allowed to spin down to save power and prolong their lifetime.</p>
</li>
<li>
<p><strong>It&rsquo;s relatively quiet and low power</strong>. I measured my power consumption over the course of 1 month and it comes to about 40 Watts on average, for a monthly cost of £3.50. It is fitted with 4 hard drives, which are probably powered down about 90% of the time. I use <a href="http://en.wikipedia.org/wiki/Hdparm">hdparm</a> to power down the drives when not in use. The CPU of the machine is constantly solicited though, with various services I installed, and this probably prevents the machine from lowering to 30-35 Watt, which can be observed by just booting it and doing nothing. The large fan is relatively quiet, but it got more noisy after 1 year and absorbing dust. Currently the noise is about 40dB from 1 meter away which is comparable to my late 2008 iMac.</p>
</li>
<li>
<p><strong>Use encryption on all disks</strong>. As I explained in <a href="http://blog.barthe.ph/2013/04/22/backup-strategy/">my previous post</a>, the goal is not to stop the NSA or GCHQ from stealing my data. There is no 4th amendment in the UK, and the government <a href="http://wiki.openrightsgroup.org/wiki/Regulation_of_Investigatory_Powers_Act_2000/Part_III">can force you</a> to reveal your key or put you in jail for 2 or 5 years if you refuse. However, encryption is a good way to prevent identify theft, if someone breaks into your house and steal your toys. I use full disk encryption with <a href="http://en.wikipedia.org/wiki/Linux_Unified_Key_Setup">LUKS</a> on all hard drives, but not the thumb drive. The encrypted disks appear as regular block devices, and you can use any filesystem or utility. Since I have no keyboard to enter a password at boot time, I have SSH into the box and enter it manually after each reboot. It&rsquo;s slightly inconvenient, but I only power down the machine to dust it off, about once a month.</p>
</li>
<li>
<p><strong>Use snapraid for redundancy</strong>. I fitted the server with the hard disks I initially used as external drives for the Mac. Consequently all for disks are of different sizes. My goal is to achieve 1 disk redundancy, i.e. be immune to the failure of a single disk. Traditional RAID would have a hard time to cope with this setup, and it would be hard to expand it dynamically. Mockyblog mentioned using ZFS with RAID-Z. This fulfills the redundancy goal, but unfortunately it&rsquo;s not possible to add a disk to an existing zpool. There are <a href="https://web.archive.org/web/20140701142429/http://gentoovps.net/add-drive-to-raidz/">complicated techniques</a> to work around it though&hellip; <a href="https://btrfs.wiki.kernel.org/index.php/Main_Page">BTRFS</a> is a good alternative to ZFS but it not yet ready. So in the end I adopted <a href="http://snapraid.sourceforge.net">snapraid</a>. Despite its name, it has nothing to do with RAID. It&rsquo;s a file utility than runs on Linux, MacOS X and Windows and work with any file system. It can be easily configured with 3 data disks and 1 parity disk. The parity is stored in a series of checksum files and it&rsquo;s somewhat similar to <a href="http://en.wikipedia.org/wiki/Parchive">PAR2</a>. It reads chunks of files from each data disk and store the checksum on the parity disk. You need to run snapraid regularly to update the checksums or use a cron job. It&rsquo;s very well suited for for NAS storage, where data seldom changes and is mostly added (rather than modified/deleted). Compared to RAID, you also do not need to wake up all 4 drives when choose to read or write data.</p>
</li>
<li>
<p><strong><a href="http://www.plexapp.com">Plex Media Server</a></strong>. This probably the service I use the most. This is a huge improvement over manually sorting files and firing up EyeTV or VLC, because Plex automatically retrieves thumbnails and meta data, and the UI is very good. I can also access my collection from all my small collection of iOS and Android devices, or via a web page. Streaming works even outside of the home network, and even though my upload link is not good enough for 1080p films, it does stream music very well. As a consequence, I have deleted almost all of my songs from the 32GB iPhone and for the first time ever, I have lot of space to spare. It&rsquo;s like having your own Spotify, iCloud, and other radio things, for much cheaper and without ads and privacy concerns.</p>
</li>
<li>
<p><strong><a href="https://web.archive.org/web/20130628204823/http://labs.bittorrent.com/experiments/sync.html">Bittorrent Sync</a></strong>. As an alternative to <a href="https://www.dropbox.com">Dropbox</a>, not the Pirate Bay style bittorrent. Again it&rsquo;s free, and I can share a lot more than with the dropbox free tier. You could add a dedicated server with 100MBits bandwidth in the mix (which you can get for about <a href="http://www.ovh.co.uk/dedicated_servers/kimsufi_2g.xml">£3.50 a month for 500GB these days</a>, but I use <a href="http://www.online.net/fr/serveur-dedie/dedibox-scg2">this instead</a>). My phone, my office computers, my laptop all use it. I recently synchronized 20GB of photos and videos of my brother&rsquo;s wedding.</p>
</li>
<li>
<p><strong>Various download services</strong>. You can queue large download (or upload) from HTTP, SSH, RSync, BitTorrent, NZB, or anything really&hellip; The advantage is that this server is low power, you can schedule for data transfer to occur in the middle of the night, so that bandwidth is not affected during the day. There are lots of software you can run on the server and use with a Web interface: <a href="http://labs.bittorrent.com/experiments/sync.html">Bittorrent Sync</a>, <a href="http://sabnzbd.org">Sabnzbd</a>, <a href="http://sickbeard.com">Sickbeard</a>, <a href="https://couchpota.to">Couchpotato</a>, <a href="http://www.transmissionbt.com">Transmission</a> to name a few.</p>
</li>
<li>
<p><strong>Private Minecraft server</strong>. Or any game really. This is really the kind of stuff that would be hard to achieve on a NAS. I actually had to put extra RAM on the server. In honesty the CPU is a bit weak for that kind of thing, but it can be done. I doubt a NAS would be able to do this&hellip;</p>
</li>
</ul>
<p>In the end, using commodity PC hardware and Linux you can build pretty much any solution for less money than a dedicated NAS.</p>
<p>There is no denying that researching and implementing features that come out of the box on a commercial NAS is really time consuming. But once it&rsquo;s done, maintenance does not cost any time. I hardly touch the server anymore, unless I need to dust it off or install updates.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Fixing the Twitter Timeline in Octopress]]></title>
    <link href="https://blog.barthe.ph/2013/08/10/fixing-twitter-timeline-in-octopress/"/>
    <id>https://blog.barthe.ph/2013/08/10/fixing-twitter-timeline-in-octopress/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2013-08-10T10:30:00+00:00</published>
    <updated>2013-08-10T10:30:00+00:00</updated>
    <content type="html"><![CDATA[<p>On June 11th 2013, Twitter shut down the old 1.0 API and the Twitter sidebar widget of <a href="http://octopress.org/">Octopress</a>, the software that powers this blog, suddenly stopped working.</p>
<p>In the 1.1 version of the API, every single call is authenticated by <a href="http://en.wikipedia.org/wiki/OAuth">OAuth</a>. The intended goal for Twitter was to shutdown third party Twitter clients, in order to monetize content by shoving ads into the face of their users. This controversial move was <a href="https://web.archive.org/web/20131019202024/https://dev.twitter.com/blog/changes-coming-to-twitter-api">announced about a year ago</a> and <a href="http://www.marco.org/2012/11/16/twitter-being-a-dick-again">has already made some victims</a>.</p>
<p><a href="http://blog.jmac.org/blog/2013/03/30/putting-twitter-back-into-octopress/">Jason McIntosh published on his blog</a> a technique to replace the built-in Octopress widget by an official Twitter timeline widget. It works, but I think the widget looks very gross, and since it hurts my feelings to use any kind of <em>official</em> twitter &ldquo;client&rdquo;, I decided to fix the original Octopress widget instead.</p>
<p>The most obvious way to fix the problem, is to update the <code>twitter.js</code> file to use the new API. However, it is probably not a good idea to put your OAuth tokens in JavaScript, where anybody could grab them and abuse them. These OAuth tokens need to be kept on the server side. The solution I describe below does this in a very straightforward manner.</p>
<h2 id="1-register-as-a-twitter-developer-and-get-oauth-credentials">1. Register as a Twitter developer and get OAuth credentials</h2>
<ul>
<li>Log into <a href="https://dev.twitter.com/apps">https://dev.twitter.com/apps</a> with your Twitter credentials (eg: <code>bartheph</code>).</li>
<li>Create a new application. (eg: <code>blog.barthe.ph</code>).</li>
<li>Accept the controversial rules of the road.</li>
<li>Click on &ldquo;Create my access token&rdquo;.</li>
<li>Write down the following values:
<ul>
<li>Consumer key</li>
<li>Consumer secret</li>
<li>Access token</li>
<li>Access token secret</li>
</ul>
</li>
</ul>
<h2 id="2-set-up-a-cron-job-to-generate-a-static-timelinejson-file">2. Set up a cron job to generate a static timeline.json file</h2>
<ul>
<li>
<p>This file will contain the timeline, and be loaded by Octopress&rsquo; slightly modified JavaScript code</p>
</li>
<li>
<p>Install <code>ruby</code> with the <code>oauth</code> gem. On Ubuntu, you do something like that:</p>
<pre tabindex="0"><code>sudo apt-get install ruby rubygems
sudo gem install oauth
</code></pre></li>
<li>
<p>Create a ruby file on the server. You need to put your Twitter OAuth token and choose an output path.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="ch">#!/usr/bin/env ruby</span>
</span></span><span class="line"><span class="cl"><span class="nb">require</span> <span class="s1">&#39;rubygems&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nb">require</span> <span class="s1">&#39;oauth&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Edit config to suit your needs</span>
</span></span><span class="line"><span class="cl"><span class="n">config</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="ss">:consumer_key</span> <span class="o">=&gt;</span> <span class="s1">&#39;xxxxx&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="ss">:consumer_secret</span> <span class="o">=&gt;</span> <span class="s1">&#39;xxxxxx&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="ss">:oauth_token</span> <span class="o">=&gt;</span> <span class="s1">&#39;xxxx-xxxxxx&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="ss">:oauth_token_secret</span> <span class="o">=&gt;</span> <span class="s1">&#39;xxxxx&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="ss">:output_path</span> <span class="o">=&gt;</span> <span class="s1">&#39;/srv/blog.barthe.ph/www/timeline.json&#39;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Create OAuth context</span>
</span></span><span class="line"><span class="cl"><span class="n">oauth</span> <span class="o">=</span> <span class="no">OAuth</span><span class="o">::</span><span class="no">Consumer</span><span class="o">.</span><span class="n">new</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">config</span><span class="o">[</span><span class="ss">:consumer_key</span><span class="o">]</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">    <span class="n">config</span><span class="o">[</span><span class="ss">:consumer_secret</span><span class="o">]</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="ss">:site</span> <span class="o">=&gt;</span> <span class="s2">&#34;https://twitter.com&#34;</span><span class="p">,</span> <span class="ss">:scheme</span> <span class="o">=&gt;</span> <span class="ss">:header</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">access_token</span> <span class="o">=</span> <span class="no">OAuth</span><span class="o">::</span><span class="no">AccessToken</span><span class="o">.</span><span class="n">from_hash</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">oauth</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="ss">:oauth_token</span> <span class="o">=&gt;</span> <span class="n">config</span><span class="o">[</span><span class="ss">:oauth_token</span><span class="o">]</span><span class="p">,</span> <span class="ss">:oauth_token_secret</span> <span class="o">=&gt;</span> <span class="n">config</span><span class="o">[</span><span class="ss">:oauth_token_secret</span><span class="o">]</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Get timeline</span>
</span></span><span class="line"><span class="cl"><span class="n">url</span> <span class="o">=</span> <span class="s1">&#39;https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=bartheph&amp;trim_user=true&amp;count=22&amp;include_entities=1&amp;exclude_replies=1&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">access_token</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="ss">:get</span><span class="p">,</span> <span class="n">url</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Write response into output file with JSONP wrapper</span>
</span></span><span class="line"><span class="cl"><span class="no">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">config</span><span class="o">[</span><span class="ss">:output_path</span><span class="o">]</span><span class="p">,</span> <span class="s1">&#39;w&#39;</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span> 
</span></span><span class="line"><span class="cl">    <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">&#39;processTweeter(&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">body</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">&#39;);&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></li>
<li>
<p>Make sure the file is executable and not readable by anyone but the web server, since it contains OAuth tokens.</p>
<pre tabindex="0"><code>chmod 700 /srv/blog.barthe.ph/cron/update_twitter.rb
</code></pre></li>
<li>
<p>Add the ruby script to <strong>crontab</strong> to run it periodically. Type <code>crontab -e</code> and add a line similar to what follows.</p>
<pre tabindex="0"><code># Update every 10 minutes
*/10 * * * * /srv/blog.barthe.ph/cron/update_twitter.rb
</code></pre></li>
</ul>
<h2 id="3-modify-octopress-to-use-timelinejson-instead-of-the-twitter-api">3. Modify Octopress to use <code>timeline.json</code> instead of the Twitter API</h2>
<ul>
<li>Edit your local version of <a href="https://github.com/imathis/octopress/blob/master/.themes/classic/source/javascripts/twitter.js">source/javascripts/twitter.js</a>.</li>
<li>Edit the <code>getTwitterFeed()</code> function. Add a <code>jasonp</code> attribute and change the value of <code>url</code>.</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">getTwitterFeed</span><span class="p">(</span><span class="nx">user</span><span class="p">,</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">replies</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">count</span> <span class="o">=</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">count</span><span class="p">,</span> <span class="mi">10</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">//  REMOVED     url: &#34;http://api.twitter.com/1/statuses/user_timeline/&#34; + user + &#34;.json?trim_user=true&amp;count=&#34; + (count + 20) + &#34;&amp;include_entities=1&amp;exclude_replies=&#34; + (replies ? &#34;0&#34; : &#34;1&#34;) + &#34;&amp;callback=?&#34;
</span></span></span><span class="line"><span class="cl"><span class="cm">/* ADDED */</span> <span class="nx">url</span><span class="o">:</span> <span class="s1">&#39;http://blog.barthe.ph/timeline.json?callback=processTweeter&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;jsonp&#39;</span>
</span></span><span class="line"><span class="cl"><span class="cm">/* ADDED */</span><span class="p">,</span> <span class="nx">jsonp</span><span class="o">:</span> <span class="s1">&#39;processTweeter&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="p">,</span> <span class="nx">error</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span> <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#tweets li.loading&#39;</span><span class="p">).</span><span class="nx">addClass</span><span class="p">(</span><span class="s1">&#39;error&#39;</span><span class="p">).</span><span class="nx">text</span><span class="p">(</span><span class="s2">&#34;Twitter&#39;s busted&#34;</span><span class="p">);</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">,</span> <span class="nx">success</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span> <span class="nx">showTwitterFeed</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">count</span><span class="p">),</span> <span class="nx">user</span><span class="p">);</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>That&rsquo;s all. As you can see, on my blog, it looks just like before the old API was shut down. Using dynamic server side code goes a bit against the spirit of Octopress, but it&rsquo;s a very tiny self contained change.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[A JavaScript Object Oriented Programming Technique]]></title>
    <link href="https://blog.barthe.ph/2013/05/21/js-oo-programming/"/>
    <id>https://blog.barthe.ph/2013/05/21/js-oo-programming/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2013-05-21T18:32:00+00:00</published>
    <updated>2013-05-21T18:32:00+00:00</updated>
    <content type="html"><![CDATA[<p>There are many conflicting approaches to object oriented programming in JavaScript. On the one hand, the language was designed with <a href="http://en.wikipedia.org/wiki/Prototype-based_programming">prototypal object oriented programming</a> in mind, with the only built-in mechanism for inheritance being object inheritance. However, the language is also fitted with a <code>new</code> keyword of <a href="http://tech.groups.yahoo.com/group/jslint_com/message/314">dubious quality</a> which shows aspects of a more traditional class based OO programming.</p>
<p>Douglas Crockford presented in his book <a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742">JavaScript: The Good Parts</a> one of the earliest techniques of consistent OO programming. However, I found it quite outdated, and after some of research and experimentation, I came up with the following technique which I now use in <a href="http://exposition.barthe.ph/">Exposition</a>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Namespace
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">ph</span> <span class="o">=</span> <span class="nx">ph</span> <span class="o">||</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl"><span class="nx">ph</span><span class="p">.</span><span class="nx">barthe</span> <span class="o">=</span> <span class="nx">ph</span><span class="p">.</span><span class="nx">barthe</span> <span class="o">||</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Use strict header
</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="s2">&#34;use strict&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Class declaration
</span></span></span><span class="line"><span class="cl"><span class="nx">ph</span><span class="p">.</span><span class="nx">barthe</span><span class="p">.</span><span class="nx">MyClass</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">ctr_param</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	
</span></span><span class="line"><span class="cl">	<span class="c1">// Remap this
</span></span></span><span class="line"><span class="cl">	<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c1">// Private variable
</span></span></span><span class="line"><span class="cl">	<span class="kd">var</span> <span class="nx">m_private_var</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c1">// Private method
</span></span></span><span class="line"><span class="cl">	<span class="kd">var</span> <span class="nx">privateMethod</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">param</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="c1">// ...
</span></span></span><span class="line"><span class="cl">	<span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c1">// Public method
</span></span></span><span class="line"><span class="cl">	<span class="nx">self</span><span class="p">.</span><span class="nx">publicMethod</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">param</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="c1">// ...
</span></span></span><span class="line"><span class="cl">	<span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c1">// Constructor body
</span></span></span><span class="line"><span class="cl">	<span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="c1">// Temporary variable i, does not leak
</span></span></span><span class="line"><span class="cl">		<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o">&lt;</span><span class="nx">ctr_param</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		   <span class="nx">m_private_var</span> <span class="o">+=</span> <span class="nx">privateMethod</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="nx">self</span><span class="p">.</span><span class="nx">publicMethod</span><span class="p">(</span><span class="s1">&#39;stuff&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="p">})();</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Object usage
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">ph</span><span class="p">.</span><span class="nx">barthe</span><span class="p">.</span><span class="nx">exampleUsage</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="kd">var</span> <span class="nx">my_instance</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ph</span><span class="p">.</span><span class="nx">barthe</span><span class="p">.</span><span class="nx">MyClass</span><span class="p">(</span><span class="mi">15</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="nx">my_instance</span><span class="p">.</span><span class="nx">publicMethod</span><span class="p">(</span><span class="s1">&#39;other stuff&#39;</span><span class="p">);</span>	
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Use strict footer
</span></span></span><span class="line"><span class="cl"><span class="p">})();</span>
</span></span></code></pre></div><p>In the previous code sample, I employed the following techniques:</p>
<ul>
<li>
<p><strong>Use pseudo namespaces</strong> to avoid cluttering the global namespace and avoid potential naming conflicts with third party scripts. The namespace is in reality a single global object to which properties are appended. The OR operator in <code>var ph = ph || {};</code> is used to make sure the object is only created if it does not already exist. This makes the code tolerant to changes in the order <code>&lt;script&gt;</code> statements.</p>
</li>
<li>
<p><strong>Use <a href="https://developer.mozilla.org/en/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode">ECMAScript 5 strict mode</a></strong>. This is what the seemingly useless <code>&quot;use strict&quot;</code> statement is about. Instead of adding the statement to every function, I create an anonymous function whose scope is the entire file, and execute it immediately in the static context.</p>
</li>
<li>
<p><strong>Use &ldquo;classical&rdquo; OO programming with constructor functions</strong> instead of <em>prototypes</em>. I am more familiar with classical OO programming and the upcoming <a href="https://plus.google.com/+BorisSmus/posts/bxNnAzr19pz">ECMAScript 6 is going to add support for classes</a>. But a more pragmatic reason for that choice, is that relying on  closures within constructor functions, <a href="http://javascript.crockford.com/private.html">appears to be the only known technique to get private members</a> in JavaScript.</p>
</li>
<li>
<p><strong>Use the <code>new</code> keyword</strong> instead of <code>Object.create</code> or some kind of custom make function. I think it signals my intent to use classical OO programming more clearly. The <em>ECMAScript 5 strict mode</em> fixes the <a href="http://stackoverflow.com/questions/383402/is-javascript-s-new-keyword-considered-harmful?answertab=votes#tab-top">main argument Crockford uses against the &ldquo;new&rdquo; keyword</a>. In non-strict mode, if you forget to use <code>new</code> when you invoke a constructor function, <code>this</code> ends up pointing to the global context instead of the object itself. This can lead to silent failures of disastrous consequences. In strict mode, an exception is raised instead, making the mistake obvious. In addition, naming conventions enforced by <a href="http://jshint.com">JSHint</a> and <a href="http://www.jslint.com">JSLint</a> help mitigate this risk.</p>
</li>
<li>
<p><strong>Use <code>self = this</code> to avoid the confusing remapping of <code>this</code></strong>. This <a href="http://alistapart.com/article/getoutbindingsituations">article</a> illustrates how <code>this</code> is dynamically remapped and why we need to keep a reference to the original value. This is a variant of the <code>that = this</code> technique <a href="http://www.crockford.com/javascript/private.html">also mentioned by Crockford</a>. I prefer <code>self</code> because I am familiar with ObjectiveC and <code>this</code> and <code>that</code> look too similar to my eyes.</p>
</li>
<li>
<p><strong>Use an anonymous function for the constructor body</strong>. Otherwise, temporary variables can leak to clutter the constructor closure forever. I believe this pattern also increase the readability of the code, by restricting statements outside the constructor body to mere assignments. This reduces the amount of code to scan.</p>
</li>
</ul>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Future Proof Backup Strategy]]></title>
    <link href="https://blog.barthe.ph/2013/04/22/backup-strategy/"/>
    <id>https://blog.barthe.ph/2013/04/22/backup-strategy/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2013-04-22T22:17:00+00:00</published>
    <updated>2013-04-22T22:17:00+00:00</updated>
    <content type="html"><![CDATA[<p>Mechanical spinning disks and modern SSDs are fallible components. Over the course of the past 10 years, I have crashed 3 different hard disks among the dozen that I have owned. It is a far cry from the <a href="https://web.archive.org/web/20130516230252/http://www.dailytech.com/article.aspx?newsid=6404">failure rates announced by manufacturers</a>.</p>
<p><strong>So obviously you have backups</strong>. But are these up to date? Are you sure your backups work? What if your house burns or someone steals your equipment? What if you primary disk gets corrupted?</p>
<p>It does not take much for things to go wrong. After each hard drive failure, I either barely avoided catastrophe or lost a little bit of data. Here is a few things I have learned in the process:</p>
<ol>
<li>
<p><strong>One copy is not enough</strong>. You may think you would have time to duplicate the data after one of the disks crashed, but think again. Maybe the backup has been corrupted, and a secondary backup would be useful. Maybe your backup drive will die. As unlikely as it sounds, it happened to me on my old PowerMac G4. I had two disks in software RAID-1. The second disk died a few days later while mirroring the data after I inserted a brand new disk.</p>
</li>
<li>
<p><strong>You need off-site backups</strong>. In case your house burns. In case someone breaks in, steal your computer and your backup drive. In case a power surge fries all the equipment plugged on the same socket.</p>
</li>
<li>
<p><strong>Encrypt your data</strong>. Not because the government wants to snoop on you. They can <a href="http://xkcd.com/538/">use a $5 wrench</a> or <a href="http://en.wikipedia.org/wiki/Key_disclosure_law">the law</a>. But because someone might steal your gear or, if if you use an online storage, their security could be breached. And even if you have nothing to hide, the data contained on your computer can be used for a lot of nefarious purposes, such as identity theft.</p>
</li>
<li>
<p><strong>Use incremental backups</strong> instead of mirroring. Not just to save time, but also to avoid propagating errors from your primary disk. Most file systems do not include checksums of the data. So when you copy a file, and the data had been corrupted, you copy the same errors to your backup disk. On a checksumed filesystem, you would normally get an I/O error instead. I have over 100GB of pictures, and one day, I discovered a handful (10 files or so) had been corrupted. One of my backups (mirrored) was also corrupted, but fortunately, not the incremental backups.</p>
</li>
</ol>
<p>Here is what I currently use. This is Mac OS X specific.</p>
<ol>
<li>
<p><strong>I use <a href="http://en.wikipedia.org/wiki/FileVault">Filevault 2</a></strong> on all my drives. Filevault 2 is real full disk encryption, and has nothing to do with its predecessor of the same name, which was an abomination. It&rsquo;s <a href="http://www.lightbluetouchpaper.org/2012/08/06/analysis-of-filevault-2-apples-full-disk-encryption/">very secure</a> even though Apple has not published formal specifications.</p>
</li>
<li>
<p><strong>I use <a href="http://en.wikipedia.org/wiki/Time_Machine_%28Mac_OS%29">TimeMachine</a></strong>. This is a no brainer. It just works and there is no better way to have up to date backups.</p>
</li>
<li>
<p><strong>I use <a href="http://www.shirt-pocket.com/SuperDuper/SuperDuperDescription.html">SuperDuper!</a></strong> with the <em>smart update</em> option instead of the regular cloning, to avoid coping mistakes from the primary. I have a <a href="http://www.newertech.com/products/voyagerq.php">Newer Tech external Voyager</a> and a set of 2 internal hard drives. I always keep one at home and one off-site, at the office. I typically do a backup once a month, or before every MacOS X update. If things go wrong, I can directly boot from the backup.</p>
</li>
<li>
<p><strong>I use <a href="https://www.arqbackup.com/">Arq</a> and <a href="http://aws.amazon.com/glacier/">Amazon Glaciers</a></strong>. This is a little bit like an insurance, a solution of last resort in case everything fails. I have about 500GB of data backed up there. To limit the number of requests and pay less, I make only one backup every month. I end up paying about $5 per month.</p>
</li>
<li>
<p><strong>I have a local <a href="https://web.archive.org/web/20120601165930/http://h18004.www1.hp.com/products/quickspecs/13716_div/13716_div.HTML">Linux Miniserver</a></strong>. This is my NAS. I use it to backup super critical data like photos and family videos, as I do not have sufficient storage to keep more than a couple of years on the iMac. I use <a href="http://snapraid.sourceforge.net">snapraid</a> to provide redundancy on my 4 disks array. Snapraid would allow me to reconstruct the data if a single disk in the array were to die. I monitor the SMART status of all the disks with <a href="http://sourceforge.net/apps/trac/smartmontools/wiki">smartmontools</a>, and I have a spare disk I can swap in at any moment. A lot of the critical data is also backed up to Amazon Glaciers, before being uploaded to the NAS.</p>
</li>
</ol>
<p>With that kind of crazy setup, even if North Korea was to nuke Oxfordshire tomorrow, my data would be safe&hellip; but nobody would be left around to decipher it.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Migrated to Octopress]]></title>
    <link href="https://blog.barthe.ph/2013/04/10/octopress-migration/"/>
    <id>https://blog.barthe.ph/2013/04/10/octopress-migration/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2013-04-10T23:42:00+00:00</published>
    <updated>2013-04-10T23:42:00+00:00</updated>
    <content type="html"><![CDATA[<p>This site came up in February 2009, and has been running the same version of Wordpress (unpatched obviously), with an old theme from <a href="http://www.neoease.com/">Neoease</a>. A slightly hacked up version of the theme is still powering <a href="http://diskwave.barthe.ph">Diskwave</a> website.</p>
<p>To say that this blog needed to be refreshed, is an understatement. The blog looked so ugly and I was so ashamed of it, that I pretty much stopped writing for it.</p>
<p>My motivations for switching to Octopress are the following:</p>
<ul>
<li>
<p><strong>Responsive design</strong>. Most people read blogs on their phones or tablets. Having a website with a hardcoded sizes optimized for the desktop is no longer acceptable in 2013.</p>
</li>
<li>
<p><strong>Static deployment</strong>. I never really understood why I needed to run dynamic code to serve a blog. I chose Wordpress back in 2009, because of its widespread use. I was not aware of the existence of <a href="http://www.movabletype.org">Moveable Type</a> at the time.</p>
</li>
<li>
<p><strong>Use GIT and Markdown files</strong>, instead of some clunky online editor storing data in a complicated MySQL schema. Hopefully this will make my next blog migration much easier.</p>
</li>
<li>
<p><strong>No comments</strong>. This was probably the only dynamic feature I used. It was hassle to maintain and keep spam free. Direct contact via twitter and optionally linking to your own blog post is a better way to provide feedback.</p>
</li>
<li>
<p><strong>Migrate away from <a href="http://dreamhost.com">Dreamhost</a></strong>. I have been happy with them, but I need dedicated hosting for some private projects. I can also get much better performance for my photo gallery powered by <a href="http://exposition.barthe.ph">Exposition</a>.</p>
</li>
</ul>
<p>Ok. There is <em>one</em> dynamic feature I had in Wordpress, and that I am now lacking: <em>Search</em>.</p>
<p>At the moment, the migration is not completely finished. Some pages are missing from the site and I use temporary DNS redirections. Things will probably change a lot in the next few weeks.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Design and Coding Guidelines]]></title>
    <link href="https://blog.barthe.ph/2013/04/09/design-and-coding-guidelines/"/>
    <id>https://blog.barthe.ph/2013/04/09/design-and-coding-guidelines/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2013-04-09T00:00:00+00:00</published>
    <updated>2013-04-09T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>Today I was asked to come up with a set of guidelines to help a junior developer. The goal was to create a short bullet point list, of high level design ideas that can be applied to any kind of programming language and technology.</p>
<p>Here is the list I came up with.</p>
<p>First, I would like to emphasize the facts that these rules are not set in stone. They constitute good guidelines but any developer should exercise its own judgment and discretion in using them. There are times where these points will be conflict between each others or when they cannot be achieved in a reasonable amount of time. If these rules were absolutes, then they would likely be enforced by the compiler or code analysis tools. But that’s not the case. It means that for every single rule, there must exist at least one legitimate reason for a developer to differ from it.</p>
<h2 id="design-rules">Design Rules</h2>
<ul>
<li>Use <strong>object oriented principles</strong>, such as <strong>encapsulation</strong> and the <strong>principle of least knowledge</strong>, instead of relying on global states, functions, and sharing too much information.</li>
<li>Aim for the <strong>simplest solution</strong> that can possibly work and yet remain maintainable.</li>
<li>Aim for <strong>loose coupling</strong> between objects. Try to minimize the surface of contact and interactions between objects, as much as possible.</li>
<li>Use <strong>design patterns</strong> when they make sense, and if you do, stick to well-known naming conventions.</li>
<li><strong>Do not plan for future features in your design</strong>. These features may never ship. Stick to what is needed to complete your goal.</li>
<li>Try re-using patterns that already exist in the code, rather than introducing new, slightly different patterns even if they are equivalents.</li>
</ul>
<h2 id="coding-rules">Coding Rules</h2>
<ul>
<li><strong>Less code is always better</strong>. But less code does not mean cryptic code without any comments.</li>
<li><strong>Make the code as predictable and as obvious as possible</strong>, almost to the point of boredom. You are not the intended audience of your own code. You write code for other reasonably competent programmers to read, and they should almost be able to “guess” what comes after each line.</li>
<li><strong>Make the relationships between different parts of the code as explicit as possible</strong>. Use signal/slots, the observer design pattern, event notifications, or any such communication techniques to make relationships between objects more explicit. Avoid hidden flag variables. Avoid too much tight coupling that disseminate the relationships between objects.</li>
<li><strong>Avoid side effects</strong>. Your code should do what it says on the tin. Nothing more. It should be obvious whether a method modifies the internal state of an object, or not.</li>
<li><strong>Avoid code duplication</strong>. There should not be any copy/pasted code anywhere. If your code needs to do similar and yet slightly different tasks, then it should be refactored in such a way that the similar code is written once but used multiple times. You should refactor existing code when you identify or create new duplicates.</li>
<li><strong>Handle errors properly</strong>, and make it explicit what happens when errors occur.
<ul>
<li>Some errors should be thrown and handled by the caller, because you cannot decide what to do.</li>
<li>Some errors are non-critical and should be logged, and remain invisible to the end-user.</li>
<li>Some errors are critical and will have an impact on the user. In the worst case the program should exit.</li>
</ul>
</li>
<li><strong>Use design by contract</strong>. Not religiously so. But use assertions for <strong>pre-conditions</strong> and <strong>post-conditions</strong> to detect problems. If you have a tricky algorithm, you should also use <strong>invariants</strong>. This is useful for detecting programming errors, i.e. errors that should never really happen in real production code. This also makes it obvious when you break or use existing code incorrectly.</li>
<li><strong>Provide just enough information in the logs</strong>. Too much information will pollute the logs. Not enough will make certain problems impossible to debug without extra logging. Try to think what you would like to know, if the feature your wrote broke.</li>
<li><strong>Use comments judiciously</strong>. In particular, you should document everything that would not be obvious for the intended audience. Focus on explaining workarounds, hacks, side effects or particularly tricky algorithms. Comments should also be used to provide good documentation about the role of top-level classes and the effect of the most complicated methods, and what happens when they fail.</li>
<li>Follow the relevant <strong>coding guidelines</strong>. Even if no formal guidelines exist, try to stick to the same style as the file you edit. A particular emphasis should be given into naming things properly.</li>
</ul>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[How to Store Passwords Securely]]></title>
    <link href="https://blog.barthe.ph/2012/06/15/howto-store-passwords/"/>
    <id>https://blog.barthe.ph/2012/06/15/howto-store-passwords/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2012-06-15T00:00:00+00:00</published>
    <updated>2012-06-15T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>I am not a security specialist, but I would have thought that by now, one year after the <a href="http://www.engadget.com/2011/06/02/sony-pictures-hacked-by-lulz-security-1-000-000-passwords-claim/">humiliating hack of Sony Pictures</a> by LulzSec, people would have learned how to handle passwords properly. Apparently <strong>NOT</strong>.</p>
<p>In the past week, <a href="http://leakedin.org/">LinkedIn</a>, <a href="http://arstechnica.com/security/2012/06/eharmony-confirms-member-passwords-compromise/">eHarmony</a> and <a href="http://gigaom.com/europe/last-fm-suspected-password-breach-weeks-ago/">Last.fm</a> got their password databases hacked and stollen. It’s hard to know how the database was compromised in the first place, but the sheer level of <strike>amateurism</strike> incompetence that these large companies have demonstrated is shocking.</p>
<p>So, here is how it should be done:</p>
<ol>
<li>
<p><strong>Do not store passwords in plaintext in the database</strong></p>
<ul>
<li>
<p>Duh! Well Sony did store a million passwords like that&hellip;</p>
</li>
<li>
<p>So did Savannah, a GNU website hosting free software, <a href="http://news.slashdot.org/story/10/11/30/2134203/gnu-savannah-site-compromised">until they got hacked in December 2010</a>.</p>
</li>
<li>
<p>Users tend to re-use passwords everywhere. So even if your website does not have sensitive data, if it gets hacked, your users might get compromised on other websites such as gmail, Facebook, etc&hellip;</p>
</li>
</ul>
</li>
<li>
<p><strong>Do not use MD5</strong></p>
<ul>
<li>
<p>Seriously. MD5 is dead, broken. It should be removed from every library and operating system, as it provides no more security than a CRC.
MD5 is too easy to parallelize and too cheap to compute. Relatively inexpensive hardware such as high end <a href="http://www.golubev.com/hashgpu.htm">GPUs</a>, or <a href="http://infinityexists.com/videos/fpga-md5-cracker/">FPGAs</a>, make it possible to compute large number of hashes without spending much money nor time.</p>
</li>
<li>
<p>In fact, MD5 is so broken that we have seen <a href="http://en.wikipedia.org/wiki/Collision_attack#Chosen-prefix_collision_attack">a chosen prefix collision attack</a> used in the wild to <a href="http://trailofbits.files.wordpress.com/2012/06/flame-md5.pdf">spoof Windows Update certificates and distribute the Flame malware</a>. (And yeah you guessed it, Microsoft subsequently <a href="http://technet.microsoft.com/en-us/security/advisory/2718704">revoked all its remaining MD5 certificates</a>!)</p>
</li>
<li>
<p><a href="http://arstechnica.com/security/2012/06/eharmony-confirms-member-passwords-compromise/">eHarmony</a> and <a href="http://gigaom.com/europe/last-fm-suspected-password-breach-weeks-ago/">Last.fm</a> both used MD5. But that was also the case of the so-called &ldquo;experts&rdquo; of HBGary, that security firm with government contracts, that threatened Anonymous last year and got hacked by them soon afterwards.</p>
</li>
</ul>
</li>
<li>
<p><strong>Use a Salt</strong></p>
<ul>
<li>
<p>Do not just hash the password and store the result into the database. Even if your hash function is better than MD5, it is possible to compute all hashes in advance for common passwords and create a <a href="http://en.wikipedia.org/wiki/Rainbow_table">rainbow table</a>. It is trivial to <a href="http://www.freerainbowtables.com/en/tables2/">download</a> existing rainbow tables for standard hash functions, and get <a href="http://project-rainbowcrack.com/index.htm#download">off-the-shelf tools</a> to use them.</p>
</li>
<li>
<p>Instead you should <strong>salt</strong> your hashes. A salt is a random piece of data that is somehow combined to the password before it is hashed. Using a salt can be as simple as performing a XOR between the password and the salt, <strong>before</strong> using the hashing function.</p>
</li>
<li>
<p>Be sure that you use a cryptographically secure random number generator to create the salt, such as <a href="http://www.schneier.com/yarrow.html">Yarrow</a> or <a href="http://en.wikipedia.org/wiki/Fortuna_%28PRNG%29">Fortuna</a> with a good source of <a href="http://en.wikipedia.org/wiki/Entropy_%28computing%29">entropy</a>, rather than the built-in <code>rand()</code> function which is only a pseudo random number generator (hence predictable and non-secure). Many operating systems provide this facility via <code>/dev/random</code>.</p>
</li>
<li>
<p>None of the sites hacked last week (<em>LinkedIn</em>, <em>eHarmony</em> and <em>Last.fm</em>) used a salt, nor did the so-called &ldquo;experts&rdquo; from <em>HBGary</em>. Some of these password hashes can be downloaded from the PirateBay <a href="http://thepiratebay.se/torrent/7334168/Linkedin_SHA1_passwords">here</a> and <a href="http://thepiratebay.se/torrent/7341755/eHarmony_Unsalted_MD5_Hash_Database">here</a>.</p>
</li>
</ul>
</li>
<li>
<p><strong>Use more than one salt</strong></p>
<ul>
<li>
<p>To make it even harder, it’s best to <strong>not</strong> re-use the same salt for every password. A good strategy is to create a unique salt for each password and to store it along side the hash in the database.</p>
</li>
<li>
<p>You can also combine this “per-password salt” with a &ldquo;global salt&rdquo; that you do <strong>not</strong> store in the database. This makes is virtually impossible to attack your passwords if only the database was compromised (via a SQL injection for example…)</p>
</li>
</ul>
</li>
<li>
<p><strong>Use the hash function multiple times (PBKDF2)</strong></p>
<ul>
<li>
<p>Cryptographic hashing functions are usually optimized for speed. But in the case of passwords, the amount of data to hash is very small and therefore the hash function runs very quickly. The speed plays to the advantage of the attacker not you. A good way to slow down the computation process is to re-use the same hashing function multiple times.</p>
</li>
<li>
<p>In fact, rather than re-inventing the wheel and taking risks, one can use an off-the-shelf key derivation algorithm such as <a href="http://en.wikipedia.org/wiki/PBKDF2">PBKDF2</a> or <a href="http://www.tarsnap.com/scrypt.html">scrypt</a>.</p>
</li>
<li>
<p>For example, <a href="http://images.apple.com/ipad/business/docs/iOS_Security_May12.pdf">Apple uses PBKDF2 with 10,000 iterations</a> on iOS devices.</p>
</li>
</ul>
</li>
<li>
<p><strong>Probably stay away from SHA-1 too</strong></p>
<ul>
<li>
<p><a href="http://en.wikipedia.org/wiki/SHA-1">SHA-1</a> is still considered secure, but it is definitely on the way out. It’s 17 years old after all.</p>
</li>
<li>
<p>You should use the more recent <a href="http://en.wikipedia.org/wiki/SHA-2">SHA-2</a> variants (SHA-256, SHA-512, SHA-384) or, if you do not trust the NSA, something like <a href="http://en.wikipedia.org/wiki/Whirlpool_%28cryptography%29">Whirlpool</a>.</p>
</li>
</ul>
</li>
</ol>
<p>Obviously, having a proper password &ldquo;storage&rdquo; system in place will not save your website from being hacked. But it will make it more difficult to exploit the password data if that were to happen. You should also test and pay attention to the implementation of the cryptographic functions. Try to re-use well established, peer reviewed implementations that have withstood the test of time.</p>
<p>And as a final note, do not forget to <strong>test</strong> your authentication system <strong>regularly</strong>. Recently, a vulnerability was discovered in MySQL that completely broke the authentication for some combinations of compilers and operating system. The bug was caused by a simple &ldquo;loss of precision&rdquo; cast from a 4 bytes to 1 byte, which probably trigged a warning in GCC but was ignored for a while. The smallest details matter.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[That Strange Flash Resizing Bug when using 32 bits WebViews on Mac OS X]]></title>
    <link href="https://blog.barthe.ph/2012/05/20/flash_resize_bug/"/>
    <id>https://blog.barthe.ph/2012/05/20/flash_resize_bug/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2012-05-20T00:00:00+00:00</published>
    <updated>2012-05-20T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<h2 id="the-problem">The Problem</h2>
<p>Have you ever noticed some strange behavior when you resize a WebView hosting resizable Flash content? Does the Flash content seems to be play catch up with the resizing of the WebView?</p>
<p>If so you are particularly unlucky. The problem only arises if you have the following set of conditions:</p>
<ul>
<li>The hosted flash content is resized when the WebView itself is resized, a bit like in this website.</li>
<li>Your process is running in 32 bit mode. The 64 bit mode seems to be immune, probably because Flash is hosted in an external process.</li>
<li>You app is running on 10.5 or 10.6. Other versions are immune, including 10.7.</li>
<li>You are running Flash 10.1 or later which includes the <a href="http://www.kaourantin.net/2010/02/core-animation.html">Core Animation</a> rendering model. At the time I write this, the latest version of Flash is 11.2.202.235 and it still has the bug.</li>
</ul>
<h2 id="caused-by-core-animation">Caused by Core Animation?</h2>
<p>The resizing behavior made me think of Core Animation <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/AnimatingLayers.html">implicit animations</a>. Core Animation introduced the notion of &ldquo;layers&rdquo; to the already existing &ldquo;view&rdquo; hierarchy in Cocoa. Views backed by layers are rendered using a more efficient hardware accelerated rendering pipeline than &ldquo;vanilla&rdquo; views. Each layer is associated to a set of properties such as position, opacity, etc&hellip; and whenever a property is changed, by default, the system generates an implicit animation. For instance, if you make the layer visible, you will have a fade-in effect. And you guessed it, if you resize it, some kind of resize animation. This approach makes it possible to make eye candy animations without introducing much complexity to the code. And of course, Core Animation makes it possible to make explicit animations for more complex cases&hellip;</p>
<p>My suspicion was reinforced when I discovered that older versions of the Flash plugin (10.0) which do not use the Core Animation rendering model were exempt from the problem.
Core Animation
According to <a href="http://www.kaourantin.net/2010/02/core-animation.html">the blog of an Adobe employee</a>, three rendering models are offered to plugins on the Mac platform: QuickDraw, Quartz and CoreAnimation. I quickly corroborated this by looking at Mozilla’s Plugin API documentation, and I discovered the notes on <a href="https://wiki.mozilla.org/NPAPI:CoreAnimationDrawingModel">NPDrawingModelCoreAnimation</a>. The drawing model of a plugin is chosen after a simple negotiation. First, the plugin checks what the browser advertises, and decides to choose the best model. Second, the browser checks what rendering model the plugin has chosen. In the case of Core Animation, it appears that the plugin <a href="https://wiki.mozilla.org/NPAPI:CoreAnimationDrawingModel#Vending_a_layer">creates its own CALayer</a> and provides it to the browser via <code>NPP_GetValue</code>.</p>
<p>To confirm my suspicions, I needed to access the layer returned by the plugin. But this turned out to be more complicated than I anticipated. I could not find any public API in the WebKit that gives me access to the “plugin instance”, which is the first parameter of <code>NPP_GetValue</code>. And since there must be one plugin instance per Flash object in the DOM, loading the flash plugin bundle directly from “Internet Plugin” would do no good. So, after reviewing the source code of the WebKit I opted to use the <code>pluginLayer</code> method from the <a href="http://www.opensource.apple.com/source/WebKit/WebKit-6531.9/mac/Plugins/WebNetscapePluginView.mm">WebNetscapePluginView</a> class. Both the method and the class and private APIs, but they looked like a fairly stable choice given the circumstances: the <code>WebNetscapePluginView</code> class name is hardcoded to <code>WebNetscapePluginDocumentView</code> via a macro because of an old bug in Acrobat’s plugin, and the <code>pluginLayer</code> method looks indispensable.</p>
<p>The next steps consisted in disabling the implicit animations. If you modify the property of a layer yourself, you can use <code>CATransaction</code>. However in my case, the <code>bounds</code> property of the layer is modified internally by the WebView, as it reacts to the resize event. So the only options available are:</p>
<ul>
<li>Use <code>setAction:</code> on <code>CALayer</code> to set a new array of actions, which are set to <code>NSNull</code></li>
<li>Associate a delegate via <code>setDelegate:</code> to the <code>CALayer</code> and implement <code>actionForLayer:forKey:</code> to return <code>NSNull</code>.</li>
<li>Or override the <code>actionForKey:</code> method for the target layer, via some kind of dark voodoo method swizzling.</li>
</ul>
<p>I opted to use the least intrusive methods, which is to use <code>setActions:</code>. I soon discovered that it did not work, and that in fact the layer given by the plugin already had Null actions. However, by digging in the layer hierarchy, I found out that 2 levels below the plugin root layer, the plugin had created a layer from a class named <code>FP_FPCAOpenGLLayer</code>, which did not override the default actions. There was my problem and as suspected it was a lame Flash bug.</p>
<h2 id="fix--workaround">Fix / Workaround</h2>
<p>In my Cocoa application I intercept the <code>webView:didFinishLoadForFrame:</code> from the <code>WebFrameLoadDelegate</code>. There I run my own <code>FixFlashResizingBug()</code> function, which does the following:</p>
<ul>
<li>Browse the view hierarchy and look for <code>WebNetscapePluginDocumentView</code>.</li>
<li>For each <code>WebNetscapePluginDocumentView</code> it finds, try to call the <code>pluginLayer</code> method</li>
<li>Then drill two levels down the layer hierarchy, and look for a <code>FP_FPCAOpenGLLayer</code></li>
<li>Set the actions of <code>FP_FPCAOpenGLLayer</code> to <code>NSNull</code>.</li>
</ul>
<p>Obviously this is fragile since it both relies on private WebKit API’s and manipulate internal structures of the Flash plugin directly, but I could not think of a better idea.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[A History of the DMG File Format]]></title>
    <link href="https://blog.barthe.ph/2011/04/05/dmg_history/"/>
    <id>https://blog.barthe.ph/2011/04/05/dmg_history/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2011-04-05T00:00:00+00:00</published>
    <updated>2011-04-05T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<h2 id="what-are-disk-images">What are Disk Images</h2>
<p>Disk Images have always been popular on the Mac. They play a similar role to “ISO” images on other platforms, in the sense that they can be used to clone medias or can be mounted/unmounted as a virtual disks.</p>
<p>However DMG images offer a <strong>LOT</strong> more functionalities than traditional ISO images:</p>
<ul>
<li>They can hold a partition table, and therefore contain more than one volume. (Typically a partition table with a single partition).</li>
<li>They may contain any kind of filesystem. (Typically <a href="http://en.wikipedia.org/wiki/HFS%2B">HFS+</a>).</li>
<li>Images can be compressed (via bzip2, zlib, or Apple’s own format for the old ones).</li>
<li>Images can be made as read-only, but also as read-write. (Installer images are typically read-only).</li>
<li>Read-write images can be sparse. That means the image file only grows as more content is put inside, rather than be pre-allocated to the full capacity of the virtual disk.</li>
<li>Images can have checksums to verify their integrity (options: several CRCs, MD5, several SHAs).</li>
<li>Images can embed Mac specific behaviors: contain a <a href="http://en.wikipedia.org/wiki/EULA">EULA</a>, have a custom icon, automatically mount when downloaded by Safari, etc…</li>
<li>And I probably forget a lot of other features (<a href="http://en.wikipedia.org/wiki/RTFM">RTFM</a>: <code>man hdiutils</code>).</li>
</ul>
<h2 id="the-mac-os-classic-era">The Mac OS &ldquo;Classic&rdquo; Era</h2>
<p>One of the initial motivations for using disk images, during the Mac OS classic era, is that application files could not be reliably transmitted over non-Mac specific networks like the Internet. This limitation stems from the fact that files were divided into two logical parts, called <em>forks</em>: the &ldquo;<strong>data fork</strong>&rdquo; and the &ldquo;<strong>resource fork</strong>&rdquo;. The <em>data fork</em> is what is traditionally considered to be a file. The structure of the data is entirely determined by the developer. The <em>resource fork</em> on the other hand, contains a collection of data organized in a standard way and accessible through a dedicated API. Although it is possible to define custom resources, the OS would also provide lots of default types to hold classical information: user interface elements, rich text, pictures, etc…</p>
<p>On Mac OS X, <em>resource forks</em> are still supported for backward compatibility reasons, but all application now use <a href="http://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFBundles/Introduction/Introduction.html">bundles</a> instead. A bundle appears as a single icon to the end user, but it is in reality a directory containing several files. The role that the resource fork used to play to organize data is now played by the file system: each resource appears as an individual file within a hierarchy of directories. Hence, a typical Mac OS X application is composed of several files, and disk images remain useful to solve the problem of their distribution across networks.</p>
<p>In order to safely transport data, and installers, Apple chose to favor the usage of disk images rather self extracting installers. Since the early 90s, all Apple software installation disks have been distributed as either disk images or physical medias. Early Mac users would probably remember either using Apple’s <em>DiskCopy</em>, or <a href="http://www.atpm.com/5.10/shrinkwrap.shtml">Aladdin’s ShrinkWrap</a>, for creating or mounting disk images. The current DMG file format is a direct descendant of the <strong>New Disk Image Format</strong> (aka <em>NDIS</em>) that Apple introduced <a href="http://www.tidbits.com/static/html/TidBITS-339.html">with Disk Copy 6 in 1996</a>. This file format used the <em>resource fork</em> to store all the meta data: file version, partition table, type of compression, checksums, etc… and more importantly where to find the data for the virtual disk sectors. The <em>data fork</em> only contained the raw data (compressed or not) of the virtual disk.</p>
<h2 id="the-mac-os-x-era">The Mac OS X Era</h2>
<p>The astute reader may have noticed that, since the NDIS images used forks, it was not suitable for safe redistribution across the Internet. Disk images had typically to be encoded with either <a href="http://en.wikipedia.org/wiki/BinHex">BinHex</a> or <a href="http://en.wikipedia.org/wiki/UUencode">UUencode</a>.</p>
<p>When Apple introduced Mac OS X in 2001, they decided to solve the problem once and for all. They designed the DMG file format, which they called <strong>Universal Disk Image Format</strong> (aka <em>UDIF</em>). DMG is a <strong>flat</strong> file format in the sense that it does not contain any forks, but it is basically a wrapper around the traditional NDIS format. A typical DMG file is a concatenation of the <em>data fork</em>, followed by the <em>resource fork</em> of an NDIS disk image.</p>
<p>Apple has never published the specifications of either the NDIS or the UDIF file format. The private DiskImage framework plays a central role in the implementation of DMG parsing and the mounting of disk images in general. The framework apparently supports plugins (see <code>hdiutil plugins</code>) but there is no developer documentation available. The only non-Apple plugin known was made by Connectix for VirtualPC images, during the PowerPC era (see <a href="http://crypto.nsa.org/vilefault/23C3-VileFault.pdf">Unlocking FireVault</a>). However it does not appear that either VMWare nor Parallels have been able to use the private framework in recent times.</p>
<h2 id="useful-tools">Useful Tools</h2>
<p>Although it is sad the DiskImage framework is closed, the DMG file format itself, is a bit of an open secret. It has been successfully reverse engineered many times, and there are a few open source implementations:</p>
<ul>
<li>Several commercial software support it: <a href="http://www.mediafour.com/products/macdrive">MacDrive</a>, <a href="http://www.poweriso.com/">PowerISO</a>, <a href="http://www.magiciso.com/FAQ/FAQ0011.htm">MagicISO</a>.</li>
<li><strong>Vultur’s</strong> <strong><a href="http://vu1tur.eu.org/tools/">dmg2iso</a></strong> is probably the older open source implementation. It is a quick and dirty perl script to convert a DMG file into an ISO. It is deprecated, and its replacement is a cleaner and more complete C implementation called <em>dmg2img</em>.</li>
<li><strong>Erik Larsson</strong> provides a series of Java tools that can parse DMG files. There is the simple <strong><a href="http://www.catacombae.org/dmgx.html">DMGExtractor</a></strong>, but also the more complete <strong><a href="http://www.catacombae.org/hfsx.html">HFSExplorer</a></strong> which provides a graphical interface to browse HFS+ volumes and DMG files.</li>
<li>Another interesting source is <strong><a href="https://github.com/planetbeing/libdmg-hfsplus">libdmg</a></strong> from <strong>planetbeing</strong>. It is a C library with UDIF and HFS+ support. It can be used to convert DMG from/to ISOs; extract files; or create DMG images from * scratch. The project was initially started as a way to manipulate Apple’s software restore packages for iPhone devices.</li>
<li>Finally, <a href="http://www.7-zip.org/">7-zip</a> on Windows is able to open and extract DMG files.</li>
</ul>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Sharing a VPN connection with VMWare fusion]]></title>
    <link href="https://blog.barthe.ph/2010/11/30/vmware-fusion-vpn-share/"/>
    <id>https://blog.barthe.ph/2010/11/30/vmware-fusion-vpn-share/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2010-11-30T00:00:00+00:00</published>
    <updated>2010-11-30T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<h2 id="rationale">Rationale</h2>
<p>My company has set up a VPN access that can be used from home. This proved to be extremely useful last winter when I got snowed in, and I have used it occasionally ever since.</p>
<p>The VPN system we use (<em>Sonicwall</em>) is not supported on MacOS X, and Sonicwall only provides connection software for Windows. I have tried to use <a href="http://www.lobotomo.com/products/IPSecuritas">IPSecuritas</a> but I could not find a way to configure it properly. The commercial software <a href="http://www.equinux.com/us/products/vpntracker/index.html">VPN Tracker</a> worked like a charm, but when I saw the price (€99 excl VAT) I stopped considering it. For about half of that price ($60 excl VAT) you can get a license to VMWare Fusion.</p>
<p>So, I decided to VMWare Fusion for my VPN access. The obvious disadvantage is that VMWare uses a lot of resources, but this is not really a problem for me. In addition, the setup is difficult but hopefully this post should help you with that. The obvious advantage is that, of course, VMWare can do a lot more than provide access to a VPN!</p>
<h2 id="summary-of-the-setup">Summary of the Setup</h2>
<p>My goal is to access the company network (<code>10.100.10.x/24</code>) from home on my iMac running Mac OS X 10.6. Since the VPN software is only supported on Windows, I connect to the VPN via Windows XP SP3 running inside VMWare Fusion. The virtual machine Internet connection is provided via a NAT network interface connected to the iMac.</p>
<p>My setup consists in creating another network interface between the iMac and the VM. Then, I configure both Windows and MacOS X so that my packets get properly routed.</p>
<p>A picture is worth a thousand words.</p>
<p><img src="/assets/2010/vpn_sharing_setup.png" alt="Overview of the VPN sharing setup"></p>
<h2 id="setting-up-vmware-fusion">Setting up VMWare Fusion</h2>
<p>I assume that you have correctly installed the virtual machine, Windows XP, and that the VPN software works as expected. My network configuration uses NAT to provide internet access to the VM, but it is certainly possible to use other configurations.</p>
<p>The first thing to do is to create a new network interface to provide access to the VPN from the Mac to the VM.</p>
<h3 id="steps">Steps</h3>
<ul>
<li>Switch off the VM</li>
<li>Go to “Settings”, “Network”</li>
<li>Add a network interface with the “+” button at the bottom.</li>
<li>Choose “The host only” option at the bottom.</li>
</ul>
<p><img src="/assets/2010/vpn_vmware_screenshot.png" alt="Create a Network Interface in VMWare"></p>
<h2 id="setting-up-windows-xp">Setting up Windows XP</h2>
<p>The next part of the setup consists in configuring the newly created “Local Area Network 2″ interface (LAN2) so that it shares the connection with the VPN. We need to share the internet connection from the “Virtual Private Network” interface to the LAN2 interface. We also need to enable IP packet routing.</p>
<h3 id="steps-1">Steps</h3>
<ul>
<li><strong>Sharing the connection</strong>
<ul>
<li>Go to “Control Panel”, “Network Connections”.</li>
<li>Right click on the “Virtual Private Network” interface, select “properties”, go the the “advanced” tab and select the option “<strong>Allow other network users to connect through this computer’s Internet connection</strong>“.</li>
<li>In the combo box below select “Local Area Network 2″.</li>
<li>Deselect the option “Allow other network users to control or disable the shared Internet connection”.</li>
<li>Click on “Ok” to validate the settings.</li>
</ul>
</li>
<li><strong>Enabling IP routing</strong>
<ul>
<li>Open &ldquo;regedit.exe&rdquo;.</li>
<li>Go to <code>HKEY_LOCAL_MACHINE SYSTEM\CurrentControlSet\Services\Tcpip\Parameters</code>.</li>
<li>Locate the key <code>IPEnableRouter</code> and set it to <code>1</code>.</li>
<li>This setting is different on older or newer versions of Windows.</li>
</ul>
</li>
<li><strong>Set up Local Area Network 2 interface</strong>
<ul>
<li>Open the “Terminal.app” application on the Mac and type “ifconfig”.</li>
<li>Note the IP address (inet) associated to the “vmnet1″ interface and the network mask. In my case it’s 192.168.245.1 and 0xffffff00.</li>
<li>Go the “Control Panel”, “Network Conections” on the VM</li>
<li>Open the “Local Area Network 2″ interface properties window.</li>
<li>In the “general” tab, double click on the “TCP/IP” item.</li>
<li><strong>Choose an IP address on the same network than the one from the Mac</strong>, and set the network mask. In my case, I chose 192.168.245.2 and 255.255.255.0.</li>
<li>Click “Ok” to validate the settings</li>
</ul>
</li>
</ul>
<p><img src="/assets/2010/vpn_winxp_screenshot.png" alt="Setup Network Interfaces on Windows XP"></p>
<p>At this stage, although this is not strictly necessary, you may want to enable the ping on Windows XP, to verify that your connection works.</p>
<ul>
<li>Go to “Control Panel”, “Windows Firewall”.</li>
<li>Go to the “advanced” tab and select “settings” in the “ICMP” section.</li>
<li>Enable the “allow incoming echo request” option.</li>
<li>On the Mac, open “Terminal.app”</li>
<li>Type <code>ping 192.168.245.2</code> and the Virtual machine, should normally reply to the ping. If it does not, you may have made a configuration mistake. Use <code>ifconfig</code> on the Mac and <code>ipconfig</code> on Windows to debug the issue.</li>
</ul>
<h2 id="setting-up-mac-os-x">Setting up Mac OS X</h2>
<p>At this stage we need to set up Mac OS X routing so that VPN addresses are resolved through the vmnet1 interface. We also optionally set up the company DNS. If you have not done it yet, you should connect to the VPN from the virtual machine.</p>
<h3 id="steps-2">Steps</h3>
<ul>
<li>Once you are connected to the VPN on Windows, launch “cmd.exe” and type “ipconfig /all”.</li>
<li>Look for the following details: your IP address on the VPN network, the mask, and the addresses of the VPN.</li>
<li>In my example I have an IP of <code>10.100.10.212</code>, a mask of <code>255.255.255.0</code> and two DNS servers at addresses <code>10.100.10.12</code> and <code>10.100.10.14</code></li>
<li>Go back to Mac OS X.</li>
<li>In the terminal type a command line similar to <code>sudo route -n add 10.100.10.0/24 192.168.245.2</code>. (Or alternatively if you do not wish to worry about the CIDR notation for the mask, <code>sudo route -n * add 10.100.10.0 192.168.245.2 255.255.255.0</code>)</li>
<li>The first partial IP corresponds to the IP of your network (normally the first digits, until the mask is zero).</li>
<li>The second IP is the IP of the VM on the LAN2 interface.</li>
<li>This line instructs MacOS X to route all IPs from the <code>10.100.10.x</code> network to the <code>192.168.245.2</code> gateway, i.e. the virtual machine.</li>
<li>You must the enable IP routing. Type <code>sudo sysctl -w net.inet.ip.forwarding=1</code>.</li>
</ul>
<p>At this stage you should be able to ping yourself on the VPN from the Mac. In my example <code>ping 10.100.10.212</code> should reply. Now what if it does not work</p>
<ul>
<li>Try <code>traceroute 10.100.10.212</code>. If you see your message routed through your normal internet connection, then something is wrong on the Mac. Otherwise it’s on Windows.</li>
<li>On the Mac <code>netstat -rn</code> will dump the route table.</li>
<li>Verify that you still have an internet connection, on the Mac and the VM. If you do trash your route table you may lose it entirely. (Try removing your incorrect route with “route delete …” and/or plug in and off your modem connection).</li>
</ul>
<h2 id="optional-steps-to-set-up-the-dns">Optional Steps to Set Up the DNS</h2>
<ul>
<li>Go to “System Preferences” on the Mac.</li>
<li>Select “Network”.</li>
<li>Click on “Advanced” at the bottom of the interface that provides your internet connection.</li>
<li>Go to the “DNS” tab. In the “DNS server” sections add the DNS servers of your VPN, on top of the list. In my case it’s 10.100.10.12 and 10.100.10.14.</li>
<li>Close, validate and do not forget to “apply” the settings.</li>
</ul>
<h2 id="going-further">Going Further&hellip;</h2>
<ul>
<li>You can snapshot the Windows virtual machine to retrieve your settings next time.</li>
<li>On the Mac you can put the combination of the <code>route</code> and <code>sysctl</code> commands in a script to further automate the process. Maybe it’s possible to write a launchd script and do it at startup</li>
<li>I’m not sure how to configure the DNS from the command line, nor how to make the DNS of the company be used only for domains unknown from your regular DNS server.</li>
</ul>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[First Public Release of DiskWave]]></title>
    <link href="https://blog.barthe.ph/2010/03/12/first-release-whichsize/"/>
    <id>https://blog.barthe.ph/2010/03/12/first-release-whichsize/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2010-03-12T00:00:00+00:00</published>
    <updated>2010-03-12T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>I have not been blogging a lot lately. Truth be told, I was busy coding…</p>
<p><del>WhichSize</del> DiskWave is a freeware for MacOS X 10.6 (hence Intel Macs only for now) that can recursively size the directories on your drive. This allows to quickly identify and reclaim wasted space.</p>
<p>It is freely available here: <a href="http://diskwave.barthe.ph/">http://diskwave.barthe.ph/</a></p>
<p>DiskWave was basically hacked in a weekend, but this is not a new idea. I already worked on a similar project, back in 2004, after discovering OmniDiskSweeper. I was appalled by the terrible performance of OmniDiskSweeper and quickly realized I could do a better job. So I learned Cocoa, ObjectiveC, the Carbon APIs, and came up painfully with a prototype only to discover that another software named WhatSize was free and worked very well. I also had a tricky memory leak due to a bug in Cocoa API.  So I quitted.</p>
<p>Fast forward to 2010. OmniDiskSweeper is no longer a shareware, but its performance is still bad.  WhatSize is no longer a freeware. The old freeware version of WhatSize I have is a PowerPC version, but since I moved to Snow Leopard, I felt like I did not want to install Rosetta. So here is DiskWave.</p>
<p>So this time, I did my homework, and it does not look like there is a suitable alternative. Here is the list of similar tools (on MacOS X) I came up with:</p>
<ul>
<li><a href="http://www.omnigroup.com/products/omnidisksweeper/">OmniDiskSweeper</a>
<ul>
<li>Freeware (formerly shareware).</li>
<li>Slower because it relies on Cocoa APIs. It also consumes a lot of memory.</li>
<li>Does not have many more features than DiskWave. I hope to catch up pretty soon&hellip;</li>
</ul>
</li>
<li><a href="http://www.id-design.com/software/whatsize/index.php">WhatSize</a>
<ul>
<li>Shareware (formerly freeware).</li>
<li>Same speed. Consumes a little bit more of memory, because it supports another feature that requires it</li>
<li>Does have many more features than DiskWave. Some of them, I never intend to get: fat binaries removal, locale removals, etc&hellip;</li>
<li>The thing that annoys me is that you can size/browse only one drive at a time.</li>
</ul>
</li>
<li><a href="http://www.daisydiskapp.com/">DaisyDisk</a>
<ul>
<li>Shareware.</li>
<li>New kid on the block. The visualization is really awesome but… I do not find it that practical.</li>
<li>If I ever wish to play with CoreAnimation, I may add an animated sunburst view.</li>
</ul>
</li>
<li><a href="http://grandperspectiv.sourceforge.net/">GrandPerspective</a>
<ul>
<li>Opensource</li>
<li>Seems to work well and is properly maintained. But I do not like this kind of visualization.</li>
</ul>
</li>
<li><a href="http://www.derlien.com/">DiskInventory X</a>
<ul>
<li>Opensource</li>
<li>It looks like it is no longer maintained. I do not fancy the GUI. Same as GrandPerspective.</li>
<li>DiskWave being in its early infancy is somewhat limited in terms of features. I hope to gradually upgrade it. If you have ideas of features you would like to see added, just let me know.</li>
</ul>
</li>
</ul>
<p><strong>Reference</strong>:</p>
<ul>
<li>DiskWave homepage: <a href="http://diskwave.barthe.ph/">http://diskwave.barthe.ph/</a></li>
</ul>
<p><strong>Update</strong>  April 12th 2010:</p>
<ul>
<li>Renamed WhichSize into DiskWave after receiving complaints from id design, inc.</li>
</ul>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Force Windows to Refresh the Desktop (and Start Menu)]]></title>
    <link href="https://blog.barthe.ph/2010/02/23/force-desktop-refresh/"/>
    <id>https://blog.barthe.ph/2010/02/23/force-desktop-refresh/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2010-02-23T00:00:00+00:00</published>
    <updated>2010-02-23T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>Today I learned a new trick.</p>
<p>When you programmatically delete a shortcut from the Desktop folder, Windows is usually smart enough to update the <em>Desktop</em> and the <em>recently used programs</em> section of the <em>Start Menu</em>. But sometimes, it does not work, and you are left with a &ldquo;ghost&rdquo; icon.</p>
<p>As a regular end user, you can hit the F5 key to force a refresh of the <em>Desktop</em>, but for the <em>Start Menu</em> you are left with no alternative than killing/restarting <code>explorer.exe</code>.</p>
<p>I was looking for a better solution for a custom installer application. And after a lot of MSDN scattering and googling around, Eureka, I finally found a magic incantation to programmatically force a refresh of the Desktop.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">SHChangeNotify</span> <span class="p">(</span><span class="n">SHCNE_ASSOCCHANGED</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span></span></code></pre></div>]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Make LoadLibrary() Failures Silent on Win2k]]></title>
    <link href="https://blog.barthe.ph/2009/12/03/silent_loadlibrary/"/>
    <id>https://blog.barthe.ph/2009/12/03/silent_loadlibrary/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2009-12-03T00:00:00+00:00</published>
    <updated>2009-12-03T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>For a custom installer application, I have been working on a crude but efficient way to determine whether a particular version of the C runtime (CRT) needs to be installed or not. The technique I use is simply to check if a dummy DLL linked to the CRT libraries would load up properly.</p>
<p><img src="/assets/2009/win2k_messagebox.png" alt="Win2k LoadLibrary failure"></p>
<p>This works  well, except for one small detail. When the CRT is not installed, on Windows 2000 ~~~only~~~, the LoadLibrary error would also cause a <code>MessageBox</code> to be displayed. This stops the flow of the installer and of course, is not very elegant&hellip;</p>
<p>But there is a simple trick to get rid of the <code>MessageBox</code>, using the very obscure <code>SetErrorMode</code> system call.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="o">::</span><span class="n">SetErrorMode</span><span class="p">(</span><span class="n">SEM_FAILCRITICALERRORS</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">HMODULE</span> <span class="n">hDll</span> <span class="o">=</span> <span class="o">::</span><span class="n">LoadLibrary</span><span class="p">(</span><span class="s">&#34;CrtCheck.Dll&#34;</span><span class="p">);</span> <span class="c1">// Won&#39;t bark
</span></span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">hDll</span><span class="p">)</span>   <span class="p">;</span> <span class="c1">// CRT is installed
</span></span></span><span class="line"><span class="cl"><span class="k">else</span>        <span class="p">;</span> <span class="c1">// CRT is NOT installed
</span></span></span></code></pre></div><p>Do you guys know a better (yet simple) way to determine if the CRT is installed?</p>
<p><strong>Update</strong>: this is not a Windows 2000 specific issue (thanks Ferruccio). It’s also true for older versions of Windows. As far as I know WinXP, Vista and 7 do NOT display a <code>MessageBox</code> under the same circumstances.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[XCode Has Dropped Support for Java!]]></title>
    <link href="https://blog.barthe.ph/2009/11/26/xcode-nojava/"/>
    <id>https://blog.barthe.ph/2009/11/26/xcode-nojava/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2009-11-26T00:00:00+00:00</published>
    <updated>2009-11-26T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>I guess this is hardly news to anyone but me, since I have not written a single line of Java for the past 4 years, but apparently Xcode has dropped the support for Java projects.</p>
<p>As of Xcode 3.2.1, there is no way to create a command line or Swing application project which is fully managed by Xcode. There is still support for the Java syntax in the text editor and the java compilation tools are also installed, though.</p>
<p>One of the default project templates, JNI library, does actually let you create a project containing java files. However these files are compiled with ANT. This demonstrates that Xcode can still be used for Java development through the use of “external build systems”, but that’s it… Java is no longer a first class citizen in Xcode.</p>
<p>I guess this decision makes sense for Apple. The Cocoa bindings for Java have not been supported since MacOS X 10.4 after all.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[C&#43;&#43; Object Initialization and Error Handling]]></title>
    <link href="https://blog.barthe.ph/2009/08/28/cpp_object_init_and_errors/"/>
    <id>https://blog.barthe.ph/2009/08/28/cpp_object_init_and_errors/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2009-08-28T00:00:00+00:00</published>
    <updated>2009-08-28T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>This column is in no way revolutionary. But looking back in the past, when I was learning C++, this is the kind of summary that I would have liked to read. So here it is, for the happy few!</p>
<h2 id="object-initialization">Object Initialization</h2>
<p>In C++, there are two common idioms with regards to object construction and initialization:</p>
<ul>
<li>
<p><strong>the constructor fully initializes the object</strong>: this idiom makes it impossible to construct an object which is not correctly initialized and ready to use.</p>
</li>
<li>
<p><strong>the constructor does not initialize (or partially initialize) the object</strong>: the initialization is performed at a latter stage by calling some <code>init()</code> method. This, in effect, splits the object allocation and initialization. It is common to encounter this pattern whenever the class mimics some transactional behavior like opening/closing a file, connection/disconnecting from a server&hellip;</p>
</li>
</ul>
<p>One may have legitimate reasons to use one idiom over the other, but as a rule of thumb, the first approach (full initialization in constructor) should be favored. This is because it makes it hard to use the interface of the object incorrectly. In the second case it is possible to construct the object and call a method on it before the initialization was performed.</p>
<p>There are two ways to handle this improper usage:</p>
<ul>
<li>
<p><strong>do nothing and state that this is an “undefined behavior”</strong>. It will probably make the class a bit faster to write, but harder to debug. Not a good idea&hellip;</p>
</li>
<li>
<p><strong>carry an internal state to remember whether or not the object was initialized</strong>. This make it possible to report errors in a much more graceful way. On the other hand it puts the burden on maintaining an internal state and checking against it. Maintaining an internal state looks very easy but my experience is that it is error prone in the long run&hellip;</p>
</li>
</ul>
<p>So in summary, unless you have a good reason not to construct a fully initialized object, then you should avoid doing it. It will make your code harder to use incorrectly and much simpler. And you probably will have to write less.</p>
<p>There’s one issue though: error handling.</p>
<h2 id="error-handling-at-initialization">Error Handling at Initialization</h2>
<p>There are three general ways to handle errors:</p>
<ul>
<li>
<p><strong>exceptions</strong>: this is the recommended and <strong>the best possible way</strong>.</p>
</li>
<li>
<p><strong>return error code on each function</strong>: this is the classical C idiom. In practice it means every function you call returns an error code and that <strong>you MUST!</strong> check against it.</p>
</li>
<li>
<p><strong>global error state</strong>: there is a function or method that you need to call after each method of the public API. This is similar to the role of the <code>GetLastError()</code> function in Win32. It’s quite unpractical, and very seldom used. Therefore, I will not discuss it any further&hellip;</p>
</li>
</ul>
<p>In the case of a fully initializing constructor, it is not possible to use the “return error code” idiom, because the constructor does not return anything. That makes it mandatory to use an exception based system.</p>
<p>I worked in a large organization that essentially banned the use of exceptions in their code, for rather dubious reasons. The consequence of this move was that people were forced to use the “non initializing constructor” idiom almost everywhere. This made the code more verbose (init/terminate functions everywhere), the interface easy to use incorrectly (many bugs were related to calling methods on a non initialized object) and put the burden on maintaining an internal state on each object (many bugs were related to failing to maintain this internal state correctly). But the main source of bug was by far, people “forgetting” to check against the error code, leading to much more subtle bugs long after the point of error.</p>
<h2 id="use-raii-to-avoid-leaks">Use RAII to avoid leaks</h2>
<p>It sounds like a good idea to favor the fully initializing constructor isn’t it? If you use this idiom, then you must know how to use exceptions properly. Techniques like <a href="http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization">RAII</a> and smart pointers are mandatory. Here’s one reason:</p>
<blockquote>
<p><strong>If an exception is throw in the constructor of an object, the destructor of that object is not called.</strong></p>
</blockquote>
<p>So if you do something like in the (counter)example below, you are in troubles:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// class Child1 and Child2 defined earlier...
</span></span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Parent</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">Parent</span><span class="p">()</span> <span class="o">:</span> <span class="n">m_child1</span><span class="p">(</span><span class="k">new</span> <span class="n">Child1</span><span class="p">()),</span> <span class="n">m_child2</span><span class="p">(</span><span class="k">new</span> <span class="n">Child2</span><span class="p">())</span> <span class="p">{</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">~</span><span class="n">Parent</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">m_child1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">             <span class="k">delete</span> <span class="n">m_child1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">m_child2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">             <span class="k">delete</span> <span class="n">m_child2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">     <span class="n">Parent</span><span class="p">(</span><span class="k">const</span> <span class="n">Parent</span><span class="o">&amp;</span><span class="n">amp</span><span class="p">;</span> <span class="p">);</span> <span class="c1">// non copyable
</span></span></span><span class="line"><span class="cl">     <span class="n">Parent</span> <span class="o">&amp;</span><span class="n">amp</span><span class="p">;</span><span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">Parent</span> <span class="o">&amp;</span><span class="n">amp</span><span class="p">;);</span> <span class="c1">// non assignable
</span></span></span><span class="line"><span class="cl">     <span class="n">Child1</span><span class="o">*</span> <span class="n">m_child1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">     <span class="n">Child2</span><span class="o">*</span> <span class="n">m_child2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><p>In this example if the constructor of <code>Child2</code> throws and exception, then the constructor of <code>Parent</code> also throws. Since the destructor of <code>Parent</code> is not called, the newly constructed <code>Child1</code> is not destroyed. It leaks!</p>
<p>However if you rely on smart pointers, the problem disappears. While the destructor of a class is not called if an exception is thrown in its constructor, the destructor of each instance variable is called. The following code would fix the leak:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// class Child1 and Child2 defined earlier...
</span></span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Parent</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">Parent</span><span class="p">()</span> <span class="o">:</span> <span class="n">m_child1</span><span class="p">(</span><span class="k">new</span> <span class="n">Child1</span><span class="p">()),</span> <span class="n">m_child2</span><span class="p">(</span><span class="k">new</span> <span class="n">Child2</span><span class="p">())</span> <span class="p">{</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">     <span class="n">Parent</span><span class="p">(</span><span class="k">const</span> <span class="n">Parent</span><span class="o">&amp;</span><span class="n">amp</span><span class="p">;</span> <span class="p">);</span> <span class="c1">// non copyable
</span></span></span><span class="line"><span class="cl">     <span class="n">Parent</span> <span class="o">&amp;</span><span class="n">amp</span><span class="p">;</span><span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">Parent</span> <span class="o">&amp;</span><span class="n">amp</span><span class="p">;);</span> <span class="c1">// non assignable
</span></span></span><span class="line"><span class="cl">     <span class="n">std</span><span class="o">::</span><span class="n">auto_ptr</span> <span class="n">m_child1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">     <span class="n">std</span><span class="o">::</span><span class="n">auto_ptr</span> <span class="n">m_child2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><p>That’s all folks!</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[The $2,000 one line bug fix]]></title>
    <link href="https://blog.barthe.ph/2009/08/04/one-line-bugfix/"/>
    <id>https://blog.barthe.ph/2009/08/04/one-line-bugfix/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2009-08-04T00:00:00+00:00</published>
    <updated>2009-08-04T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>Today, after 4 days of work, I have finally fixed a bug. The fix? Removing a single line of code which should have been there in the first place!</p>
<h2 id="the-bug">The Bug</h2>
<p>Sometimes, and at random, our application was crashing on exit. The crash was always some dodgy memory access violation. This happened after calling a <code>SendMessage()</code> to <code>HWND_BROADCAST</code>… I did not quite understand what was wrong with it, but calling <code>SendMessage</code> was stupid enough in the first place. So, I removed the <code>SendMessage</code>, replaced it by something much better, and promptly claimed to have fixed the bug. Voilà! Not surprisingly, on the very next day, QA found a similar crash in <code>DestroyWindow()</code>, albeit much harder to reproduce.</p>
<p>Time for a proper proper investigation!</p>
<h2 id="the-cause">The Cause</h2>
<p>A few days later, after unrolling tons and tons of code, I found miles away from the code that was crashing this little jewel:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">FrameWidget</span><span class="o">::~</span><span class="n">FrameWidget</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">m_hWnd</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="n">IsWindow</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">    <span class="n">DestroyWindow</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// etc...
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Suddenly, the whole picture got clearer.</p>
<p>The first line resets the window handle. The next one checks if the handle represents a window. Of course not! So no need to destroy the window object associated to the handle, right?! Then, by the time you get out of the destructor, your message map/callback functions have been destroyed and point to garbage memory… So, all it takes to crash it now, is one message routed to this window. And thanks to Murphy’s law, it indeed does happen, sometimes!</p>
<p>What <code>SendMessage()</code> to <code>HWND_BROADCAST</code> and <code>DestroyWindow()</code> have in common, is that they both actually send a message to this phantom window. In case you did not know, <code>DestroyWindow()</code> does purge the message loop before destroying the window…</p>
<p>Why was the handle  set to <code>null</code> in the first place is beyond me, but it sure was a bitch to find!</p>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/ms632682%28VS.85%29.aspx">DestroyWindow (MSDN)</a></li>
</ul>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Don’t Use Standard library/CRT Functions in Static initializers/DllMain!]]></title>
    <link href="https://blog.barthe.ph/2009/07/30/no-stdlib-in-dllmai/"/>
    <id>https://blog.barthe.ph/2009/07/30/no-stdlib-in-dllmai/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2009-07-30T00:00:00+00:00</published>
    <updated>2009-07-30T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<h2 id="the-problem">The Problem</h2>
<p>Today, <a href="https://groups.google.com/g/osg-users/c/tYMFKd4wI3s/m/YAoAOAKkdekJ">my colleague and I</a>, have found a bug in <a href="http://www.openscenegraph.org/">OpenSceneGraph</a>. Everybody knows that singletons are <a href="https://web.archive.org/web/20100124084725/http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx">evil</a> and may <a href="http://www.prestonlee.com/2006/07/11/singletons-cause-cancer/">cause cancer</a>, but that does not prevent OpenSceneGraph from using them all over the place. One of them, in particular, is initialized in the static context, and happens to call the standard library function <code>getenv()</code>. This was the beginning of all our troubles: from time to time, this seemingly benign initialization would cause a deadlock in our software.</p>
<p>Static initialization occurs, for instance, when you construct an object outside of any function body by writing something like <code>static ObjectBlah myGlobalVar = new ObjectBlah()</code>. The constructors are called before the entry point of your program (i.e. the <code>main()</code> function). In the case of a shared library, the static initialization generally occurs when the shared library is loaded. On Windows, the <code>DllMain</code> callback function is used for that purpose.</p>
<p>The rest of this post will detail the specific behavior on Windows, and explain why it is prone to deadlocks. I think it is generally a bad practice to call standard library functions on other platforms too, although I do not have a detailed proof to back my words (yet!).</p>
<h2 id="the-dangers-of-dllmain">The Dangers of DllMain</h2>
<p>If you read the <a href="http://msdn.microsoft.com/en-us/library/ms682583%28VS.85%29.aspx">MSDN documentation of DllMain</a>, you should realize that this function is quite dangerous to use. I extracted and highlighted some parts below:</p>
<blockquote>
<p><strong>Warning</strong> There are serious limits on what you can do in a DLL entry point. To provide more complex initialization, create an initialization routine for the DLL. You can require applications to call the initialization routine before calling any other routines in the DLL.</p>
</blockquote>
<blockquote>
<p>Because Kernel32.dll is guaranteed to be loaded in the process address space when the entry-point function is called, calling functions in Kernel32.dll does not result in the DLL being used before its initialization code has been executed. Therefore, the entry-point function can call functions in Kernel32.dll that do not load other DLLs. For example, <code>DllMain</code> can create <a href="http://msdn.microsoft.com/en-us/library/ms686364%28VS.85%29.aspx">synchronization objects</a> such as critical sections and mutexes, and use TLS. Unfortunately, there is not a comprehensive list of safe functions in Kernel32.dll.</p>
</blockquote>
<blockquote>
<p><strong>Windows 2000</strong>: Do not create a named synchronization object in <code>DllMain</code> because the system will then load an additional DLL.</p>
</blockquote>
<p>One of the reasons why it is so critical to not use <code>LoadLibrary()</code> or any kernel32.dll functions susceptible to call <code>LoadLibrary()</code> (like user32.dll) is because the process private critical section is locked while <code>DllMain</code> is running. This “loader lock” is taken any time a library is loaded but also when functions like <code>GetModuleHandle()</code> or <code>GetModuleFileName()</code> are used.</p>
<p>At this point you might think it is safe to call a standard library function, as long as it does not appear to require anything more than kernel32.dll functions, and is not using <code>GetModuleHandle()</code> nor <code>GetModuleFileName()</code>. This relies on implementation details of the standard library, so it’s a bit border line, but still might work, right? No… wrong! Now all you need to cause a deadlock is another lock. Guess what? There are plenty of locks taken in the standard library functions&hellip;</p>
<blockquote>
<p><strong>Principle</strong>: do not call any standard library functions that acquire locks in <code>DllMain()</code>.</p>
</blockquote>
<p>It’s quite another thing to know whether a function uses advanced kernel functions (unlikely to change) than to know whether it does acquire internal locks (subject to change every time Microsoft releases a new CRT). Therefore the following corollary can be deduced:</p>
<blockquote>
<p><strong>Corollary</strong>: do not use any standard library functions at all in <code>DllMain()</code> (because you really have no idea whether it will change and acquire a lock in the future).</p>
</blockquote>
<h2 id="the-deadlock">The Deadlock</h2>
<p>If you use CRT functions in your <code>DllMain()</code>, the following events might occur in the wrong preemption order and, consequently, cause a deadlock.</p>
<p>Imagine that you have one thread that calls <code>LoadLibrary()</code> on your DLL. It acquires the loader lock, then executes <code>DllMain()</code>, which finally executes your static initializer. At this stage if you use a CRT function, you will try to acquire an internal CRT lock…</p>
<p>Meanwhile, in the rest of you program, you might want to access another CRT function that happens to do the following: attempt to acquire the same CRT lock, then attempt to call <code>LoadLibrary</code> (because it uses an advanced kernel function that requires a new DLL to be loaded). <code>LoadLibrary</code> will attempt to acquire the loader lock as well.</p>
<p>Boom! You now have two thread that are trying to acquire two access locks in opposite orders.</p>
<p>In practice, the bug we discovered involved the following race condition:</p>
<ul>
<li>Thread A
<ol>
<li><code>LoadLibrary()</code> called. Acquire loader lock.</li>
<li><code>DllMain()</code> executes <code>getenv()</code>. Acquire <code>_ENV_LOCK</code>.</li>
</ol>
</li>
<li>Thread B
<ol>
<li><code>stat()</code> is called. Acquire <code>_ENV_LOCK</code></li>
<li><code>stat()</code> calls <code>GetTimeZoneInformation()</code>, which requires ntdll.dll to be loaded.</li>
<li>Then calls <code>LoadLibrary()</code> to get ntdll. Acquire loader lock.</li>
</ol>
</li>
</ul>
<p>If your threads are preempted such as 1, 3, 4, 2, 5 are executed in sequence, then you have a deadlock!</p>
<p>I discovered a posteriori that Richard Chen and Larry Osterman documented the problem. Although in their case they do not explicitly mention the C runtime, it is obvious that their remarks are relevant once you know that the CRT uses internal locks.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://devblogs.microsoft.com/oldnewthing/20040128-00/?p=40853">Another reason not to do anything scary in your DllMain: Inadvertent deadlock</a>, Raymond Chen, The Old New thing blog</li>
<li><a href="https://web.archive.org/web/20091211223634/http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx">Best practices for DllMain</a>, Larry Osterman’s blog</li>
</ul>
<h2 id="correction">Correction</h2>
<p>I previously wrote &ldquo;<em>the rest of this post will detail the behavior on Windows, but the same general principles are true for other platforms as well.</em>&rdquo;. This was a gross exaggeration. I’m still convinced that using libc in static initializers is prone to troubles on other platforms as well. Having it all work correctly depends on so many implementation details: kernel (how are shared objects loaded, how system calls works), libc (how does it interact with the kernel), and the linker (does it load stuff in the right order w.r.t. static initializers).</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[How to use WM_SETICON Properly]]></title>
    <link href="https://blog.barthe.ph/2009/07/17/wmseticon/"/>
    <id>https://blog.barthe.ph/2009/07/17/wmseticon/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2009-07-17T00:00:00+00:00</published>
    <updated>2009-07-17T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<h2 id="how-not-to-use-wm_seticon">How NOT to use <code>WM_SETICON</code></h2>
<p>It’s not rocket science, but you’d be surprised to see how many people get this wrong. Here’s a code snippet of what people usually do:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">const</span> <span class="n">HICON</span> <span class="n">hicon</span> <span class="o">=</span> <span class="o">::</span><span class="n">LoadIcon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="o">::</span><span class="n">GetModuleHandle</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="n">MAKEINTRESOURCE</span><span class="p">(</span><span class="n">IDR_MAINFRAME</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">hicon</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="o">::</span><span class="n">SendMessage</span><span class="p">(</span><span class="n">hwnd</span><span class="p">,</span> <span class="n">WM_SETICON</span><span class="p">,</span> <span class="n">ICON_BIG</span><span class="p">,</span> <span class="k">reinterpret_cast</span><span class="p">(</span><span class="n">hicon</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="o">::</span><span class="n">SendMessage</span><span class="p">(</span><span class="n">hwnd</span><span class="p">,</span> <span class="n">WM_SETICON</span><span class="p">,</span> <span class="n">ICON_SMALL</span><span class="p">,</span> <span class="k">reinterpret_cast</span><span class="p">(</span><span class="n">hicon</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>The code above would set the large icon (as displayed in the ALT-TAB switch window dialog) and the small icon (as displayed in the window title bar or the task bar) of the window (whose handle is <code>hwnd</code>).</p>
<p>Except for the error checking which is not particularly thorough, most people would consider this code to be correct. You could also have used <code>LoadImage</code> with <code>LR_DEFAULTSIZE</code>.</p>
<h2 id="why-this-is-wrong">Why this is wrong</h2>
<p>The problem reveals itself with an icon which has a slightly different design for the small 16×16 size compared to the large 32×32 size. The 16×16 icon will look like a scaled down version of the 32×32 one. The reason why the smaller icon looks different in the first place is usually because the large icon’s design is a bit overloaded and cannot be downscaled without becoming unrecognizable; so you will notice!</p>
<p>What’s wrong? If you dig into the documentation you will found the following information:</p>
<ul>
<li><code>LoadIcon</code> loads the most appropriate icon, at one fixed size, which is <code>SM_CXICON</code> by <code>SM_CYICON</code> pixels, i.e. the size of a large icon.</li>
<li>The small icon should be <code>SM_CXSMICON</code> by <code>SM_CYSMICON</code> pixels.</li>
<li><code>WM_SETICON</code> for <code>ICON_SMALL</code> would downscale a larger icon to <code>SM_CXSMICON</code> by <code>SM_CYSMICON</code> pixels automatically.</li>
<li>This odd behavior is due to backward compatibility with legacy versions of Windows, which only had one size of icons.</li>
</ul>
<h2 id="how-to-use-wm_seticon">How to use <code>WM_SETICON</code></h2>
<p>Now that we understand the problem (the wrong size of the icon is loaded), we know how to fix it. The solution is to call <code>LoadImage</code> twice and explicitly provides the size of the icon to avoid the downscaling.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">const</span> <span class="n">HANDLE</span> <span class="n">hbicon</span> <span class="o">=</span> <span class="o">::</span><span class="n">LoadImage</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="o">::</span><span class="n">GetModuleHandle</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="n">MAKEINTRESOURCE</span><span class="p">(</span><span class="n">IDR_MAINFRAME</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="n">IMAGE_ICON</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">::</span><span class="n">GetSystemMetrics</span><span class="p">(</span><span class="n">SM_CXICON</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="o">::</span><span class="n">GetSystemMetrics</span><span class="p">(</span><span class="n">SM_CYICON</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">hbicon</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="o">::</span><span class="n">SendMessage</span><span class="p">(</span><span class="n">hwnd</span><span class="p">,</span> <span class="n">WM_SETICON</span><span class="p">,</span> <span class="n">ICON_BIG</span><span class="p">,</span> <span class="k">reinterpret_cast</span><span class="p">(</span><span class="n">hbicon</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">const</span> <span class="n">HANDLE</span> <span class="n">hsicon</span> <span class="o">=</span> <span class="o">::</span><span class="n">LoadImage</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="o">::</span><span class="n">GetModuleHandle</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="n">MAKEINTRESOURCE</span><span class="p">(</span><span class="n">IDR_MAINFRAME</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="n">IMAGE_ICON</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">::</span><span class="n">GetSystemMetrics</span><span class="p">(</span><span class="n">SM_CXSMICON</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="o">::</span><span class="n">GetSystemMetrics</span><span class="p">(</span><span class="n">SM_CYSMICON</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">hsicon</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="o">::</span><span class="n">SendMessage</span><span class="p">(</span><span class="n">hwnd</span><span class="p">,</span> <span class="n">WM_SETICON</span><span class="p">,</span> <span class="n">ICON_SMALL</span><span class="p">,</span> <span class="k">reinterpret_cast</span><span class="p">(</span><span class="n">hsicon</span><span class="p">));</span>
</span></span></code></pre></div><h2 id="references">References</h2>
<p>Links to MSDN:</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/ms648045%28VS.85%29.aspx">LoadImage</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms648072%28VS.85%29.aspx">LoadIcon</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms633574%28VS.85%29.aspx#class_icons">Window classes, icon section</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms632643%28VS.85%29.aspx">WM_SETICON</a></li>
</ul>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Fast Subversion Update on a Rarely Updated Large Third Party Repository]]></title>
    <link href="https://blog.barthe.ph/2009/06/01/fast-svn-update/"/>
    <id>https://blog.barthe.ph/2009/06/01/fast-svn-update/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2009-06-01T00:00:00+00:00</published>
    <updated>2009-06-01T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>I have a project with a large repository, which contains a lot of ThirdParty sources and binaries, that are seldom updated. While subversion might not be the best suited tool for the job, the size of that repository is not insane enough to consider using something else… yet!</p>
<p>The problem with that rarely updated large repository is that performing an <code>svn update</code> on it can take quite a while even though there are no updates to perform. The reason is that subversion checks that no files are missing on the local checkout directory, because you can perform non recursive partial checkouts or updates, or potentially alter the whole structure after a checkout.</p>
<p>Nevertheless, if all you do is mirror the subversion directory content on your drive, you may have a faster option than <code>svn update</code>. You can use <code>svn info</code> to compare the local revision of your checkout to the latest available version on the server. If the revisions match it means your repository is up to date and you can avoid the costly <code>svn update</code>.</p>
<p>I regularly use a powershell script to automate that process.</p>
<h2 id="powershell-script">Powershell Script</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># Set your svn path</span>
</span></span><span class="line"><span class="cl"><span class="nv">$Svn</span> <span class="p">=</span> <span class="s2">&#34;svn.exe&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">trap</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">Write-Error</span> <span class="s2">&#34;</span><span class="nv">$_</span><span class="s2">.Exception.GetType().FullName + </span><span class="nv">$_</span><span class="s2">.Exception.Message&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nv">$args</span><span class="p">.</span><span class="py">length</span> <span class="o">-ne</span> <span class="mf">1</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">throw</span> <span class="s2">&#34;Invalid arguments&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$source_path</span> <span class="p">=</span> <span class="nv">$args</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">$local_info</span> <span class="p">=</span> <span class="p">&amp;</span> <span class="nv">$Svn</span> <span class="n">info</span> <span class="nv">$source_path</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nv">$LastExitCode</span> <span class="o">-ne</span> <span class="mf">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">throw</span> <span class="s2">&#34;Local svn info failed&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="nv">$local_revision</span> <span class="p">=</span> <span class="nv">$local_info</span> <span class="p">|</span> <span class="p">%{</span> <span class="k">if</span> <span class="p">(</span><span class="nv">$_</span><span class="p">.</span><span class="py">startsWith</span><span class="p">(</span><span class="s2">&#34;Revision&#34;</span><span class="p">))</span> <span class="p">{</span> <span class="nb">Write-Output</span> <span class="nv">$_</span> <span class="p">}</span> <span class="p">}</span> <span class="p">|</span> <span class="p">%{</span> <span class="nb">Write-Output</span> <span class="nv">$_</span><span class="p">.</span><span class="py">substring</span><span class="p">(</span><span class="nv">$_</span><span class="p">.</span><span class="py">indexOf</span><span class="p">(</span><span class="s2">&#34;: &#34;</span><span class="p">)</span><span class="mf">+2</span><span class="p">)</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="nv">$url</span> <span class="p">=</span> <span class="nv">$local_info</span> <span class="p">|</span> <span class="p">%{</span> <span class="k">if</span> <span class="p">(</span><span class="nv">$_</span><span class="p">.</span><span class="py">startsWith</span><span class="p">(</span><span class="s2">&#34;Repository Root&#34;</span><span class="p">))</span> <span class="p">{</span> <span class="nb">Write-Output</span> <span class="nv">$_</span> <span class="p">}</span> <span class="p">}</span> <span class="p">|</span> <span class="p">%{</span> <span class="nb">Write-Output</span> <span class="nv">$_</span><span class="p">.</span><span class="py">substring</span><span class="p">(</span><span class="nv">$_</span><span class="p">.</span><span class="py">indexOf</span><span class="p">(</span><span class="s2">&#34;: &#34;</span><span class="p">)</span><span class="mf">+2</span><span class="p">)</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="nv">$remote_info</span> <span class="p">=</span> <span class="p">&amp;</span> <span class="nv">$Svn</span> <span class="n">info</span> <span class="nv">$url</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nv">$LastExitCode</span> <span class="o">-ne</span> <span class="mf">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">throw</span> <span class="s2">&#34;Remote svn info failed&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="nv">$remote_revision</span> <span class="p">=</span> <span class="nv">$remote_info</span> <span class="p">|</span> <span class="p">%{</span> <span class="k">if</span> <span class="p">(</span><span class="nv">$_</span><span class="p">.</span><span class="py">startsWith</span><span class="p">(</span><span class="s2">&#34;Revision&#34;</span><span class="p">))</span> <span class="p">{</span> <span class="nb">Write-Output</span> <span class="nv">$_</span> <span class="p">}</span> <span class="p">}</span> <span class="p">|</span> <span class="p">%{</span> <span class="nb">Write-Output</span> <span class="nv">$_</span><span class="p">.</span><span class="py">substring</span><span class="p">(</span><span class="nv">$_</span><span class="p">.</span><span class="py">indexOf</span><span class="p">(</span><span class="s2">&#34;: &#34;</span><span class="p">)</span><span class="mf">+2</span><span class="p">)</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nv">$local_revision</span> <span class="o">-ne</span> <span class="nv">$remote_revision</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">svn</span> <span class="n">update</span> <span class="nv">$source_path</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nb">Write-Host</span> <span class="s2">&#34;Up to date&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div>]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[10 Tips to Avoid Spam]]></title>
    <link href="https://blog.barthe.ph/2009/03/01/no-spam-email/"/>
    <id>https://blog.barthe.ph/2009/03/01/no-spam-email/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2009-03-01T00:00:00+00:00</published>
    <updated>2009-03-01T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>I set up email on my phone and, even though I did not receive that many spams, it was more annoying than on a computer. Over the past few months, I have changed one of my main email addresses and took some radical steps to fight against spam.</p>
<p>Here are my few tips for a spamless life:</p>
<ol>
<li>
<p><strong>Do not publish your email address anywhere.</strong></p>
</li>
<li>
<p><strong>Do not register your email address anywhere.</strong></p>
</li>
<li>
<p><strong>If you need to register to a website then create a new account.</strong> Use this account just for the purpose of registering and enable mail forwarding to your main account. As soon as you start receiving spam from that account, or legitimate but annoying commercial content, disable email forwarding but leave the account alive (so that spammers waste resources).</p>
</li>
<li>
<p><strong>Never click on “un-register” links from emails.</strong></p>
</li>
<li>
<p><strong>Disable HTML viewing especially the viewing of images.</strong> You may set up a whitelist from known senders.</p>
</li>
<li>
<p><strong>Use state of the art anti-spam.</strong> I really like google gmail spam filters. I forward it to my final email provider that does use good spam-assassin rules.</p>
</li>
<li>
<p><strong>Try to have a core of 2 or 3 different email addresses shared among the people you know (no websites!).</strong> When you need to change your email, you will be upsetting fewer people. An idea is to set up groups like: family, friends from university, other friends, colleagues or former colleagues… groups of people you are unlikely to email simultaneously.</p>
</li>
<li>
<p><strong>Update your core email addresses when they are compromised.</strong> Do it gradually over an entire year by keeping email forwarding on and adding an auto reply rule informing your contacts they should stop using the old email. Do not write your new email in clear inside the automated message because it could be harvested by bots.</p>
</li>
<li>
<p>If your address is publicly available and spammed in huge amounts, make it mandatory for people to add some text in the title in order to contact you. Filter out everything not complying to the rule.</p>
</li>
<li>
<p>If your address is publicly available and the previous tip does not work (someone is deliberately targeting you) remove the contact email address from public space and replace it with a contact form using captcha.</p>
</li>
</ol>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Use the iPhone SDK on old Mac PPC machines]]></title>
    <link href="https://blog.barthe.ph/2009/03/01/iphone-sdk-ppc/"/>
    <id>https://blog.barthe.ph/2009/03/01/iphone-sdk-ppc/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2009-03-01T00:00:00+00:00</published>
    <updated>2009-03-01T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>Apple states that the iPhone SDK should only be used on Intel Macs.</p>
<p>However, the compiler, emulator and code signing tools work perfectly on older PPC Macs provided you work around the arbitrary limitations of the installer.</p>
<p>My iMac broke down so I had to revert to using my old and venerable PowerBook using Mac OS X 10.5.6 (9G55). I used the first public SDK (<code>md5=96849e4a17674d55d5af75b2d1d6579f</code>). The following tricks might not work with the latest versions.</p>
<h2 id="installation-steps">Installation Steps</h2>
<p>The installation steps are simple:</p>
<ol>
<li><strong>Install the iPhone SDK</strong>. The installer will install XCode but it will not let you select the iPhone components.</li>
<li><strong>Install the missing iPhone packages manually</strong>.
<ul>
<li>Those packages are located inside the <code>Packages</code> subdirectory of the SDK installation disk image.</li>
<li>You can simply double click on them to start installing.</li>
<li>You need to select the <code>/Developer</code> directory as the install location for each of them.</li>
<li>The packages to install manually are: <code>DeveloperDiskImage.pkg</code> and all the packages starting by <code>iPhone</code>.</li>
</ul>
</li>
<li><strong>Change <code>iPhone Simulator Architectures.xcspec</code>.</strong>
<ul>
<li>This allows to compile iPhone apps and to use the simulator on PPC machines.</li>
<li>The file is located into &ldquo;/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications/&rdquo;.</li>
</ul>
</li>
<li><strong>Change <code>/usr/bin/codesign</code>.</strong>
<ul>
<li>This allows to upload signed executable to the iPhone.</li>
<li>For some mysterious reasons <code>codesign</code> requires a universal binary, so the trick is to make it believe it got one.</li>
<li>You need to rename codesign <code>sudo mv /usr/bin/codesign /usr/bin/codesign.orig</code>.</li>
<li>Then replace it by the perl script attached below. Don’t forget to give it executable rights: <code>sudo chmod +x /usr/bin/codesign</code>.</li>
</ul>
</li>
</ol>
<p>That’s it. It should now work.</p>
<h2 id="files-to-replace">Files to Replace</h2>
<ul>
<li><a href="/download/2009/iPhone_Simulator_Architectures.xcspec">iPhone_Simulator_Architectures.xcspec</a></li>
<li><a href="/download/2009/codesign">codesign</a></li>
</ul>
<h2 id="links-to-original-authors">Links to Original Authors</h2>
<ul>
<li><a href="https://web.archive.org/web/20090103144337/http://discussions.apple.com/thread.jspa?threadID=1455699&amp;tstart=0">http://discussions.apple.com/thread.jspa?threadID=1455699&amp;tstart=0</a></li>
<li><a href="https://web.archive.org/web/20100306180848/http://www.tbradford.org/2008/03/iphone-sdk-beta-2-possible-ppc-fix.html">http://www.tbradford.org/2008/03/iphone-sdk-beta-2-possible-ppc-fix.html</a></li>
</ul>
<h2 id="updates">Updates</h2>
<p><strong>Update</strong>: it works perfectly with the latest version of the SDK i.e.</p>
<pre tabindex="0"><code>iphone_sdk_for_iphone_os_2.2.19m2621afinal.dmg, md5=9d0a818f41be507537495920cd0ef9bc
</code></pre><p><strong>Update</strong>: Obviously this trick no longer works for iOS 3 and more recent versions.</p>
]]></content>
  </entry>  
  <entry>
    <title type="html"><![CDATA[Changing a Signed Executable without Altering Windows Digital Signatures]]></title>
    <link href="https://blog.barthe.ph/2009/02/22/change-signed-executable/"/>
    <id>https://blog.barthe.ph/2009/02/22/change-signed-executable/</id>
    <author>
      <name>Aymeric Barthe</name>
    </author>
    <published>2009-02-22T00:00:00+00:00</published>
    <updated>2009-02-22T00:00:00+00:00</updated>
    <content type="html"><![CDATA[<p>It should not be possible, but it is… sort of.</p>
<h2 id="how-it-works">How it Works</h2>
<p>Microsoft Authenticode works as follows: it computes a cryptographic hash of the executable file. The hash is then used to make a digital certificate which is authenticated by some trusted authority.</p>
<p>The certificate is attached to the end of the PE executable, in a dedicated section called the Certificate Table. When the executable is loaded, Windows computes the hash value, and compares it to the one attached to the Certificate table. It should “normally” be impossible to change anything in the file without breaking the digital authentication.</p>
<p>However three areas of a PE executable are excluded from the hash computation:</p>
<ul>
<li>the Checksum in the optional Windows specific header: 4 bytes.</li>
<li>the Certificate Table entry in the optional Windows specific header: 8 bytes.</li>
<li>the Digital Certificate section at the end of the file: variable length.</li>
</ul>
<p>You should be able to change those area without breaking the signature. I have discovered by accident that it is possible to append an arbitrary amount of data at the end of the Digital Certificate. The data are ignored by both the signature parsing and hash computation algorithms. It works on all version of Windows I tested (2000, XP, Vista), as long as the length of the Certificate Table is correctly increased. The length is stored in two different location: the PE header and the beginning of the certificate table.</p>
<h2 id="how-to-add-a-payload-to-a-signed-executable">How to Add a Payload to a Signed Executable</h2>
<ol>
<li>Locate beginning of PE header (<code>PE</code>)</li>
<li>Skip COFF header (+=28 bytes)</li>
<li>Go to Certification Table Entry in the Windows specific optional PE header (+=120 bytes after COFF; total +=148 bytes)</li>
<li>Change size of Certificate Table as defined in <code>IMAGE_DATA_DIRECTORY.Size</code> to add the size of the payload.</li>
<li>Go to location defined <code>IMAGE_DATA_DIRECTORY.VirtualAddress</code>. This is the absolute location of the Certificate Table within the file.</li>
<li>Change again the size of the header, inside the <code>PKCS1_MODULE_SIGN.dwLength</code></li>
<li>This should normally be the last section in the executable; so go to the end and add payload</li>
<li>Possibly calculate the new checksum of the file</li>
</ol>
<p><strong>Caution</strong>: the previous constants are true for the 32 bit x86 versions of Windows. Payload needs to be 64 bits aligned. All the 32 bits constants are of course little endians woo woo!</p>
<h2 id="documentation-links">Documentation Links</h2>
<ul>
<li><a href="https://web.archive.org/web/20090219224404/http://www.thehackerslibrary.com/?p=377">http://www.thehackerslibrary.com/?p=377</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms904424.aspx">http://msdn.microsoft.com/en-us/library/ms904424.aspx</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/aa448396.aspx">http://msdn.microsoft.com/en-us/library/aa448396.aspx</a></li>
</ul>
<h2 id="sources">Sources</h2>
<ul>
<li><a href="/download/2009/AppendPayLoad.tar.bz2">AppendPayLoad.tar.bz2</a></li>
</ul>
]]></content>
  </entry>
</feed> 
