How To Add Translation Feature To Twitter

I don’t know about you but, I follow few peple that sometimes tweet in different language then English. And English is the only foreign language I know. So if I want to see what they tweet about sometimes I use google translate to read the content.

I always thought that it will be nice feature for Twitter to have translate button, so I created one, using WebSockets and Ruby.

So how I did this, first I downloaded websockets ruby library from github web-socket-ruby, I already had translation script written in Ruby that use google translate, so I added websocket server to it.

#!/usr/bin/ruby

require 'net/http'
require 'uri'
require 'optparse'
require 'json'
require 'socket'
require 'web_socket'

class NotConnectedException < Exception
end

def server(port, domains)
  server = WebSocketServer.new(
    :accepted_domains => domains,
    :port => port)
  puts("Server is running at port %d" % server.port)
  server.run() do |ws|
    puts("Connection accepted")
    puts("Path: #{ws.path}, Origin: #{ws.origin}")
    if ws.path == "/translate"
      ws.handshake()
      while data = ws.receive()
        printf("Received: %p\n", data)
        data = JSON.parse(data)
        response = translate(data['text'], nil, data['to_lang']).join("\n")
        ws.send(response)
        printf("Sent: %p\n", response)
      end
    else
      ws.handshake("404 Not Found")
    end
    puts("Connection closed")
  end
end

def escape(o)
  o.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
    '%' + $1.unpack('H2' * $1.size).join('%').upcase
  }.tr(' ', '+')
end

def translate(text, from=nil, to=nil, cookie=nil)
  url = URI.parse("http://translate.google.com/translate_a/t")
  query = "?hl=en&client=t&text=#{escape(text)}&multires=1&otf=1&pc=0&sc=1&ie=UTF-8&oe=UTF-8"
  query += "&sl=" + (from ? from : 'auto')
  if to
    query += "&tl=#{to}"
  end
  begin
    http = Net::HTTP.new(url.host)
    res = http.get(url.path + query)
    res.response['content-type'] =~ /charset=(.*)/
    charset = $1
    JSON.parse(res.body.gsub(/,{2,}/, ',').gsub(/,\]/, ']'))[0].map {|i|
      # google sometimes put spaces around numbers
      i[0].gsub(/\{ *([0-9]) *\}/, '{\1}')
    }
  rescue NoMethodError
    raise NotConnectedException
  rescue SocketError
    raise NotConnectedException
  rescue 
  end  
 
end

def msg(str, type='info')
  system("zenity --#{type} --title='translation' --text='#{str}'")
end

params = ARGV.getopts('i:o:gcsp:')

def error(msg, gui=false)
  if gui
    msg(msg, 'error')
  else
    puts msg
  end
end

def usage()
  puts "usage:"
  puts "translate [-i <INPUT LANG>] -o <OUTPUT LANG> [MORE OPTIONS]"
  puts "-g - show zenity dialog"
  puts "-c - get input from clipboard"
  puts "-s - run as server"
  puts "-p - server port"
end

begin
  if params['s']
     begin
       server(params['p'] ? params['p'].to_i() : 8080, 'twitter.com')
     rescue Interrupt
       puts "Server Exit"
     end
  else
    if params['c']
      input = `xclip -o -sel clip`
    else
      input = ARGF.read()
    end
    translation = translate(input, params['i'], params['o'])
    if params['g']
      msg(translation.join(". "))
    else
      translation.each{|sentence|
        if sentence != ''
          puts sentence
        end
      }
    end
  end
rescue JSON::ParserError => e
  error("Response Error: " + e.message, params['g'])
rescue NotConnectedException
  error("sorry but it seems that your internet connection is down", params['g'])
end

Then I created this bookmarklet. (I notice that profile page use jQuery.noConflict() so I can’t access it from bookmarklet. So here is updated code that insert jQuery script again – in use continuation to block execution of the script until jQuery is loaded). To use bookmarklet just copy code below and insert into url address bar when twitter tab is active

javascript:(function(continuation) {
    function attr(elem, key, value) {
        elem.setAttribute(document.createAttribute(key, value));
    }
    var script = (function() {
        var head = document.getElementsByTagName('head')[0];
        return function(src) {
            var script = document.createElement('script');
            script.setAttribute('src', src);
            script.setAttribute('type', 'text/javascript');
            script.setAttribute('async', 'false');
            head.appendChild(script);
            return script;
        };
    })();
    script('https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js');
    var interval = 100;
    setTimeout(function() {
        if (jQuery) {
            continuation(jQuery.noConflict());
        } else {
            setTimeout(arguments.callee, interval);
        }
    }, interval);
})(function($) {
    function translator(fun, lang) {
        var socket = new WebSocket("ws://localhost:8080/translate");
        socket.onopen = function() {
            console.log("Socket has been opened!");
        };
        socket.onclose = function() {
            console.log("closed");
        };
        return fun(function(text, respond) {
            socket.onmessage = function(msg) {
                respond(msg.data);
            };
            var data = JSON.stringify({to_lang: lang, text: text});
            socket.send(data);
        });
    }
    var translate_tweet = translator(function(translate) {
        return function(content) {
            var tweet_container = content.find('.js-tweet-text');
            var tweet = tweet_container.html();
            content.data('original', tweet);
            var links = [];
            var i = 0;
            tweet = tweet.replace(/<a[^>]+>[^<]+<\/a>|<a[^>]+><s>(#|@)<\/s><b>[^<]+<\/b><\/a>/g, function(link) {
                links.push(link);
                return '{' + i++ + '}';
            });
            translate(tweet, function(result) {
                for (var i=links.length; i--;) {
                    result = result.replace('{' + i + '}', links[i]);
                }
                tweet_container.html(result);
                var actions = content.find('.tweet-actions');
                if (actions.find('.action-orig-container').length == 0) {
                    actions.append('<li class="action-orig-container"><a href="#">Original</a></li>');
                }
            });
        };
    }, prompt('Select Language: af - afrikaans, sk - albánskej, ar - عربي, be - Беларускі, bg - Български, zh - 荃湾, zh - 太阳, hr - Hrvatski, cs - Český, da - Danske, et - Eesti, tl - filipiński, fi - Suomi, fr - Français, gl - galijski, el - Ελληνικά, iw - עברית, hi - हिन्दी, es - Español, nl - Nederlands, id - indonezyjski, ga - Gaeilge, is - Íslenska, ja - 日本語, yi - ייִדיש, ca - Català, ko - 한국의, lt - Lietuvos, lv - Latvijas, mk - Македонски, ms - Melayu, mt - Malti, de - Deutsch, no - Norsk, fa - فارسی, pl - polski, ru - Русский, ro - Română, sr - Српски, sk - Slovenský, sl - Slovenski, sw - Swahili, sv - Svenska, th - ภาษาไทย, tr - Türk, uk - Український, cy - walijski, hu - Magyar, vi - Việt, it - Italiano'));
    $('.content').unbind('mouseover').live('mouseover', function() {
        var $this = $(this);
        if ($this.find('.action-trans-container').length == 0) {
            $this.find('.action-fav-container').
                after('<li class="action-trans-container"><a href="#">Translate</a></li>');
        }
    });
    $('.action-orig-container').unbind('onclick').live('click', function() {
        var content = $(this).parents('.content');
        content.find('.js-tweet-text').html(content.data('original'));
        content.find('.action-orig-container').remove();
        return false;
    });
    $('.action-trans-container').unbind('onclick').live('click', function() {
        translate_tweet($(this).parents('.content'));
        return false;
    });
});

CODE LICENSE: you can use the code for whatever purpose you like it’s realeas on Sharing Agreement.

Really wicked web application source code hiding

I saw this video on YouTube from DefCon Conference.

I go to samy website, and it’s web application which look like Microsoft Windows. So first think I do to see how it is build. I look at source code and it’s look like there is no code at all, but in the middle (line 281) there is this

<script>/*
No source for you!
*//
</script>

Before and after script tags are only empty lines (\n), I check the end of the line 283 and there is following code (line breaks and indentations are mine):

/.source.replace(/.{7}/g,function(w){document.write(
    String.fromCharCode(parseInt(w.replace(/ /g,'0').
                                 replace(/	/g,'1'),2)))});

And thats it. So where is the real code? And the answer is this:

  1. He encode all characters in html as binary and replace zeros as space and ones as tabulations. there is no string, but in 283 line there is this: "*//" which is the end of multi-line comment and beginning of Regular Expression (which look like simple closing comment)
  2. He get value of the string representation of the RegEx using source field
  3. replace all whitespace with '0' and '1'
  4. convert it to decimal
  5. get the value of characters encoded and print all of that out

Pretty clever.

Of course you can get generated code from a menu “View Generated Source” from WebDeveloper toolbar in Firefox or see the the DOM in Firebug.

10 books every hacker should read

Steven Levy – Hackers: Heroes of Computer Revolution


Hackers early history. The story is split into three parts.

  1. Early days mostly at Tech Model Railroad Club and AI. Lab at MIT
  2. Hardware Hackers (Homebrew Computer Club and Woz)
  3. Game Hackers, history of early games mostly created in assembler and basic for apple computer

Sam Williams – Free as in Freedom


Book about Richard M. Stallman, the origin on Free Software Foundation and GNU/Linux. You can read this book online.

Paul Graham – Hackers and Painters


Compilations of Graham essays. Graham is creator of Viaweb, which become Yahho Store and designer of arc lisp dialect. If you want more you can find it on Graham web site

William Gibson – Neuromancer


Classic cyberpunk book. Gibson is a father of cyberpunk he coined the term “cyberspace”.

Lawrence Lessig – Free Culture


Book about Open Society, Free Licensing and Open Source. The book was relased on Creative Commons Attribution/Non-commercial license (by-nc 1.0). You can download the book from offical web site.

Harold Abelson, Gerald Jay Sussman – Structure and Interpretation of Computer Programs


Classic book about programming and solving problems, all examples are in scheme programming language. Sussman design Scheme with Guy L. Steele. You can watch video lectures by authors of this book. You can read it online.

Eric Raymond – The Art of UNIX Programming


Book about the history and culture of Unix programming, and a guide to create open source program in *nix environment. You can read it online.

Open Sources: Voices from the Open Source Revolution


Group of Essays about Open Source. The essays contained were written by Chris DiBona, Sam Ockman, Mark Stone, Brian Behlendorf, Scott Bradner, Jim Hamerly, Marshall Kirk McKusick, Tim O’Reilly, Tom Paquin, Bruce Perens, Eric Raymond, Richard Stallman, Michael Tiemann, Linus Torvalds, Paul Vixie, Larry Wall, and Bob Young. You can read this book online.

Open Sources 2.0 : The Continuing Evolution


Continuation of previous book. The authors of essays are Mitchell Baker, Chris DiBona, Jeremy Allison, Ben Laurie, Michael Olson, Ian Murdock, Matthew N. Asay, Stephen R. Walli, Russ Nelson, Wendy Seltzer, Jusus M. Gonzalez-Barahona, Gregorio Robles, Alotita Sharma, Robert Adkins, Boon-Lock Yeo, Louisa Liu, Sunil Saxena, Bruno Souza, Doc Searls, Tim O’Reilly,Pamela Jones, Andrew Hessel, Eugene Kim, Larry Sanger, Sonali K. Shah, Steven Weber, Jeff Bates, Mark Stone. read this book online

Eric Raymond – New Hacker’s Dictionary


Dead-tree version of Jargon File

 

Video about Metasploit Framework

  1. Metasploit Intro [Irongeek]:
    download AVI | presentation PDF
  2. Metasploit Scanning and Pivoting [Pwrcycle]
    download AVI | presentation PDF
  3. Metasploit Fuzzing and Exploit Development [Nullthreat]
    download AVI | presentation + examples
  4. Meterpreter and Post Exploitation + Metasploit Express demo [Purehate]
    download AVI | presentation ZIP
  5. Social Engineering Toolkit [ReL1K]
    download AVI
  6. More Encoding Fun, Fasttrack and Closing [ReL1K]
    download AVI


Blog services