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.
}

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

.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/sh
cd "$(dirname "$0")"
 
PREFIX=wwdc2014
bwlimit="1000K"
 
for url in $(curl https://developer.apple.com/videos/wwdc/2014/ | egrep -hoe '[^"]+.pdf[^"]+')
do
  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
done
 
for url in $(curl https://developer.apple.com/videos/wwdc/2014/ | egrep -hoe '[^"]+_sd[^"]+')
do
  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
done

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
    1
    2
    3
    4
    5
    6
    7
    
    $ 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
    activate_control_app
  8. $ grep puma /your/app/path/Gemfile.local
    gem "puma"
  9. lighttpd proxy config:
    1
    2
    
    $ grep 8082 /etc/lighttpd/conf-enabled/10-proxy.conf
    $HTTP["host"] == "redmine.example.com" { proxy.server = ( "" => (("host" => "127.0.0.1", "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

Versions:

  • 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"
 
#define NSERROR_UIWEBVIEW_SCRIPT @"NSERROR_UIWEBVIEW_SCRIPT"
#define NSERROR_UIWEBVIEW_SCRIPT_CODE 1
 
@implementation UIWebView(JavaScriptNSError)
 
-(NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script error:(NSError * __autoreleasing *)error
{
  NSString *errorPrefix = NSERROR_UIWEBVIEW_SCRIPT;
  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;
}
@end

flattr this!

UIColor from hex string, once again

I end up doing this once per year – at least it’s getting leaner each time.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
static inline NSInteger NSIntegerFromHexDigit(const unichar c)
{
  switch( c ) {
  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
    return c - '0';
  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
    return c - 'a' + 10;
  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
    return c - 'A' + 10;
  default:
    return -1;
  }
}
 
typedef NSUInteger RGBA32;
 
/** RGBA hex color matching /^(?:0x|#)?([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?$/i
 */
static BOOL RGBAFromNSStringHex(NSString *hex, RGBA32 *value)
{
  const NSUInteger len = hex.length;
  if( len < 6 || len > 9 )
    return NO;
  unichar buffer[len];
  [hex getCharacters:buffer range:NSMakeRange(0, len)];
 
  // check if either 6 or 8 char hex
  const BOOL hasHashPrefix = buffer[0] == '#';
  const NSInteger netlen = len - hasHashPrefix;
  if( netlen != 6 && netlen != 8 )
    return NO;
 
  // turn hex to integer
  NSUInteger ret = 0;
  assert(sizeof(ret) >= 4); // need at least 4 bytes
  for( NSInteger i = hasHashPrefix; i < len; i++ ) {
    const NSInteger v = NSIntegerFromHexDigit(buffer[i]);
    if( v < 0 )
      return NO;
    ret <<= 4;
    ret |= v;
  }
  // if 6-char hex assume alpha 0xFF
  if( netlen == 6 ) {
    ret <<= 8;
    ret |= 0xFF;
  }
 
  if( value )
    *value = ret;
  return YES;
}

How to get a UIColor from here should be straightforward.

P.S.: Wikipedia about ‘RGBA’

flattr this!

git version sha in iOS apps

there’s tons of recipes out there how to do this – nevertheless I want to add another one:

xcode-git-sha-info-plist

  1. create a new build phase (here named “Git Sha -> Info.plist”)
  2. paste
    1
    2
    3
    4
    5
    6
    7
    8
    
    # write git version SHA into Info.plist
    #
    # inspired by
    # - http://kswizz.com/post/2686511526/git-xcode-versioning
    # - http://stackoverflow.com/a/12658311
    cd "$PROJECT_DIR"
    # say hello
    /usr/libexec/PlistBuddy -c "Set :CFBundleVersionGitSHA $(git rev-parse --short HEAD)" "$TARGET_BUILD_DIR/$INFOPLIST_PATH"
  3. add key CFBundleVersionGitSHA with placeholder text to your Info.plist

I went for this one because

  1. easy setup,
  2. no build/compiler settings changes,
  3. doesn’t interfere with ‘normal’ versioning,
  4. simplest I’ve seen so far, no dependencies except git,
  5. explicit failure if e.g. git is missing.

Credits:

flattr this!

Rank sql(ite) text search results

When searching for text snippets in sql databases you might want to rank the results according to “how good did it match”. And: the ranking shouldn’t make the query slower.

Let’s take a simple example using the LIKE operator. (I know, FTS does a better job, but let’s stick to like for now).

Assume the search expression ‘a bc de’ and a table ‘my_table’ with text columns ‘title’ and ‘description’.

We want to find all rows with ‘title’ matching all three blank-separated parts of the search term:

SELECT rowid, title
FROM my_table
WHERE (title LIKE '%a%' AND title LIKE '%bc%' AND title LIKE '%de%')

To sort them, we apply a bonus for parts matching the column start:

SELECT rowid, title,
    -- column start bonus
    LIKE('a%', title) +
    LIKE('bc%', title) +
    LIKE('de%', title) +
0 AS bonus
FROM my_table
WHERE ((title LIKE '%a%') AND (title LIKE '%bc%') AND (title LIKE '%de%'))
ORDER BY bonus DESC, title ASC, rowid ASC

Next, we’d like to add a (somewhat smaller) bonus for word-starts:

SELECT rowid, title,
    -- column start bonus
    LIKE('a%', title) * 2 +
    LIKE('bc%', title) * 2 +
    LIKE('de%', title) * 2 +
    -- word start bonus
    LIKE('% a%', title) * 1 +
    LIKE('% bc%', title) * 1 +
    LIKE('% de%', title) * 1 +
0 AS bonus
FROM my_table
WHERE ((title LIKE '%a%') AND (title LIKE '%bc%') AND (title LIKE '%de%'))
ORDER BY bonus DESC, title ASC, rowid ASC

Rows matching the three terms in order get an even bigger bonus:

SELECT rowid, title,
    -- correct order bonus
    LIKE('%a%bc%de%', title) * 5 * 3 +
    -- column start bonus
    LIKE('a%', title) * 2 +
    LIKE('bc%', title) * 2 +
    LIKE('de%', title) * 2 +
    -- word start bonus
    LIKE('% a%', title) * 1 +
    LIKE('% bc%', title) * 1 +
    LIKE('% de%', title) * 1 +
0 AS bonus
FROM my_table
WHERE ((title LIKE '%a%') AND (title LIKE '%bc%') AND (title LIKE '%de%'))
ORDER BY bonus DESC, title ASC, rowid ASC

And finally adding the match on ‘description’ secondary:

SELECT rowid, title, description,
    -- title is primary match:
    -- correct order bonus
    LIKE('%a%bc%de%', title) * 50 * 3 +
    -- column start bonus
    LIKE('a%', title) * 20 +
    LIKE('bc%', title) * 20 +
    LIKE('de%', title) * 20 +
    -- word start bonus
    LIKE('% a%', title) * 10 +
    LIKE('% bc%', title) * 10 +
    LIKE('% de%', title) * 10 +
    -- description is secondary match:
    -- correct order bonus
    LIKE('%a%bc%de%', description) * 5 * 3 +
    -- column start bonus
    LIKE('a%', description) * 2 +
    LIKE('bc%', description) * 2 +
    LIKE('de%', description) * 2 +
    -- word start bonus
    LIKE('% a%', description) * 1 +
    LIKE('% bc%', description) * 1 +
    LIKE('% de%', description) * 1 +
0 AS bonus
FROM my_table
WHERE ((title       LIKE '%a%') AND (title       LIKE '%bc%') AND (title       LIKE '%de%'))
OR    ((description LIKE '%a%') AND (description LIKE '%bc%') AND (description LIKE '%de%'))
ORDER BY bonus DESC, title ASC, description ASC, rowid ASC

You get the idea.

Funny thing is – the whole ranking logic doesn’t hit performance (at least for small texts in the two columns)!

So, key is:

  1. scan the table only once to find match candidates using the LIKE operator,
  2. use the LIKE function(!) plus weighting-factors to compute a bonus for each hit,
  3. evtl. add secondary matching columns.

P.S.: This post was inspired by a chat with Deesa on the way home riding False Creek Ferry.

flattr this!

Ruby: Simple Fast Fourier Transform

by far not as powerful as the Fastest Fourier Transform in the West but maybe sometimes useful for a quick data analysis or de-noising. Reads stdin and writes to stdout.

Algorithm taken from Meyberg, Vachenauer: Höhere Mathematik II and ported to plain ruby myself.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/usr/bin/env ruby
require 'complex'
 
class Array
  # DFT and inverse.
  # 
  # Algorithm from 
  # 'Meyberg, Vachenauer: Hoehere Mathematik II, Springer Berlin, 1991, page 332'
  #
  # See http://blog.mro.name/2011/04/simple-ruby-fast-fourier-transform/ 
  #
  def fft doinverse = false
    src = self
    # raise ArgumentError.new "Expected array input but was '#{src.class}'" unless src.kind_of? Array
    n = src.length
    nlog2 = Math.log( n ) / Math.log( 2 )
    raise ArgumentError.new "Input array size must be a power of two but was '#{n}'" unless nlog2.floor - nlog2 == 0.0
    n2 = n / 2
    phi = Math::PI / n2
    if doinverse
      phi = -phi
    else
      src.collect!{|c| c /= n.to_f}
    end
 
    # build a sine/cosine table
    wt = Array.new n2
    wt.each_index { |i| wt[i] = Complex.new Math.cos(i * phi), Math.sin(i * phi) }
 
    # bit reordering
    n1 = n - 1
    j = 0
    1.upto(n1) do |i|
      m = n2
      while j >= m
        j -= m
        m /= 2
      end
      j += m
      src[i],src[j] = src[j],src[i] if j > i
    end
 
    # 1d(N) Ueberlagerungen
    mm = 1
    begin
      m = mm
      mm *= 2
      0.upto(m - 1) do |k|
        w = wt[ k * n2 ]
        k.step(n1, mm) do |i|
          j = i + m
          src[j] = src[i] - (temp = w * src[j])
          src[i] += temp
        end
      end
      n2 /= 2
    end while mm != n
    src
  end
end
 
class String
  # parse Complex.new.to_s
  def to_c
    m = @@PATTERN.match self
    return nil if m.nil?
    Complex.new m[1].to_f, m[2].to_f
  end
private
  # float_pat = /(-?\d+(?:\.\d+)?(?:e[+-]?\d+)?)/
  @@PATTERN = /^[ \t\r\n]*(-?\d+(?:\.\d+)?(?:e[+-]?\d+)?)?\s*((?:\s+|[+-])\d+(?:\.\d+)?(?:e[+-]?\d+)?i)?[ \t\r\n]*$/
end
 
values = []
$stdin.each_line do |l|
  c = l.to_c
  if c.nil?
    $stderr.puts "unmatched '#{l}'"
  else
    values << c
  end
end
INVERSE = ARGV[0] == 'inverse'
$stderr.puts INVERSE ? 'inverse' : 'forward'
 
values.fft(INVERSE).each {|i| puts "#{i.real} #{i.image}i"}

WordPress messes up the angle brackets as usual, but there’s a gist for that.

flattr this!