Why PHP is utterly broken

tl;dr: neither does DATE_RFC1123 produce a rfc1123-date, nor does DATE_RFC850rfc850-date. What sense does that make?

This example may look scrupulous but seems typical.

Mind the mandatory word ‘GMT‘ at the end of rfc1123-date. While DATE_RFC1123 renders something ending with +0000. Which is the same timezone but not the same string.

So DATE_RFC1123 is useless for HTTP headers (RFC2616). I wonder what else it should be there for.

While this isn’t an issue of PHP (the language) itself, it’s IMO typical for the actual PHP code existing. It does work somehow, despite the fact that it’s totally agnostic of the basics it claims to be based upon. So it may fail any given, unforeseeable, moment, when any of the implicitly assumed side-conditions change.

P.S.: The newer RFC7231 (HTTP-Date) and e.g. RFC 7232, Last-Modified don’t change a thing.

P.P.S.: I don’t do PHP, I just came across when patching https://github.com/mro/Shaarli a bit.

Flattr this!

Validate GPX

xmllint --noout --schema http://www.topografix.com/GPX/1/1/gpx.xsd <gpx file or url>

Flattr this!

T-Kom WLAN Hotspot auf einigen Bahnhöfen…

Nehmen wir mal kurz an, man ist T-Kom Kunde, steht im Zug auf dem Bahngleis und möchte per WLAN in’s Netz.

DB WLAN im Bahnhof: Täglich 30 Minuten kostenlos sagt:

30 Minuten gratis WLAN an über 120 Bahnhöfen

Das nennt man Service: Mit diesem innovativen und kundenorientierten Servicekonzept geben wir dem Warten eine neue Qualität.

Nutzen Sie Ihre Reisezeit noch effizienter: In über 120 Bahnhöfen bieten wir Ihnen einen Zugang zum Internet über das WLAN der Telekom. Jeden Tag sind die ersten 30 Minuten WLAN kostenlos, danach kann zu Telekom-Tarifen weiter gesurft werden.

An vielen Bahnhöfen können Sie WLAN nutzen. Mit dem Service von Telekom und der Deutschen Bahn surfen Sie problemlos mit Ihrem WLAN-fähigen Smartphone oder Tablet kabellos im Internet. Überall, wo Sie nebenstehendes blaues Piktogramm sehen, können Sie online gehen.

Die folgende Anleitung hat 8(!) Schritte.

Und so sieht das in der Praxis aus (obwohl die T-Kom noch nicht mal dem Risiko der Störerhaftung ausgesetzt ist):

Continue Reading »

Flattr this!

Key-based FTP authentication

  1. make a strong ssh key $ ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa
  2. turn to RFC 4716 $ ssh-keygen -e -f ~/.ssh/id_rsa.pub
  3. add to ~/.ssh/authorized_sftpkeys on destination host
  4. try out:
    1. $ curl -u "<username>:" --key ~/.ssh/id_rsa --pubkey ~/.ssh/id_rsa.pub -T <file to upload> sftp://<target host>/<target path>/
    2. $ lftp -u <username>,xx ... sftp://<target host>

P.S.: Hetzner FAQ zum Thema SFTP + Keys.

Flattr this!

Ad Blocking Proxy = abloprox

as an act of digital hygiene, I installed abloprox on a raspi and added this PAC file to save some keystrokes when configuring:

function FindProxyForURL(url, host) {
  if (shExpMatch(host,"*.fritz.box")) return "DIRECT";
  if (shExpMatch(host,"*.local")) return "DIRECT";
  if (shExpMatch(host,"*.akamaistream.net")) return "DIRECT";
  if (shExpMatch(host,"*.m945.mwn.de")) return "DIRECT";
  // auto config:
  // 1. ensure there's a host 'wpad' in the current network, see
  //   - https://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol#Context
  //   - http://fritz.box/net/network_user_devices.lua
  // 2. have a http webserver running on that host
  // 3. ensure http://wpad/wpad.dat or http://wpad.fritz.box/wpad.dat contains a PAC file like in http://blog.mro.name/2014/06/ad-blocking-proxy-abloprox/
  // return "PROXY wpad:3126"; // Default return condition is the proxy on host 'wpad'.
  return "PROXY <hostname_of_the_raspi>:3126"; // Default return condition is the proxy.

Update: I pushed this one step further recently and use the automatic proxy-configuration itself to filter — see http://purl.mro.name/wpad.

Flattr this!

Opening Xcode projects and workspaces

Inspired by ortas post about it I came up with this one-liner:

alias openx='open *.xcworkspace 2>/dev/null || open *.xcodeproj 2>/dev/null || echo "nagnagnag"'

Flattr this!

Download WWDC2014 session pdf + mov


cd "$(dirname "$0")"
for url in $(curl https://developer.apple.com/videos/wwdc/2014/ | egrep -hoe '[^"]+.pdf[^"]+')
  dst="$PREFIX/$(basename $url ?dl=1)"
  echo "$dst"
  curl --output "$dst" --time-cond "$dst" --remote-time --silent --create-dirs --location --limit-rate "$bwlimit" --url "$url" 2>/dev/null
for url in $(curl https://developer.apple.com/videos/wwdc/2014/ | egrep -hoe '[^"]+_sd[^"]+')
  dst="$PREFIX/$(basename $url ?dl=1)"
  echo "$dst"
  curl --output "$dst" --time-cond "$dst" --remote-time --silent --create-dirs --location --limit-rate "$bwlimit" --url "$url" 2>/dev/null

I think downloading them this way is fair use. If you think otherwise, leave a comment below and I shall take appropriate action.

P.S.: See also the awesome wwdc transcript fulltext index.

Flattr this!

install ruby @ OS X

OS X comes with a pretty hung ruby (1.8.7) until ‘Mavericks’. ruby 1.8.7 had it’s planned EOL long ago, even debian/stable nowadays comes with a newer one.

So if you’re still running Mountain Lion or older, you may need to install ruby.

I chose rbenv and here’s how I did:

  • RTFM
  • install rbenv: $ brew install rbenv ruby-build
  • add : $ brew install rbenv ruby-build
  • patch .bashrc
  • do a $ rbenv rehash
  • purge all previously installed gems: $ gem list | cut -d ' ' -f 1 | xargs sudo gem uninstall
  • restart terminal
  • install a ruby of choice, and happily bundle install ever after

Flattr this!

redmine (rails) + puma + lighttpd

Running redmine with a lightweight ruby on rails/webserver stack on a debian server – puma and lighttpd:

Assumed you’ve got both redmine and lighttpd already installed:

  1. install puma gem:
    $ sudo gem install puma
  2. caution: ArgumentError on ruby 1.8.7
  3. get tools/jungle/init.d/puma to /etc/init.d/
  4. get tools/jungle/init.d/run-puma to /usr/local/bin/
  5. add a puma app:
    $ sudo /etc/init.d/puma add /your/app/path www-data
  6. $ sudo -u www-data mkdir /your/app/path/tmp/puma
  7. puma config in rails app /your/app/path/config/puma.rb
    $ cat your/app/path/config/puma.rb
    environment 'production'
    pidfile File.expand_path( File.dirname(__FILE__) + "/../tmp/puma/pid" )
    state_path File.expand_path( File.dirname(__FILE__) + "/../tmp/puma/state" )
    threads 1,4
    port 8082
  8. $ grep puma /your/app/path/Gemfile.local
    gem "puma"
  9. lighttpd proxy config:
    $ grep 8082 /etc/lighttpd/conf-enabled/10-proxy.conf
    $HTTP["host"] == "redmine.example.com" { proxy.server = ( "" => (("host" => "", "port" => 8082))) }
  10. $ sudo /etc/init.d/puma start
  11. $ sleep 5 ; cat /your/app/path/tmp/puma/state
  12. $ sudo update-rc.d -f puma defaults


  • ruby: 1.8.7-p358 (2012-02-08) [x86_64-linux]
  • rails: 3.2.15
  • lighttpd: 1.4.28
  • puma: 2.7.1
  • redmine: 2.4.0

Flattr this!

Catch JavaScript exceptions in UIWebViews

A small but useful category method on UIWebView: Turn uncaught JavaScript Exception into a NSError!

// Created by Marcus Rohrmoser on 05.12.13.
// Copyright (c) 2013 Marcus Rohrmoser mobile Software. All rights reserved.
#import "UIWebView+JavaScriptNSError.h"
@implementation UIWebView(JavaScriptNSError)
-(NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script error:(NSError * __autoreleasing *)error
  NSString *exec = [NSString stringWithFormat:@"try { %@ } catch (e) { '%@' + e; }", script, errorPrefix, nil];
  NSString *ret = [self stringByEvaluatingJavaScriptFromString:exec];
  if( ![ret hasPrefix:errorPrefix] )
    return ret;
  if( error ) {
    NSString *msg = [ret substringFromIndex:errorPrefix.length];
    NSDictionary *ui = @ {
      NSLocalizedDescriptionKey: msg,
      NSFilePathErrorKey:[self.request.URL absoluteString],
      NSURLErrorKey: self.request.URL,
      NSLocalizedFailureReasonErrorKey: msg,
      NSURLErrorFailingURLErrorKey: self.request.URL,
      NSURLErrorFailingURLStringErrorKey: self.request.URL
    *error = [NSError errorWithDomain:NSERROR_UIWEBVIEW_SCRIPT code:NSERROR_UIWEBVIEW_SCRIPT_CODE userInfo:ui];
  return nil;

Flattr this!