Permalink
Browse files

first commit

  • Loading branch information...
0 parents commit 972074931eeb994e9ea662a8c7b0fdf5cbe07a26 @thejh committed Jun 18, 2011
Showing with 213 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +30 −0 blacklist.txt
  3. +9 −0 injections/heise-doubleclick.coffee
  4. +9 −0 injections/sitestat-script.coffee
  5. +80 −0 proxy.coffee
  6. +40 −0 streaminsert.coffee
  7. +44 −0 urlcheck.coffee
@@ -0,0 +1 @@
+node_modules
@@ -0,0 +1,30 @@
+# General stuff
+host ivwbox.de
+host doubleclick.net
+host googlesyndication.com
+host google-analytics.com
+host googleadservices.com
+host sitestat.com
+host facebook.com
+host fbcdn.net
+host addthis.com
+host inqnet.at
+host specificclick.net
+host scorecardresearch.com
+host intellitxt.com
+host platform.twitter.com
+host plista.com
+host api.flattr.com
+host uimserv.net
+
+# Heise
+raw rl.heise.de/images/pic.gif
+raw www.heise.de/ivw-bin/
+#ist nicht böse, aber lädt unnötige Bilder
+raw www.heise.de/support/lib/social_bookmarks.js
+
+# Gulli
+raw static.gulli.com/layout/partner/camao/cads-min.js
+
+# Google
+raw google.de/csi?
@@ -0,0 +1,9 @@
+{
+ urlregex: /heise\.de/
+ search: '''
+document.write('<script src="http://ad-emea.doubleclick.net/
+ '''
+ append: '''
+'&&''&&'
+ '''
+}
@@ -0,0 +1,9 @@
+{
+ urlregex: /tagesschau\.de/
+ search: '''
+function sitestat(ns_l){
+ '''
+ append: '''
+return;
+ '''
+}
@@ -0,0 +1,80 @@
+coffee = require 'coffee-script'
+
+async = require 'async'
+fs = require 'fs'
+http = require 'http'
+{checkURL} = require './urlcheck'
+{InsertingStream} = require './streaminsert'
+
+console.error = ->
+
+# Script injections (scripts to insert into server->client data)
+injections = []
+
+proxyUrlRegex = /^http:\/\/([^\/]*)\/(.*)$/
+
+denyRequest = (response, reason, code = 403) ->
+ response.writeHead code
+ response.write reason, 'utf8'
+ response.end()
+
+# Prepare the proxy.
+server_cb = (request, response) ->
+ [host] = request.headers.host.split ':'
+ delete request.headers['accept-encoding']
+ request.headers['accept-charset'] = 'utf-8'
+ if 0 is request.url.indexOf 'http://'
+ [_, host, request.url] = proxyUrlRegex.exec request.url
+ request.url = '/' + request.url
+ fullurl = "#{host}#{request.url}"
+
+ {block, blockReason} = checkURL fullurl
+ if block
+ console.error "blocked request for '#{fullurl}', reason: #{blockReason}"
+ return denyRequest response, blockReason
+
+ proxy_request = http.request
+ method: request.method
+ path: request.url
+ headers: request.headers
+ host: host
+ port: 80
+ proxy_request.on 'error', (err) ->
+ denyRequest response, err+'', 404
+ proxy_request.addListener 'response', (proxy_response) ->
+ writeToClient = (chunk) -> response.write chunk
+ console.error "request for '#{fullurl}'"
+ #console.error " HEADERS: #{JSON.stringify request.headers}"
+ if not proxy_response.headers["content-type"]?.indexOf("text/")
+ for injection in injections when ~fullurl.search injection.urlregex
+ writeToClient = do (writeToClient) ->
+ inserter = new InsertingStream injection.search, injection.append, writeToClient
+ (chunk) -> inserter.write chunk
+ console.error " bugging '#{fullurl}'"
+ proxy_response.addListener 'data', writeToClient
+ proxy_response.addListener 'end', -> response.end()
+ delete proxy_response.headers['content-length']
+ delete proxy_response.headers['content-range']
+ response.writeHead proxy_response.statusCode, proxy_response.headers
+ request.addListener 'data', (chunk) -> proxy_request.write chunk
+ request.addListener 'end', -> proxy_request.end()
+
+# Activate it.
+http.createServer(server_cb).listen 8421
+
+# Load the injection commands.
+fs.readdir 'injections', (err, files) ->
+ throw err if err
+ files = (file for file in files when ~file.search /\.coffee$/)
+ async.forEachSeries files, (file, fileLoaded) ->
+ fs.readFile 'injections/' + file, 'utf8', (err, data) ->
+ throw err if err
+ fileContent = coffee.eval data
+ if not fileContent?
+ throw "gnarf"
+ injections.push fileContent
+ console.error "loaded injection configfile #{file}"
+ fileLoaded()
+ , (err) ->
+ throw err if err
+ console.error 'successfully loaded injection configuration'
@@ -0,0 +1,40 @@
+{EventEmitter} = require 'events'
+
+bufInsert = (buf, i, buf2) ->
+ newbuf = new Buffer buf.length + buf2.length
+ buf.copy newbuf, 0, 0, i
+ buf2.copy newbuf, i
+ buf.copy newbuf, i+buf2.length, i
+ newbuf
+
+exports.InsertingStream = class InsertingStream extends EventEmitter
+ constructor: (searchString, appendString, callback) ->
+ @searchBuffer = new Buffer searchString
+ console.error " searching for '#{searchString}'"
+ @appendBuffer = new Buffer appendString
+ # This is the next expected character.
+ # Position 0 means: Expect the first character.
+ @searchPosition = 0
+ if callback?
+ @on 'data', callback
+
+ write: (chunk) ->
+ i = 0
+ #console.log "chunktype: #{chunk.constructor.name}"
+ while i < chunk.length
+ byte = chunk[i]
+ expectedByte = @searchBuffer[@searchPosition]
+ if byte is expectedByte
+ @searchPosition++
+ if @searchPosition is @searchBuffer.length
+ @searchPosition = 0
+ chunk = bufInsert chunk, i+1, @appendBuffer
+ console.error ' inserting...'
+ else
+ @searchPosition = 0
+ i++
+ @_write chunk
+
+ _write: (chunk) ->
+ #console.error "inserting stream writes data"
+ @emit 'data', chunk
@@ -0,0 +1,44 @@
+fs = require 'fs'
+
+blacklist = []
+
+split2 = (str, delimiter) ->
+ i = str.indexOf delimiter
+ if ~i
+ [str.substring(0, i), str.substring(i+1)]
+ else
+ null
+
+endsWith = (haystack, needle) ->
+ haystack.length - needle.length >= 0 and haystack.length - needle.length is haystack.lastIndexOf needle
+
+exports.checkURL = (url) ->
+ [host] = url.split '/', 1
+ for {type, data: needle} in blacklist
+ hit = switch type
+ when 'raw' then ~url.indexOf needle
+ when 'host' then endsWith host, needle
+ else throw "this shouldn't happen"
+ if hit
+ return {
+ block: true
+ blockReason: "blocked by '#{needle}'"
+ }
+ block: false
+
+parseBlacklist = (text) ->
+ blacklist = for line in text.split '\n'
+ continue if 0 is line.indexOf '#'
+ continue if line.length is 0
+ if entry = split2 line, ' '
+ [type, data] = entry
+ if not type in ['raw', 'host']
+ throw 'unknown entry type'
+ {type, data}
+ else
+ throw "invalid line: #{line}"
+
+fs.readFile 'blacklist.txt', 'utf8', (err, data) ->
+ throw err if err
+ parseBlacklist data
+ console.error "loaded blacklist"

0 comments on commit 9720749

Please sign in to comment.