DefaultType text/plain
AddType audio/mp4 m4r
AddType application/rss+xml rss
# for /projects/samhuri.net ... sigh
AddType text/html net
SetOutputFilter DEFLATE
AddDefaultCharset utf-8

# Turn on Expires and set default expires to 3 days
ExpiresActive On
ExpiresDefault A259200

# Set up caching on media files for 1 month
<FilesMatch "\.(ico|gif|jpg|jpeg|png|pdf|mov|mp3|m4r|m4a)$">
  ExpiresDefault A2419200
  Header append Cache-Control "public"
  SetOutputFilter NONE
</FilesMatch>

# Set up 2 week caching on commonly updated files
<FilesMatch "\.(xml|txt|html|js|css|rss)$">
  ExpiresDefault A1209600
  Header append Cache-Control "private, must-revalidate"
</FilesMatch>

# Add HSTS header https://tools.ietf.org/html/rfc6797
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS

# Block pages from loading when they detect reflected XSS attacks
Header set X-XSS-Protection "1; mode=block"

# Prevent browsers from incorrectly detecting non-scripts as scripts
Header set X-Content-Type-Options "nosniff"

# Block site from being framed
Header set X-Frame-Options "DENY"

# Content Security Policy generated by Mozilla's CSP Toolkit
Header set Content-Security-Policy "default-src 'none'; img-src 'self' data: https://p.typekit.net; font-src 'self' https://use.typekit.net https://netdna.bootstrapcdn.com; script-src 'self' 'unsafe-inline' https://ajax.googleapis.com https://api.github.com https://gist.github.com https://use.typekit.net; style-src 'unsafe-inline' https://assets-cdn.github.com https://netdna.bootstrapcdn.com; base-uri 'none'; frame-ancestors 'none'; form-action 'none'"

# https://infosec.mozilla.org/guidelines/web_security#referrer-policy
Header set Referrer-Policy "no-referrer, strict-origin-when-cross-origin"

################
### Rewrites ###
################
RewriteEngine On

# Expose DreamHost stats
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/(stats|failed_auth\.html).*$ [NC]
RewriteRule . - [L]
</IfModule>

# Redirect http to https
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !beta\.samhuri\.net [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

# Make super old posts redirect properly.
#   e.g. http://sami.samhuri.net/2007/6/23/emacs-for-textmate-junkies
RewriteRule ^posts/([0-9][0-9][0-9][0-9])/([0-9])/[0-9]/(.*)$ /posts/$1/0$2/$3 [R=301]
RewriteRule ^posts/([0-9][0-9][0-9][0-9])/([0-9])/[0-9][0-9]/(.*)$ /posts/$1/0$2/$3 [R=301]
RewriteRule ^posts/([0-9][0-9][0-9][0-9])/([0-9][0-9])/[0-9]/(.*)$ /posts/$1/$2/$3 [R=301]
RewriteRule ^posts/([0-9][0-9][0-9][0-9])/([0-9][0-9])/[0-9][0-9]/(.*)$ /posts/$1/$2/$3 [R=301]

# Don't redirect to URLs with trailing slashes (because everything from harp is a directory)
DirectorySlash Off
RewriteCond %{REQUEST_FILENAME} !/$
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}/index.html -f
RewriteRule ^(.*)$ $1/index.html [L]

# Never ended up running with this, give it back.
Redirect 301 /json-diff http://tlrobinson.net/projects/javascript-fun/jsondiff

# The great vowel shortage of 1974 is over.
Redirect 301 /proj /projects

Redirect 301 /blog/sjs.rss /feed.xml
Redirect 301 /blog /posts

# Old naming scheme, incompatible with Harp.
Redirect 301 /blog/2006.02.08-first-post /posts/2006/02/first-post
Redirect 301 /blog/2006.02.08-touch-screen-on-steroids /posts/2006/02/touch-screen-on-steroids
Redirect 301 /blog/2006.02.15-urban-extreme-gymnastics /posts/2006/02/urban-extreme-gymnastics
Redirect 301 /blog/2006.02.18-girlfriend-x /posts/2006/02/girlfriend-x
Redirect 301 /blog/2006.02.18-jump-to-viewcontroller-in-textmate /posts/2006/02/jump-to-viewcontroller-in-textmate
Redirect 301 /blog/2006.02.18-some-textmate-snippets-for-rails-migrations /posts/2006/02/some-textmate-snippets-for-rails-migrations
Redirect 301 /blog/2006.02.20-obligatory-post-about-ruby-on-rails /posts/2006/02/obligatory-post-about-ruby-on-rails
Redirect 301 /blog/2006.02.20-textmate-snippets-for-rails-assertions /posts/2006/02/textmate-snippets-for-rails-assertions
Redirect 301 /blog/2006.02.21-textmate-insert-text-into-self-down /posts/2006/02/textmate-insert-text-into-self-down
Redirect 301 /blog/2006.02.21-textmate-move-selection-to-self-down /posts/2006/02/textmate-move-selection-to-self-down
Redirect 301 /blog/2006.02.22-intelligent-migration-snippets-0.1-for-textmate /posts/2006/02/intelligent-migration-snippets-0_1-for-textmate
Redirect 301 /blog/2006.02.23-sjs-rails-bundle-0.2-for-textmate /posts/2006/02/sjs-rails-bundle-0_2-for-textmate
Redirect 301 /blog/2006.03.03-generate-selfdown-in-your-rails-migrations /posts/2006/03/generate-selfdown-in-your-rails-migrations
Redirect 301 /blog/2006.03.03-i-dont-mind-fairplay-either /posts/2006/03/i-dont-mind-fairplay-either
Redirect 301 /blog/2006.03.03-spore /posts/2006/03/spore
Redirect 301 /blog/2006.04.04-zsh-terminal-goodness-on-os-x /posts/2006/04/zsh-terminal-goodness-on-os-x
Redirect 301 /blog/2006.05.07-os-x-and-fitts-law /posts/2006/05/os-x-and-fitts-law
Redirect 301 /blog/2006.05.07-wikipediafs-on-linux-in-python /posts/2006/05/wikipediafs-on-linux-in-python
Redirect 301 /blog/2006.06.05-ich-bin-auslnder-und-spreche-nicht-gut-deutsch /posts/2006/06/ich-bin-auslnder-und-spreche-nicht-gut-deutsch
Redirect 301 /blog/2006.06.09-never-buy-a-german-keyboard /posts/2006/06/never-buy-a-german-keyboard
Redirect 301 /blog/2006.06.10-theres-nothing-regular-about-regular-expressions /posts/2006/06/theres-nothing-regular-about-regular-expressions
Redirect 301 /blog/2006.06.11-apple-pays-attention-to-detail /posts/2006/06/apple-pays-attention-to-detail
Redirect 301 /blog/2006.07.06-working-with-the-zend-framework /posts/2006/07/working-with-the-zend-framework
Redirect 301 /blog/2006.07.13-ubuntu-linux-for-linux-users-please /posts/2006/07/ubuntu-linux-for-linux-users-please
Redirect 301 /blog/2006.07.17-ruby-and-rails-have-spoiled-me-rotten /posts/2006/07/ruby-and-rails-have-spoiled-me-rotten
Redirect 301 /blog/2006.07.19-late-static-binding /posts/2006/07/late-static-binding
Redirect 301 /blog/2006.07.21-class-method-instance-method-it-doesnt-matter-to-php /posts/2006/07/class-method-instance-method-it-doesnt-matter-to-php
Redirect 301 /blog/2006.08.22-where-are-my-headphones /posts/2006/08/where-are-my-headphones
Redirect 301 /blog/2006.09.16-buffalo-buffalo-buffalo-buffalo-buffalo-buffalo-buffalo-buffalo /posts/2006/09/buffalo-buffalo-buffalo-buffalo-buffalo-buffalo-buffalo-buffalo
Redirect 301 /blog/2006.09.22-some-features-you-might-have-missed-in-itunes-7 /posts/2006/09/some-features-you-might-have-missed-in-itunes-7
Redirect 301 /blog/2006.12.17-coping-with-windows-xp-activiation-on-a-mac /posts/2006/12/coping-with-windows-xp-activiation-on-a-mac
Redirect 301 /blog/2007.03.06-full-screen-cover-flow /posts/2007/03/full-screen-cover-flow
Redirect 301 /blog/2007.03.08-digg-v4-reply-to-replies-greasemonkey-script /posts/2007/03/digg-v4-reply-to-replies-greasemonkey-script
Redirect 301 /blog/2007.03.25-diggscuss-0.9 /posts/2007/03/diggscuss-0_9
Redirect 301 /blog/2007.04.04-a-triple-booting-schizophrenic-macbook /posts/2007/04/a-triple-booting-schizophrenic-macbook
Redirect 301 /blog/2007.04.11-activerecord-base.find_or_create-and-find_or_initialize /posts/2007/04/activerecord-base.find_or_create-and-find_or_initialize
Redirect 301 /blog/2007.04.16-getting-to-know-vista /posts/2007/04/getting-to-know-vista
Redirect 301 /blog/2007.04.26-quickly-inserting-millions-of-rows-with-mysql-innodb /posts/2007/04/quickly-inserting-millions-of-rows-with-mysql-innodb
Redirect 301 /blog/2007.04.30-funny-how-code-can-be-beautiful /posts/2007/04/funny-how-code-can-be-beautiful
Redirect 301 /blog/2007.05.01-typo-and-i-are-friends-again /posts/2007/05/typo-and-i-are-friends-again
Redirect 301 /blog/2007.05.03-a-scheme-parser-in-haskell-part-1 /posts/2007/05/a-scheme-parser-in-haskell-part-1
Redirect 301 /blog/2007.05.05-a-new-way-to-look-at-networking /posts/2007/05/a-new-way-to-look-at-networking
Redirect 301 /blog/2007.05.05-gotta-love-the-ferry-ride /posts/2007/05/gotta-love-the-ferry-ride
Redirect 301 /blog/2007.05.09-dtrace-ruby-goodness-for-sun /posts/2007/05/dtrace-ruby-goodness-for-sun
Redirect 301 /blog/2007.05.09-i-cant-wait-to-see-what-matt-stone-trey-parker-do-with-this /posts/2007/05/i-cant-wait-to-see-what-matt-stone-trey-parker-do-with-this
Redirect 301 /blog/2007.05.10-enumerable-pluck-and-string-to_proc-for-ruby /posts/2007/05/enumerable-pluck-and-string-to_proc-for-ruby
Redirect 301 /blog/2007.05.10-rails-plugins-link-dump /posts/2007/05/rails-plugins-link-dump
Redirect 301 /blog/2007.05.15-dumping-objects-to-the-browser-in-rails /posts/2007/05/dumping-objects-to-the-browser-in-rails
Redirect 301 /blog/2007.05.16-cheating-at-life-in-general /posts/2007/05/cheating-at-life-in-general
Redirect 301 /blog/2007.05.18-iphone-humour /posts/2007/05/iphone-humour
Redirect 301 /blog/2007.05.22-inspirado /posts/2007/05/inspirado
Redirect 301 /blog/2007.05.26-finnish-court-rules-css-ineffective-at-protecting-dvds /posts/2007/05/finnish-court-rules-css-ineffective-at-protecting-dvds
Redirect 301 /blog/2007.06.08-301-moved-permanently /posts/2007/06/301-moved-permanently
Redirect 301 /blog/2007.06.08-so-long-typo-and-thanks-for-all-the-timeouts /posts/2007/06/so-long-typo-and-thanks-for-all-the-timeouts
Redirect 301 /blog/2007.06.14-more-scheming-with-haskell /posts/2007/06/more-scheming-with-haskell
Redirect 301 /blog/2007.06.14-testspec-on-rails-declared-awesome-just-one-catch /posts/2007/06/testspec-on-rails-declared-awesome-just-one-catch
Redirect 301 /blog/2007.06.15-begging-the-question /posts/2007/06/begging-the-question
Redirect 301 /blog/2007.06.18-back-on-gentoo-trying-new-things /posts/2007/06/back-on-gentoo-trying-new-things
Redirect 301 /blog/2007.06.20-reinventing-the-wheel /posts/2007/06/reinventing-the-wheel
Redirect 301 /blog/2007.06.22-embrace-the-database /posts/2007/06/embrace-the-database
Redirect 301 /blog/2007.06.23-emacs-for-textmate-junkies /posts/2007/06/emacs-for-textmate-junkies
Redirect 301 /blog/2007.06.24-floating-point-in-elschemo /posts/2007/06/floating-point-in-elschemo
Redirect 301 /blog/2007.06.25-emacs-tagify-region-or-insert-tag /posts/2007/06/emacs-tagify-region-or-insert-tag
Redirect 301 /blog/2007.06.25-propaganda-makes-me-sick /posts/2007/06/propaganda-makes-me-sick
Redirect 301 /blog/2007.06.26-rtfm /posts/2007/06/rtfm
Redirect 301 /blog/2007.06.28-recent-ruby-and-rails-regales /posts/2007/06/recent-ruby-and-rails-regales
Redirect 301 /blog/2007.06.30-controlling-volume-via-the-keyboard-on-linux /posts/2007/06/controlling-volume-via-the-keyboard-on-linux
Redirect 301 /blog/2007.07.03-a-textmate-tip-for-emacs-users /posts/2007/07/a-textmate-tip-for-emacs-users
Redirect 301 /blog/2007.07.05-rushcheck-quickcheck-for-ruby /posts/2007/07/rushcheck-quickcheck-for-ruby
Redirect 301 /blog/2007.07.06-see-your-regular-expressions-in-emacs /posts/2007/07/see-your-regular-expressions-in-emacs
Redirect 301 /blog/2007.07.12-people /posts/2007/07/people
Redirect 301 /blog/2007.08.02-elschemo-boolean-logic-and-branching /posts/2007/08/elschemo-boolean-logic-and-branching
Redirect 301 /blog/2007.08.09-cheat-from-emacs /posts/2007/08/cheat-from-emacs
Redirect 301 /blog/2007.08.09-snap-crunchle-pop /posts/2007/08/snap-crunchle-pop
Redirect 301 /blog/2007.08.11-opera-is-pretty-slick /posts/2007/08/opera-is-pretty-slick
Redirect 301 /blog/2007.08.19-catch-compiler-errors-at-runtime /posts/2007/08/catch-compiler-errors-at-runtime
Redirect 301 /blog/2007.08.21-cheat-productively-in-emacs /posts/2007/08/cheat-productively-in-emacs
Redirect 301 /blog/2007.08.26-captivating-little-creatures /posts/2007/08/captivating-little-creatures
Redirect 301 /blog/2007.08.30-5-ways-to-avoid-looking-like-a-jerk-on-the-internet /posts/2007/08/5-ways-to-avoid-looking-like-a-jerk-on-the-internet
Redirect 301 /blog/2007.09.25-learning-lisp-read-pcl /posts/2007/09/learning-lisp-read-pcl
Redirect 301 /blog/2007.09.26-python-and-ruby-brain-dump /posts/2007/09/python-and-ruby-brain-dump
Redirect 301 /blog/2007.10.29-gtkpod-in-gutsy-got-you-groaning /posts/2007/10/gtkpod-in-gutsy-got-you-groaning
Redirect 301 /blog/2008.01.07-random-pet-peeve-of-the-day /posts/2008/01/random-pet-peeve-of-the-day
Redirect 301 /blog/2008.02.19-thoughts-on-arc /posts/2008/02/thoughts-on-arc
Redirect 301 /blog/2008.03.03-project-euler-code-repo-in-arc /posts/2008/03/project-euler-code-repo-in-arc
Redirect 301 /blog/2009.11.21-using-emacs-to-develop-mojo-apps-for-webos /posts/2009/11/using-emacs-to-develop-mojo-apps-for-webos
Redirect 301 /blog/2010.01.17-working-with-c-style-structs-in-ruby /posts/2010/01/working-with-c-style-structs-in-ruby
Redirect 301 /blog/2010.01.18-basics-of-the-mach-o-file-format /posts/2010/01/basics-of-the-mach-o-file-format
Redirect 301 /blog/2010.01.20-a-preview-of-mach-o-file-generation /posts/2010/01/a-preview-of-mach-o-file-generation
Redirect 301 /blog/2010.11.04-37signals-chalk-dissected /posts/2010/11/37signals-chalk-dissected
Redirect 301 /blog/2011.11.27-lights /posts/2011/11/lights
Redirect 301 /blog/2011.11.27-recovering-old-posts /posts/2011/11/recovering-old-posts
Redirect 301 /blog/2011.12.10-static-url-shortener-using-htaccess /posts/2011/12/static-url-shortener-using-htaccess
Redirect 301 /blog/2011.12.11-pure-css3-images-hmm-maybe-later /posts/2011/12/pure-css3-images-hmm-maybe-later
Redirect 301 /blog/2011.12.15-i-see-http /posts/2011/12/i-see-http
Redirect 301 /blog/2011.12.19-my-kind-of-feature-checklist /posts/2011/12/my-kind-of-feature-checklist
Redirect 301 /blog/2011.12.22-new-release-of-firefox-for-android-optimized-for-tablets /posts/2011/12/new-release-of-firefox-for-android-optimized-for-tablets
Redirect 301 /blog/2011.12.25-the-broken-pixel-theory /posts/2011/12/the-broken-pixel-theory
Redirect 301 /blog/2012.01.04-yak-shaving /posts/2012/01/yak-shaving
Redirect 301 /blog/2012.01.09-the-40-standup-desk /posts/2012/01/the-40-standup-desk
Redirect 301 /blog/2012.01.17-recovering-from-a-computer-science-education /posts/2012/01/recovering-from-a-computer-science-education
Redirect 301 /blog/2012.01.17-sopa-lives-and-mpaa-calls-protests-an-abuse-of-power /posts/2012/01/sopa-lives-and-mpaa-calls-protests-an-abuse-of-power
Redirect 301 /blog/2012.01.19-fujitsu-has-lost-their-mind /posts/2012/01/fujitsu-has-lost-their-mind
Redirect 301 /blog/2013.03.06-zelda-tones-for-ios /posts/2013/03/zelda-tones-for-ios
Redirect 301 /blog/2013.09.27-linky /posts/2013/09/linky
Redirect 301 /blog/2014.02.03-ember-structure /posts/2014/02/ember-structure
