summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMario Fetka <mario@localhost.localdomain>2016-06-12 10:31:04 (GMT)
committer Mario Fetka <mario@localhost.localdomain>2016-06-12 10:31:04 (GMT)
commitf96eb9b97667051f0b504e07f2056bdfd70ed887 (patch)
tree1b9ff9af286fe266c364213c4852e29ef0b110fd
Imported Upstream version 0.4.2upstream/0.4.2
-rw-r--r--.gitignore8
-rw-r--r--Gemfile6
-rw-r--r--History25
-rw-r--r--LICENSE20
-rw-r--r--README.md44
-rw-r--r--crack.gemspec20
-rw-r--r--lib/crack.rb7
-rw-r--r--lib/crack/json.rb107
-rw-r--r--lib/crack/util.rb17
-rw-r--r--lib/crack/version.rb3
-rw-r--r--lib/crack/xml.rb238
-rwxr-xr-xscript/bootstrap21
-rwxr-xr-xscript/release42
-rwxr-xr-xscript/test25
-rw-r--r--test/data/twittersearch-firefox.json1
-rw-r--r--test/data/twittersearch-ie.json1
-rw-r--r--test/hash_test.rb26
-rw-r--r--test/json_test.rb80
-rw-r--r--test/parser_test.rb27
-rw-r--r--test/string_test.rb31
-rw-r--r--test/test_helper.rb3
-rw-r--r--test/xml_test.rb514
22 files changed, 1266 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7cb93ef
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+*.sw?
+.DS_Store
+coverage
+rdoc
+pkg
+*.gem
+/.bundle
+/Gemfile.lock
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..53f5237
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,6 @@
+source 'https://rubygems.org'
+gemspec
+
+gem "rake"
+gem "jnunemaker-matchy"
+gem "minitest"
diff --git a/History b/History
new file mode 100644
index 0000000..9e664d6
--- /dev/null
+++ b/History
@@ -0,0 +1,25 @@
+== 0.1.7 2010-02-19
+* 1 minor patch
+ * Added patch from @purp for ISO 8601 date/time format
+== 0.1.6 2010-01-31
+* 1 minor patch
+ * Added Crack::VERSION constant - http://weblog.rubyonrails.org/2009/9/1/gem-packaging-best-practices
+== 0.1.5 2010-01-27
+* 1 minor patch
+ * Strings that begin with dates shouldn't be parsed as such (sandro)
+
+== 0.1.3 2009-06-22
+* 1 minor patch
+ * Parsing a text node with attributes stores them in the attributes method (tamalw)
+
+== 0.1.2 2009-04-21
+* 2 minor patches
+ * Correct unnormalization of attribute values (der-flo)
+ * Fix error in parsing YAML in the case where a hash value ends with backslashes, and there are subsequent values in the hash (deadprogrammer)
+
+== 0.1.1 2009-03-31
+* 1 minor patch
+ * Parsing empty or blank xml now returns empty hash instead of raising error.
+
+== 0.1.0 2009-03-28
+* Initial release. \ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..fbbebe1
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2009 John Nunemaker
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a45170e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,44 @@
+# crack
+
+Really simple JSON and XML parsing, ripped from Merb and Rails. The XML parser is ripped from Merb and the JSON parser is ripped from Rails. I take no credit, just packaged them for all to enjoy and easily use.
+
+## compatibility
+
+* ruby 1.8.7
+* ruby 1.9+ (3 failures related to time parsing, would love it if someone could figure them out)
+
+## note on patches/pull requests
+
+* Fork the project.
+* Make your feature addition or bug fix.
+* Add tests for it. This is important so I don't break it in a future version unintentionally.
+* `script/test` - this will bootstrap and run the tests
+* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself in another branch so I can ignore when I pull)
+* Send me a pull request. Bonus points for topic branches.
+
+## usage
+
+```ruby
+gem 'crack' # in Gemfile
+require 'crack' # for xml and json
+require 'crack/json' # for just json
+require 'crack/xml' # for just xml
+```
+
+## examples
+
+```ruby
+Crack::XML.parse("<tag>This is the contents</tag>")
+# => {'tag' => 'This is the contents'}
+
+Crack::JSON.parse('{"tag":"This is the contents"}')
+# => {'tag' => 'This is the contents'}
+```
+
+## Copyright
+
+Copyright (c) 2009 John Nunemaker. See LICENSE for details.
+
+## Docs
+
+http://rdoc.info/projects/jnunemaker/crack
diff --git a/crack.gemspec b/crack.gemspec
new file mode 100644
index 0000000..2225c16
--- /dev/null
+++ b/crack.gemspec
@@ -0,0 +1,20 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../lib/crack/version', __FILE__)
+
+Gem::Specification.new do |gem|
+ gem.authors = ["John Nunemaker"]
+ gem.email = ["nunemaker@gmail.com"]
+ gem.description = %q{Really simple JSON and XML parsing, ripped from Merb and Rails.}
+ gem.summary = %q{Really simple JSON and XML parsing, ripped from Merb and Rails.}
+ gem.homepage = "http://github.com/jnunemaker/crack"
+
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
+ gem.files = `git ls-files`.split("\n")
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ gem.name = "crack"
+ gem.require_paths = ["lib"]
+ gem.version = Crack::VERSION
+ gem.license = "MIT"
+
+ gem.add_dependency "safe_yaml", "~> 1.0.0"
+end
diff --git a/lib/crack.rb b/lib/crack.rb
new file mode 100644
index 0000000..a211d2a
--- /dev/null
+++ b/lib/crack.rb
@@ -0,0 +1,7 @@
+module Crack
+ class ParseError < StandardError; end
+end
+
+require 'crack/util'
+require 'crack/json'
+require 'crack/xml'
diff --git a/lib/crack/json.rb b/lib/crack/json.rb
new file mode 100644
index 0000000..7bb890c
--- /dev/null
+++ b/lib/crack/json.rb
@@ -0,0 +1,107 @@
+# Copyright (c) 2004-2008 David Heinemeier Hansson
+# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+require 'safe_yaml/load'
+require 'strscan'
+
+module Crack
+ class JSON
+ def self.parser_exceptions
+ @parser_exceptions ||= begin
+ exceptions = [ArgumentError]
+
+ if const_defined?(:Psych)
+ if Psych.const_defined?(:SyntaxError)
+ exceptions << Psych::SyntaxError
+ end
+ end
+
+ exceptions
+ end
+ end
+
+ def self.parse(json)
+ args = [unescape(convert_json_to_yaml(json))]
+ args << nil if SafeYAML::MULTI_ARGUMENT_YAML_LOAD
+ args << { :whitelisted_tags => ['!ruby/regexp'] }
+
+ SafeYAML.load(*args)
+
+ rescue *parser_exceptions
+ raise ParseError, "Invalid JSON string"
+ end
+
+ protected
+ def self.unescape(str)
+ # Force the encoding to be UTF-8 so we can perform regular expressions
+ # on 1.9.2 without blowing up.
+ # see http://stackoverflow.com/questions/1224204/ruby-mechanize-getting-force-encoding-exception for a similar issue
+ str.force_encoding('UTF-8') if defined?(Encoding) && str.respond_to?(:force_encoding)
+ str.gsub(/\\u0000/, "").gsub(/\\[u|U]([0-9a-fA-F]{4})/) { [$1.hex].pack("U") }
+ end
+
+ # matches YAML-formatted dates
+ DATE_REGEX = /^\d{4}-\d{2}-\d{2}$|^\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)$/
+
+ # Ensure that ":" and "," are always followed by a space
+ def self.convert_json_to_yaml(json) #:nodoc:
+ json = String.new(json) #can't modify a frozen string
+ scanner, quoting, marks, pos, date_starts, date_ends = StringScanner.new(json), false, [], nil, [], []
+ while scanner.scan_until(/(\\['"]|['":,\/\\]|\\.)/)
+ case char = scanner[1]
+ when '"', "'"
+ if !quoting
+ quoting = char
+ pos = scanner.pos
+ elsif quoting == char
+ if json[pos..scanner.pos-2] =~ DATE_REGEX
+ # found a date, track the exact positions of the quotes so we can remove them later.
+ # oh, and increment them for each current mark, each one is an extra padded space that bumps
+ # the position in the final YAML output
+ total_marks = marks.size
+ date_starts << pos+total_marks
+ date_ends << scanner.pos+total_marks
+ end
+ quoting = false
+ end
+ when "/"
+ if !quoting
+ json[scanner.pos - 1] = "!ruby/regexp /"
+ scanner.pos += 13
+ scanner.scan_until(/\/[mix]*/)
+ end
+ when ":",","
+ marks << scanner.pos - 1 unless quoting
+ when "\\"
+ scanner.skip(/\\/)
+ end
+ end
+
+ if marks.empty?
+ json.gsub(/\\\//, '/')
+ else
+ left_pos = [-1].push(*marks)
+ right_pos = marks << json.length
+ output = []
+ left_pos.each_with_index do |left, i|
+ output << json[left.succ..right_pos[i]]
+ end
+ output = output * " "
+
+ format_dates(output, date_starts, date_ends)
+ output.gsub!(/\\\//, '/')
+ output
+ end
+ end
+
+ def self.format_dates(output, date_starts, date_ends)
+ if YAML.constants.include?('Syck')
+ (date_starts + date_ends).each { |i| output[i-1] = ' ' }
+ else
+ date_starts.each { |i| output[i-2] = '!!timestamp ' }
+ end
+ end
+ end
+end
diff --git a/lib/crack/util.rb b/lib/crack/util.rb
new file mode 100644
index 0000000..60c9442
--- /dev/null
+++ b/lib/crack/util.rb
@@ -0,0 +1,17 @@
+module Crack
+ module Util
+ def snake_case(str)
+ return str.downcase if str =~ /^[A-Z]+$/
+ str.gsub(/([A-Z]+)(?=[A-Z][a-z]?)|\B[A-Z]/, '_\&') =~ /_*(.*)/
+ return $+.downcase
+ end
+
+ def to_xml_attributes(hash)
+ hash.map do |k,v|
+ %{#{Crack::Util.snake_case(k.to_s).sub(/^(.{1,1})/) { |m| m.downcase }}="#{v.to_s.gsub('"', '&quot;')}"}
+ end.join(' ')
+ end
+
+ extend self
+ end
+end \ No newline at end of file
diff --git a/lib/crack/version.rb b/lib/crack/version.rb
new file mode 100644
index 0000000..dc97d74
--- /dev/null
+++ b/lib/crack/version.rb
@@ -0,0 +1,3 @@
+module Crack
+ VERSION = "0.4.2"
+end
diff --git a/lib/crack/xml.rb b/lib/crack/xml.rb
new file mode 100644
index 0000000..6985689
--- /dev/null
+++ b/lib/crack/xml.rb
@@ -0,0 +1,238 @@
+require 'rexml/parsers/streamparser'
+require 'rexml/parsers/baseparser'
+require 'rexml/light/node'
+require 'rexml/text'
+require "rexml/document"
+require 'date'
+require 'time'
+require 'yaml'
+require 'bigdecimal'
+
+# The Reason behind redefining the String Class for this specific plugin is to
+# avoid the dynamic insertion of stuff on it (see version previous to this commit).
+# Doing that disables the possibility of efectuating a dump on the structure. This way it goes.
+class REXMLUtiliyNodeString < String
+ attr_accessor :attributes
+end
+
+# This is a slighly modified version of the XMLUtilityNode from
+# http://merb.devjavu.com/projects/merb/ticket/95 (has.sox@gmail.com)
+# It's mainly just adding vowels, as I ht cd wth n vwls :)
+# This represents the hard part of the work, all I did was change the
+# underlying parser.
+class REXMLUtilityNode #:nodoc:
+ attr_accessor :name, :attributes, :children, :type
+
+ def self.typecasts
+ @@typecasts
+ end
+
+ def self.typecasts=(obj)
+ @@typecasts = obj
+ end
+
+ def self.available_typecasts
+ @@available_typecasts
+ end
+
+ def self.available_typecasts=(obj)
+ @@available_typecasts = obj
+ end
+
+ self.typecasts = {}
+ self.typecasts["integer"] = lambda{|v| v.nil? ? nil : v.to_i}
+ self.typecasts["boolean"] = lambda{|v| v.nil? ? nil : (v.strip != "false")}
+ self.typecasts["datetime"] = lambda{|v| v.nil? ? nil : Time.parse(v).utc}
+ self.typecasts["date"] = lambda{|v| v.nil? ? nil : Date.parse(v)}
+ self.typecasts["dateTime"] = lambda{|v| v.nil? ? nil : Time.parse(v).utc}
+ self.typecasts["decimal"] = lambda{|v| v.nil? ? nil : BigDecimal(v.to_s)}
+ self.typecasts["double"] = lambda{|v| v.nil? ? nil : v.to_f}
+ self.typecasts["float"] = lambda{|v| v.nil? ? nil : v.to_f}
+ self.typecasts["string"] = lambda{|v| v.to_s}
+ self.typecasts["base64Binary"] = lambda{|v| v.unpack('m').first }
+
+ self.available_typecasts = self.typecasts.keys
+
+ def initialize(name, normalized_attributes = {})
+
+ # unnormalize attribute values
+ attributes = Hash[* normalized_attributes.map { |key, value|
+ [ key, unnormalize_xml_entities(value) ]
+ }.flatten]
+
+ @name = name.tr("-", "_")
+ # leave the type alone if we don't know what it is
+ @type = self.class.available_typecasts.include?(attributes["type"]) ? attributes.delete("type") : attributes["type"]
+
+ @nil_element = attributes.delete("nil") == "true"
+ @attributes = undasherize_keys(attributes)
+ @children = []
+ @text = false
+ end
+
+ def add_node(node)
+ @text = true if node.is_a? String
+ @children << node
+ end
+
+ def to_hash
+ # ACG: Added a check here to prevent an exception a type == "file" tag has nodes within it
+ if @type == "file" and (@children.first.nil? or @children.first.is_a?(String))
+ f = StringIO.new((@children.first || '').unpack('m').first)
+ class << f
+ attr_accessor :original_filename, :content_type
+ end
+ f.original_filename = attributes['name'] || 'untitled'
+ f.content_type = attributes['content_type'] || 'application/octet-stream'
+ return {name => f}
+ end
+
+ if @text
+ t = typecast_value( unnormalize_xml_entities( inner_html ) )
+ if t.is_a?(String)
+ t = REXMLUtiliyNodeString.new(t)
+ t.attributes = attributes
+ end
+ return { name => t }
+ else
+ #change repeating groups into an array
+ groups = @children.inject({}) { |s,e| (s[e.name] ||= []) << e; s }
+
+ out = nil
+ if @type == "array"
+ out = []
+ groups.each do |k, v|
+ if v.size == 1
+ out << v.first.to_hash.entries.first.last
+ else
+ out << v.map{|e| e.to_hash[k]}
+ end
+ end
+ out = out.flatten
+
+ else # If Hash
+ out = {}
+ groups.each do |k,v|
+ if v.size == 1
+ out.merge!(v.first)
+ else
+ out.merge!( k => v.map{|e| e.to_hash[k]})
+ end
+ end
+ out.merge! attributes unless attributes.empty?
+ out = out.empty? ? nil : out
+ end
+
+ if @type && out.nil?
+ { name => typecast_value(out) }
+ else
+ { name => out }
+ end
+ end
+ end
+
+ # Typecasts a value based upon its type. For instance, if
+ # +node+ has #type == "integer",
+ # {{[node.typecast_value("12") #=> 12]}}
+ #
+ # @param value<String> The value that is being typecast.
+ #
+ # @details [:type options]
+ # "integer"::
+ # converts +value+ to an integer with #to_i
+ # "boolean"::
+ # checks whether +value+, after removing spaces, is the literal
+ # "true"
+ # "datetime"::
+ # Parses +value+ using Time.parse, and returns a UTC Time
+ # "date"::
+ # Parses +value+ using Date.parse
+ #
+ # @return <Integer, TrueClass, FalseClass, Time, Date, Object>
+ # The result of typecasting +value+.
+ #
+ # @note
+ # If +self+ does not have a "type" key, or if it's not one of the
+ # options specified above, the raw +value+ will be returned.
+ def typecast_value(value)
+ return value unless @type
+ proc = self.class.typecasts[@type]
+ proc.nil? ? value : proc.call(value)
+ end
+
+ # Take keys of the form foo-bar and convert them to foo_bar
+ def undasherize_keys(params)
+ params.keys.each do |key, value|
+ params[key.tr("-", "_")] = params.delete(key)
+ end
+ params
+ end
+
+ # Get the inner_html of the REXML node.
+ def inner_html
+ @children.join
+ end
+
+ # Converts the node into a readable HTML node.
+ #
+ # @return <String> The HTML node in text form.
+ def to_html
+ attributes.merge!(:type => @type ) if @type
+ "<#{name}#{Crack::Util.to_xml_attributes(attributes)}>#{@nil_element ? '' : inner_html}</#{name}>"
+ end
+
+ # @alias #to_html #to_s
+ def to_s
+ to_html
+ end
+
+ private
+
+ def unnormalize_xml_entities value
+ REXML::Text.unnormalize(value)
+ end
+end
+
+module Crack
+ class REXMLParser
+ def self.parse(xml)
+ stack = []
+ parser = REXML::Parsers::BaseParser.new(xml)
+
+ while true
+ event = parser.pull
+ case event[0]
+ when :end_document
+ break
+ when :end_doctype, :start_doctype
+ # do nothing
+ when :start_element
+ stack.push REXMLUtilityNode.new(event[1], event[2])
+ when :end_element
+ if stack.size > 1
+ temp = stack.pop
+ stack.last.add_node(temp)
+ end
+ when :text, :cdata
+ stack.last.add_node(event[1]) unless event[1].strip.length == 0 || stack.empty?
+ end
+ end
+
+ stack.length > 0 ? stack.pop.to_hash : {}
+ end
+ end
+
+ class XML
+ def self.parser
+ @@parser ||= REXMLParser
+ end
+
+ def self.parser=(parser)
+ @@parser = parser
+ end
+
+ def self.parse(xml)
+ parser.parse(xml)
+ end
+ end
+end
diff --git a/script/bootstrap b/script/bootstrap
new file mode 100755
index 0000000..d38fd1d
--- /dev/null
+++ b/script/bootstrap
@@ -0,0 +1,21 @@
+#!/bin/sh
+#/ Usage: bootstrap [bundle options]
+#/
+#/ Bundle install the dependencies.
+#/
+#/ Examples:
+#/
+#/ bootstrap
+#/ bootstrap --local
+#/
+
+set -e
+cd $(dirname "$0")/..
+
+[ "$1" = "--help" -o "$1" = "-h" -o "$1" = "help" ] && {
+ grep '^#/' <"$0"| cut -c4-
+ exit 0
+}
+
+rm -rf .bundle/{binstubs,config}
+bundle install --binstubs .bundle/binstubs --path .bundle --quiet "$@"
diff --git a/script/release b/script/release
new file mode 100755
index 0000000..43e04f9
--- /dev/null
+++ b/script/release
@@ -0,0 +1,42 @@
+#!/bin/sh
+#/ Usage: release
+#/
+#/ Tag the version in the repo and push the gem.
+#/
+
+set -e
+cd $(dirname "$0")/..
+
+[ "$1" = "--help" -o "$1" = "-h" -o "$1" = "help" ] && {
+ grep '^#/' <"$0"| cut -c4-
+ exit 0
+}
+
+gem_name=crack
+
+# Build a new gem archive.
+rm -rf $gem_name-*.gem
+gem build -q $gem_name.gemspec
+
+# Make sure we're on the master branch.
+(git branch | grep -q '* master') || {
+ echo "Only release from the master branch."
+ exit 1
+}
+
+# Figure out what version we're releasing.
+tag=v`ls $gem_name-*.gem | sed "s/^$gem_name-\(.*\)\.gem$/\1/"`
+
+echo "Releasing $tag"
+
+# Make sure we haven't released this version before.
+git fetch -t origin
+
+(git tag -l | grep -q "$tag") && {
+ echo "Whoops, there's already a '${tag}' tag."
+ exit 1
+}
+
+# Tag it and bag it.
+gem push $gem_name-*.gem && git tag "$tag" &&
+ git push origin master && git push origin "$tag"
diff --git a/script/test b/script/test
new file mode 100755
index 0000000..c50314e
--- /dev/null
+++ b/script/test
@@ -0,0 +1,25 @@
+#!/bin/sh
+#/ Usage: test [individual test file]
+#/
+#/ Bootstrap and run all tests or an individual test.
+#/
+#/ Examples:
+#/
+#/ # run all tests
+#/ test
+#/
+#/ # run individual test
+#/ test test/controller_instrumentation_test.rb
+#/
+
+set -e
+cd $(dirname "$0")/..
+
+[ "$1" = "--help" -o "$1" = "-h" -o "$1" = "help" ] && {
+ grep '^#/' <"$0"| cut -c4-
+ exit 0
+}
+
+script/bootstrap && ruby -I lib -I test -r rubygems \
+ -e 'require "bundler/setup"' \
+ -e '(ARGV.empty? ? Dir["test/**/*_test.rb"] : ARGV).each { |f| load f }' -- "$@"
diff --git a/test/data/twittersearch-firefox.json b/test/data/twittersearch-firefox.json
new file mode 100644
index 0000000..0ee9f03
--- /dev/null
+++ b/test/data/twittersearch-firefox.json
@@ -0,0 +1 @@
+{"results":[{"text":"#let\u00f6lt\u00e9s - Mozilla SeaMonkey 1.1.16 magyar: B\u00f6ng\u00e9sz\u00f5 (Firefox), chat program (ChatZilla), weboldal.. http:\/\/tinyurl.com\/clvydf","to_user_id":null,"from_user":"mp33portal","id":1567167290,"from_user_id":7191223,"iso_language_code":"hu","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/96234069\/mp33teamlogo_normal.JPG","created_at":"Mon, 20 Apr 2009 17:25:16 +0000"},{"text":"#veille-sur-internet Speedtile 0.4, un nouveau plugin de bookmarks en visuel pour Firefox: \n.. http:\/\/twurl.nl\/43eq0o","to_user_id":null,"from_user":"rez0","id":1567164191,"from_user_id":87975,"iso_language_code":"fr","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/71734441\/80x80-2_normal.jpg","created_at":"Mon, 20 Apr 2009 17:24:53 +0000"},{"text":"Firefox #fail 2 do dia...","to_user_id":null,"from_user":"lucascimino","id":1567163150,"from_user_id":561101,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/www.nambu.com&quot;&gt;Nambu&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/108061839\/macbookpro_7_normal.gif","created_at":"Mon, 20 Apr 2009 17:24:45 +0000"},{"text":"Download Squad: AVG offers standalone realtime web page scanning for Firefox and IE: Filed under:.. http:\/\/tinyurl.com\/c4v923","to_user_id":null,"from_user":"techwatch","id":1567162787,"from_user_id":907915,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/118338486\/FotoFlexer_Photo_normal.jpg","created_at":"Mon, 20 Apr 2009 17:24:42 +0000"},{"text":"oops.....thought I was typing in my address bar. Using my Sidekick as web for past 3 days...Need...Firefox...Back...In...Life...","to_user_id":null,"from_user":"MikeMorganJr","id":1567162698,"from_user_id":8472813,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterhelp.blogspot.com\/2008\/05\/twitter-via-mobile-web-mtwittercom.html&quot;&gt;mobile web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/101742681\/S4201261_normal.JPG","created_at":"Mon, 20 Apr 2009 17:24:42 +0000"},{"text":"Top 10 Firefox Add-ons for Linux Users http:\/\/www.linux-mag.com\/id\/7307 @LinuxMagazine","to_user_id":null,"from_user":"jtcatchenco","id":1567161761,"from_user_id":102514,"iso_language_code":"no","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/67647355\/jairo2_normal.jpg","created_at":"Mon, 20 Apr 2009 17:24:32 +0000"},{"text":"@mamamali Try &quot;TwitterFox&quot; for Firefox?","to_user_id":11418879,"to_user":"mamamali","from_user":"coldmilktea","id":1567160292,"from_user_id":366808,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/58805948\/n546821674_1689558_9769_normal.jpg","created_at":"Mon, 20 Apr 2009 17:24:24 +0000"},{"text":"@cbcurran i have and i like it, but i use firefox for dev. because of the dev tools available to users","to_user_id":4604162,"to_user":"cbcurran","from_user":"joshuamc","id":1567160224,"from_user_id":1038770,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/57059100\/1a8f013_normal.jpg","created_at":"Mon, 20 Apr 2009 17:24:24 +0000"},{"text":"@salustio A vers\u00e3o portuguesa do Firefox inclui motor de pesquisa para o Dicion\u00e1rio Priberam que funciona correctamente!? N\u00e3o \u00e9 essa?","to_user_id":2011109,"to_user":"salustio","from_user":"priberam","id":1567158943,"from_user_id":12725990,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/148282351\/logoquadrado_normal.jpg","created_at":"Mon, 20 Apr 2009 17:24:15 +0000"},{"text":"@enver555 hoy. En todos los ordenadores hay firefox y explorer, menos en el que me ha tocado hoy, que s\u00f3lo hay explorer.","to_user_id":1117,"to_user":"enver555","from_user":"Purnas","id":1567153499,"from_user_id":2869,"iso_language_code":"es","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/122746846\/ventanica_normal.jpg","created_at":"Mon, 20 Apr 2009 17:23:31 +0000"},{"text":"uffff por favor prueben la evolucion de las pesta\u00f1as en firefox... http:\/\/tinyurl.com\/3bhosa","to_user_id":null,"from_user":"rubbenslife","id":1567152871,"from_user_id":318865,"iso_language_code":"es","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/109636341\/gir-vector2_normal.png","created_at":"Mon, 20 Apr 2009 17:23:27 +0000"},{"text":"@Andrew_Taylor I used to use IE as an excuse to not get any work done--you know, when a web page looks great in Firefox but is crap in IE.","to_user_id":920152,"to_user":"Andrew_Taylor","from_user":"thepete","id":1567151382,"from_user_id":20159,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/software\/bigbird\/&quot;&gt;Bigbird&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/78425271\/ThePeteHead_normal.png","created_at":"Mon, 20 Apr 2009 17:23:16 +0000"},{"text":"15 cool tricks for firefox users http:\/\/twurl.nl\/ydpfj4 found via delicious network","to_user_id":null,"from_user":"mcfarljo","id":1567150610,"from_user_id":543823,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/67908105\/twitterprofile_normal.jpg","created_at":"Mon, 20 Apr 2009 17:23:10 +0000"},{"text":"Is there a good reason why it's taking so long for Firefox to load images since the last update?","to_user_id":null,"from_user":"KidKaz","id":1567150504,"from_user_id":2473590,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/78432331\/009_a_normal.png","created_at":"Mon, 20 Apr 2009 17:23:08 +0000"},{"text":"now its not working in Firefox on clients machine and they have exact same version as me (3.0.8) on a PC. Oh well....","to_user_id":null,"from_user":"andrewyee","id":1567150403,"from_user_id":1297173,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/destroytwitter.com\/&quot;&gt;DestroyTwitter&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/107140778\/CIMG738a5_normal.jpg","created_at":"Mon, 20 Apr 2009 17:23:07 +0000"},{"text":"Voltei para o Firefox 3.0.8, o 3.1b3 est\u00e1 com alguns bugs que acabam com a produtividade...","to_user_id":null,"from_user":"yporti","id":1567148429,"from_user_id":1470378,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/126029039\/avatar2_normal.png","created_at":"Mon, 20 Apr 2009 17:22:51 +0000"},{"text":"recovered bookmarks with firefox's automatic recovery - nice feature when you need it.","to_user_id":null,"from_user":"coffeeshrk","id":1567147766,"from_user_id":2776616,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twitterlight.com\/&quot;&gt;Twitterlight&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/132290339\/cg_normal.jpg","created_at":"Mon, 20 Apr 2009 17:22:48 +0000"},{"text":"@ewillett I'm using Firefox Portable. It has Flash, but not the latest version. I just checked in IE 7, and the titles appear last, and slow","to_user_id":1112964,"to_user":"ewillett","from_user":"fallapart","id":1567143242,"from_user_id":570499,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/55279513\/marturia_normal.gif","created_at":"Mon, 20 Apr 2009 17:22:12 +0000"},{"text":"Is there any &quot;Stop Susan Boyle News&quot; button on Firefox or IE7?","to_user_id":null,"from_user":"MyCaricaturecom","id":1567141153,"from_user_id":8967683,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/103773093\/untitled_normal.jpg","created_at":"Mon, 20 Apr 2009 17:21:56 +0000"},{"text":"Firefox Question: why is firefox not working for me? http:\/\/twurl.nl\/7dvotq","to_user_id":null,"from_user":"Firefox_Queries","id":1567139413,"from_user_id":994884,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/56842902\/fxq-a_normal.png","created_at":"Mon, 20 Apr 2009 17:21:42 +0000"},{"text":"Showing Joan the coolest add on for firefox = twitterfox","to_user_id":null,"from_user":"shannonels","id":1567130581,"from_user_id":8743358,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/112823048\/small_text1_17_normal.JPG","created_at":"Mon, 20 Apr 2009 17:20:34 +0000"},{"text":"Mientras espero la integraci\u00f3n en el Adium uso Twitbin en Firefox","to_user_id":null,"from_user":"elgaita","id":1567124994,"from_user_id":6025355,"iso_language_code":"es","source":"&lt;a href=&quot;http:\/\/www.twitbin.com\/&quot;&gt;TwitBin&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/86912947\/Ojo_normal.png","created_at":"Mon, 20 Apr 2009 17:19:53 +0000"},{"text":"@tenketanken fikk du noe svar p\u00e5 den addonen til firefox?","to_user_id":4597139,"to_user":"tenketanken","from_user":"cluver","id":1567120286,"from_user_id":3489762,"iso_language_code":"no","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/119889955\/Bilde_326_normal.jpg","created_at":"Mon, 20 Apr 2009 17:19:18 +0000"},{"text":"@KurtScholle Digg had Ads? lol, With Firefox, AdBlock &amp; RSS I never see the ads","to_user_id":333651,"to_user":"KurtScholle","from_user":"bcbeatty","id":1567119630,"from_user_id":68460,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/64319687\/Me_from_the_Lodge_7-13-08_normal.jpeg","created_at":"Mon, 20 Apr 2009 17:19:12 +0000"},{"text":"@spittingcat ahhh! didn't know, I only look at youtube on firefox. don't have any mobile communicators.","to_user_id":4254917,"to_user":"spittingcat","from_user":"mattmagic","id":1567117100,"from_user_id":5727306,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/84251889\/795405-big_normal.jpg","created_at":"Mon, 20 Apr 2009 17:18:53 +0000"},{"text":"@maboa - Mozilla\/5.0 (X11; U; Linux i686; en-GB; rv:1.8.1.13) Gecko\/20080316 SUSE\/2.0.0.13-0.2 Firefox\/2.0.0.13","to_user_id":33370,"to_user":"maboa","from_user":"lhearl","id":1567116047,"from_user_id":11145048,"iso_language_code":"no","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png","created_at":"Mon, 20 Apr 2009 17:18:47 +0000"},{"text":"Finally upgrading to Firefox 3 (from 2), on both my work and home computers. Why did it take me so long?","to_user_id":null,"from_user":"FrederikGoris","id":1567114241,"from_user_id":2183657,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/57245090\/binkley_trans_normal.gif","created_at":"Mon, 20 Apr 2009 17:18:34 +0000"},{"text":"really people. stop using internet explorer! FIREFOX! that way I don't have to keep changing my details on my site :)","to_user_id":null,"from_user":"StilettoSportsJ","id":1567114128,"from_user_id":3263198,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/140589587\/summer_me_normal.jpg","created_at":"Mon, 20 Apr 2009 17:18:32 +0000"},{"text":"at\u00e9q esse firefox 308 n\u00e3o est\u00e1 t\u00e3o ruim. mas ainda me irritam alguns bugs ~~","to_user_id":null,"from_user":"caduzito","id":1567111654,"from_user_id":5051483,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/76892540\/package_toys_normal.png","created_at":"Mon, 20 Apr 2009 17:18:15 +0000"},{"text":"Cierro Firefox y tweetdeck que tengo bastante tarea que hacer","to_user_id":null,"from_user":"marv3x","id":1567110471,"from_user_id":111779,"iso_language_code":"es","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/135137954\/moto_0679_normal.jpg","created_at":"Mon, 20 Apr 2009 17:18:05 +0000"},{"text":"@tmc057 love firefox, but now I use that google chrome on my laptop...like it too!","to_user_id":8622848,"to_user":"tmc057","from_user":"jennmet","id":1567108866,"from_user_id":7219827,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/129220839\/smile_feet_normal.jpg","created_at":"Mon, 20 Apr 2009 17:17:52 +0000"},{"text":"Firefox Plugin for Twitter http:\/\/tinyurl.com\/2bmr3q","to_user_id":null,"from_user":"mazharin","id":1567108398,"from_user_id":12764228,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/148417263\/logo_normal.gif","created_at":"Mon, 20 Apr 2009 17:17:51 +0000"},{"text":"firefox needs to not use a problematic cache","to_user_id":null,"from_user":"jakedahn","id":1567108188,"from_user_id":89635,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/iconfactory.com\/software\/twitterrific&quot;&gt;twitterrific&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/57291688\/n1277970100_2225_normal.jpg","created_at":"Mon, 20 Apr 2009 17:17:47 +0000"},{"text":"Dodajte Gmail Tasks u Firefox sidebar: Po\u0161to ste verovatno po\u010deli da koristite Gmail Tasks za pam\u0107enje va\u0161ih dne.. http:\/\/tinyurl.com\/df7dgt","to_user_id":null,"from_user":"djevrek","id":1567104166,"from_user_id":6752155,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/112428857\/Picture_202_normal.jpg","created_at":"Mon, 20 Apr 2009 17:17:17 +0000"},{"text":"sandwich? sandwhich? can i spell at all? why doesn't safari have spellcheck like firefox does?","to_user_id":null,"from_user":"slimfender","id":1567102131,"from_user_id":461073,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/125212882\/20-02-2009_1-2_normal.jpg","created_at":"Mon, 20 Apr 2009 17:16:58 +0000"},{"text":"Did you know that you can drag a tab from Firefox to Chome and back? Neat.","to_user_id":null,"from_user":"joshutk","id":1567100604,"from_user_id":222578,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/destroytwitter.com\/&quot;&gt;DestroyTwitter&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/53112855\/josh_cs3_normal.png","created_at":"Mon, 20 Apr 2009 17:16:48 +0000"},{"text":"@cineboy \n\nI think it's Firefox. Safari seems faster. I thought it was comcast.","to_user_id":3502968,"to_user":"cineboy","from_user":"AndrewFRobinson","id":1567092336,"from_user_id":5219854,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/80758440\/Blog_Picture_normal.jpg","created_at":"Mon, 20 Apr 2009 17:15:46 +0000"},{"text":"@Avinio thank you, firefox didn't work. it always gives back an error. thanks for helping though :)","to_user_id":218611,"to_user":"Avinio","from_user":"Sarah_Stuart","id":1567091592,"from_user_id":1854673,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/148425394\/n1050963749_30402544_5294812_normal.jpg","created_at":"Mon, 20 Apr 2009 17:15:40 +0000"},{"text":"Speed Up Firefox web browser http:\/\/tinyurl.com\/28zjbm","to_user_id":null,"from_user":"jayminkapish","id":1567089438,"from_user_id":227615,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/51442432\/jay_normal.png","created_at":"Mon, 20 Apr 2009 17:15:26 +0000"},{"text":"Minimap sidebar for Firefox ~ Mapping, addresses and directions @ http:\/\/tinyurl.com\/6f3yt6","to_user_id":null,"from_user":"steven2509","id":1567087844,"from_user_id":10204537,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/124435871\/Thor_3_normal.JPG","created_at":"Mon, 20 Apr 2009 17:15:12 +0000"},{"text":"@plutoniumpage Firefox -&gt; Safari: Mac or PC?","to_user_id":3185443,"to_user":"plutoniumpage","from_user":"Malacandra","id":1567087584,"from_user_id":1174499,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/91904641\/miles_for_twitter_normal.jpg","created_at":"Mon, 20 Apr 2009 17:15:10 +0000"},{"text":"@Beeeeg except firefox gets bored after a while and asks if you want the script to be stopped.","to_user_id":9535974,"to_user":"Beeeeg","from_user":"Drarok","id":1567080622,"from_user_id":941369,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/56645906\/Goomba_normal.jpg","created_at":"Mon, 20 Apr 2009 17:14:18 +0000"},{"text":"Screen resizing problems in Firefox http:\/\/tinyurl.com\/chz3wb","to_user_id":null,"from_user":"otherinboxhelp","id":1567079152,"from_user_id":2263650,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/63409998\/otherinbox_icon_normal.png","created_at":"Mon, 20 Apr 2009 17:14:07 +0000"},{"text":"@johnfbraun I really don't like Tweetdeck. Even with two monitors it takes up too much space. Tweetie fits perfectly just next to Firefox.","to_user_id":1291479,"to_user":"johnfbraun","from_user":"nentecular","id":1567076517,"from_user_id":928787,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/57182988\/nentecular_normal.jpg","created_at":"Mon, 20 Apr 2009 17:13:45 +0000"},{"text":"t\u00f4 de boa com a organiza\u00e7\u00e3o das abas do firefox. se mta coisa acumula pra ler, organiza nos favoritos! :)","to_user_id":null,"from_user":"foxpretender","id":1567075265,"from_user_id":2199243,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/72981570\/DSC00347_normal.JPG","created_at":"Mon, 20 Apr 2009 17:13:37 +0000"},{"text":"Queria o Gmail sempre aberto sem precisar usar o Firefox pra isso","to_user_id":null,"from_user":"rustymind","id":1567072458,"from_user_id":6155,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/88642915\/c_normal.jpg","created_at":"Mon, 20 Apr 2009 17:13:14 +0000"},{"text":"@BostonWealthMan i'll try to fix, but Firefox users can see the blog fine; come back to the blog in 20 mins and c what happens","to_user_id":6438140,"to_user":"BostonWealthMan","from_user":"yesandnotyes","id":1567067108,"from_user_id":3780901,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/118180349\/deo-portrait_normal.JPG","created_at":"Mon, 20 Apr 2009 17:12:34 +0000"},{"text":"@viciousbleu @benipsen if you have firefox, you can get a script via Greasemonkey to block apps\/quizzes in swathes. but it's a little work","to_user_id":1681225,"to_user":"viciousbleu","from_user":"SamCousins","id":1567066165,"from_user_id":5090625,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twhirl.org\/&quot;&gt;twhirl&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/127496405\/Sam_normal.jpg","created_at":"Mon, 20 Apr 2009 17:12:27 +0000"},{"text":"PS It seems like the photo album only works in Firefox, not IE right now. Good a reason as any to switch :)","to_user_id":null,"from_user":"toosunnyouthere","id":1567061723,"from_user_id":312807,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/57121330\/Twitter_profile_photo_normal.jpg","created_at":"Mon, 20 Apr 2009 17:11:53 +0000"},{"text":"@mackaffinity thanks for tip on firefox threaded tabs. Nice!","to_user_id":267931,"to_user":"mackaffinity","from_user":"malcolmbot","id":1567056739,"from_user_id":11583811,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/83degrees.com\/to\/powertwitter&quot;&gt;Power Twitter&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/78425206\/malcom_hat3_normal.jpg","created_at":"Mon, 20 Apr 2009 17:11:14 +0000"},{"text":"@Biertjuh JA, ik lul teveel :) Ene FireFox Pimp en ene Henk van Dijke zijn ineens verdwenen :) Ene Jenny Doverspike heb ik heengezonden","to_user_id":9701261,"to_user":"Biertjuh","from_user":"Kruimeldief","id":1567056294,"from_user_id":4748714,"iso_language_code":"nl","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/126656948\/8b06388c-1206-43df-b9dd-4b51228b373b_normal.jpg","created_at":"Mon, 20 Apr 2009 17:11:11 +0000"},{"text":"@bravenewcode tested in safari 4 beta &amp; 3.1.2 &amp; latest firefox on mac. the ajax stuff doesn't work in any of them.","to_user_id":994961,"to_user":"bravenewcode","from_user":"khlrqa","id":1567052831,"from_user_id":224717,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/57154560\/rrr300_normal.jpg","created_at":"Mon, 20 Apr 2009 17:10:45 +0000"},{"text":"RT: &quot;Throw all the tiny red lines you wish, I shall destroy them all!&quot;\n-- Fox, da SJ Games, sobre o corretor ortogr\u00e1fico do Firefox.","to_user_id":null,"from_user":"mamangava","id":1567052258,"from_user_id":4390018,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/75652189\/DSC04072_normal.JPG","created_at":"Mon, 20 Apr 2009 17:10:41 +0000"},{"text":"#Firefox prend officialement le nom de #Firefox3.5 dans la quatri\u00e8me beta de ce dernier :)","to_user_id":null,"from_user":"OyoKooN","id":1567044110,"from_user_id":176092,"iso_language_code":"fr","source":"&lt;a href=&quot;http:\/\/desktop.seesmic.com\/&quot;&gt;Seesmic Desktop&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/129147038\/OliviaDunhamJPG_normal.jpg","created_at":"Mon, 20 Apr 2009 17:09:40 +0000"},{"text":"Atlantainternetmarketing.net News: &quot;Top 10 Firefox Add-ons for Linux Users - Linux Magazine (registration)&quot; - http:\/\/tinyurl.com\/cfgdqb","to_user_id":null,"from_user":"SEOAtlanta","id":1567034693,"from_user_id":5051211,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.bravenewcode.com\/wordtwit\/&quot;&gt;WordTwit&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/126242512\/atlanta-seo-1_normal.png","created_at":"Mon, 20 Apr 2009 17:08:28 +0000"},{"text":"@Avinio i haven't tried firefox, just safari, good idea. am going to try it out now :) thanks","to_user_id":218611,"to_user":"Avinio","from_user":"Sarah_Stuart","id":1567028645,"from_user_id":1854673,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/148425394\/n1050963749_30402544_5294812_normal.jpg","created_at":"Mon, 20 Apr 2009 17:07:41 +0000"},{"text":"me voy a regresar a firefox porke google chrome no me convenci\u00f3","to_user_id":null,"from_user":"SonneMx","id":1567020771,"from_user_id":1065217,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/59431140\/DSC00072_normal.JPG","created_at":"Mon, 20 Apr 2009 17:06:41 +0000"},{"text":"Wyzo 3.0.1 The New Customized Browser Of FireFox 3.0.8 - http:\/\/tinyurl.com\/cm98td","to_user_id":null,"from_user":"anwarwagdi","id":1567016110,"from_user_id":2183567,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.sharethis.com&quot;&gt;ShareThis.com&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/83273512\/125x125_banner_normal.png","created_at":"Mon, 20 Apr 2009 17:06:06 +0000"},{"text":"Firefox = passoire ?: C\u2018est en tout cas ce que semble d\u00e9montrer une \u00e9tude men\u00e9e en 2008 par la soci\u00e9t\u00e9 Secunia, .. http:\/\/tinyurl.com\/dkgkj5","to_user_id":null,"from_user":"fuzzfr","id":1567013785,"from_user_id":3239997,"iso_language_code":"fr","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/68899486\/avatar_fuzz_normal.jpg","created_at":"Mon, 20 Apr 2009 17:05:47 +0000"},{"text":"@DavidEntremont It is a decent iPhone webb app. I need to start using a desktop app since Twitter.com always seems so laggy on firefox.","to_user_id":150359,"to_user":"DavidEntremont","from_user":"DrArdtagon","id":1567006240,"from_user_id":4627853,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/70564130\/Anthony93_normal.JPG","created_at":"Mon, 20 Apr 2009 17:04:51 +0000"},{"text":"Firefox 3.5b4 \u0432\u044b\u0439\u0434\u0435\u0442 22-24 \u0430\u043f\u0440\u0435\u043b\u044f http:\/\/tr.im\/jflf","to_user_id":null,"from_user":"smartfon","id":1567002479,"from_user_id":1538736,"iso_language_code":"ru","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/130824428\/av-150_normal.png","created_at":"Mon, 20 Apr 2009 17:04:23 +0000"},{"text":"im using firefox right now for my tweets but ima be on tweet deck or Tweetie in a minute","to_user_id":null,"from_user":"solaravada","id":1567000487,"from_user_id":3205793,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/140410086\/Picture_060_normal.jpg","created_at":"Mon, 20 Apr 2009 17:04:06 +0000"},{"text":"Speedtile 0.4, un nouveau plugin de bookmarks en visuel pour Firefox: \n\t\t\n\t\t\t\n\t\t\n\tPour les utiisateurs du naviga.. http:\/\/tinyurl.com\/cp9ado","to_user_id":null,"from_user":"jmgall","id":1566997778,"from_user_id":23853,"iso_language_code":"fr","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/90306573\/jmbg54000_normal.jpg","created_at":"Mon, 20 Apr 2009 17:03:47 +0000"},{"text":"Top 10 Firefox Add-ons for Linux Users http:\/\/bit.ly\/15v1bC","to_user_id":null,"from_user":"ielite","id":1566997201,"from_user_id":3174070,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/68501431\/logo_normal.PNG","created_at":"Mon, 20 Apr 2009 17:03:43 +0000"},{"text":"@AngryChad Use the Better GReader extension for Firefox!","to_user_id":310949,"to_user":"AngryChad","from_user":"abeldanger","id":1566992843,"from_user_id":611593,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/56922450\/my_head_normal.jpg","created_at":"Mon, 20 Apr 2009 17:03:11 +0000"},{"text":"twitter travando o firefox de cinco em cinco minutos!","to_user_id":null,"from_user":"marcel_silva","id":1566987360,"from_user_id":12757889,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/148430974\/7wBCg9Y8AaNEqXT_normal.jpg","created_at":"Mon, 20 Apr 2009 17:02:31 +0000"},{"text":"Anyone notice Firefox trying to be more like Chrome? &amp; with the FB\/twitter ap\/look and &amp; copy-tition it's like one big virtual brand soup","to_user_id":null,"from_user":"rachelcw","id":1566986955,"from_user_id":3051268,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/68342500\/rach_glasses_normal.jpg","created_at":"Mon, 20 Apr 2009 17:02:27 +0000"},{"text":"#Titook: The research was conducted by NSS labs and they had included the likes of Firefox (3.07), Apple.. http:\/\/tinyurl.com\/cnqhjs","to_user_id":null,"from_user":"TechnoZero","id":1566980725,"from_user_id":12687581,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/147420706\/TiDolphi_normal.jpg","created_at":"Mon, 20 Apr 2009 17:01:42 +0000"},{"text":"Turning OFF firefox so I get WORK!","to_user_id":null,"from_user":"CandiedFabrics","id":1566978524,"from_user_id":8190119,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/146694105\/Vimeo_avatar_300_normal.jpg","created_at":"Mon, 20 Apr 2009 17:01:27 +0000"},{"text":"Likes Mozilla Labs Weave 0.3 : Need to wait it be upgraded, hope to sync all of my firefox plugins and add-o... - http:\/\/likaholix.com\/r\/fBK","to_user_id":null,"from_user":"betashow","id":1566977384,"from_user_id":181186,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/147546718\/Leo_mobile_normal.jpg","created_at":"Mon, 20 Apr 2009 17:01:19 +0000"},{"text":"Firefox users, you probably know of the Twitter search add-on http:\/\/tinyurl.com\/c58xm9","to_user_id":null,"from_user":"edizquierdo","id":1566977150,"from_user_id":2010561,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/54481780\/ed_normal.png","created_at":"Mon, 20 Apr 2009 17:01:19 +0000"},{"text":"Download Facebook Albums to Your PC with FacePAD Firefox Add-on http:\/\/tinyurl.com\/daglp8","to_user_id":null,"from_user":"pcsbox","id":1566974888,"from_user_id":754736,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/76459142\/single_normal.JPG","created_at":"Mon, 20 Apr 2009 17:01:00 +0000"},{"text":"Testar Firefox 3.1 Beta 3","to_user_id":null,"from_user":"jonstg","id":1566974831,"from_user_id":2801022,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/www.chrisfinke.com\/addons\/twitterbar\/&quot;&gt;TwitterBar&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/70746207\/johan_stenberg_normal.JPG","created_at":"Mon, 20 Apr 2009 17:00:59 +0000"},{"text":"@priberam Uso o motor de pesquisa do dicion\u00e1rio instalado no Firefox. Sempre que procuro palavra com acentos, cedilha ou til, n\u00e3o reconhece.","to_user_id":12725990,"to_user":"priberam","from_user":"salustio","id":1566970119,"from_user_id":2011109,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/122514367\/maca2-twitter_normal.jpg","created_at":"Mon, 20 Apr 2009 17:00:28 +0000"},{"text":"Me hecho a dormir o pruebo Firefox 3.5 ? me hecho a dormir eso es mejor XD","to_user_id":null,"from_user":"icekrypto","id":1566965118,"from_user_id":11255742,"iso_language_code":"es","source":"&lt;a href=&quot;http:\/\/itweet.net\/&quot;&gt;iTweet&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/135479149\/icekrypto-mini_normal.jpg","created_at":"Mon, 20 Apr 2009 16:59:53 +0000"},{"text":"How to get a better Firefox with Ubiquity extension http:\/\/tinyurl.com\/c8pxlr","to_user_id":null,"from_user":"macstories","id":1566964874,"from_user_id":12757200,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/bluebirdapp.com&quot;&gt;Bluebird&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/148456587\/apple_logo_rainbow_6_color_normal.jpg","created_at":"Mon, 20 Apr 2009 16:59:51 +0000"},{"text":"@passionpit the video won't play on my Mac in neither Safari 4 nor Firefox 3. It jumps right to the end where it says &quot;replay&quot;\/&quot;share&quot;...","to_user_id":1195668,"to_user":"passionpit","from_user":"julscho","id":1566960035,"from_user_id":424071,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/loungeapp.com&quot;&gt;Lounge&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/148317755\/Tamala2010_330x296_normal.jpg","created_at":"Mon, 20 Apr 2009 16:59:17 +0000"},{"text":"@haacked Better yet, goes around and installs Firefox and makes it the default browser?","to_user_id":34575,"to_user":"haacked","from_user":"beebe4","id":1566958997,"from_user_id":183100,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/57482684\/Photo_5_normal.jpg","created_at":"Mon, 20 Apr 2009 16:59:08 +0000"},{"text":"@therealmaz Ideas for other topics: IDEs (Eclipse, Visual Studio, etc,,,) and Firefox + Firebug","to_user_id":381054,"to_user":"therealmaz","from_user":"elevine","id":1566957248,"from_user_id":83133,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twhirl.org\/&quot;&gt;twhirl&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/24654522\/avatar2_normal.jpg","created_at":"Mon, 20 Apr 2009 16:58:56 +0000"},{"text":"@Carol_Meneses @Carol_Meneses F\u00e1cil... se vc usa o firefox, baixe o twitter fox, a~i vai funcionar que nem orkut o seu twitter","to_user_id":12710301,"to_user":"Carol_Meneses","from_user":"koiann","id":1566956562,"from_user_id":8928327,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/112468850\/030209180946_normal.jpg","created_at":"Mon, 20 Apr 2009 16:58:49 +0000"},{"text":"is anyone else having problems with Firefox crashing? It's been crashing nonstop for me at work and at home...I do not want to go back to IE","to_user_id":null,"from_user":"Joveth","id":1566952618,"from_user_id":5661754,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/84254585\/Jono1_normal.jpg","created_at":"Mon, 20 Apr 2009 16:58:18 +0000"},{"text":"Wyzo 3.0.1 The New Customized Browser Of FireFox 3.0.8","to_user_id":null,"from_user":"ibraheiem","id":1566952321,"from_user_id":6483451,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png","created_at":"Mon, 20 Apr 2009 16:58:19 +0000"},{"text":"Enjoying the fruits of Firefox 3","to_user_id":null,"from_user":"NeonXero","id":1566949639,"from_user_id":4159819,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twhirl.org\/&quot;&gt;twhirl&lt;\/a&gt;","profile_image_url":"https:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/131049544\/Photo_147_normal.jpg","created_at":"Mon, 20 Apr 2009 16:57:59 +0000"},{"text":"New Post: [tip] \u5c07\u4efb\u4f55\u641c\u5c0b\u6846\u52a0\u5165\u706b\u72d0\u641c\u5c0b\u5217 \u2013 add any search engine into firefox search bar http:\/\/tinyurl.com\/dymzhm","to_user_id":null,"from_user":"brownywalking","id":1566948188,"from_user_id":130823,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/37532782\/\u5f71\u50cf008_normal.jpg","created_at":"Mon, 20 Apr 2009 16:57:47 +0000"},{"text":"&quot;Conflux&quot; is too a word, Firefox! You won't make me use &quot;confluence.&quot; Throw all the tiny red lines you wish, I shall destroy them all! -Fox","to_user_id":null,"from_user":"SJGames","id":1566946967,"from_user_id":2097481,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/64317528\/bigpyr_normal.png","created_at":"Mon, 20 Apr 2009 16:57:39 +0000"},{"text":"c4est relou d ecrire sur un clqvier qwerty. pis yq pqs firefox donc pqs de ;qils. fqil.","to_user_id":null,"from_user":"delgoff","id":1566944285,"from_user_id":1508369,"iso_language_code":"fr","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/94776151\/3318979772_3a9675756c_b_normal.jpg","created_at":"Mon, 20 Apr 2009 16:57:20 +0000"},{"text":"check out &quot;Personas&quot; for Firefox. Much easier than messing with themes. Dull Browser? get it here! http:\/\/digg.com\/d1nfa0 #newtechmondays","to_user_id":null,"from_user":"RosenKratz","id":1566935847,"from_user_id":2460052,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/56395851\/n7021936_38073746_8583_normal.jpg","created_at":"Mon, 20 Apr 2009 16:56:16 +0000"},{"text":"20+ Great Twitter Tools for Firefox http:\/\/ping.fm\/qQDf1","to_user_id":null,"from_user":"RealEstateXpert","id":1566927762,"from_user_id":461121,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.ping.fm\/&quot;&gt;Ping.fm&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/54324508\/jons_pic_normal.jpg","created_at":"Mon, 20 Apr 2009 16:55:14 +0000"},{"text":"@filipekiss \u00e9 verdade! O Foxytunes, extens\u00e3o pro Firefox, usa a Amazon pra pegar as capas.. eaHeaouhAEOUahe","to_user_id":216075,"to_user":"filipekiss","from_user":"mustabr","id":1566927275,"from_user_id":872878,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/138775391\/elitegeek_normal.png","created_at":"Mon, 20 Apr 2009 16:55:09 +0000"},{"text":"Come on PayPal, you don't support Firefox on your developer website?","to_user_id":null,"from_user":"paulwpagel","id":1566925393,"from_user_id":1145227,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/57536184\/Photo_8_normal.jpg","created_at":"Mon, 20 Apr 2009 16:54:55 +0000"},{"text":"Cool Firefox extension, Firediff: http:\/\/www.incaseofstairs.com\/firediff\/","to_user_id":null,"from_user":"nderksen","id":1566920249,"from_user_id":410013,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/108693203\/opus_small_normal.png","created_at":"Mon, 20 Apr 2009 16:54:18 +0000"},{"text":"Firefox.next: an iTunes-like browser? http:\/\/tinyurl.com\/dexkrr","to_user_id":null,"from_user":"macstories","id":1566919449,"from_user_id":12757200,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/bluebirdapp.com&quot;&gt;Bluebird&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/148456587\/apple_logo_rainbow_6_color_normal.jpg","created_at":"Mon, 20 Apr 2009 16:54:12 +0000"},{"text":"*sigh* I do cruel things to Firefox. *restarts browser*","to_user_id":null,"from_user":"mactavish","id":1566917670,"from_user_id":60868,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/59435649\/maryforprofileaug08_normal.jpg","created_at":"Mon, 20 Apr 2009 16:53:57 +0000"},{"text":"@mandiebear oh thats foxy tunes for firefox. its a plugin. that can control your music apps on your comp and post your song to twitter.","to_user_id":1734139,"to_user":"mandiebear","from_user":"samuraipanzer","id":1566914895,"from_user_id":126457,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.digsby.com\/&quot;&gt;digsby&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/79442241\/IMG00201_normal.jpg","created_at":"Mon, 20 Apr 2009 16:53:37 +0000"},{"text":"Its really confusing to keep track of windows in multiple desktops.. I have four windows of Firefox with the same page on each desktop.. :\\","to_user_id":null,"from_user":"itsanimesh","id":1566912616,"from_user_id":6778642,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/93907938\/DSC00370_normal.JPG","created_at":"Mon, 20 Apr 2009 16:53:19 +0000"},{"text":"Reading: &quot;10 Essential Firefox Addons\/Extensions For Bloggers | PCandWEB&quot; ( http:\/\/tinyurl.com\/dfrprz )","to_user_id":null,"from_user":"sgayen","id":1566912172,"from_user_id":4381856,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitthat.com\/&quot;&gt;twitthat&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/75387168\/sg_normal.JPG","created_at":"Mon, 20 Apr 2009 16:53:17 +0000"},{"text":"is sayin download skipscreen for firefox no more wait times for zshare rapidshare etc.....","to_user_id":null,"from_user":"r__dub","id":1566909817,"from_user_id":3204128,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png","created_at":"Mon, 20 Apr 2009 16:52:59 +0000"},{"text":"@rbieber you using Firefox 3.0 or the 3.1 beta? I was using 3.1 beta (very stable) until Safari 4 beta came out","to_user_id":29636,"to_user":"rbieber","from_user":"frumpa","id":1566905518,"from_user_id":192534,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.nambu.com&quot;&gt;Nambu&lt;\/a&gt;","profile_image_url":"https:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/137414986\/3437301687_7edf805439_normal.jpg","created_at":"Mon, 20 Apr 2009 16:52:25 +0000"},{"text":"Can it be true that Google @Adsense doesn't support Firefox on the Mac OS? For real?! Google hangs &amp; doesn't offer any confirmations. WTF?","to_user_id":null,"from_user":"mylerdude","id":1566905089,"from_user_id":10384,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twhirl.org\/&quot;&gt;twhirl&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/125612392\/mylerdude_gmail.com_615b413c_normal.jpg","created_at":"Mon, 20 Apr 2009 16:52:24 +0000"},{"text":"amo el hack &quot;open new tabs in background&quot; de firefox. creo que deber\u00eda venir por defecto.","to_user_id":null,"from_user":"claudio","id":1566903611,"from_user_id":14147,"iso_language_code":"es","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/77314492\/Imagen_1_normal.png","created_at":"Mon, 20 Apr 2009 16:52:13 +0000"}],"since_id":0,"max_id":1567167290,"refresh_url":"?since_id=1567167290&q=firefox","results_per_page":100,"next_page":"?page=2&max_id=1567167290&rpp=100&q=firefox","completed_in":0.041434,"page":1,"query":"firefox"} \ No newline at end of file
diff --git a/test/data/twittersearch-ie.json b/test/data/twittersearch-ie.json
new file mode 100644
index 0000000..8b0664a
--- /dev/null
+++ b/test/data/twittersearch-ie.json
@@ -0,0 +1 @@
+{"results":[{"text":"@4v4t4r La verdad ? No creo. Esas barritas vienen en la instalcion por defecto de Internet explorer, creeme es NORMAL.","to_user_id":5259518,"to_user":"4v4t4r","from_user":"Do0kK1em4n","id":1567118165,"from_user_id":11709821,"iso_language_code":"es","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/139688381\/avatar_new_normal.jpg","created_at":"Mon, 20 Apr 2009 17:19:04 +0000"},{"text":"really people. stop using internet explorer! FIREFOX! that way I don't have to keep changing my details on my site :)","to_user_id":null,"from_user":"StilettoSportsJ","id":1567114128,"from_user_id":3263198,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/140589587\/summer_me_normal.jpg","created_at":"Mon, 20 Apr 2009 17:18:32 +0000"},{"text":"MS09-014 MS Internet Explorer EMBED Memory Corruption PoC http:\/\/is.gd\/tv29","to_user_id":null,"from_user":"magic7502","id":1567099676,"from_user_id":6119063,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/116434670\/0312091732_normal.jpg","created_at":"Mon, 20 Apr 2009 17:16:43 +0000"},{"text":"Jo, no es que twitpic no lance el rss, no, es que Internet Explorer (donde me obligan a trabajar hoy) no los lee...caguen","to_user_id":null,"from_user":"Purnas","id":1567091912,"from_user_id":2869,"iso_language_code":"es","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/122746846\/ventanica_normal.jpg","created_at":"Mon, 20 Apr 2009 17:15:43 +0000"},{"text":"&lt;3'ing Internet Explorer 8's rendering. *God* I never thought i'd say that about an IE product....","to_user_id":null,"from_user":"jimmysparkle","id":1567090044,"from_user_id":1108298,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/20314752\/twitter2_normal.jpg","created_at":"Mon, 20 Apr 2009 17:15:28 +0000"},{"text":"adblocking with internet explorer 8 http:\/\/tinyurl.com\/d53of5 via @thurrott","to_user_id":null,"from_user":"KnightMare","id":1567087820,"from_user_id":328746,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/83949896\/sfu_normal.jpg","created_at":"Mon, 20 Apr 2009 17:15:12 +0000"},{"text":"Help kill Internet Explorer 6: http:\/\/ie6update.com","to_user_id":null,"from_user":"ninjamultimedia","id":1567086481,"from_user_id":2114255,"iso_language_code":"no","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/81114036\/twitter-pic_normal.jpg","created_at":"Mon, 20 Apr 2009 17:15:03 +0000"},{"text":"Meant to RT last week: Help kill Internet Explorer 6 http:\/\/bit.ly\/HkBgS (via @KISSmetrics)","to_user_id":null,"from_user":"mannyblum","id":1567082340,"from_user_id":30005,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/94915611\/photo_normal.jpg","created_at":"Mon, 20 Apr 2009 17:14:31 +0000"},{"text":"Dear Internet Explorer, You suck. &lt;3 Kristi","to_user_id":null,"from_user":"kristijoklemm","id":1567071123,"from_user_id":3190712,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/68600911\/Avatar_normal.jpg","created_at":"Mon, 20 Apr 2009 17:13:04 +0000"},{"text":"The North America Mission Board requires Internet explorer for all of their applications... baptist FAIL!","to_user_id":null,"from_user":"bradchristian","id":1567034289,"from_user_id":463002,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/62316824\/n742680170_4110871_9789_normal.jpg","created_at":"Mon, 20 Apr 2009 17:08:24 +0000"},{"text":"Looks like it's gonna be another week of me saying &quot;FUCK INTERNET EXPLORER!&quot; at least once a day.","to_user_id":null,"from_user":"travistubbs","id":1566938125,"from_user_id":37852,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twhirl.org\/&quot;&gt;twhirl&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/63067002\/Me_2008_Oct_28_-_192_normal.jpg","created_at":"Mon, 20 Apr 2009 16:56:31 +0000"},{"text":"MS Internet Explorer EMBED Memory Corruption PoC (MS09-014) http:\/\/tinyurl.com\/cglo9b","to_user_id":null,"from_user":"os555feed","id":1566891006,"from_user_id":4265807,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/91975412\/24122008884_normal.jpg","created_at":"Mon, 20 Apr 2009 16:50:37 +0000"},{"text":"@jhgagle A bug? Are you using Internet Explorer by any chance? lol","to_user_id":5204845,"to_user":"jhgagle","from_user":"JohnONolan","id":1566839803,"from_user_id":4194942,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/110880326\/gravatar-j_normal.jpg","created_at":"Mon, 20 Apr 2009 16:44:14 +0000"},{"text":"O blogue j\u00e1 \u00e9 99,7% compat\u00edvel com o Internet Explorer, falta pouco para os 99,9%.","to_user_id":null,"from_user":"ByGruph","id":1566835526,"from_user_id":7213531,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/111208842\/bygruph_logo_normal.jpg","created_at":"Mon, 20 Apr 2009 16:43:42 +0000"},{"text":"RT @nicknewlin: &quot;Internet Explorer is missing updates required to view this webpage&quot; http:\/\/ie6update.com\/","to_user_id":null,"from_user":"emmalpitts","id":1566824643,"from_user_id":849091,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twhirl.org\/&quot;&gt;twhirl&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/71384508\/twitter_normal.JPG","created_at":"Mon, 20 Apr 2009 16:42:20 +0000"},{"text":"@merlyn I like that MySQL gotcha quote:&quot;this page may not render well in Internet Explorer, run along and get yourself a proper browser.&quot; :)","to_user_id":332680,"to_user":"merlyn","from_user":"Ve2dmn","id":1566804056,"from_user_id":423826,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twhirl.org\/&quot;&gt;twhirl&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/53988981\/dave_simpson-1_normal.JPG","created_at":"Mon, 20 Apr 2009 16:39:46 +0000"},{"text":"Internet Explorer 6 smells of farts! Eggy ones!!!","to_user_id":null,"from_user":"Sulcalibur","id":1566803094,"from_user_id":9708,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/thecosmicmachine.com\/eventbox\/&quot;&gt;EventBox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/115919343\/house_av_normal.jpg","created_at":"Mon, 20 Apr 2009 16:39:39 +0000"},{"text":"vTalKi: MS Internet Explorer EMBED Memory Corruption PoC (MS09-014): MS Internet Explorer EMBED Memory Co.. http:\/\/tinyurl.com\/csm8tq","to_user_id":null,"from_user":"AdeelAhmad","id":1566801314,"from_user_id":6728,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/78465959\/SANY0169_normal.jpg","created_at":"Mon, 20 Apr 2009 16:39:26 +0000"},{"text":"&quot;Internet Explorer is missing updates required to view this webpage&quot; http:\/\/ie6update.com\/","to_user_id":null,"from_user":"nicknewlin","id":1566787085,"from_user_id":4723040,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/thecosmicmachine.com\/eventbox\/&quot;&gt;EventBox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/96068335\/twitter_normal.png","created_at":"Mon, 20 Apr 2009 16:37:38 +0000"},{"text":"@anapaulaludin AH, outra coisa: no Opera d\u00e1 de &quot;disfar\u00e7ar&quot; o browser como firefox ou Internet Explorer. Se no Safari tiver isso tb, tente.","to_user_id":3385343,"to_user":"anapaulaludin","from_user":"arielcardeal","id":1566751445,"from_user_id":8176469,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/106792395\/S6302098_normal.JPG","created_at":"Mon, 20 Apr 2009 16:33:12 +0000"},{"text":"is installing internet explorer 8... I don't even know why, I should just stick with Firefox","to_user_id":null,"from_user":"fbcyouthpastor","id":1566748760,"from_user_id":2496853,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/help.twitter.com\/index.php?pg=kb.page&amp;id=75&quot;&gt;txt&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/69581651\/Pizza_normal.jpg","created_at":"Mon, 20 Apr 2009 16:32:52 +0000"},{"text":"I did not think this was possible, but I hate Internet Explorer more today than I did yesterday.","to_user_id":null,"from_user":"arunningfool","id":1566745983,"from_user_id":1260812,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twhirl.org\/&quot;&gt;twhirl&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/73073734\/1231514992_normal.jpg","created_at":"Mon, 20 Apr 2009 16:32:31 +0000"},{"text":"Just had to open Internet Explorer in order to have 2 Twitter accounts open at once... had forgotten how much I loathe IE.","to_user_id":null,"from_user":"KylaJuett","id":1566711126,"from_user_id":12733890,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/117289537\/side_view_hair_shot_normal.jpg","created_at":"Mon, 20 Apr 2009 16:28:15 +0000"},{"text":"had to open Internet Explorer in order to have 2 Twitter accounts open at once... had forgotten how much I loathe IE. yucky.","to_user_id":null,"from_user":"kahlia","id":1566707487,"from_user_id":151880,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/148245858\/side_view_hair_shot_-_copia_normal.jpg","created_at":"Mon, 20 Apr 2009 16:27:47 +0000"},{"text":"@KamikazeKitty yep.. completely.. There's plugins for Firefox, and must be for Internet Explorer too.. &amp; the best part is, it's all online!","to_user_id":1740099,"to_user":"kamikazekitty","from_user":"farhan","id":1566672135,"from_user_id":150999,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/68949504\/largefacepicofme_normal.jpg","created_at":"Mon, 20 Apr 2009 16:23:25 +0000"},{"text":"ZDNet.de - Browstertest Internet Explorer 8 vs Google Chrome http:\/\/ff.im\/2eZKq","to_user_id":null,"from_user":"windowsos","id":1566662738,"from_user_id":5306236,"iso_language_code":"fr","source":"&lt;a href=&quot;http:\/\/friendfeed.com\/&quot;&gt;FriendFeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/81313254\/windows7-logo_normal.jpg","created_at":"Mon, 20 Apr 2009 16:22:13 +0000"},{"text":"How to Install Internet Explorer 8r http:\/\/ff.im\/2eZKu","to_user_id":null,"from_user":"windowsos","id":1566659663,"from_user_id":5306236,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/friendfeed.com\/&quot;&gt;FriendFeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/81313254\/windows7-logo_normal.jpg","created_at":"Mon, 20 Apr 2009 16:21:50 +0000"},{"text":"(I was about to moan about internet explorer but I keep crashing firefox too, suddenly remembering why PCs suck)","to_user_id":null,"from_user":"helenjaques","id":1566640635,"from_user_id":2301337,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/89328426\/H_Jaques_normal.JPG","created_at":"Mon, 20 Apr 2009 16:19:26 +0000"},{"text":"Nossa, a Interface do Twitter \u00e9 toda arredondada com -moz-border-radius, olha como fica o layout no Internet Explorer...","to_user_id":null,"from_user":"mikaelcarrara","id":1566614819,"from_user_id":1852892,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/147312394\/DSC05801_normal.jpg","created_at":"Mon, 20 Apr 2009 16:16:11 +0000"},{"text":"Help kill Internet Explorer 6 http:\/\/ie6update.com\/","to_user_id":null,"from_user":"balachandar","id":1566610906,"from_user_id":89981,"iso_language_code":"no","source":"&lt;a href=&quot;http:\/\/iconfactory.com\/software\/twitterrific&quot;&gt;twitterrific&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/68094517\/me-lomo-center_normal.jpg","created_at":"Mon, 20 Apr 2009 16:15:42 +0000"},{"text":"internet explorer + conex\u00e3o lent\u00edssima = infeeeeerno!","to_user_id":null,"from_user":"daniarrais","id":1566582349,"from_user_id":22932,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/65637888\/bzbzbz_normal.jpg","created_at":"Mon, 20 Apr 2009 16:12:11 +0000"},{"text":"has just installed Internet Explorer 8 on his Windows machine. It'll be used for testing websites compatibility only.","to_user_id":null,"from_user":"Jupe","id":1566538888,"from_user_id":41984,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/itweet.net\/&quot;&gt;iTweet&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/51410723\/Johnny_Depp_normal.jpg","created_at":"Mon, 20 Apr 2009 16:06:46 +0000"},{"text":"Pleaaaaase stop using Internet Explorer!","to_user_id":null,"from_user":"muratalibaba","id":1566535914,"from_user_id":9140550,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twittergadget.com&quot;&gt;TwitterGadget&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/114003933\/8_normal.jpg","created_at":"Mon, 20 Apr 2009 16:06:23 +0000"},{"text":"RT SannWoodReading: Twitter Plagued with Annoying Worm - Do Not Use Internet Explorer ( http:\/\/tinyurl.com\/df4vyt )","to_user_id":null,"from_user":"DWsCoverGirl1","id":1566517464,"from_user_id":10956377,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/147202714\/Picture_065_normal.jpg","created_at":"Mon, 20 Apr 2009 16:04:13 +0000"},{"text":"Internet Explorer 8 Web Accelerators http:\/\/ff.im\/2eZte","to_user_id":null,"from_user":"windowsos","id":1566498044,"from_user_id":5306236,"iso_language_code":"fr","source":"&lt;a href=&quot;http:\/\/friendfeed.com\/&quot;&gt;FriendFeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/81313254\/windows7-logo_normal.jpg","created_at":"Mon, 20 Apr 2009 16:01:52 +0000"},{"text":"Abri o Microsoft Windows Internet Explorer e fui direto pro Facebook. Vou ver o Twitter do @dennylira.","to_user_id":null,"from_user":"cwks","id":1566493322,"from_user_id":3101152,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/destroytwitter.com\/&quot;&gt;DestroyTwitter&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/122467825\/wall_post_normal.png","created_at":"Mon, 20 Apr 2009 16:01:17 +0000"},{"text":"Internet Explorer 8 Easier Browsing http:\/\/ff.im\/2eZtf","to_user_id":null,"from_user":"windowsos","id":1566491939,"from_user_id":5306236,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/friendfeed.com\/&quot;&gt;FriendFeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/81313254\/windows7-logo_normal.jpg","created_at":"Mon, 20 Apr 2009 16:01:08 +0000"},{"text":"@shaymorris it is the new version of internet explorer.","to_user_id":9024003,"to_user":"shaymorris","from_user":"Evaid","id":1566466536,"from_user_id":9457085,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/141044641\/thumb_normal.jpg","created_at":"Mon, 20 Apr 2009 15:58:07 +0000"},{"text":"A detestar o Internet Explorer s\u00f3 um bocadinho!","to_user_id":null,"from_user":"usaralho","id":1566454790,"from_user_id":4141064,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/119807777\/Albergaria_2009__24__normal.JPG","created_at":"Mon, 20 Apr 2009 15:56:41 +0000"},{"text":"www.ThunDi.com Download Internet Explorer 8 All Versions Full Setup Offline Standalone Installer For http:\/\/u.mavrev.com\/2vwb","to_user_id":null,"from_user":"ThunDi","id":1566449624,"from_user_id":2520137,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/118360174\/n599657087_2508_1__normal.jpg","created_at":"Mon, 20 Apr 2009 15:56:04 +0000"},{"text":"Thinking about switching to Windows? The Windows hardware compatibility list (HCL) can only be viewed with Internet Explorer.","to_user_id":null,"from_user":"chaz_6","id":1566422783,"from_user_id":5979546,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/identi.ca\/&quot;&gt;Identica&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/88105653\/chaz6-avatar-alt-trans_normal.png","created_at":"Mon, 20 Apr 2009 15:52:45 +0000"},{"text":"Reading: Twitter Plagued with Annoying Worm - Do Not Use Internet Explorer ( http:\/\/tinyurl.com\/df4vyt )","to_user_id":null,"from_user":"SannWood","id":1566359020,"from_user_id":7039,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitthat.com\/&quot;&gt;twitthat&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/51719837\/staci_avatar2_normal.jpg","created_at":"Mon, 20 Apr 2009 15:44:54 +0000"},{"text":"J\u00e1 consegui descobrir a causa de um bug no Internet Explorer, mas ainda falta descobrir e corrigir outro.","to_user_id":null,"from_user":"ByGruph","id":1566321286,"from_user_id":7213531,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/111208842\/bygruph_logo_normal.jpg","created_at":"Mon, 20 Apr 2009 15:40:15 +0000"},{"text":"@Glinner Can I be a clued in Twtter type who uses a combination of Firefox AND Internet Explorer AND Chrome for different uses?","to_user_id":414478,"to_user":"Glinner","from_user":"niviking","id":1566314778,"from_user_id":2494734,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twhirl.org\/&quot;&gt;twhirl&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/81692652\/060122_Me_normal.jpg","created_at":"Mon, 20 Apr 2009 15:39:28 +0000"},{"text":"at the bottom of MSN emails: &quot;Get the new Internet Explorer 8 Optimised for MSN&quot; the last 3 words there scare me","to_user_id":null,"from_user":"pixelenvy","id":1566277338,"from_user_id":122930,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/blog.codahale.com\/2007\/01\/15\/tweet-twitter-quicksilver\/&quot;&gt;Qu\u0131c\u0138s\u0131\u0269\u2174\u03b5\u0280&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/67508889\/first_choice_normal.jpg","created_at":"Mon, 20 Apr 2009 15:34:56 +0000"},{"text":"@Glinner Anyone using Internet Explorer is onlikely to be on here. They're probably at the dry cleaners picking up their spare hair shirt.","to_user_id":414478,"to_user":"Glinner","from_user":"rob_hyde","id":1566275213,"from_user_id":3445699,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/127583120\/n871955857_506717_9726_normal.jpg","created_at":"Mon, 20 Apr 2009 15:34:39 +0000"},{"text":"@Glinner Internet Explorer?? Next you'll be telling us of some new fangled horseless carriage which travels along a black carpet of tar! ;-)","to_user_id":414478,"to_user":"Glinner","from_user":"icybloke","id":1566272575,"from_user_id":4233910,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/88388455\/me_normal.png","created_at":"Mon, 20 Apr 2009 15:34:21 +0000"},{"text":"everything changes one you open up internet explorer... got some spiffing up to do in the moonlight hours. loving the ortlieb bike packers.","to_user_id":null,"from_user":"mimiflynn","id":1566258732,"from_user_id":5536946,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/84122388\/DSCF4076_normal.jpg","created_at":"Mon, 20 Apr 2009 15:32:35 +0000"},{"text":"@LondonEater I can't even get in the page, it says internet explorer can't display etc.","to_user_id":1658084,"to_user":"londoneater","from_user":"hollowlegs","id":1566247230,"from_user_id":1328869,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twittergadget.com&quot;&gt;TwitterGadget&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/142065903\/s514357173_1150793_8485_normal.jpg","created_at":"Mon, 20 Apr 2009 15:31:12 +0000"},{"text":"RT @Glinner: I realise most of you aren't using Internet Explorer, being clued-in Twitter types, but just in case.http:\/\/tinyurl.com\/6a37pp","to_user_id":null,"from_user":"andersoicouk","id":1566231989,"from_user_id":642429,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png","created_at":"Mon, 20 Apr 2009 15:29:22 +0000"},{"text":"RT @Glinner: I realise most of you aren't using Internet Explorer, being clued-in Twitter types, but just in case...http:\/\/tinyurl.com\/6 ...","to_user_id":null,"from_user":"andersoicouk","id":1566225949,"from_user_id":642429,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png","created_at":"Mon, 20 Apr 2009 15:28:36 +0000"},{"text":"I realise most of you aren't using Internet Explorer, being clued-in Twitter types, but just in case...http:\/\/tinyurl.com\/6a37pp","to_user_id":null,"from_user":"Glinner","id":1566218970,"from_user_id":414478,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/48545652\/glinner-128_normal.jpg","created_at":"Mon, 20 Apr 2009 15:27:45 +0000"},{"text":"IE Favorites Center Shortcuts: You know about Internet Explorer's Favorites Center, right? Do you want to make y.. http:\/\/tinyurl.com\/dbky2e","to_user_id":null,"from_user":"FasTekSolutions","id":1566205555,"from_user_id":12673182,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/147843815\/fts3_normal.gif","created_at":"Mon, 20 Apr 2009 15:26:07 +0000"},{"text":"SVG Tiger in Internet Explorer: http:\/\/tinyurl.com\/bwx4ub #svgie","to_user_id":null,"from_user":"ilinsky","id":1566181781,"from_user_id":1603038,"iso_language_code":"no","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/59922497\/sergey_ilinsky_normal.jpg","created_at":"Mon, 20 Apr 2009 15:23:09 +0000"},{"text":"Is your website ready for Internet Explorer 8? http:\/\/bit.ly\/5tFGz","to_user_id":null,"from_user":"FletchMcGull","id":1566170143,"from_user_id":5605296,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/83371976\/fletchmcbadboy2_normal.jpg","created_at":"Mon, 20 Apr 2009 15:21:44 +0000"},{"text":"I HATE programming a web application to be cross-browser compatible. Internet Explorer makes this too damn difficult.","to_user_id":null,"from_user":"level10","id":1566125694,"from_user_id":892608,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/72748210\/avatar-seth_normal.jpg","created_at":"Mon, 20 Apr 2009 15:16:12 +0000"},{"text":"hating internet explorer, it fails majorly...","to_user_id":null,"from_user":"SampsonW","id":1566108019,"from_user_id":12725625,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/148185431\/n794830012_4855990_9040_normal.jpg","created_at":"Mon, 20 Apr 2009 15:14:06 +0000"},{"text":"Got my new macbook up and running; with Internet Explorer and Outlook running through Parallel Desktop 4.0 It works great! Ready 4 the week.","to_user_id":null,"from_user":"johncarle","id":1566082833,"from_user_id":7733278,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/orangatame.com\/products\/twitterberry\/&quot;&gt;TwitterBerry&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/102687812\/iStock_000006069267Small_normal.jpg","created_at":"Mon, 20 Apr 2009 15:10:56 +0000"},{"text":"O blogue \u00e9 96% compat\u00edvel com o Internet Explorer. Os restantes browsers Firefox, Safari e Opera 99,9%. Existe ainda dois bugs no IE.","to_user_id":null,"from_user":"ByGruph","id":1566071355,"from_user_id":7213531,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/111208842\/bygruph_logo_normal.jpg","created_at":"Mon, 20 Apr 2009 15:09:31 +0000"},{"text":"Internet Explorer 8.0 Final [For XP]\nhttp:\/\/tinyurl.com\/cwj5j6","to_user_id":null,"from_user":"liveoutsource","id":1566052983,"from_user_id":5926625,"iso_language_code":"fr","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/85965061\/live-outsource-logo_normal.gif","created_at":"Mon, 20 Apr 2009 15:07:12 +0000"},{"text":"@popelizbet Yah but I'm a rebel and internet explorer refuses to work on my lappy. If it works for you go for it, as for me I filed mine np","to_user_id":4132150,"to_user":"popelizbet","from_user":"maggs07","id":1565996678,"from_user_id":11256184,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/148251632\/onthewayto_grad_interview_normal.jpg","created_at":"Mon, 20 Apr 2009 15:00:12 +0000"},{"text":"Maldito Internet Explorer.","to_user_id":null,"from_user":"ByGruph","id":1565972305,"from_user_id":7213531,"iso_language_code":"fr","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/111208842\/bygruph_logo_normal.jpg","created_at":"Mon, 20 Apr 2009 14:57:07 +0000"},{"text":"RT @gacconsultants &quot;Twitter Plagued with Annoying Worm - Do Not Use Internet Explorer&quot; http:\/\/hub.tm\/?HLVWJ","to_user_id":null,"from_user":"danielngsh","id":1565964732,"from_user_id":2124434,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/119922222\/seline_normal.jpg","created_at":"Mon, 20 Apr 2009 14:56:08 +0000"},{"text":"latest version of Mozilla not an approved browser in which to fill out the FAFSA. y halo thar, Internet Explorer, we meet again.","to_user_id":null,"from_user":"popelizbet","id":1565957004,"from_user_id":4132150,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/74155220\/220png_normal.PNG","created_at":"Mon, 20 Apr 2009 14:55:08 +0000"},{"text":"RT @gacconsultants: &quot;Twitter Plagued with Annoying Worm - Do Not Use Internet Explorer&quot; http:\/\/hub.tm\/?HLVWJ","to_user_id":null,"from_user":"mnazrulhisyam","id":1565955303,"from_user_id":5077164,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/109695942\/DSC00681_normal.JPG","created_at":"Mon, 20 Apr 2009 14:54:54 +0000"},{"text":"&quot;Twitter Plagued with Annoying Worm - Do Not Use Internet Explorer&quot; http:\/\/hub.tm\/?HLVWJ","to_user_id":null,"from_user":"gacconsultants","id":1565940431,"from_user_id":2365333,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.grader.com&quot;&gt;Twitter Grader&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/68430271\/Hello..._normal.jpg","created_at":"Mon, 20 Apr 2009 14:53:01 +0000"},{"text":"i hate internet explorer. it's not letting me update my twitter at school.","to_user_id":null,"from_user":"thejoshosaurus","id":1565923978,"from_user_id":1810512,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/61037694\/241852_large_normal.jpg","created_at":"Mon, 20 Apr 2009 14:50:55 +0000"},{"text":"What do Internet Explorer and Lotus Notes in common? -- v8 is out there but corporate dinos cling to v6.","to_user_id":null,"from_user":"notessensei","id":1565907925,"from_user_id":37829,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/52169724\/StephanAndTheCat140x185_normal.jpg","created_at":"Mon, 20 Apr 2009 14:48:53 +0000"},{"text":"Internet Explorer 8 add-in how to\n\nhttp:\/\/tinyurl.com\/cl9g9q","to_user_id":null,"from_user":"CyberComputerSt","id":1565907073,"from_user_id":8867781,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/116097560\/ccs1_normal.jpg","created_at":"Mon, 20 Apr 2009 14:48:45 +0000"},{"text":"Internet Explorer 8 - InPrivate-Browsen: http:\/\/tinyurl.com\/d9jq82","to_user_id":null,"from_user":"WindowsGermany","id":1565893337,"from_user_id":9387160,"iso_language_code":"sv","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/147842477\/StartBTN-Vista_rgb_normal.png","created_at":"Mon, 20 Apr 2009 14:46:57 +0000"},{"text":"Whao. Internet explorer 8 is FAST","to_user_id":null,"from_user":"Ashvixen","id":1565891692,"from_user_id":6016970,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/orangatame.com\/products\/twitterberry\/&quot;&gt;TwitterBerry&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/147184752\/n500466776_2127527_1876248_normal.jpg","created_at":"Mon, 20 Apr 2009 14:46:44 +0000"},{"text":"Fix Internet Explorer 6 and 7 bugs (Make IE behave like a standards-compliant browser) http:\/\/bit.ly\/aUOSt RT @webupd8","to_user_id":null,"from_user":"kirako","id":1565882418,"from_user_id":2297,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.hootsuite.com&quot;&gt;HootSuite&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/136164291\/melly84_normal.jpg","created_at":"Mon, 20 Apr 2009 14:45:35 +0000"},{"text":"Internet Explorer &lt; 8 is broken and obsolete. Web sites requiring Internet Explorer &lt; 8 are likewise also broken and obsolete.","to_user_id":null,"from_user":"mcornick","id":1565847317,"from_user_id":7397,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/77442678\/Photo_1_normal.jpg","created_at":"Mon, 20 Apr 2009 14:41:00 +0000"},{"text":"MS Internet Explorer EMBED Memory Corruption PoC (MS09-014)","to_user_id":null,"from_user":"niktrix","id":1565830605,"from_user_id":3457414,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/134374205\/download_normal.jpg","created_at":"Mon, 20 Apr 2009 14:38:49 +0000"},{"text":"@Japh &quot;Internet Explorer is missing updates required to view this site.&quot; That's misleading unless you really have locked IE6 users out.","to_user_id":1317941,"to_user":"Japh","from_user":"friskdesign","id":1565830261,"from_user_id":7665755,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/129021924\/lastfm_normal.jpg","created_at":"Mon, 20 Apr 2009 14:38:46 +0000"},{"text":"Fechando o Microsoft Windows Internet Explorer, clicando na bolinha e em Shut down. Tchau, e at\u00e9 os #2700 :)","to_user_id":null,"from_user":"cwks","id":1565786325,"from_user_id":3101152,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/destroytwitter.com\/&quot;&gt;DestroyTwitter&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/122467825\/wall_post_normal.png","created_at":"Mon, 20 Apr 2009 14:33:02 +0000"},{"text":"RT @xutopia: Internet Explorer 6 Update Trick #ie6 #webdesign #webprogramming http:\/\/ie6update.com\/","to_user_id":null,"from_user":"JessyO","id":1565755580,"from_user_id":2191850,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/desktop.seesmic.com\/&quot;&gt;Seesmic Desktop&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/124298504\/Photo_54_normal.jpg","created_at":"Mon, 20 Apr 2009 14:29:04 +0000"},{"text":"Automated: Internet Explorer 6 http:\/\/tinyurl.com\/c2ht3u","to_user_id":null,"from_user":"ara_p","id":1565737524,"from_user_id":25594,"iso_language_code":"fr","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/114724699\/avatar_normal.png","created_at":"Mon, 20 Apr 2009 14:26:41 +0000"},{"text":"RT @jbooth83: RT @Hall_Web: Do Not Use Internet Explorer http:\/\/tinyurl.com\/df4vyt -- best advice I've heard in a while!","to_user_id":null,"from_user":"finalrune","id":1565728238,"from_user_id":1414501,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/70917649\/fred-2_normal.jpg","created_at":"Mon, 20 Apr 2009 14:25:26 +0000"},{"text":"Twitter Plagued with Annoying Worm - Do Not Use Internet Explorer http:\/\/is.gd\/tsKm","to_user_id":null,"from_user":"dialogicmed","id":1565719266,"from_user_id":2769926,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.newsfirex.com\/safari140\/&quot;&gt;safari140&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/66204807\/F1000021_normal.jpg","created_at":"Mon, 20 Apr 2009 14:24:14 +0000"},{"text":"Help kill Internet Explorer 6 #ie6update http:\/\/ow.ly\/3kpr via @leemunroe","to_user_id":null,"from_user":"ghooghe","id":1565703968,"from_user_id":3408076,"iso_language_code":"nl","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/69901165\/ghooghe_normal.jpg","created_at":"Mon, 20 Apr 2009 14:22:13 +0000"},{"text":"Internet Explorer 6 Update Trick #ie6 #webdesign #webprogramming http:\/\/ie6update.com\/","to_user_id":null,"from_user":"xutopia","id":1565699013,"from_user_id":350298,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/identi.ca\/&quot;&gt;Identica&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/130684111\/n594340287_6946_normal.jpg","created_at":"Mon, 20 Apr 2009 14:21:33 +0000"},{"text":"Twitter Plagued with Annoying Worm - Do Not Use Internet Explorer - http:\/\/tinyurl.com\/df4vyt","to_user_id":null,"from_user":"nishadsn","id":1565643584,"from_user_id":4175863,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.sharethis.com&quot;&gt;ShareThis.com&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/74403312\/DSC_0345_normal.JPG","created_at":"Mon, 20 Apr 2009 14:14:08 +0000"},{"text":"having a fight with Internet Explorer 7. And losing. Windows folks, upgrade to IE8. (and then go to http:\/\/www.scottcrews.com )","to_user_id":null,"from_user":"scottcrews","id":1565640501,"from_user_id":193280,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/66364301\/7682769_normal.jpg","created_at":"Mon, 20 Apr 2009 14:13:44 +0000"},{"text":"Just downloaded the Internet Explorer 8. Looks alright but it will never convert me","to_user_id":null,"from_user":"ryanmawhinney","id":1565634164,"from_user_id":3546086,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitterfox.net\/&quot;&gt;TwitterFox&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/75889651\/ryandeborah_normal.png","created_at":"Mon, 20 Apr 2009 14:12:51 +0000"},{"text":"Another Twitter worm: http:\/\/tinyurl.com\/cjzxmm It seems to only be a problem for Internet Explorer users, or those who follow celebrities.","to_user_id":null,"from_user":"rlainhart","id":1565626398,"from_user_id":4251120,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/74857807\/DarkAvatar_normal.jpg","created_at":"Mon, 20 Apr 2009 14:11:45 +0000"},{"text":"RT @Hall_Web: Twitter Plagued with Annoying Worm - Do Not Use Internet Explorer http:\/\/tinyurl.com\/df4vyt","to_user_id":null,"from_user":"jbooth83","id":1565625363,"from_user_id":1468154,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.tweetdeck.com\/&quot;&gt;TweetDeck&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/59048474\/1139021_normal.png","created_at":"Mon, 20 Apr 2009 14:11:38 +0000"},{"text":"sick of internet explorer..always F**king up!","to_user_id":null,"from_user":"yodadapug","id":1565622663,"from_user_id":12620982,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/146966177\/IMG_1031_normal.JPG","created_at":"Mon, 20 Apr 2009 14:11:15 +0000"},{"text":"We've sorted out our order form issues for Internet Explorer users, you can now submit orders. We're working hard on the contact page.","to_user_id":null,"from_user":"slicestation","id":1565603428,"from_user_id":4780367,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twuffer.com&quot;&gt;Twuffer&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/144962167\/app_48_normal.png","created_at":"Mon, 20 Apr 2009 14:08:36 +0000"},{"text":"Petition: the internet to stop using Internet Explorer! http:\/\/twitition.com\/zv4mg @greygorn","to_user_id":null,"from_user":"colindpritchard","id":1565600593,"from_user_id":3694030,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/81513344\/Photo_192_normal.jpg","created_at":"Mon, 20 Apr 2009 14:08:11 +0000"},{"text":"@Tech_Mate Not work tech Internet Explorer cannot display the webpage 8o|","to_user_id":12686895,"to_user":"Tech_Mate","from_user":"Tara_Rose","id":1565599045,"from_user_id":9805925,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/125223730\/0_7016_normal.jpg","created_at":"Mon, 20 Apr 2009 14:07:58 +0000"},{"text":"Twitter Plagued with Annoying Worm - Do Not Use Internet Explorer http:\/\/tinyurl.com\/df4vyt","to_user_id":null,"from_user":"Hall_Web","id":1565595648,"from_user_id":284802,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/70194610\/hall-logo-sq_normal.jpg","created_at":"Mon, 20 Apr 2009 14:07:30 +0000"},{"text":"@cusimano I couldn't watch in Firefox (you're on wbztv.com?)... was able to jump on a PC and watch in Internet Explorer. #BostonMarathon","to_user_id":2300645,"to_user":"cusimano","from_user":"andrewphelps","id":1565576031,"from_user_id":501355,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/83degrees.com\/to\/powertwitter&quot;&gt;Power Twitter&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/98893360\/haircut_normal.jpg","created_at":"Mon, 20 Apr 2009 14:04:46 +0000"},{"text":"We've had some Gumtree.com users reporting that they can't click into text fields in Internet Explorer on the ad posting form. Can you try?","to_user_id":null,"from_user":"antoniojl","id":1565568983,"from_user_id":61036,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/iconfactory.com\/software\/twitterrific&quot;&gt;twitterrific&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/146595521\/Photo_3-1_normal.jpg","created_at":"Mon, 20 Apr 2009 14:03:47 +0000"},{"text":"Poucos homens de bem usam Internet Explorer 6...","to_user_id":null,"from_user":"leonardoreis","id":1565560621,"from_user_id":6047517,"iso_language_code":"pt","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/87063762\/leonardoreisibest_normal.jpg","created_at":"Mon, 20 Apr 2009 14:02:38 +0000"},{"text":"Anyone can please help me? A good internet program. Not Internet explorer or safari. I am thinking of google chrome. any programs? XD","to_user_id":null,"from_user":"darksinjun","id":1565541090,"from_user_id":12720060,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/148139033\/MS_Monster_Christmas_slime_normal.png","created_at":"Mon, 20 Apr 2009 14:00:06 +0000"},{"text":"FYI, the live video link didn't work for me in Firefox or Safari. Had to pull it up on Internet Explorer on PC...","to_user_id":null,"from_user":"AdrianArroyos","id":1565484099,"from_user_id":6016767,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.atebits.com\/&quot;&gt;Tweetie&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/99776740\/AdrianTwitter_normal.jpg","created_at":"Mon, 20 Apr 2009 13:52:04 +0000"},{"text":"W00T!!! Finally solved my problems with my websites with FireFox &amp; Internet Explorer (and hope also the Windows &amp; Mac problems)","to_user_id":null,"from_user":"barryjonas","id":1565474829,"from_user_id":7905502,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/105960589\/avatar_twitter_normal.jpg","created_at":"Mon, 20 Apr 2009 13:50:44 +0000"},{"text":"@philipbeel only down side to #ie6update is that is upgrades then to internet explorer!","to_user_id":2755406,"to_user":"philipbeel","from_user":"jodiedoubleday","id":1565474229,"from_user_id":4634664,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/76982086\/n504994137_250648_1693_normal.jpg","created_at":"Mon, 20 Apr 2009 13:50:40 +0000"},{"text":"Internet Explorer 8 Auto-Update Coming. http:\/\/is.gd\/ts9N","to_user_id":null,"from_user":"gullage","id":1565417582,"from_user_id":2145976,"iso_language_code":"en","source":"&lt;a href=&quot;http:\/\/www.twhirl.org\/&quot;&gt;twhirl&lt;\/a&gt;","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/129607278\/troy-20090331-sm_normal.jpg","created_at":"Mon, 20 Apr 2009 13:42:29 +0000"}],"since_id":0,"max_id":1567118165,"refresh_url":"?since_id=1567118165&q=internet+explorer","results_per_page":100,"next_page":"?page=2&max_id=1567118165&rpp=100&q=internet+explorer","completed_in":0.062616,"page":1,"query":"internet+explorer"} \ No newline at end of file
diff --git a/test/hash_test.rb b/test/hash_test.rb
new file mode 100644
index 0000000..da38a31
--- /dev/null
+++ b/test/hash_test.rb
@@ -0,0 +1,26 @@
+require 'test_helper'
+
+describe "Crack::Util.to_xml_attributes" do
+ before do
+ @hash = { :one => "ONE", "two" => "TWO", :three => "it \"should\" work" }
+ end
+
+ it "turn the hash into xml attributes" do
+ attrs = Crack::Util.to_xml_attributes(@hash)
+ attrs.must_match /one="ONE"/m
+ attrs.must_match /two="TWO"/m
+ attrs.must_match /three="it &quot;should&quot; work"/m
+ end
+
+ it "preserve _ in hash keys" do
+ attrs = Crack::Util.to_xml_attributes({
+ :some_long_attribute => "with short value",
+ :crash => :burn,
+ :merb => "uses extlib"
+ })
+
+ attrs.must_match /some_long_attribute="with short value"/
+ attrs.must_match /merb="uses extlib"/
+ attrs.must_match /crash="burn"/
+ end
+end
diff --git a/test/json_test.rb b/test/json_test.rb
new file mode 100644
index 0000000..08de1f7
--- /dev/null
+++ b/test/json_test.rb
@@ -0,0 +1,80 @@
+# coding: utf-8
+require 'test_helper'
+
+describe "JSON Parsing" do
+ TESTS = {
+ %q({"data": "G\u00fcnter"}) => {"data" => "G√ľnter"},
+ %q({"html": "\u003Cdiv\\u003E"}) => {"html" => "<div>"},
+ %q({"returnTo":{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
+ %q({returnTo:{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
+ %q({"return\\"To\\":":{"\/categories":"\/"}}) => {"return\"To\":" => {"/categories" => "/"}},
+ %q({"returnTo":{"\/categories":1}}) => {"returnTo" => {"/categories" => 1}},
+ %({"returnTo":[1,"a"]}) => {"returnTo" => [1, "a"]},
+ %({"returnTo":[1,"\\"a\\",", "b"]}) => {"returnTo" => [1, "\"a\",", "b"]},
+ %({"a": "'", "b": "5,000"}) => {"a" => "'", "b" => "5,000"},
+ %({"a": "a's, b's and c's", "b": "5,000"}) => {"a" => "a's, b's and c's", "b" => "5,000"},
+ %({"a": "2007-01-01"}) => {'a' => Date.new(2007, 1, 1)},
+ %({"a": "2007-01-01 01:12:34 Z"}) => {'a' => Time.utc(2007, 1, 1, 1, 12, 34)},
+ # Handle ISO 8601 date/time format http://en.wikipedia.org/wiki/ISO_8601
+ %({"a": "2007-01-01T01:12:34Z"}) => {'a' => Time.utc(2007, 1, 1, 1, 12, 34)},
+ # no time zone
+ %({"a": "2007-01-01 01:12:34"}) => {'a' => "2007-01-01 01:12:34"},
+ %({"bio": "1985-01-29: birthdate"}) => {'bio' => '1985-01-29: birthdate'},
+ %({"regex": /foo.*/}) => {'regex' => /foo.*/},
+ %({"regex": /foo.*/i}) => {'regex' => /foo.*/i},
+ %({"regex": /foo.*/mix}) => {'regex' => /foo.*/mix},
+ %([]) => [],
+ %({}) => {},
+ %(1) => 1,
+ %("") => "",
+ %("\\"") => "\"",
+ %(null) => nil,
+ %(true) => true,
+ %(false) => false,
+ %q("http:\/\/test.host\/posts\/1") => "http://test.host/posts/1",
+
+ # \u0000 and \x00 escape sequences
+ %q({"foo":"bar\u0000"}) => {"foo" => "bar"},
+ %q({"foo":"bar\u0000baz"}) => {"foo" => "barbaz"},
+ %q(bar\u0000) => "bar",
+ %q(bar\u0000baz) => "barbaz",
+
+ %q({"foo":"bar\x00"}) => {"foo" => "bar\x00"},
+ %q({"foo":"bar\x00baz"}) => {"foo" => "bar\x00baz"}
+ }
+
+ TESTS.each do |json, expected|
+ it "decode json (#{json})" do
+ Crack::JSON.parse(json).must_equal expected
+ end
+ end
+
+ it "is not vulnerable to YAML deserialization exploits" do
+ class Foo; end
+ refute_instance_of(Foo, Crack::JSON.parse("# '---/\n--- !ruby/object:Foo\n foo: bar"))
+ end
+
+ it "raise error for failed decoding" do
+ assert_raises(Crack::ParseError) {
+ Crack::JSON.parse(%({: 1}))
+ }
+ end
+
+ it "be able to parse a JSON response from a Twitter search about 'firefox'" do
+ data = ''
+ File.open(File.dirname(__FILE__) + "/data/twittersearch-firefox.json", "r") { |f|
+ data = f.read
+ }
+
+ Crack::JSON.parse(data)
+ end
+
+ it "be able to parse a JSON response from a Twitter search about 'internet explorer'" do
+ data = ''
+ File.open(File.dirname(__FILE__) + "/data/twittersearch-ie.json", "r") { |f|
+ data = f.read
+ }
+
+ Crack::JSON.parse(data)
+ end
+end
diff --git a/test/parser_test.rb b/test/parser_test.rb
new file mode 100644
index 0000000..51336f7
--- /dev/null
+++ b/test/parser_test.rb
@@ -0,0 +1,27 @@
+require 'test_helper'
+
+describe Crack::XML do
+ it "default to REXMLParser" do
+ Crack::XML.parser.must_equal Crack::REXMLParser
+ end
+
+ describe "with a custom Parser" do
+ class CustomParser
+ def self.parse(xml)
+ xml
+ end
+ end
+
+ before do
+ Crack::XML.parser = CustomParser
+ end
+
+ it "use the custom Parser" do
+ Crack::XML.parse("<xml/>").must_equal "<xml/>"
+ end
+
+ after do
+ Crack::XML.parser = nil
+ end
+ end
+end
diff --git a/test/string_test.rb b/test/string_test.rb
new file mode 100644
index 0000000..c73f172
--- /dev/null
+++ b/test/string_test.rb
@@ -0,0 +1,31 @@
+require 'test_helper'
+
+describe Crack::Util do
+ describe "snake_case" do
+ it "lowercases one word CamelCase" do
+ Crack::Util.snake_case("Merb").must_equal "merb"
+ end
+
+ it "makes one underscore snake_case two word CamelCase" do
+ Crack::Util.snake_case("MerbCore").must_equal "merb_core"
+ end
+
+ it "handles CamelCase with more than 2 words" do
+ Crack::Util.snake_case("SoYouWantContributeToMerbCore").must_equal "so_you_want_contribute_to_merb_core"
+ end
+
+ it "handles CamelCase with more than 2 capital letter in a row" do
+ Crack::Util.snake_case("CNN").must_equal "cnn"
+ Crack::Util.snake_case("CNNNews").must_equal "cnn_news"
+ Crack::Util.snake_case("HeadlineCNNNews").must_equal "headline_cnn_news"
+ end
+
+ it "does NOT change one word lowercase" do
+ Crack::Util.snake_case("merb").must_equal "merb"
+ end
+
+ it "leaves snake_case as is" do
+ Crack::Util.snake_case("merb_core").must_equal "merb_core"
+ end
+ end
+end
diff --git a/test/test_helper.rb b/test/test_helper.rb
new file mode 100644
index 0000000..1149de3
--- /dev/null
+++ b/test/test_helper.rb
@@ -0,0 +1,3 @@
+require 'pp'
+require 'minitest/autorun'
+require 'crack'
diff --git a/test/xml_test.rb b/test/xml_test.rb
new file mode 100644
index 0000000..b71b2d5
--- /dev/null
+++ b/test/xml_test.rb
@@ -0,0 +1,514 @@
+require 'test_helper'
+
+describe Crack::XML do
+ it "should transform a simple tag with content" do
+ xml = "<tag>This is the contents</tag>"
+ Crack::XML.parse(xml).must_equal({ 'tag' => 'This is the contents' })
+ end
+
+ it "should work with cdata tags" do
+ xml = <<-END
+ <tag>
+ <![CDATA[
+ text inside cdata
+ ]]>
+ </tag>
+ END
+ Crack::XML.parse(xml)["tag"].strip.must_equal "text inside cdata"
+ end
+
+ it "should transform a simple tag with attributes" do
+ xml = "<tag attr1='1' attr2='2'></tag>"
+ hash = { 'tag' => { 'attr1' => '1', 'attr2' => '2' } }
+ Crack::XML.parse(xml).must_equal hash
+ end
+
+ it "should transform repeating siblings into an array" do
+ xml =<<-XML
+ <opt>
+ <user login="grep" fullname="Gary R Epstein" />
+ <user login="stty" fullname="Simon T Tyson" />
+ </opt>
+ XML
+
+ Crack::XML.parse(xml)['opt']['user'].class.must_equal Array
+
+ hash = {
+ 'opt' => {
+ 'user' => [{
+ 'login' => 'grep',
+ 'fullname' => 'Gary R Epstein'
+ },{
+ 'login' => 'stty',
+ 'fullname' => 'Simon T Tyson'
+ }]
+ }
+ }
+
+ Crack::XML.parse(xml).must_equal hash
+ end
+
+ it "should not transform non-repeating siblings into an array" do
+ xml =<<-XML
+ <opt>
+ <user login="grep" fullname="Gary R Epstein" />
+ </opt>
+ XML
+
+ Crack::XML.parse(xml)['opt']['user'].class.must_equal Hash
+
+ hash = {
+ 'opt' => {
+ 'user' => {
+ 'login' => 'grep',
+ 'fullname' => 'Gary R Epstein'
+ }
+ }
+ }
+
+ Crack::XML.parse(xml).must_equal hash
+ end
+
+ describe "Parsing xml with text and attributes" do
+ before do
+ xml =<<-XML
+ <opt>
+ <user login="grep">Gary R Epstein</user>
+ <user>Simon T Tyson</user>
+ </opt>
+ XML
+ @data = Crack::XML.parse(xml)
+ end
+
+ it "correctly parse text nodes" do
+ @data.must_equal({
+ 'opt' => {
+ 'user' => [
+ 'Gary R Epstein',
+ 'Simon T Tyson'
+ ]
+ }
+ })
+ end
+
+ it "be parse attributes for text node if present" do
+ @data['opt']['user'][0].attributes.must_equal({'login' => 'grep'})
+ end
+
+ it "default attributes to empty hash if not present" do
+ @data['opt']['user'][1].attributes.must_equal({})
+ end
+
+ it "add 'attributes' accessor methods to parsed instances of String" do
+ @data['opt']['user'][0].respond_to?(:attributes).must_equal(true)
+ @data['opt']['user'][0].respond_to?(:attributes=).must_equal(true)
+ end
+
+ it "not add 'attributes' accessor methods to all instances of String" do
+ "some-string".respond_to?(:attributes).must_equal(false)
+ "some-string".respond_to?(:attributes=).must_equal(false)
+ end
+ end
+
+ it "should typecast an integer" do
+ xml = "<tag type='integer'>10</tag>"
+ Crack::XML.parse(xml)['tag'].must_equal 10
+ end
+
+ it "should typecast a true boolean" do
+ xml = "<tag type='boolean'>true</tag>"
+ Crack::XML.parse(xml)['tag'].must_equal(true)
+ end
+
+ it "should typecast a false boolean" do
+ ["false"].each do |w|
+ Crack::XML.parse("<tag type='boolean'>#{w}</tag>")['tag'].must_equal(false)
+ end
+ end
+
+ it "should typecast a datetime" do
+ xml = "<tag type='datetime'>2007-12-31 10:32</tag>"
+ Crack::XML.parse(xml)['tag'].must_equal Time.parse( '2007-12-31 10:32' ).utc
+ end
+
+ it "should typecast a date" do
+ xml = "<tag type='date'>2007-12-31</tag>"
+ Crack::XML.parse(xml)['tag'].must_equal Date.parse('2007-12-31')
+ end
+
+ xml_entities = {
+ "<" => "&lt;",
+ ">" => "&gt;",
+ '"' => "&quot;",
+ "'" => "&apos;",
+ "&" => "&amp;"
+ }
+ it "should unescape html entities" do
+ xml_entities.each do |k,v|
+ xml = "<tag>Some content #{v}</tag>"
+ Crack::XML.parse(xml)['tag'].must_match Regexp.new(k)
+ end
+ end
+
+ it "should unescape XML entities in attributes" do
+ xml_entities.each do |k,v|
+ xml = "<tag attr='Some content #{v}'></tag>"
+ Crack::XML.parse(xml)['tag']['attr'].must_match Regexp.new(k)
+ end
+ end
+
+ it "should undasherize keys as tags" do
+ xml = "<tag-1>Stuff</tag-1>"
+ Crack::XML.parse(xml).keys.must_include( 'tag_1' )
+ end
+
+ it "should undasherize keys as attributes" do
+ xml = "<tag1 attr-1='1'></tag1>"
+ Crack::XML.parse(xml)['tag1'].keys.must_include( 'attr_1')
+ end
+
+ it "should undasherize keys as tags and attributes" do
+ xml = "<tag-1 attr-1='1'></tag-1>"
+ Crack::XML.parse(xml).keys.must_include( 'tag_1' )
+ Crack::XML.parse(xml)['tag_1'].keys.must_include( 'attr_1')
+ end
+
+ it "should render nested content correctly" do
+ xml = "<root><tag1>Tag1 Content <em><strong>This is strong</strong></em></tag1></root>"
+ Crack::XML.parse(xml)['root']['tag1'].must_equal "Tag1 Content <em><strong>This is strong</strong></em>"
+ end
+
+ it "should render nested content with splshould text nodes correctly" do
+ xml = "<root>Tag1 Content<em>Stuff</em> Hi There</root>"
+ Crack::XML.parse(xml)['root'].must_equal "Tag1 Content<em>Stuff</em> Hi There"
+ end
+
+ it "should ignore attributes when a child is a text node" do
+ xml = "<root attr1='1'>Stuff</root>"
+ Crack::XML.parse(xml).must_equal({ "root" => "Stuff" })
+ end
+
+ it "should ignore attributes when any child is a text node" do
+ xml = "<root attr1='1'>Stuff <em>in italics</em></root>"
+ Crack::XML.parse(xml).must_equal({ "root" => "Stuff <em>in italics</em>" })
+ end
+
+ it "should correctly transform multiple children" do
+ xml = <<-XML
+ <user gender='m'>
+ <age type='integer'>35</age>
+ <name>Home Simpson</name>
+ <dob type='date'>1988-01-01</dob>
+ <joined-at type='datetime'>2000-04-28 23:01</joined-at>
+ <is-cool type='boolean'>true</is-cool>
+ </user>
+ XML
+
+ hash = {
+ "user" => {
+ "gender" => "m",
+ "age" => 35,
+ "name" => "Home Simpson",
+ "dob" => Date.parse('1988-01-01'),
+ "joined_at" => Time.parse("2000-04-28 23:01"),
+ "is_cool" => true
+ }
+ }
+
+ Crack::XML.parse(xml).must_equal hash
+ end
+
+ it "should properly handle nil values (ActiveSupport Compatible)" do
+ topic_xml = <<-EOT
+ <topic>
+ <title></title>
+ <id type="integer"></id>
+ <approved type="boolean"></approved>
+ <written-on type="date"></written-on>
+ <viewed-at type="datetime"></viewed-at>
+ <parent-id></parent-id>
+ </topic>
+ EOT
+
+ expected_topic_hash = {
+ 'title' => nil,
+ 'id' => nil,
+ 'approved' => nil,
+ 'written_on' => nil,
+ 'viewed_at' => nil,
+ 'parent_id' => nil
+ }
+ Crack::XML.parse(topic_xml)["topic"].must_equal expected_topic_hash
+ end
+
+ it "should handle a single record from xml (ActiveSupport Compatible)" do
+ topic_xml = <<-EOT
+ <topic>
+ <title>The First Topic</title>
+ <author-name>David</author-name>
+ <id type="integer">1</id>
+ <approved type="boolean"> true </approved>
+ <replies-count type="integer">0</replies-count>
+ <replies-close-in type="integer">2592000000</replies-close-in>
+ <written-on type="date">2003-07-16</written-on>
+ <viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
+ <author-email-address>david@loudthinking.com</author-email-address>
+ <parent-id></parent-id>
+ <ad-revenue type="decimal">1.5</ad-revenue>
+ <optimum-viewing-angle type="float">135</optimum-viewing-angle>
+ <resident type="symbol">yes</resident>
+ </topic>
+ EOT
+
+ expected_topic_hash = {
+ 'title' => "The First Topic",
+ 'author_name' => "David",
+ 'id' => 1,
+ 'approved' => true,
+ 'replies_count' => 0,
+ 'replies_close_in' => 2592000000,
+ 'written_on' => Date.new(2003, 7, 16),
+ 'viewed_at' => Time.utc(2003, 7, 16, 9, 28),
+ 'author_email_address' => "david@loudthinking.com",
+ 'parent_id' => nil,
+ 'ad_revenue' => BigDecimal("1.50"),
+ 'optimum_viewing_angle' => 135.0,
+ 'resident' => 'yes',
+ }
+
+ Crack::XML.parse(topic_xml)["topic"].each do |k,v|
+ v.must_equal expected_topic_hash[k]
+ end
+ end
+
+ it "should handle multiple records (ActiveSupport Compatible)" do
+ topics_xml = <<-EOT
+ <topics type="array">
+ <topic>
+ <title>The First Topic</title>
+ <author-name>David</author-name>
+ <id type="integer">1</id>
+ <approved type="boolean">false</approved>
+ <replies-count type="integer">0</replies-count>
+ <replies-close-in type="integer">2592000000</replies-close-in>
+ <written-on type="date">2003-07-16</written-on>
+ <viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
+ <content>Have a nice day</content>
+ <author-email-address>david@loudthinking.com</author-email-address>
+ <parent-id nil="true"></parent-id>
+ </topic>
+ <topic>
+ <title>The Second Topic</title>
+ <author-name>Jason</author-name>
+ <id type="integer">1</id>
+ <approved type="boolean">false</approved>
+ <replies-count type="integer">0</replies-count>
+ <replies-close-in type="integer">2592000000</replies-close-in>
+ <written-on type="date">2003-07-16</written-on>
+ <viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
+ <content>Have a nice day</content>
+ <author-email-address>david@loudthinking.com</author-email-address>
+ <parent-id></parent-id>
+ </topic>
+ </topics>
+ EOT
+
+ expected_topic_hash = {
+ 'title' => "The First Topic",
+ 'author_name' => "David",
+ 'id' => 1,
+ 'approved' => false,
+ 'replies_count' => 0,
+ 'replies_close_in' => 2592000000,
+ 'written_on' => Date.new(2003, 7, 16),
+ 'viewed_at' => Time.utc(2003, 7, 16, 9, 28),
+ 'content' => "Have a nice day",
+ 'author_email_address' => "david@loudthinking.com",
+ 'parent_id' => nil
+ }
+ # puts Crack::XML.parse(topics_xml)['topics'].first.inspect
+ Crack::XML.parse(topics_xml)["topics"].first.each do |k,v|
+ v.must_equal expected_topic_hash[k]
+ end
+ end
+
+ it "should handle a single record from_xml with attributes other than type (ActiveSupport Compatible)" do
+ topic_xml = <<-EOT
+ <rsp stat="ok">
+ <photos page="1" pages="1" perpage="100" total="16">
+ <photo id="175756086" owner="55569174@N00" secret="0279bf37a1" server="76" title="Colored Pencil PhotoBooth Fun" ispublic="1" isfriend="0" isfamily="0"/>
+ </photos>
+ </rsp>
+ EOT
+
+ expected_topic_hash = {
+ 'id' => "175756086",
+ 'owner' => "55569174@N00",
+ 'secret' => "0279bf37a1",
+ 'server' => "76",
+ 'title' => "Colored Pencil PhotoBooth Fun",
+ 'ispublic' => "1",
+ 'isfriend' => "0",
+ 'isfamily' => "0",
+ }
+ Crack::XML.parse(topic_xml)["rsp"]["photos"]["photo"].each do |k,v|
+ v.must_equal expected_topic_hash[k]
+ end
+ end
+
+ it "should handle an emtpy array (ActiveSupport Compatible)" do
+ blog_xml = <<-XML
+ <blog>
+ <posts type="array"></posts>
+ </blog>
+ XML
+ expected_blog_hash = {"blog" => {"posts" => []}}
+ Crack::XML.parse(blog_xml).must_equal expected_blog_hash
+ end
+
+ it "should handle empty array with whitespace from xml (ActiveSupport Compatible)" do
+ blog_xml = <<-XML
+ <blog>
+ <posts type="array">
+ </posts>
+ </blog>
+ XML
+ expected_blog_hash = {"blog" => {"posts" => []}}
+ Crack::XML.parse(blog_xml).must_equal expected_blog_hash
+ end
+
+ it "should handle array with one entry from_xml (ActiveSupport Compatible)" do
+ blog_xml = <<-XML
+ <blog>
+ <posts type="array">
+ <post>a post</post>
+ </posts>
+ </blog>
+ XML
+ expected_blog_hash = {"blog" => {"posts" => ["a post"]}}
+ Crack::XML.parse(blog_xml).must_equal expected_blog_hash
+ end
+
+ it "should handle array with multiple entries from xml (ActiveSupport Compatible)" do
+ blog_xml = <<-XML
+ <blog>
+ <posts type="array">
+ <post>a post</post>
+ <post>another post</post>
+ </posts>
+ </blog>
+ XML
+ expected_blog_hash = {"blog" => {"posts" => ["a post", "another post"]}}
+ Crack::XML.parse(blog_xml).must_equal expected_blog_hash
+ end
+
+ it "should handle file types (ActiveSupport Compatible)" do
+ blog_xml = <<-XML
+ <blog>
+ <logo type="file" name="logo.png" content_type="image/png">
+ </logo>
+ </blog>
+ XML
+ hash = Crack::XML.parse(blog_xml)
+ hash.keys.must_include('blog')
+ hash['blog'].keys.must_include('logo')
+
+ file = hash['blog']['logo']
+ file.original_filename.must_equal 'logo.png'
+ file.content_type.must_equal 'image/png'
+ end
+
+ it "should handle file from xml with defaults (ActiveSupport Compatible)" do
+ blog_xml = <<-XML
+ <blog>
+ <logo type="file">
+ </logo>
+ </blog>
+ XML
+ file = Crack::XML.parse(blog_xml)['blog']['logo']
+ file.original_filename.must_equal 'untitled'
+ file.content_type.must_equal 'application/octet-stream'
+ end
+
+ it "should handle xsd like types from xml (ActiveSupport Compatible)" do
+ bacon_xml = <<-EOT
+ <bacon>
+ <weight type="double">0.5</weight>
+ <price type="decimal">12.50</price>
+ <chunky type="boolean"> 1 </chunky>
+ <expires-at type="dateTime">2007-12-25T12:34:56+0000</expires-at>
+ <notes type="string"></notes>
+ <illustration type="base64Binary">YmFiZS5wbmc=</illustration>
+ </bacon>
+ EOT
+
+ expected_bacon_hash = {
+ 'weight' => 0.5,
+ 'chunky' => true,
+ 'price' => BigDecimal("12.50"),
+ 'expires_at' => Time.utc(2007,12,25,12,34,56),
+ 'notes' => "",
+ 'illustration' => "babe.png"
+ }
+
+ Crack::XML.parse(bacon_xml)["bacon"].must_equal expected_bacon_hash
+ end
+
+ it "should let type trickle through when unknown (ActiveSupport Compatible)" do
+ product_xml = <<-EOT
+ <product>
+ <weight type="double">0.5</weight>
+ <image type="ProductImage"><filename>image.gif</filename></image>
+
+ </product>
+ EOT
+
+ expected_product_hash = {
+ 'weight' => 0.5,
+ 'image' => {'type' => 'ProductImage', 'filename' => 'image.gif' },
+ }
+
+ Crack::XML.parse(product_xml)["product"].must_equal expected_product_hash
+ end
+
+ it "should handle unescaping from xml (ActiveResource Compatible)" do
+ xml_string = '<person><bare-string>First &amp; Last Name</bare-string><pre-escaped-string>First &amp;amp; Last Name</pre-escaped-string></person>'
+ expected_hash = {
+ 'bare_string' => 'First & Last Name',
+ 'pre_escaped_string' => 'First &amp; Last Name'
+ }
+
+ Crack::XML.parse(xml_string)['person'].must_equal expected_hash
+ end
+
+ it "handle an empty xml string" do
+ Crack::XML.parse('').must_equal({})
+ end
+
+ # As returned in the response body by the unfuddle XML API when creating objects
+ it "handle an xml string containing a single space" do
+ Crack::XML.parse(' ').must_equal({})
+ end
+
+ it "can dump parsed xml" do
+ xml = <<-XML
+ <blog>
+ <posts language="english">I like big butts and I cannot Lie</posts>
+ </blog>
+ XML
+
+ Marshal.dump(Crack::XML.parse(xml))
+ end
+
+ it "properly handles a node with type == file that has children" do
+ # Example is an excerpt from a problematic kvm domain config file
+ example_xml = <<-EOT
+ <disk type='file' device='cdrom'>
+ <driver name='qemu' type='raw' cache='none' io='native'/>
+ <source file='/tmp/cdrom.iso'/>
+ </disk>
+ EOT
+
+ Crack::XML.parse(example_xml).must_equal({"disk"=>{"driver"=>{"name"=>"qemu", "type"=>"raw", "cache"=>"none", "io"=>"native"}, "source"=>{"file"=>"/tmp/cdrom.iso"}, "type"=>"file", "device"=>"cdrom"}})
+ end
+end

Powered by Domaintechnik.at | Hosting - Domain - Webspace