Final Musings tumblr import

This commit is contained in:
JP Hastings-Spital 2023-05-27 09:23:55 +01:00
parent 05e0e09636
commit 7aa1b1ed42
19 changed files with 345 additions and 13 deletions

View file

@ -15,7 +15,7 @@ She didn't know what the shapes meant, but they felt like home.
A sharp tug on the chains dragged her through the door, her red hair thrown into her face.
She knew this was the end - even if the clang of machinery and misery of cold laughter woven together hadn't destroyed all hope, she knew at her core that fate's plans for her ended here. Despite this her head was high and her chest proud -- she would face this with honour and dignity.
She knew this was the end - even if the clang of machinery and misery of cold laughter woven together hadn't destroyed all hope, she knew at her core that fate's plans for her ended here. Despite this her head was high and her chest proud she would face this with honour and dignity.
She stood and stared at the distant figures in front of her as the chains slackened around her waist. One looked at her briefly, paused, and continued working, head hung. The other didn't seem to notice her.

View file

@ -0,0 +1,24 @@
---
title: Crunch boxes
date: 2010-10-20T23:18:00+01:00
draft: false
emoji: 💻
tags:
- idea
- computing
- from-tumblr
---
After a quick support request from the Plex team I [mentioned](http://www.exquisitetweets.com/tweets?ids=27961963239.27962240192.27962528580.27962628615) how much I'd like a linux version of the Plex Media Server so I could look to getting it working on a [Drobo FS](http://www.drobo.com/products/drobo-fs.php).
As the anonymous Plexian noted, the major issue with this would be the lack of power in Drobo's CPU for transcoding — you just wouldn't be able to live-stream videos to mobile devices from PMS running on embedded systems.
With a bit of tinkering you can farm out data intensive tasks like this to more powerful processors, I suggested leveraging the power from a PMS on a traditional computer on the network, but it got me to thinking:
Wouldn't it be cool if you could buy or create a totally headless computer which you could hook up to power and the network and would provide number crunching power to any application which needed it?
My first thoughts would be to create/use a specific distro of linux. You'd create daemons for a few common place CPU intensive tasks (video transcoding for example) and, as the OS would be standard, any specific daemons could be pushed to the 'crunch box' to perform any other task.
The major benefit of these, as far as I can see, is being able to have the grunt force for processing sleeping on your network, using minimal power, until it's required. I'm pretty conscious of how much power my iMac would use if I left it on just to funnel video to my iPhone via Plex while I'm travelling.
So, for anyone reading this, do you think such a system could be created? Is there anything you would want included?

View file

@ -0,0 +1,29 @@
---
title: It's a Good Day for this film to Die Hard
date: 2013-02-14T23:12:00+00:00
draft: false
emoji: 🔫
images:
tags:
- film
- review
- imdb:tt1606378
- terrible
- from-tumblr
---
{{% importnote 2023-05-27 %}}
I don't normally prefix my very old and imported blog posts like this (I quite like them to stand alone as an artifact of my past) but I find this review I wrote particulaly hard to read! I know my sense of pacing has had a chance to improve specifically because of writing a lot while I was younger, but I feel like my disgust for this film brings a new layer of difficulty to reading this! Good luck…
Oh, and I'd warn you of spoilers ahead, but you'll be more spoiled if you **do** watch this film.
{{%/ importnote %}}
John McClane, a man who puts his job as a policeman above all else, is quickly brought to realise that he missing out on the finer things in life. Just as this sinks in, he discovers he is alone, caught behind enemy lines in an unlikely situation where his unique blend of don't-give-a-shit and in-your-face arrogance can aggravate "the baddie" to the point where they sideline their original plot in order to stop him instead.
In doing this, he buys enough time for: the baddies to thin themselves out (and be picked off), the reinforcements to arrive, and his ex-wife/partner/family member to appreciate his passion for his job. Cue credits: the baddies are foiled, family is closer; "Yippee-ki-yay mo fo".
This is the plot of Die Hard, Die Hard 2: Die Harder, Die Hard: With A Vengence and Live Free or Die Hard. It works. It's not complicated—it doesn't need to be—it's a Die Hard film.
My general point is: It is *not* a Good Day to Die Hard. One or two people do die, but not particularly hard. There is no 'behind enemy lines', there's little quick talking attitude to get our protagonists out of trouble (there's little talking at all), there isn't really a baddie to speak of, there's no plot (which the baddies are tying to complete; there's also no plot to the film), there's no "good man trying to do right by his own morals", there are no reinforcements, and in general **there is no tension**. The film starts with an extended action sequence which finishes an hour an half later, having given Bruce Willis enough time to catch his breath and say enough to allow him to call it a "speaking role". The clincher? (if one was needed) We do not watch Die Hard films for cerebral engagement, we watch for simple, enjoyable action with enough predictable moments for the secondary characters to shake their heads at each other, chuckle, and say "That John McClane, always getting into trouble." - this film misses that by such a margin as to be completely unfollowable, forgettable and, frankly, irritating. The words "Yippee-ki-yay" don't even pass Bruce's lips.
Do not waste your time with the so-called "5th" Die Hard film. It never existed.

View file

@ -2,7 +2,7 @@
title: Facebook API Niggle
date: 2009-07-29T00:49:00+01:00
draft: false
emoji: 🗣
emoji:
images:
tags:
- facebook
@ -11,7 +11,11 @@ tags:
- from-tumblr
---
I like Facebook (despite its recent frustrating changes that make walls confusing) but I have a niggle as a developer using their APIs. If you choose to use Facebook's XFBML to put a commenting system on your blog (like I do here) then anyone posting that page inside facebook has a separate comments list. Try posting this page on facebook[^1], if you comment on that post in your feed the comments won't appear on this page and things you write here won't appear there. Granted, sometimes this behaviour is preferable (popular sites might have thousands of comments on one page, and 99% will probably not be your friends or anyone you care about) but it would be good if when you initially 'share' a link on facebook, while the javascript is grabbing the pictures and headlines from the page, it would also look for XFBML and tie the commenting systems together if the site publisher had the relevant option toggled in their [developer settings](http://www.facebook.com/developers/). You could even have non-friends' posts hidden by default (or listed merely as '34 other posts'). I realise its hardly a pressing problem, but I really love Facebook's interconnectivity and I use off-site Facebook commenting in a couple of places[^2], it'd be nice to see it happen!
I like Facebook (despite its recent frustrating changes that make walls confusing) but I have a niggle as a developer using their APIs. If you choose to use Facebook's XFBML to put a commenting system on your blog (like I do here) then anyone posting that page inside facebook has a separate comments list. Try posting this page on facebook[^1], if you comment on that post in your feed the comments won't appear on this page and things you write here won't appear there.
Granted, sometimes this behaviour is preferable (popular sites might have thousands of comments on one page, and 99% will probably not be your friends or anyone you care about) but it would be good if when you initially 'share' a link on facebook, while the javascript is grabbing the pictures and headlines from the page, it would also look for XFBML and tie the commenting systems together if the site publisher had the relevant option toggled in their [developer settings](http://www.facebook.com/developers/). You could even have non-friends' posts hidden by default (or listed merely as '34 other posts').
I realise its hardly a pressing problem, but I really love Facebook's interconnectivity and I use off-site Facebook commenting in a couple of places[^2], it'd be nice to see it happen!
[^1]: Import note: This won't work any more, as this site no longer uses Facebook's XFBML comments. (I'm not even sure if that feature still exists!)
[^2]: Import note: There were three links to other blogs/websites of mine, all of which now exist within this one.

View file

@ -0,0 +1,39 @@
---
title: mini_magic and Apache Passenger
date: 2013-01-23T11:26:00+00:00
draft: false
emoji: 🌇
tags:
- ruby
- apache
- passenger
- code
- fix
- imagemagick
- homebrew
- from-tumblr
---
A note out there to anyone else having the same problem as me:
If you're trying to use [mini_magick](https://github.com/minimagick/minimagick) in a ruby application being run via [Passenger](https://www.phusionpassenger.com/) on Mac OS X Mountain Lion's Apache2, when you've installed imagemagick via [Homebrew](http://mxcl.github.com/homebrew) - _mouthful_ - then you may notice that that you get a Server Error when you try to process an image.
This may be because the `PATH` variable Apache is supplying to your ruby instance doesn't have `/usr/local/bin` in it, which is where homebrew installs to.
It seems that the `_www` user doesn't check the `/etc/paths` file for additions to the PATH variable, so you get squat.
My solution is hacky, but it gets the job done. I have a file called `/etc/apache2/other/passenger.conf` which holds the details for the virtual hosts for my passenger apps. I added the `SetEnv` line at the top to force Apache to set the PATH variable correctly.
It now looks something like this:
```Tcl
SetEnv PATH /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
ServerName my.rubyapp.com
ServerAlias my.rubyapp.com
DocumentRoot /var/www/myapp/public
RackEnv production
Order allow,deny
Allow from all
ErrorLog "/var/log/apache2/my.rubyapp.com_error-log"
CustomLog "/var/log/apache2/my.rubyapp.com_access-log" common
```

View file

@ -0,0 +1,23 @@
---
title: Pretty JSON in the terminal
date: 2013-03-20T16:02:00+00:00
draft: false
emoji: ✨
tags:
- terminal
- tools
- from-tumblr
---
[kaspertidemann.com](https://web.archive.org/web/20141024021149/http://www.kaspertidemann.com/pretty-printing-json-in-the-terminal/)
This was _exactly_ what I was looking for.
If you're investingating JSON returned from a web service, get the control you need with the terminal and [jsonpp](https://github.com/jmhodges/jsonpp):
```sh
brew install jsonpp
curl -u username:password http://awesome.com/stuff.json | jsonpp
```
BOOM. As they say.

View file

@ -19,4 +19,4 @@ Though these are, perhaps, uninspiring names they were chosen to allow readers (
Each person is represented in the artwork below by a coloured shape. Each shape's centre is placed on the canvas according to their age, with older people towards the right, and the first people to collaborate nearer the bottom. The colour of the shape shows their preference towards each poem the stronger the primary colour the more they liked that poem; red for Chapter II, green for Chapter III and blue for Chapter IV. Chapter I has is preference shown by transparency, the faster a shape pulses the more it was liked by the person it represents.
If you're interested in the code I used to generate the work, you can see it [in a gist on github](https://gist.github.com/jphastings/362995) -- I hope you enjoy it!
If you're interested in the code I used to generate the work, you can see it [in a gist on github](https://gist.github.com/jphastings/362995) I hope you enjoy it!

View file

@ -0,0 +1,14 @@
---
title: REST and how to do it right
date: 2013-03-21T13:41:00+00:00
draft: false
emoji: 📄
tags:
- code
- rest
- from-tumblr
---
[gregbeech.com](https://www.gregbeech.com/2013/05/21/restful-api-design-the-fundamentals/)
Bossman Greg has posted a thorough and readable rundown of REST design concepts. Well worth a read.

View file

@ -0,0 +1,29 @@
---
title: Ruby and Jenkins
date: 2013-03-01T09:37:00+00:00
draft: false
emoji: ⚙️
images:
tags:
- jenkins
- code
- ruby
- from-tumblr
---
I was trying to integrate my Cucumber and RSpec tests with Jenkins earlier this week and came across a bunch of character encoding errors.
It took me a while to figure out the problem, essentially Jenkins loads a session without all your usual environment variables, so your `PATH` and `LANG` won't be set to the same as a terminal window, making the outcomes different.
My Jenkins executed shell script now looks like this, note the PATH and LANG exports!
```sh
export LANG=en_GB.UTF-8
export PATH=/Users/admin/.rvm/gems/ruby-1.9.3-p385/bin:/Users/admin/.rvm/gems/ruby-1.9.3-p385@global/bin:/Users/admin/.rvm/rubies/ruby-1.9.3-p385/bin:/Users/admin/.rvm/bin:/usr/local/bin:$PATH
rvm use 1.9.3 --install --binary --fuzzy
bundle install
ruby --version
gem --version
rake spec
rake features
```

View file

@ -0,0 +1,14 @@
---
title: Speakable web links
date: 2012-10-08T09:53:00+00:00
draft: false
emoji: 🔗
tags:
- from-tumblr
---
A long time ago [benosteen wrote](http://benosteen.tumblr.com/post/465782940/thinking-about-making-a-url-shortener-which) that he'd link to make a URL shortener that creates speakable URLs.
Looking back over this (hideously unkempt) blog I realised I finished building exactly this a few weeks back. Take a peek at [Iconic.im](http://iconic.im)[^1].
[^1]: Import note: I don't own this domain any more, but I'd like to run this service again!

View file

@ -15,4 +15,4 @@ tags:
If he doesn't get on it soon I certainly will![^1] URLs can be a real pain to speak.
[^1]: Import note: I did! iconic.im existed for a fair while, the code still [sits on github](https://github.com/jphastings/iconic).
[^1]: Import note: I did! iconic.im existed for a fair while, the code still [sits on github](https://github.com/jphastings/iconic). I actually [posted about it](/posts/speakable-web-links) on this same tumblr 2 years later!

View file

@ -0,0 +1,17 @@
---
title: The Extra Mile
date: 2013-03-27T14:54:00+00:00
draft: false
emoji: 🤓
tags:
- humans
- from-tumblr
---
I'm not sure whether it was the company or the lovely lady who looked after me (or both), but Optical Express have surprised me this afternoon with a personal touch uncharacteristic of busy London shops.
I asked how quickly I could have new prescription sunglasses made and she not only offered the company's standard 2-day turn around, but also offered that if I was prepared to deliver the frames to their lab/branch myself I's reduce that time by a day, as their intra-store delivered are every morning.
It may seem little, but this thinking-outside-the-system really impressed me. It'd be very simple to say "this is the process", but I've now delivered my glasses (a short 10 minute walk away), will receive my glasses sooner and, if they don't have any other glasses to pick up tomorrow, they've saved themselves a journey.
A lovely little win-win because of some attention and flexible thinking.

View file

@ -13,7 +13,7 @@ tags:
{{< vimeo 10866898 >}}
I've released [Thimblr](https://github.com/jphastings/thimblr) -- a tool to speed up your Tumblr theme development. Its a Ruby gem, so it's very simple to install, with `gem install Thimblr`, once that's done you just need to run `thimblr`, as a binary is installed for you with the gem.
I've released [Thimblr](https://github.com/jphastings/thimblr) a tool to speed up your Tumblr theme development. Its a Ruby gem, so it's very simple to install, with `gem install Thimblr`, once that's done you just need to run `thimblr`, as a binary is installed for you with the gem.
This screencast should help you with the basics, though I've designed it to be totally self explanatory, but if you have any problems please open an [issue on github](http://github.com/jphastings/thimblr/issues) and I'll get right on it!

View file

@ -0,0 +1,83 @@
---
title: Thoughts on storing passwords
date: 2013-03-20T14:53:00+00:00
draft: false
emoji: 🔐
tags:
- passwords
- code
- security
- database
- from-tumblr
---
Yesterday at work I was discussing the design of password databases with my boss. I don't claim to have any deep knowledge in the area, but we came out with the following structure which seems to have good inherent security as well as the possibility to improve that as technology improves.
## Password
**Store:** Password
Without going over password databases 101, you obviously should never store just a plaintext against an email address/username, as in the eventuality where your database is compromised — let's say [Doctor Claw](https://en.wikipedia.org/wiki/Doctor_Claw) has stolen your database — anyone with that data can access anyone else's accounts. Bad times.
## Hashed password
The simple solution is hashing the passwords using a [one-way hash algorithm](https://en.wikipedia.org/wiki/Cryptographic_hash_function). You store `HASH(password)`, and when the user wants to authenticate, you compare `HASH(what_they_sent)` against the stored `HASH(password)` and if they match then the passwords are the same[^1].
**Store:** Password hash
The benefit here is that Doctor Claw now can't use the data he has to log in to anyone else's account. If he tries sending a hash from the stolen database to the site, the calculation performed will be `HASH(the_hash_doctor_claw_sent)` which will not match `HASH(the_real_user_password)`.
The hash algorithm used can be one of many, [MD5](https://en.wikipedia.org/wiki/MD5) is an old favourite, but it's considered [insecure these days](https://en.wikipedia.org/wiki/MD5#Security), and the same goes for [SHA1](https://en.wikipedia.org/wiki/SHA-1). The current advice is to use [SHA256](https://en.wikipedia.org/wiki/SHA-256), but this will undoubtedly change with time.
## Salted hashed password
There's a cloud in our perfect passworded sky; storage is cheap and people in the real world often don't use complex passwords. Doctor Claw has done some pre-work and he's set a home computer off calculating the hashes of all the most popular passwords — he'd put this in a lookup specialised database called a [rainbow table](https://en.wikipedia.org/wiki/Rainbow_table). He can now do a rapid lookup to see if any of the hashes in his stolen database match any in his rainbow table and will immediately know the original password for that user account.
**Store:** Salted password hash, Salt
The solution is simple, _[salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) the password_. To do this, when you're writing a password to your database you follow these steps:
1. Generate a salt by creating a random string of characters, like `gZ7s(28d}"+`
2. Concatenate the salt and the password before you hash them (you could append the salt, prepend it, or anything else repeatable).
3. Write the result of `HASH(salt + password)` to your database along with the salt you used.
Now when a legitimate user sends you the right password, you simply add the salt to it in the same way, hash it, and compare against your database. Doctor Claw on the other hand has to generate a rainbow table for _each_ entry in the stolen database, and he doesn't necessarily know that the salt is prepended, appended or sprinkled around within the password. Doctor Claw's life grows harder…
## Repeated hashing & derrived keys
Any technologically savvy person can see that available computing power is by no means static and Doctor Claw could potentially have created or bought himself use of a [botnet](https://en.wikipedia.org/wiki/Botnet) to generate his rainbow tables, allowing him relatively speedy access to getting at your customer data yet again. So how can we tackle this one?
**Store:** Derrived key, salt, iterations
The one thing which is, within the forseeable technological future, always going to be true is that generating a hash takes _time_. Not necessarily much time, but it does (currently around the hundreds of microsecondsmark). The one thing which Doctor Claw here has always been interested in has been accessing accounts fairly quickly (on the order of days, not years or decades), so this is something we can use to our advantage.
Rather than storing just the hash of a salted password (1 time), we can store the hash of the salted hash of a salted password (2 times), or the hash of a salted hash of a salted hash of a salted password (3 times). With each additional salting and hashing we're increasing the amount of time it takes _us_ to check a legitimate user's credentials, but also increasing the time it takes Doctor Claw to either [brute force](https://en.wikipedia.org/wiki/Brute-force_attack) all possible passwords to their hashes, or generate a rainbow table.
If you salt and hash in the order of thousands of times for each password, it takes you around one second to authenticate that the password your legitimate user has sent you is correct or incorrect, but for Doctor Claw to reverse engineer or guess any user's password even from a complete password database will take in the order of millennia. Doctor Claw has been foiled again.
Your design could specify "we repeat hashing 1000 times", but this is a bit restrictive, as within 2 years computers may be quick enough that 1000 iterations may only take milliseconds rather than seconds, so it's worth considering storing the salt, the derrived key _and_ the number of repetitions of hashing that has taken place to create that hash. This means that if you want to upgrade your database to take account of that new quantum processor that's just been released, you only need to set a program iterating through your database, reading the info, hashing another N times, and replacing the data with the new derrived key and the incremented value for 'iterations'.
It's important to note that if you were to always put the salt in the same position next to the hash before performing the next hash, it would be simple(ish) for Doctor Claw to create a rainbow table of all possible salt + hash combinations and skip all the hard work you've done iterating a large number of times, so it's a good idea to have your hashing being a function of the previous hash, the salt _and_ the iteration number. A entirely unoptimised example of this would be:
```javascript
function hashIt(string,salt,iterations) {
if (iterations <= 1) {
var hashThis = string;
} else {
var hashThis = hashIt(string,salt,iterations - 1);
}
// Split the salt at a predictable, non regular point
var saltParts = salt.splitAtPosition(iterations % salt.length);
// Do the hash
return SHA256(saltParts[0] + hashThis + saltParts[1]);
}
```
There are formalised methods for achieving this, like [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2), to prevent the need to worry about small but important details like this.[^2]
## Conclusion
Password databases require some serious thought (there are very likely to be angles of attack I haven't considered above too) but if you've avoided the traps I mentioned above then you're in reasonably good stead!
[^1]: There is a possibility that there would be a 'hash collision' - because the hash is not a 1:1 mapping, it is a certainty that there are values for `A` and `B` such that `HASH(A) == HASH(B)`, but by choosing the right hash algorithm this can be reduced to a statistical improbability.
[^2]: Import note: More than that, there are lots of subtle ways bugs can creep into complex key derrivation functions like this — use one that's been security audited!

View file

@ -0,0 +1,20 @@
---
title: Thoughts on Twitter as a Weapon
date: 2013-09-04T08:34:00+00:00
draft: false
emoji: 🥊
tags:
- news
- twitter
- from-tumblr
---
My brother just showed me to "[an interesting news story](https://bbc.co.uk/news/technology-23943480)" - it really is.
Mr. Syed won't be the first person to use advertising space to get eyeballs on a private grievance (though you can argue this one has public appeal too), but before the dawn of promoted messages on social media this method of being heard cost _serious_ money; I think the decreasing cost and general availability of releasing weighty negative advertisements is a serious potential problem.
![An illustration of an angry blue bird punching with UFC gloves](ufc-twitter.png)
The parallel Ms Wakefield draws with David & Goliath in her article is apt - Goliath isn't tech-savvy enough to use a targeted weapon like David and the damage is done before Goliath gets a chance to respond. My concern arises when I imagine a world where self-righteous Davids attack Goliaths in preference to more amiable methods of solving the problem; Goliaths will find this very difficult to defend against, as every person - David or otherwise - who they raise a shield at is a potential customer seeing a less compelling service.
Mr. Syed tells the BBC that he turned to promoted tweets after being frustrated at the lack of a suitable response from the usual complaint channels, this I applaud. It's clever, targeted and doesn't appear (too?) vindictive (we've all been down the poor customer service route with a Goliath before) so here's to hoping we, as Davids with a newly publicised anti-Goliath weapon, can keep ourselves from becoming too aggressive.

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

View file

@ -33,12 +33,8 @@
<line x1="8" y1="2" x2="8" y2="6"></line>
<line x1="3" y1="10" x2="21" y2="10"></line>
</svg>
<date datetime="{{ dateFormat "2006-01-02 15:04:05 MST" .Date }}">
{{ if .Site.Params.dateformNumTime }}
{{ dateFormat .Site.Params.dateformNumTime .Date }}
{{ else }}
{{ dateFormat "2006-01-02 15:04 MST" .Date }}
{{ end }}
<date datetime="{{ dateFormat .Site.Params.dateformHTML .Date }}">
{{ dateFormat .Site.Params.dateformNumTime .Date }}
</date>
{{ if .Lastmod }}

View file

@ -0,0 +1,5 @@
{{ $date := .Get 0 | time }}
<section class="import-note">
<p class="date">Some context, from <date datetime="{{ dateFormat .Site.Params.dateformHTML $date }}">{{ sub $date.Year .Page.Date.Year }} years later</date>:</p>
{{ .Inner }}
</section>

View file

@ -123,6 +123,19 @@ a {
color: inherit;
}
a[href^="https://web.archive.org/"] {
&::after {
position: absolute;
content: "🏛️";
margin-left: 0.25em;
vertical-align: super;
font-size: x-small;
text-decoration: none;
}
margin-right: 1em;
}
.always-accented, .always a {
color: var(--accent);
text-decoration: none;
@ -387,7 +400,7 @@ pre {
}
blockquote {
border-left: 3px solid #3eb0ef;
border-left: 3px solid var(--accent);
margin: 40px;
padding: 10px 20px;
@ -592,4 +605,26 @@ a[href^="#fn:"] {
text-align: center;
margin-top: 60px;
}
}
.import-note {
font-style: italic;
border-left: 3px solid var(--accent);
opacity: 0.6;
margin: 20px;
padding: 10px 20px;
@media #{$media-size-phone} {
margin: 10px;
padding: 10px;
}
p:first-of-type {
margin-top: 0;
}
p:last-of-type {
margin-bottom: 0;
}
}