Browse Source

Made JBidwatcher Better

Samuel W. Flint 8 years ago
parent
commit
69527f57c2
100 changed files with 7418 additions and 0 deletions
  1. BIN
      JBidwatcher/app/JBidwatcher.jar
  2. 9 0
      JBidwatcher/jbidwatcher.sh
  3. BIN
      JBidwatcher/lib/annotations.jar
  4. BIN
      JBidwatcher/lib/aopalliance.jar
  5. BIN
      JBidwatcher/lib/appbundler-1.0ea.jar
  6. BIN
      JBidwatcher/lib/apple.jar
  7. BIN
      JBidwatcher/lib/derby.jar
  8. BIN
      JBidwatcher/lib/guice-3.0.jar
  9. BIN
      JBidwatcher/lib/guice-assistedinject-3.0.jar
  10. BIN
      JBidwatcher/lib/jDeskMetrics.jar
  11. BIN
      JBidwatcher/lib/javax.inject.jar
  12. 66 0
      JBidwatcher/lib/jbidwatcher/column_lookup.rb
  13. 73 0
      JBidwatcher/lib/jbidwatcher/column_lookup_spec.rb
  14. 164 0
      JBidwatcher/lib/jbidwatcher/ebay_parser.rb
  15. BIN
      JBidwatcher/lib/jbidwatcher/gems.jar
  16. 104 0
      JBidwatcher/lib/jbidwatcher/gixen/gixen.pem
  17. 183 0
      JBidwatcher/lib/jbidwatcher/gixen/gixen.rb
  18. 41 0
      JBidwatcher/lib/jbidwatcher/gixen/gixen_error.rb
  19. 54 0
      JBidwatcher/lib/jbidwatcher/models.rb
  20. BIN
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/isorelax.jar
  21. BIN
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/jing.jar
  22. BIN
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nekodtd.jar
  23. BIN
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nekohtml.jar
  24. 127 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri.rb
  25. 27 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css.rb
  26. 99 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/node.rb
  27. 683 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/parser.rb
  28. 240 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/parser.y
  29. 91 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/parser_extras.rb
  30. 7 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/syntax_error.rb
  31. 152 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/tokenizer.rb
  32. 55 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/tokenizer.rex
  33. 171 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/xpath_visitor.rb
  34. 35 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/decorators/slop.rb
  35. 37 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html.rb
  36. 35 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/builder.rb
  37. 253 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/document.rb
  38. 41 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/document_fragment.rb
  39. 23 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/element_description.rb
  40. 671 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/element_description_defaults.rb
  41. 13 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/entity_lookup.rb
  42. 52 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/sax/parser.rb
  43. 16 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/sax/parser_context.rb
  44. 16 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/sax/push_parser.rb
  45. BIN
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/nokogiri.jar
  46. 4 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/syntax_error.rb
  47. 88 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/version.rb
  48. 73 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml.rb
  49. 14 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/attr.rb
  50. 18 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/attribute_decl.rb
  51. 431 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/builder.rb
  52. 11 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/cdata.rb
  53. 7 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/character_data.rb
  54. 249 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/document.rb
  55. 103 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/document_fragment.rb
  56. 22 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/dtd.rb
  57. 36 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/element_content.rb
  58. 13 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/element_decl.rb
  59. 19 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/entity_decl.rb
  60. 13 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/namespace.rb
  61. 946 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/node.rb
  62. 61 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/node/save_options.rb
  63. 357 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/node_set.rb
  64. 6 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/notation.rb
  65. 93 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/parse_options.rb
  66. 2 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/pp.rb
  67. 18 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/pp/character_data.rb
  68. 56 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/pp/node.rb
  69. 8 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/processing_instruction.rb
  70. 112 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/reader.rb
  71. 32 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/relax_ng.rb
  72. 4 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/sax.rb
  73. 164 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/sax/document.rb
  74. 115 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/sax/parser.rb
  75. 16 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/sax/parser_context.rb
  76. 60 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/sax/push_parser.rb
  77. 63 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/schema.rb
  78. 47 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/syntax_error.rb
  79. 9 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/text.rb
  80. 10 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/xpath.rb
  81. 11 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/xpath/syntax_error.rb
  82. 16 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/xpath_context.rb
  83. 56 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xslt.rb
  84. 25 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xslt/stylesheet.rb
  85. BIN
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/xercesImpl.jar
  86. 90 0
      JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/xsd/xmlparser/nokogiri.rb
  87. 34 0
      JBidwatcher/lib/jbidwatcher/parser.rb
  88. 6 0
      JBidwatcher/lib/jbidwatcher/run_crazy
  89. 6 0
      JBidwatcher/lib/jbidwatcher/run_utils
  90. 324 0
      JBidwatcher/lib/jbidwatcher/utilities.rb
  91. 32 0
      JBidwatcher/lib/jbidwatcher/utilities_spec.rb
  92. BIN
      JBidwatcher/lib/jdesktop.jar
  93. BIN
      JBidwatcher/lib/jl1.0.1.jar
  94. BIN
      JBidwatcher/lib/jline-2.11.jar
  95. BIN
      JBidwatcher/lib/jruby-incomplete.jar
  96. BIN
      JBidwatcher/lib/json_simple-1.1.jar
  97. BIN
      JBidwatcher/lib/jsoup-1.7.1.jar
  98. BIN
      JBidwatcher/lib/jsr305-1.3.9.jar
  99. BIN
      JBidwatcher/lib/l2fprod-common-fontchooser.jar
  100. BIN
      JBidwatcher/lib/mahalo.jar

BIN
JBidwatcher/app/JBidwatcher.jar


+ 9 - 0
JBidwatcher/jbidwatcher.sh

@@ -0,0 +1,9 @@
+#!/bin/sh
+
+if (java -version 2>&1 | head -1 | fgrep -q "1.8")
+then
+  java -cp lib/annotations.jar:lib/aopalliance.jar:lib/appbundler-1.0ea.jar:lib/apple.jar:lib/derby.jar:lib/guice-3.0.jar:lib/guice-assistedinject-3.0.jar:lib/jDeskMetrics.jar:lib/javax.inject.jar:lib/jdesktop.jar:lib/jl1.0.1.jar:lib/jline-2.11.jar:lib/jruby-incomplete.jar:lib/json_simple-1.1.jar:lib/jsoup-1.7.1.jar:lib/jsr305-1.3.9.jar:lib/l2fprod-common-fontchooser.jar:lib/mahalo.jar:lib/mysql-connector-java-5.1.7-bin.jar:lib/readline.jar:lib/txtmark.jar:lib/jbidwatcher:app/JBidwatcher.jar com.jbidwatcher.app.JBidWatch
+else
+  echo "You must install Oracle's Java 8 to run JBidwatcher."
+  echo "Download it from here:\n\thttps://www.java.com/download"
+fi

BIN
JBidwatcher/lib/annotations.jar


BIN
JBidwatcher/lib/aopalliance.jar


BIN
JBidwatcher/lib/appbundler-1.0ea.jar


BIN
JBidwatcher/lib/apple.jar


BIN
JBidwatcher/lib/derby.jar


BIN
JBidwatcher/lib/guice-3.0.jar


BIN
JBidwatcher/lib/guice-assistedinject-3.0.jar


BIN
JBidwatcher/lib/jDeskMetrics.jar


BIN
JBidwatcher/lib/javax.inject.jar


+ 66 - 0
JBidwatcher/lib/jbidwatcher/column_lookup.rb

@@ -0,0 +1,66 @@
+# Created by IntelliJ IDEA.
+# User: mrs
+# Date: 6/20/15
+# Time: 4:33 PM
+# To change this template use File | Settings | File Templates.
+
+java_import com.jbidwatcher.ui.table.TableColumnController
+
+class ColumnLookup
+  LOOKUP_MAP = {
+      TableColumnController::ID => proc { |aEntry| aEntry.identifier },
+      TableColumnController::CUR_BID => :current_bid.to_proc,
+      TableColumnController::SNIPE_OR_MAX => :format_snipe_and_bid.to_proc,
+      TableColumnController::MAX => :max_bid.to_proc,
+      TableColumnController::SNIPE => proc { |aEntry|},
+      TableColumnController::TIME_LEFT => proc { |aEntry|},
+      TableColumnController::END_DATE => proc { |aEntry|},
+      TableColumnController::TITLE => proc { |aEntry|},
+      TableColumnController::STATUS => proc { |aEntry|},
+      TableColumnController::THUMBNAIL => proc { |aEntry|},
+      TableColumnController::SELLER => proc { |aEntry|},
+      TableColumnController::COMMENT => proc { |aEntry|},
+      TableColumnController::BIDDER => proc { |aEntry|},
+      TableColumnController::FIXED_PRICE => proc { |aEntry|},
+      TableColumnController::SHIPPING_INSURANCE => proc { |aEntry|},
+      TableColumnController::ITEM_LOCATION => proc { |aEntry|},
+      TableColumnController::BIDCOUNT => proc { |aEntry|},
+      TableColumnController::JUSTPRICE => proc { |aEntry|},
+      TableColumnController::SELLER_FEEDBACK => proc { |aEntry|},
+      TableColumnController::SELLER_POSITIVE_FEEDBACK => proc { |aEntry|},
+      TableColumnController::CUR_TOTAL => proc { |aEntry|},
+      TableColumnController::SNIPE_TOTAL => proc { |aEntry|}
+  }
+
+  def max_bid(entry)
+    entry.bid_on? ? format_bid(entry, error_note(entry)) : "n/a"
+  end
+
+  def current_bid(aEntry)
+    cur_price = aEntry.current_price
+    if aEntry.fixed?
+      quantity = aEntry.quantity > 1 ? " x #{aEntry.quantity}" : ""
+      "#{cur_price} (FP#{quantity})"
+    else
+      "#{cur_price} (#{aEntry.num_bidders})"
+    end
+  end
+
+  def get_value(entry, col_num)
+    method = LOOKUP_MAP[col_num]
+    if method.arity == 1
+      method.call(entry)
+    else
+      method.call(self, entry)
+    end
+  end
+
+  private
+  def error_note(aEntry)
+    aEntry.error_page.nil? ? "" : "*"
+  end
+
+  def format_bid(entry, note)
+    "#{note}#{entry.get_bid}"
+  end
+end

+ 73 - 0
JBidwatcher/lib/jbidwatcher/column_lookup_spec.rb

@@ -0,0 +1,73 @@
+# Created by IntelliJ IDEA.
+# User: mrs
+# Date: 6/20/15
+# Time: 8:43 PM
+# To change this template use File | Settings | File Templates.
+
+java_import com.jbidwatcher.auction.AuctionEntry
+java_import java.lang.StringBuffer
+java_import com.jbidwatcher.ui.commands.UserActions
+java_import com.jbidwatcher.ui.commands.MenuCommand
+require 'column_lookup'
+require 'ostruct'
+
+describe ColumnLookup do
+  let(:lookup) { ColumnLookup.new }
+  let(:entry) { AuctionEntry.new }
+
+  before :each do
+    entry.set("identifier", "12345678")
+    entry.set("numBids", "1")
+    entry.set("currency", "USD")
+    entry.set("curBid", "12.50")
+  end
+
+  it "should not be nil" do
+    expect(lookup).to_not be_nil
+  end
+
+  it "should give an identifier when asked for column 0" do
+    expect(lookup.get_value(entry, TableColumnController::ID)).to eq("12345678")
+  end
+
+  context "current bid" do
+    it "should give a sane current bid amount" do
+      expect(lookup.get_value(entry, TableColumnController::CUR_BID)).to eq("$12.50 (1)")
+    end
+
+    context "fixed price" do
+      before :each do
+        entry.set("fixed_price", "1")
+        entry.set("quantity", "1")
+        entry.set("currency", "USD")
+        entry.set("curBid", "9.99")
+      end
+
+      it "should show (FP)" do
+        expect(lookup.get_value(entry, TableColumnController::CUR_BID)).to eq("$9.99 (FP)")
+      end
+
+      it "should show (FP x n) when quantity > 1" do
+        entry.set("quantity", "2")
+        expect(lookup.get_value(entry, TableColumnController::CUR_BID)).to eq("$9.99 (FP x 2)")
+      end
+    end
+  end
+
+  context "max bid" do
+    it "should give a simple max bid if one is present" do
+      entry.set("last_bid_amount", "14.01")
+      expect(lookup.get_value(entry, TableColumnController::MAX)).to eq("$14.01")
+    end
+
+    it "should note an error if an error page is present" do
+      entry.set("last_bid_amount", "14.01")
+      entry.error_page = StringBuffer.new
+      expect(lookup.get_value(entry, TableColumnController::MAX)).to eq("*$14.01")
+    end
+
+    it "should say 'n/a' if no bid present" do
+      expect(lookup.get_value(entry, TableColumnController::MAX)).to eq("n/a")
+    end
+  end
+end

+ 164 - 0
JBidwatcher/lib/jbidwatcher/ebay_parser.rb

@@ -0,0 +1,164 @@
+#
+#  ebay_parser.rb
+#  MacBidwatcher
+#
+#  Created by Morgan Schweers on 7/24/11.
+#  Copyright 2011 CyberFOX Software, Inc. All rights reserved.
+#
+
+require 'parser'
+
+class NilClass; def to_nil; end end
+class String; def to_nil; self unless empty? end end
+class Array; def to_nil; self unless empty? end end
+
+class Ebay
+  class Parser < ::Parser
+    PRICE_MATCH=[%r{(Discounted.price|(Current.bid|Winning.bid|Starting.bid|Price|Sold.[Ff]or):)}, %r{.*[0-9].*}]
+    LOCATION_MATCH=[%r{(?i)item.location:}, %r{.*}]
+    END_DATE_MATCH=[%r{^\(.*$}, %r{^.*(P[SD]T|GMT)\)$}]
+    ENDED_DATE_MATCH=[%r{^Ended:$},%r{.*}, %r{.*(P[SD]T|GMT)$}]
+    SHIPPING_MATCH=[%r{^Shipping:$}, %r{.*}]
+    ITEM_MATCH=[%r{^Item.number:}, %r{[0-9]+}]
+    REVERSE_ITEM_MATCH=[%r{[0-9]+}, %r{Item.number:}]
+    HISTORY_MATCH=[%r{^Bid.history:$}, %r{[0-9]+}, %r{bids?}]
+    ENDED_HISTORY_MATCH=[%r{^Bid.history:$}, %r{[0-9]+.bids?}]
+    LIVE_HISTORY_MATCH = PRICE_MATCH + ["\\[", %r{[0-9]+ bids?}]
+    BIDCOUNT_MATCH = ["\\[", %r{\d+}, %r{bids?}, "\\]"]
+    LIVE_SELLER_MATCH = [%r{Member id}, %r{.*}, %r{\(}, %r{Feedback Score.*}, %r{[0-9]+}, %r{\)}, %r{[0-9.]+.*}]
+    ENDED_SELLER_MATCH= ['Seller:'] + LIVE_SELLER_MATCH[0..4]
+
+    def parse_extended_end_date
+      end_date = match_set(END_DATE_MATCH)
+      if end_date
+        ends_at = end_date.join(' ')
+        ends_at = ends_at[1..-2]
+        else
+        ends_at = match_set(ENDED_DATE_MATCH)
+        ends_at = ends_at[1..-1].join(' ') if ends_at
+      end
+      ends_at
+    end
+
+    def parse_bid_count
+      if bid_history = match_set(HISTORY_MATCH)
+        bid_history[1]
+      elsif bid_history = match_set(LIVE_HISTORY_MATCH)
+        bid_history[3].split.first
+      elsif bid_history = match_set(ENDED_HISTORY_MATCH)
+        bid_history[1].split.first
+      end
+    end
+
+    def extract_title(title, title_array)
+      title.gsub(title_array[0], '').to_nil || @page.css('meta[property="og:title"]').attribute('content').value
+    end
+
+    def extract_id(title_array)
+      id_match = match_set(REVERSE_ITEM_MATCH)
+      return id_match.first
+    end
+
+    def old_extract_id(title_array)
+#      return "261116602845"
+      id = title_array[1]
+      unless id
+        id_match = match_set(ITEM_MATCH)
+        id = id_match.last if id_match
+        unless id
+          id_match = match_set(REVERSE_ITEM_MATCH)
+          id = id_match.first if id_match
+          unless id
+            item_id_search = @page.css('span:contains("Item number")').text
+            if item_id_search && item_id_search != []
+              potential_id = item_id_search.match(%r{Item.number:?.(\d+)})
+              id = potential_id[1]
+            end
+          end
+        end
+      end
+      id
+    end
+
+    def parse_title
+      title = @page.title
+      title_array = title.match(%r{(?: \| eBay)|- eBay \(item ([0-9]+) end time *([^)]+)\)})
+      if title_array.nil?
+        nil
+      else
+        title = extract_title(title, title_array)
+        id = extract_id(title_array)
+        ends_at = title_array[2]
+        { :title => title, :id => id, :ends_at => ends_at }
+      end
+    end
+
+    def extract_thumbnail
+      thumbnail_image_set = (@page / 'img').select do |node|
+        if node
+          node[:src] =~ /ebayimg.com/
+        else
+          false
+        end
+      end.to_a.first
+
+      thumbnail_image = thumbnail_image_set[:src] if thumbnail_image_set
+      thumbnail_image || @page.css('meta[property="og:image"]').attribute('content').value
+    end
+
+    # @return [Array[feedback_percent, feedback_score, seller_name]] The seller-related information; feedback_percent may be nil if the item is ended.
+    def extract_seller_info
+      seller_info = match_set(LIVE_SELLER_MATCH)
+      seller_name, feedback_score, feedback_percent = if seller_info
+                                                        [seller_info[1], seller_info[4], seller_info.last.split('%').first]
+                                                      end
+      unless seller_info
+        seller_info = match_set(ENDED_SELLER_MATCH)
+        seller_name, feedback_score = if seller_info
+                                        [seller_info[2], seller_info[5]]
+                                      end
+      end
+      return feedback_percent, feedback_score, seller_name
+    end
+
+    # @return [Hash] Parsed data from the auction as a key/value hash, or nil if the title isn't recognizable.
+    def parse
+      title_info = parse_title
+      return nil unless title_info
+
+      thumbnail_field = {}
+      thumbnail_field['thumbnail_url'] = extract_thumbnail
+
+      price = match_set(PRICE_MATCH).to_a.last.to_nil || @page.css('span[itemprop="price"]').text
+      location = match_set(LOCATION_MATCH).to_a.last
+      shipping = match_set(SHIPPING_MATCH).to_a.last
+
+      ends_at = title_info[:ends_at] || parse_extended_end_date
+      bid_count = parse_bid_count
+
+      test_price = @page.css("[itemprop='offers'] .convPrice #bidPrice").text
+
+      unless bid_count
+        found = match_set(BIDCOUNT_MATCH)
+        bid_count = found[1] if found
+      end
+
+      feedback_percent, feedback_score, seller_name = extract_seller_info
+
+      { :title => title_info[:title].to_s.strip,
+        :location => location.to_s.strip,
+        :current_price => price,
+        :us_price => test_price,
+        :end_date => ends_at,
+        :shipping => shipping,
+        :bid_count => bid_count,
+        :identifier => title_info[:id].to_s.strip,
+        :seller => {
+          :seller_name => seller_name.to_s.strip,
+          :feedback => feedback_score.to_s.strip,
+          :feedback_percent => feedback_percent.to_s.strip
+        }
+      }.merge(thumbnail_field)
+    end
+  end
+end

BIN
JBidwatcher/lib/jbidwatcher/gems.jar


+ 104 - 0
JBidwatcher/lib/jbidwatcher/gixen/gixen.pem

@@ -0,0 +1,104 @@
+-----BEGIN CERTIFICATE-----
+MIIE0jCCA7qgAwIBAgIHAKUEA3aogjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
+BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY
+BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm
+aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5
+IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky
+ODcwHhcNMDkwNjE4MTUwNDMwWhcNMTIwODAzMDczODM2WjBTMRYwFAYDVQQKEw13
+d3cuZ2l4ZW4uY29tMSEwHwYDVQQLExhEb21haW4gQ29udHJvbCBWYWxpZGF0ZWQx
+FjAUBgNVBAMTDXd3dy5naXhlbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBALSSmTEpeyYvLnzBfqfliC5CuyYf0y3UmbA9p+fkGBxyiBXQPyJoKEGuot/1
+RPUyCwV61DJ4V2GJ5vAXN+f5gM//VZppEIzOxqH2hPtqCgKaHa5/St0ikl6zPZ/4
+V0IwTgDAGN7xgqpB+KbLzwPdlraC5dAsE/g6iM6FuAGTVNw/AgMBAAGjggG1MIIB
+sTAPBgNVHRMBAf8EBTADAQEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD
+AjAOBgNVHQ8BAf8EBAMCBaAwMgYDVR0fBCswKTAnoCWgI4YhaHR0cDovL2NybC5n
+b2RhZGR5LmNvbS9nZHMxLTUuY3JsMFMGA1UdIARMMEowSAYLYIZIAYb9bQEHFwEw
+OTA3BggrBgEFBQcCARYraHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9y
+ZXBvc2l0b3J5LzCBgAYIKwYBBQUHAQEEdDByMCQGCCsGAQUFBzABhhhodHRwOi8v
+b2NzcC5nb2RhZGR5LmNvbS8wSgYIKwYBBQUHMAKGPmh0dHA6Ly9jZXJ0aWZpY2F0
+ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS9nZF9pbnRlcm1lZGlhdGUuY3J0MB8G
+A1UdIwQYMBaAFP2sYTKTbEXW4u6FX5q653aZaMznMCMGA1UdEQQcMBqCDXd3dy5n
+aXhlbi5jb22CCWdpeGVuLmNvbTAdBgNVHQ4EFgQUbNQ8+1KGaPxVOw3/X96Kv133
+NPgwDQYJKoZIhvcNAQEFBQADggEBAEpS9Nb/BwdhZMRn64Aq0maa4E8Rk4G1XrN7
+RM9lsq4ShSe3aaO2yFsKqxeEDl24TaNUxcgtPnfcwT4C4GA10Nny+eTqKr4WCqNn
+BPL/dP95zYuaoB7gn+VTOu5nRPBw7wQz7MjmHeqGg3g1Vm7BKfA5EedTL76IPl1K
+0TWZNVEktO+3FMUKM1zFrBmwM1e8WOIAzg4cP3pQBE+1cmkoGW7Vl8YTLuv+t/RB
+PipTw0rtvpMhMGosQmDbcja1JHGlLLSIPcBgerEMZxtQO1+Z8piGpPigf9HruE+6
+vIRKW399x2vWe/SwfnZGVF/vVDi4CwWOut1cGxMuDstx8J/ggQw=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx
+ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
+RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw
+MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH
+QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j
+b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j
+b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H
+KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm
+VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR
+SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT
+cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ
+6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu
+MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS
+kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB
+BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f
+BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv
+c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH
+AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO
+BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG
+OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU
+A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o
+0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX
+RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH
+qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV
+U+4=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh
+bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu
+Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g
+QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe
+BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoX
+DTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBE
+YWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC
+ggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
+2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+q
+N1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiO
+r18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lN
+f4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEH
+U1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHU
+TBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMb
+VmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwg
+SW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlv
+biBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEg
+MB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUw
+AwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdv
+ZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMu
+Z29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUd
+IAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNv
+bS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1
+QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4O
+WBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0Vmsf
+SxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
+IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
+BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
+aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
+9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
+NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
+azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
+Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
+cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
+dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
+WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
+v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
+UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
+IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
+W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
+-----END CERTIFICATE-----

+ 183 - 0
JBidwatcher/lib/jbidwatcher/gixen/gixen.rb

@@ -0,0 +1,183 @@
+#!/usr/bin/env ruby
+
+require 'uri'
+require 'cgi'
+require 'net/https'
+
+require 'gixen_error'
+begin
+  require 'to_query'
+rescue LoadError => err
+  require 'active_support'
+  require 'active_support/all'
+end
+
+class Gixen
+  CORE_GIXEN_URL='https://www.gixen.com/api.php' #:nodoc:
+
+  #:nodoc:
+  LISTING_FORMAT = [:break,
+                    :itemid,
+                    :endtime,
+                    :maxbid,
+                    :status,
+                    :message,
+                    :title,
+                    :snipegroup,
+                    :quantity,
+                    :bidoffset]
+
+  # Create a Gixen object for interacting with the user's Gixen
+  # account, placing snipes, deleting snipes, and determining what
+  # snipes have been set up.
+  # 
+  # [+user+] an eBay username
+  # [+pass+] an eBay password
+  # [+validate_ssl+] true requests validation against the gixen cert file, false presumes the SSL is valid.  Defaults to false.
+  # 
+  # Gixen uses eBay authentication for its users, so it doesn't have
+  # to have a different user/pass for its users.
+  def initialize(user, pass, validate_ssl = false)
+    @username = user
+    @password = pass
+    @validate_ssl = validate_ssl
+  end
+
+  private
+  def gixen_url
+    "#{CORE_GIXEN_URL}?username=#{@username}&password=#{@password}&notags=1"
+  end
+
+  def submit(params)
+    url = "#{gixen_url}&#{params.to_query}"
+    uri = URI.parse(url)
+    http = Net::HTTP.new(uri.host, uri.port)
+    http.use_ssl = true if uri.scheme == 'https' # enable SSL/TLS
+    if @validate_ssl
+      http.verify_mode = OpenSSL::SSL::VERIFY_PEER
+      http.ca_file = pem_file
+    else
+      http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+    end
+    http.get("#{uri.path}?#{uri.query}")
+  end
+
+  def pem_file
+    File.expand_path(File.dirname(__FILE__) + "/gixen.pem")
+  end
+
+  def parse_response(resp)
+    data = resp.body
+    data.strip! if data
+    if data =~ /^ERROR \(([0-9]+)\): (.*)$/
+      error_code = $1
+      error_text = $2
+      raise GixenError.new(error_code.to_i, error_text)
+    end
+    data
+  end
+
+  def handle_snipes_list(body)
+    body.split("\n").inject([]) do |accum, line|
+      line.strip!
+      hash = {}
+      line.split("|#!#|").each_with_index do |entry, index|
+        if index < LISTING_FORMAT.length
+          hash[LISTING_FORMAT[index]] = entry
+        else
+          hash[index] = entry
+        end
+      end unless line =~ %r%^<br.*/>OK M(AIN|IRROR) LISTED$%
+      hash.empty? ? accum : (accum << hash)
+    end
+  end
+
+  def sourcify_hashes(hash_list, mirror = false)
+    hash_list.each do |h|
+      h[:mirror] = mirror
+    end
+  end
+
+  public
+  # Place a snipe on an +item+ (the auction item #) for +bid+ (string amount).
+  # [+item+] the item number of the listing on eBay
+  # [+bid+] a string amount of currency-neutral money, for example "23.50". The currency bid in will be the currency of the listing
+  # [+options+] A collection of optional parameters for setting snipe meta-data.
+  # Optional parameters include:
+  # * <tt>:snipegroup => <i>group number</i></tt>, e.g. <tt>:snipegroup => 1</tt> (default: 0, no groups used)
+  # * <tt>:quantity => <i>number</i></tt> (default: 1, single item auction) <b>[_obsolete_]</b>
+  # * <tt>:bidoffset => <i>seconds before end</i></tt> (3, 6, 8, 10 or 15. Default value is 6)
+  # * <tt>:bidoffsetmirror => <i>seconds before end</i></tt> (same as above, just for mirror server)
+  #
+  # @return [boolean] true if the snipe was successfully set, false if
+  # something other than 'OK ADDED' came back, and throws a GixenError
+  # if there is any server-side problem.
+  def snipe(item, bid, options = {})
+    response = submit({:itemid => item, :maxbid => bid}.merge(options))
+    body = parse_response(response).strip
+    !!(body =~ /^OK #{item} ADDED$/)
+  end
+
+  # Remove a snipe from an +item+ (the auction item #).
+  #
+  # @return [boolean] true if the snipe was successfully deleted, false if
+  # something other than 'OK DELETED' came back, and throws a GixenError
+  # if there is any server-side problem.
+  def unsnipe(item)
+    response = submit({:ditemid => item})
+    body = parse_response(response).strip
+    !!(body =~ /^OK #{item} DELETED$/)
+  end
+
+  # Lists all snipes set, skipped, or done on any Gixen server.
+  # 
+  # @return [array of hashes] an array where each entry is a hash
+  # containing all the info for a given snipe, an empty array if no
+  # auctions are listed on either the main Gixen server or the Gixen
+  # Mirror server.
+  # 
+  # An additional field is added, :mirror, which is either true or
+  # false, depending on if the item hash came from the mirror server
+  # or not.
+  # 
+  # It raises a GixenError if there is a server-side problem.
+  def snipes
+    sourcify_hashes(main_snipes) + sourcify_hashes(mirror_snipes, true)
+  end
+
+  # Lists all snipes currently set set, skipped, or done on Gixen's main server.
+  # 
+  # @return [array of hashes] an array where each entry is a hash
+  # containing all the info for a given snipe, an empty array if none
+  # are listed on the main Gixen server.  It raises a GixenError if
+  # there is a server-side problem.
+  def main_snipes
+    response = submit({:listsnipesmain => 1})
+    body = parse_response(response)
+    handle_snipes_list(body)
+  end
+
+  # List all snipes currently set set, skipped, or done on Gixen's mirror server.
+  # 
+  # @return [array of hashes] an array where each entry is a hash
+  # containing all the info for a given snipe, an empty array if none
+  # are listed on the Gixen Mirror server.  It raises a GixenError if
+  # there is a server-side problem.
+  def mirror_snipes
+    response = submit({:listsnipesmirror => 1})
+    body = parse_response(response)
+    handle_snipes_list(body)
+  end
+
+  # Normally the snipes that are completed are still listed when
+  # retrieving snipes from the server; this method clears completed
+  # listings, so the list of snipes is just active snipes.
+  #
+  # @return [boolean] true if the purge completed successfully.  It
+  # raises a GixenError if there is a server-side problem.
+  def purge
+    response = submit({:purgecompleted => 1})
+    body = parse_response(response).strip
+    !!(body =~ /^OK COMPLETEDPURGED$/)
+  end
+end

+ 41 - 0
JBidwatcher/lib/jbidwatcher/gixen/gixen_error.rb

@@ -0,0 +1,41 @@
+class Gixen
+  GIXEN_ERROR_MAP = {
+    501 => :ssl_required,     # ERROR (501): SSL REQUIRED
+    100 => :could_not_log_in, # ERROR (100): COULD NOT LOG IN
+    101 => :could_not_log_in, # ERROR (101): COULD NOT LOG IN
+    1001 => :down,            # ERROR (1001): GIXEN DOWN
+    111 => :not_subscriber,   # ERROR (111): NON SUBSCRIBER
+    115 => :suspended,        # ERROR (115): GIXEN ACCOUNT SUSPENDED
+    771 => :delete_failed,    # ERROR (771): DELETE QUERY FAILED
+    772 => :delete_failed,    # ERROR (772): DELETE QUERY FAILED
+    131 => :no_username,      # ERROR (131): USERNAME NOT SPECIFIED
+    132 => :no_password,      # ERROR (132): PASSWORD NOT SPECIFIED
+    133 => :no_maxbid,        # ERROR (133): MAXIMUM BID NOT SPECIFIED
+    201 => :too_many_snipes,  # ERROR (201): MAXIMUM NUMBER OF SNIPES EXCEEDED
+    202 => :already_present,  # ERROR (202): ITEM ALREADY PRESENT
+    203 => :cannot_get_info,  # ERROR (203): COULD NOT GET INFO FOR ITEM
+    301 => :format_invalid,   # ERROR (301): COULD NOT ADD SNIPE: AUCTION NUMBER OR MONEY FORMAT INVALID
+    302 => :error_adding_to_mirror, # ERROR (302): COULD NOT ADD SNIPE TO MIRROR
+    304 => :error_adding_to_mirror, # ERROR (304): COULD NOT ADD SNIPE TO MIRROR
+    401 => :empty_authentication,   # ERROR (401): EMPTY USERNAME OR EMPTY PASSWORD
+    241 => :delete_failed,    # ERROR (241): DELETE QUERY FAILED
+    242 => :delete_failed     # ERROR (242): DELETE QUERY FAILED
+  }
+
+  # GixenError is raised when there's a problem with the response, or
+  # the Gixen server has returned an error.
+  class GixenError < RuntimeError
+    def initialize(code, text)
+      super(text)
+      @code = code
+      @status = GIXEN_ERROR_MAP[@code]
+      @message = text
+    end
+
+    attr_reader :status, :code, :message
+
+    def to_s
+      "#{code} #{status} - #{message}"
+    end
+  end
+end

+ 54 - 0
JBidwatcher/lib/jbidwatcher/models.rb

@@ -0,0 +1,54 @@
+# Created by IntelliJ IDEA.
+# User: mrs
+# Date: 1/12/16
+# Time: 10:46 PM
+# To change this template use File | Settings | File Templates.
+
+require 'activerecord-jdbcderby-adapter'
+
+driver = JConfig.query_configuration("db.driver") || "org.apache.derby.jdbc.EmbeddedDriver"
+
+if driver.include? 'mysql'
+  db = JConfig.query_configuration("db.mysql.database")
+  user = JConfig.query_configuration('db.user')
+  pass = JConfig.query_configuration('db.pass')
+  protocol = JConfig.query_configuration('db.protocol') # e.g. jdbc:mysql://cyberfox.com:3306/
+  ActiveRecord::Base.establish_connection(adapter: 'jdbc', driver: 'com.mysql.jdbc.Driver', url: "#{protocol}#{db}", username: user, password: pass)
+else
+  ActiveRecord::Base.establish_connection(adapter: 'jdbcderby', database: 'jbdb', username: 'user1', password: 'user1')
+end
+
+class Auction < ActiveRecord::Base
+  has_one :entry
+  belongs_to :seller
+end
+
+class Entry < ActiveRecord::Base
+  belongs_to :auction
+  belongs_to :multisnipe
+  belongs_to :snipe
+  belongs_to :category
+
+  class << self
+    def instance_method_already_implemented?(method_name)
+      return true if method_name == "invalid?"
+      super
+    end
+  end
+end
+
+class Seller < ActiveRecord::Base
+  has_many :auctions
+end
+
+class Category < ActiveRecord::Base
+  has_many :entries
+end
+
+class Snipe < ActiveRecord::Base
+  has_one :entry
+end
+
+class Multisnipe < ActiveRecord::Base
+  has_many :entries
+end

BIN
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/isorelax.jar


BIN
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/jing.jar


BIN
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nekodtd.jar


BIN
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nekohtml.jar


+ 127 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri.rb

@@ -0,0 +1,127 @@
+# -*- coding: utf-8 -*-
+# Modify the PATH on windows so that the external DLLs will get loaded.
+
+require 'rbconfig'
+ENV['PATH'] = [File.expand_path(
+  File.join(File.dirname(__FILE__), "..", "ext", "nokogiri")
+), ENV['PATH']].compact.join(';') if RbConfig::CONFIG['host_os'] =~ /(mswin|mingw)/i
+
+if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
+  # The line below caused a problem on non-GAE rack environment.
+  # unless defined?(JRuby::Rack::VERSION) || defined?(AppEngine::ApiProxy)
+  #
+  # However, simply cutting defined?(JRuby::Rack::VERSION) off resulted in
+  # an unable-to-load-nokogiri problem. Thus, now, Nokogiri checks the presense
+  # of appengine-rack.jar in $LOAD_PATH. If Nokogiri is on GAE, Nokogiri
+  # should skip loading xml jars. This is because those are in WEB-INF/lib and 
+  # already set in the classpath.
+  unless $LOAD_PATH.to_s.include?("appengine-rack")
+    require 'isorelax.jar'
+    require 'jing.jar'
+    require 'nekohtml.jar'
+    require 'nekodtd.jar'
+    require 'xercesImpl.jar'
+  end
+end
+
+require 'nokogiri/nokogiri'
+require 'nokogiri/version'
+require 'nokogiri/syntax_error'
+require 'nokogiri/xml'
+require 'nokogiri/xslt'
+require 'nokogiri/html'
+require 'nokogiri/decorators/slop'
+require 'nokogiri/css'
+require 'nokogiri/html/builder'
+
+# Nokogiri parses and searches XML/HTML very quickly, and also has
+# correctly implemented CSS3 selector support as well as XPath support.
+#
+# Parsing a document returns either a Nokogiri::XML::Document, or a
+# Nokogiri::HTML::Document depending on the kind of document you parse.
+#
+# Here is an example:
+#
+#   require 'nokogiri'
+#   require 'open-uri'
+#
+#   # Get a Nokogiri::HTML:Document for the page we’re interested in...
+#
+#   doc = Nokogiri::HTML(open('http://www.google.com/search?q=tenderlove'))
+#
+#   # Do funky things with it using Nokogiri::XML::Node methods...
+#
+#   ####
+#   # Search for nodes by css
+#   doc.css('h3.r a.l').each do |link|
+#     puts link.content
+#   end
+#
+# See Nokogiri::XML::Node#css for more information about CSS searching.
+# See Nokogiri::XML::Node#xpath for more information about XPath searching.
+module Nokogiri
+  class << self
+    ###
+    # Parse an HTML or XML document.  +string+ contains the document.
+    def parse string, url = nil, encoding = nil, options = nil
+      doc =
+        if string.respond_to?(:read) ||
+          string =~ /^\s*<[^Hh>]*html/i # Probably html
+          Nokogiri.HTML(
+            string,
+            url,
+            encoding, options || XML::ParseOptions::DEFAULT_HTML
+          )
+        else
+          Nokogiri.XML(string, url, encoding,
+                        options || XML::ParseOptions::DEFAULT_XML)
+        end
+      yield doc if block_given?
+      doc
+    end
+
+    ###
+    # Create a new Nokogiri::XML::DocumentFragment
+    def make input = nil, opts = {}, &blk
+      if input
+        Nokogiri::HTML.fragment(input).children.first
+      else
+        Nokogiri(&blk)
+      end
+    end
+
+    ###
+    # Parse a document and add the Slop decorator.  The Slop decorator
+    # implements method_missing such that methods may be used instead of CSS
+    # or XPath.  For example:
+    #
+    #   doc = Nokogiri::Slop(<<-eohtml)
+    #     <html>
+    #       <body>
+    #         <p>first</p>
+    #         <p>second</p>
+    #       </body>
+    #     </html>
+    #   eohtml
+    #   assert_equal('second', doc.html.body.p[1].text)
+    #
+    def Slop(*args, &block)
+      Nokogiri(*args, &block).slop!
+    end
+  end
+end
+
+###
+# Parser a document contained in +args+.  Nokogiri will try to guess what
+# type of document you are attempting to parse.  For more information, see
+# Nokogiri.parse
+#
+# To specify the type of document, use Nokogiri.XML or Nokogiri.HTML.
+def Nokogiri(*args, &block)
+  if block_given?
+    builder = Nokogiri::HTML::Builder.new(&block)
+    return builder.doc.root
+  else
+    Nokogiri.parse(*args)
+  end
+end

+ 27 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css.rb

@@ -0,0 +1,27 @@
+require 'nokogiri/css/node'
+require 'nokogiri/css/xpath_visitor'
+x = $-w
+$-w = false
+require 'nokogiri/css/parser'
+$-w = x
+
+require 'nokogiri/css/tokenizer'
+require 'nokogiri/css/syntax_error'
+
+module Nokogiri
+  module CSS
+    class << self
+      ###
+      # Parse this CSS selector in +selector+.  Returns an AST.
+      def parse selector
+        Parser.new.parse selector
+      end
+
+      ###
+      # Get the XPath for +selector+.
+      def xpath_for selector, options={}
+        Parser.new(options[:ns] || {}).xpath_for selector, options
+      end
+    end
+  end
+end

+ 99 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/node.rb

@@ -0,0 +1,99 @@
+module Nokogiri
+  module CSS
+    class Node
+      # Get the type of this node
+      attr_accessor :type
+      # Get the value of this node
+      attr_accessor :value
+
+      # Create a new Node with +type+ and +value+
+      def initialize type, value
+        @type = type
+        @value = value
+      end
+
+      # Accept +visitor+
+      def accept visitor
+        visitor.send(:"visit_#{type.to_s.downcase}", self)
+      end
+
+      ###
+      # Convert this CSS node to xpath with +prefix+ using +visitor+
+      def to_xpath prefix = '//', visitor = XPathVisitor.new
+        self.preprocess!
+        prefix + visitor.accept(self)
+      end
+
+      # Preprocess this node tree
+      def preprocess!
+        ### Deal with nth-child
+        matches = find_by_type(
+          [:CONDITIONAL_SELECTOR,
+            [:ELEMENT_NAME],
+            [:PSEUDO_CLASS,
+              [:FUNCTION]
+            ]
+          ]
+        )
+        matches.each do |match|
+          if match.value[1].value[0].value[0] =~ /^nth-(last-)?child/
+            tag_name = match.value[0].value.first
+            match.value[0].value = ['*']
+            match.value[1] = Node.new(:COMBINATOR, [
+              match.value[1].value[0],
+              Node.new(:FUNCTION, ['self(', tag_name])
+            ])
+          end
+        end
+
+        ### Deal with first-child, last-child
+        matches = find_by_type(
+          [:CONDITIONAL_SELECTOR,
+            [:ELEMENT_NAME], [:PSEUDO_CLASS]
+        ])
+        matches.each do |match|
+          if ['first-child', 'last-child'].include?(match.value[1].value.first)
+            which = match.value[1].value.first.gsub(/-\w*$/, '')
+            tag_name = match.value[0].value.first
+            match.value[0].value = ['*']
+            match.value[1] = Node.new(:COMBINATOR, [
+              Node.new(:FUNCTION, ["#{which}("]),
+              Node.new(:FUNCTION, ['self(', tag_name])
+            ])
+          elsif 'only-child' == match.value[1].value.first
+            tag_name = match.value[0].value.first
+            match.value[0].value = ['*']
+            match.value[1] = Node.new(:COMBINATOR, [
+              Node.new(:FUNCTION, ["#{match.value[1].value.first}("]),
+              Node.new(:FUNCTION, ['self(', tag_name])
+            ])
+          end
+        end
+
+        self
+      end
+
+      # Find a node by type using +types+
+      def find_by_type types
+        matches = []
+        matches << self if to_type == types
+        @value.each do |v|
+          matches += v.find_by_type(types) if v.respond_to?(:find_by_type)
+        end
+        matches
+      end
+
+      # Convert to_type
+      def to_type
+        [@type] + @value.map { |n|
+          n.to_type if n.respond_to?(:to_type)
+        }.compact
+      end
+
+      # Convert to array
+      def to_a
+        [@type] + @value.map { |n| n.respond_to?(:to_a) ? n.to_a : [n] }
+      end
+    end
+  end
+end

+ 683 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/parser.rb

@@ -0,0 +1,683 @@
+#
+# DO NOT MODIFY!!!!
+# This file is automatically generated by Racc 1.4.7
+# from Racc grammer file "".
+#
+
+require 'racc/parser.rb'
+
+
+require 'nokogiri/css/parser_extras'
+module Nokogiri
+  module CSS
+    class Parser < Racc::Parser
+##### State transition tables begin ###
+
+racc_action_table = [
+     5,    57,    28,    23,    13,    25,    61,    58,     5,     1,
+     6,    60,    13,    58,    66,    24,    17,     1,    83,    20,
+    94,    93,     6,    13,     9,    11,    14,    20,    17,    42,
+     6,     5,     9,    11,    14,    13,    17,    76,    42,     5,
+     1,     6,    65,    13,    11,    62,    63,    17,     1,    60,
+    20,     5,    63,     6,    84,     9,    11,    14,    20,    17,
+     1,     6,    30,     9,    11,    14,    13,    17,    13,    85,
+    20,     1,    64,    13,    59,     9,    88,    13,    13,    89,
+    28,    54,    13,    55,     6,    42,     6,    11,    14,    11,
+    17,     6,    17,    45,    11,     6,     6,    17,    11,    11,
+     6,    17,    17,    11,     5,    92,    17,    69,    71,    28,
+    54,    22,    55,    50,    28,    54,    95,    55,    70,    72,
+    73,   -24,    75,    20,    69,    71,    67,    97,     9,    98,
+   nil,   nil,    34,    36,    38,    70,    72,    73,   nil,    75,
+   nil,   nil,    33,    67,    35,    37,    28,    54,   nil,    55 ]
+
+racc_action_check = [
+     0,    21,     5,     5,     0,     5,    23,    43,     9,     0,
+    15,    23,     9,    21,    28,     5,    15,     9,    43,     0,
+    74,    74,     0,     8,     0,     0,     0,     9,     0,    40,
+     9,    32,     9,     9,     9,    32,     9,    30,     8,    58,
+    32,     8,    27,    58,     8,    25,    25,     8,    58,    54,
+    32,     6,    55,    32,    56,    32,    32,    32,    58,    32,
+     6,    58,     6,    58,    58,    58,    42,    58,    80,    57,
+     6,    42,    26,    10,    22,     6,    61,    19,    18,    62,
+    60,    60,    16,    60,    42,    12,    80,    42,    42,    80,
+    42,    10,    80,    11,    10,    19,    18,    10,    19,    18,
+    16,    19,    18,    16,    17,    68,    16,    31,    31,    20,
+    20,     4,    20,    17,    63,    63,    77,    63,    31,    31,
+    31,     1,    31,    17,    29,    29,    31,    82,    17,    89,
+   nil,   nil,     7,     7,     7,    29,    29,    29,   nil,    29,
+   nil,   nil,     7,    29,     7,     7,    66,    66,   nil,    66 ]
+
+racc_action_pointer = [
+    -2,    92,   nil,   nil,    82,    -8,    49,   125,    17,     6,
+    67,    82,    64,   nil,   nil,   -14,    76,   102,    72,    71,
+    99,     1,    63,    -1,   nil,    34,    49,    19,     2,   121,
+    12,   104,    29,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+     8,   nil,    60,    -5,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,    37,    40,    31,    69,    37,   nil,
+    70,    63,    72,   104,   nil,   nil,   136,   nil,    80,   nil,
+   nil,   nil,   nil,   nil,    10,   nil,   nil,    91,   nil,   nil,
+    62,   nil,   104,   nil,   nil,   nil,   nil,   nil,   nil,   116,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil ]
+
+racc_action_default = [
+   -25,   -23,   -20,    -2,   -70,   -70,   -25,   -18,   -46,   -25,
+   -51,   -70,   -16,   -55,   -21,   -12,   -54,   -70,   -53,   -52,
+   -70,   -70,   -70,   -39,   -29,   -37,   -70,   -70,   -38,   -58,
+   -70,   -58,   -25,    -5,    -3,    -8,    -4,    -7,    -6,    -9,
+   -45,   -11,   -25,   -70,   -47,   -19,   -15,   -13,   -14,   -50,
+   -44,   -43,   -49,   -48,   -39,   -37,   -70,   -70,   -25,   -22,
+   -70,   -70,   -42,   -70,   -30,   -31,   -70,   -59,   -70,   -64,
+   -60,   -65,   -61,   -62,   -70,   -63,   -28,   -70,   -17,   -10,
+   -67,   -69,   -70,   -33,   -32,    99,    -1,   -36,   -41,   -70,
+   -34,   -35,   -26,   -56,   -57,   -27,   -68,   -66,   -40 ]
+
+racc_goto_table = [
+    40,    26,    44,    41,    78,    21,    31,    46,    49,    29,
+    52,    53,    47,    68,    43,    77,    56,    51,    48,    39,
+    80,    32,    27,    82,   nil,   nil,   nil,   nil,   nil,   nil,
+    86,   nil,   nil,   nil,    81,    79,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,    87,   nil,   nil,    90,
+   nil,   nil,    91,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,    96 ]
+
+racc_goto_check = [
+     7,    16,     7,     8,     2,     1,     9,     8,     7,    13,
+     7,     7,    10,    15,     1,    15,    16,     9,    11,     6,
+     5,     3,    17,    20,   nil,   nil,   nil,   nil,   nil,   nil,
+     2,   nil,   nil,   nil,     7,     8,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,    16,   nil,   nil,    16,
+   nil,   nil,    16,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,     7 ]
+
+racc_goto_pointer = [
+   nil,     5,   -28,    14,   nil,   -22,    11,    -8,    -5,     0,
+    -3,     3,   nil,     3,   nil,   -16,    -4,    17,   nil,   nil,
+   -19 ]
+
+racc_goto_default = [
+   nil,   nil,     3,   nil,     7,     8,   nil,    12,   nil,    15,
+    16,    18,    19,     2,     4,   nil,   nil,   nil,    10,    74,
+   nil ]
+
+racc_reduce_table = [
+  0, 0, :racc_error,
+  3, 32, :_reduce_1,
+  1, 32, :_reduce_2,
+  1, 34, :_reduce_3,
+  1, 34, :_reduce_4,
+  1, 34, :_reduce_5,
+  1, 34, :_reduce_6,
+  1, 34, :_reduce_7,
+  1, 34, :_reduce_8,
+  2, 35, :_reduce_9,
+  3, 35, :_reduce_10,
+  2, 35, :_reduce_11,
+  1, 35, :_reduce_none,
+  2, 35, :_reduce_13,
+  2, 35, :_reduce_14,
+  2, 35, :_reduce_15,
+  1, 35, :_reduce_16,
+  3, 33, :_reduce_17,
+  1, 33, :_reduce_none,
+  2, 43, :_reduce_19,
+  1, 36, :_reduce_none,
+  1, 36, :_reduce_21,
+  3, 44, :_reduce_22,
+  1, 44, :_reduce_23,
+  1, 45, :_reduce_24,
+  0, 45, :_reduce_none,
+  4, 42, :_reduce_26,
+  4, 42, :_reduce_27,
+  3, 42, :_reduce_28,
+  2, 40, :_reduce_29,
+  3, 40, :_reduce_30,
+  3, 40, :_reduce_31,
+  3, 40, :_reduce_32,
+  3, 40, :_reduce_33,
+  3, 47, :_reduce_34,
+  3, 47, :_reduce_35,
+  3, 47, :_reduce_36,
+  1, 47, :_reduce_none,
+  1, 47, :_reduce_none,
+  1, 47, :_reduce_39,
+  4, 48, :_reduce_40,
+  3, 48, :_reduce_41,
+  2, 48, :_reduce_42,
+  2, 41, :_reduce_43,
+  2, 41, :_reduce_44,
+  1, 37, :_reduce_none,
+  0, 37, :_reduce_none,
+  2, 38, :_reduce_47,
+  2, 38, :_reduce_48,
+  2, 38, :_reduce_49,
+  2, 38, :_reduce_50,
+  1, 38, :_reduce_none,
+  1, 38, :_reduce_none,
+  1, 38, :_reduce_none,
+  1, 38, :_reduce_none,
+  1, 49, :_reduce_55,
+  2, 46, :_reduce_56,
+  2, 46, :_reduce_57,
+  0, 46, :_reduce_none,
+  1, 50, :_reduce_59,
+  1, 50, :_reduce_60,
+  1, 50, :_reduce_61,
+  1, 50, :_reduce_62,
+  1, 50, :_reduce_63,
+  1, 50, :_reduce_64,
+  1, 50, :_reduce_65,
+  3, 39, :_reduce_66,
+  1, 51, :_reduce_none,
+  2, 51, :_reduce_none,
+  1, 51, :_reduce_none ]
+
+racc_reduce_n = 70
+
+racc_shift_n = 99
+
+racc_token_table = {
+  false => 0,
+  :error => 1,
+  :FUNCTION => 2,
+  :INCLUDES => 3,
+  :DASHMATCH => 4,
+  :LBRACE => 5,
+  :HASH => 6,
+  :PLUS => 7,
+  :GREATER => 8,
+  :S => 9,
+  :STRING => 10,
+  :IDENT => 11,
+  :COMMA => 12,
+  :NUMBER => 13,
+  :PREFIXMATCH => 14,
+  :SUFFIXMATCH => 15,
+  :SUBSTRINGMATCH => 16,
+  :TILDE => 17,
+  :NOT_EQUAL => 18,
+  :SLASH => 19,
+  :DOUBLESLASH => 20,
+  :NOT => 21,
+  :EQUAL => 22,
+  :RPAREN => 23,
+  :LSQUARE => 24,
+  :RSQUARE => 25,
+  :HAS => 26,
+  "." => 27,
+  "*" => 28,
+  "|" => 29,
+  ":" => 30 }
+
+racc_nt_base = 31
+
+racc_use_result_var = true
+
+Racc_arg = [
+  racc_action_table,
+  racc_action_check,
+  racc_action_default,
+  racc_action_pointer,
+  racc_goto_table,
+  racc_goto_check,
+  racc_goto_default,
+  racc_goto_pointer,
+  racc_nt_base,
+  racc_reduce_table,
+  racc_token_table,
+  racc_shift_n,
+  racc_reduce_n,
+  racc_use_result_var ]
+
+Racc_token_to_s_table = [
+  "$end",
+  "error",
+  "FUNCTION",
+  "INCLUDES",
+  "DASHMATCH",
+  "LBRACE",
+  "HASH",
+  "PLUS",
+  "GREATER",
+  "S",
+  "STRING",
+  "IDENT",
+  "COMMA",
+  "NUMBER",
+  "PREFIXMATCH",
+  "SUFFIXMATCH",
+  "SUBSTRINGMATCH",
+  "TILDE",
+  "NOT_EQUAL",
+  "SLASH",
+  "DOUBLESLASH",
+  "NOT",
+  "EQUAL",
+  "RPAREN",
+  "LSQUARE",
+  "RSQUARE",
+  "HAS",
+  "\".\"",
+  "\"*\"",
+  "\"|\"",
+  "\":\"",
+  "$start",
+  "selector",
+  "simple_selector_1toN",
+  "combinator",
+  "simple_selector",
+  "element_name",
+  "hcap_0toN",
+  "hcap_1toN",
+  "negation",
+  "function",
+  "pseudo",
+  "attrib",
+  "class",
+  "namespaced_ident",
+  "namespace",
+  "attrib_val_0or1",
+  "expr",
+  "an_plus_b",
+  "attribute_id",
+  "eql_incl_dash",
+  "negation_arg" ]
+
+Racc_debug_parser = false
+
+##### State transition tables end #####
+
+# reduce 0 omitted
+
+def _reduce_1(val, _values, result)
+        result = [val.first, val.last].flatten
+      
+    result
+end
+
+def _reduce_2(val, _values, result)
+ result = val.flatten 
+    result
+end
+
+def _reduce_3(val, _values, result)
+ result = :DIRECT_ADJACENT_SELECTOR 
+    result
+end
+
+def _reduce_4(val, _values, result)
+ result = :CHILD_SELECTOR 
+    result
+end
+
+def _reduce_5(val, _values, result)
+ result = :PRECEDING_SELECTOR 
+    result
+end
+
+def _reduce_6(val, _values, result)
+ result = :DESCENDANT_SELECTOR 
+    result
+end
+
+def _reduce_7(val, _values, result)
+ result = :DESCENDANT_SELECTOR 
+    result
+end
+
+def _reduce_8(val, _values, result)
+ result = :CHILD_SELECTOR 
+    result
+end
+
+def _reduce_9(val, _values, result)
+        result =  if val[1].nil?
+                    val.first
+                  else
+                    Node.new(:CONDITIONAL_SELECTOR, [val.first, val[1]])
+                  end
+      
+    result
+end
+
+def _reduce_10(val, _values, result)
+        result = Node.new(:CONDITIONAL_SELECTOR,
+          [
+            val.first,
+            Node.new(:COMBINATOR, [val[1], val.last])
+          ]
+        )
+      
+    result
+end
+
+def _reduce_11(val, _values, result)
+        result = Node.new(:CONDITIONAL_SELECTOR, val)
+      
+    result
+end
+
+# reduce 12 omitted
+
+def _reduce_13(val, _values, result)
+        result = Node.new(:CONDITIONAL_SELECTOR, val)
+      
+    result
+end
+
+def _reduce_14(val, _values, result)
+        result = Node.new(:CONDITIONAL_SELECTOR, val)
+      
+    result
+end
+
+def _reduce_15(val, _values, result)
+        result = Node.new(:CONDITIONAL_SELECTOR,
+          [
+            Node.new(:ELEMENT_NAME, ['*']),
+            Node.new(:COMBINATOR, val)
+          ]
+        )
+      
+    result
+end
+
+def _reduce_16(val, _values, result)
+        result = Node.new(:CONDITIONAL_SELECTOR,
+          [Node.new(:ELEMENT_NAME, ['*']), val.first]
+        )
+      
+    result
+end
+
+def _reduce_17(val, _values, result)
+        result = Node.new(val[1], [val.first, val.last])
+      
+    result
+end
+
+# reduce 18 omitted
+
+def _reduce_19(val, _values, result)
+ result = Node.new(:CLASS_CONDITION, [val[1]]) 
+    result
+end
+
+# reduce 20 omitted
+
+def _reduce_21(val, _values, result)
+ result = Node.new(:ELEMENT_NAME, val) 
+    result
+end
+
+def _reduce_22(val, _values, result)
+        result = Node.new(:ELEMENT_NAME,
+          [[val.first, val.last].compact.join(':')]
+        )
+      
+    result
+end
+
+def _reduce_23(val, _values, result)
+        name = @namespaces.key?('xmlns') ? "xmlns:#{val.first}" : val.first
+        result = Node.new(:ELEMENT_NAME, [name])
+      
+    result
+end
+
+def _reduce_24(val, _values, result)
+ result = val[0] 
+    result
+end
+
+# reduce 25 omitted
+
+def _reduce_26(val, _values, result)
+        result = Node.new(:ATTRIBUTE_CONDITION,
+          [val[1]] + (val[2] || [])
+        )
+      
+    result
+end
+
+def _reduce_27(val, _values, result)
+        result = Node.new(:ATTRIBUTE_CONDITION,
+          [val[1]] + (val[2] || [])
+        )
+      
+    result
+end
+
+def _reduce_28(val, _values, result)
+        # Non standard, but hpricot supports it.
+        result = Node.new(:PSEUDO_CLASS,
+          [Node.new(:FUNCTION, ['nth-child(', val[1]])]
+        )
+      
+    result
+end
+
+def _reduce_29(val, _values, result)
+        result = Node.new(:FUNCTION, [val.first.strip])
+      
+    result
+end
+
+def _reduce_30(val, _values, result)
+        result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
+      
+    result
+end
+
+def _reduce_31(val, _values, result)
+        result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
+      
+    result
+end
+
+def _reduce_32(val, _values, result)
+        result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
+      
+    result
+end
+
+def _reduce_33(val, _values, result)
+        result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
+      
+    result
+end
+
+def _reduce_34(val, _values, result)
+ result = [val.first, val.last] 
+    result
+end
+
+def _reduce_35(val, _values, result)
+ result = [val.first, val.last] 
+    result
+end
+
+def _reduce_36(val, _values, result)
+ result = [val.first, val.last] 
+    result
+end
+
+# reduce 37 omitted
+
+# reduce 38 omitted
+
+def _reduce_39(val, _values, result)
+        if val[0] == 'even'
+          val = ["2","n","+","0"]
+          result = Node.new(:AN_PLUS_B, val)
+        elsif val[0] == 'odd'
+          val = ["2","n","+","1"]
+          result = Node.new(:AN_PLUS_B, val)
+        else
+          # This is not CSS standard.  It allows us to support this:
+          # assert_xpath("//a[foo(., @href)]", @parser.parse('a:foo(@href)'))
+          # assert_xpath("//a[foo(., @a, b)]", @parser.parse('a:foo(@a, b)'))
+          # assert_xpath("//a[foo(., a, 10)]", @parser.parse('a:foo(a, 10)'))
+          result = val
+        end
+      
+    result
+end
+
+def _reduce_40(val, _values, result)
+        if val[1] == 'n'
+          result = Node.new(:AN_PLUS_B, val)
+        else
+          raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
+        end
+      
+    result
+end
+
+def _reduce_41(val, _values, result)
+               # n+3, -n+3
+        if val[0] == 'n'
+          val.unshift("1")
+          result = Node.new(:AN_PLUS_B, val)
+        elsif val[0] == '-n'
+          val[0] = 'n'
+          val.unshift("-1")
+          result = Node.new(:AN_PLUS_B, val)
+        else
+          raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
+        end
+      
+    result
+end
+
+def _reduce_42(val, _values, result)
+        if val[1] == 'n'
+          val << "+"
+          val << "0"
+          result = Node.new(:AN_PLUS_B, val)
+        else
+          raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
+        end
+      
+    result
+end
+
+def _reduce_43(val, _values, result)
+        result = Node.new(:PSEUDO_CLASS, [val[1]])
+      
+    result
+end
+
+def _reduce_44(val, _values, result)
+ result = Node.new(:PSEUDO_CLASS, [val[1]]) 
+    result
+end
+
+# reduce 45 omitted
+
+# reduce 46 omitted
+
+def _reduce_47(val, _values, result)
+        result = Node.new(:COMBINATOR, val)
+      
+    result
+end
+
+def _reduce_48(val, _values, result)
+        result = Node.new(:COMBINATOR, val)
+      
+    result
+end
+
+def _reduce_49(val, _values, result)
+        result = Node.new(:COMBINATOR, val)
+      
+    result
+end
+
+def _reduce_50(val, _values, result)
+        result = Node.new(:COMBINATOR, val)
+      
+    result
+end
+
+# reduce 51 omitted
+
+# reduce 52 omitted
+
+# reduce 53 omitted
+
+# reduce 54 omitted
+
+def _reduce_55(val, _values, result)
+ result = Node.new(:ID, val) 
+    result
+end
+
+def _reduce_56(val, _values, result)
+ result = [val.first, val[1]] 
+    result
+end
+
+def _reduce_57(val, _values, result)
+ result = [val.first, val[1]] 
+    result
+end
+
+# reduce 58 omitted
+
+def _reduce_59(val, _values, result)
+ result = :equal 
+    result
+end
+
+def _reduce_60(val, _values, result)
+ result = :prefix_match 
+    result
+end
+
+def _reduce_61(val, _values, result)
+ result = :suffix_match 
+    result
+end
+
+def _reduce_62(val, _values, result)
+ result = :substring_match 
+    result
+end
+
+def _reduce_63(val, _values, result)
+ result = :not_equal 
+    result
+end
+
+def _reduce_64(val, _values, result)
+ result = :includes 
+    result
+end
+
+def _reduce_65(val, _values, result)
+ result = :dash_match 
+    result
+end
+
+def _reduce_66(val, _values, result)
+        result = Node.new(:NOT, [val[1]])
+      
+    result
+end
+
+# reduce 67 omitted
+
+# reduce 68 omitted
+
+# reduce 69 omitted
+
+def _reduce_none(val, _values, result)
+  val[0]
+end
+
+    end   # class Parser
+    end   # module CSS
+  end   # module Nokogiri

+ 240 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/parser.y

@@ -0,0 +1,240 @@
+class Nokogiri::CSS::Parser
+
+token FUNCTION INCLUDES DASHMATCH LBRACE HASH PLUS GREATER S STRING IDENT
+token COMMA NUMBER PREFIXMATCH SUFFIXMATCH SUBSTRINGMATCH TILDE NOT_EQUAL
+token SLASH DOUBLESLASH NOT EQUAL RPAREN LSQUARE RSQUARE HAS
+
+rule
+  selector
+    : selector COMMA simple_selector_1toN {
+        result = [val.first, val.last].flatten
+      }
+    | simple_selector_1toN { result = val.flatten }
+    ;
+  combinator
+    : PLUS { result = :DIRECT_ADJACENT_SELECTOR }
+    | GREATER { result = :CHILD_SELECTOR }
+    | TILDE { result = :PRECEDING_SELECTOR }
+    | S { result = :DESCENDANT_SELECTOR }
+    | DOUBLESLASH { result = :DESCENDANT_SELECTOR }
+    | SLASH { result = :CHILD_SELECTOR }
+    ;
+  simple_selector
+    : element_name hcap_0toN {
+        result =  if val[1].nil?
+                    val.first
+                  else
+                    Node.new(:CONDITIONAL_SELECTOR, [val.first, val[1]])
+                  end
+      }
+    | element_name hcap_1toN negation {
+        result = Node.new(:CONDITIONAL_SELECTOR,
+          [
+            val.first,
+            Node.new(:COMBINATOR, [val[1], val.last])
+          ]
+        )
+      }
+    | element_name negation {
+        result = Node.new(:CONDITIONAL_SELECTOR, val)
+      }
+    | function
+    | function pseudo {
+        result = Node.new(:CONDITIONAL_SELECTOR, val)
+      }
+    | function attrib {
+        result = Node.new(:CONDITIONAL_SELECTOR, val)
+      }
+    | hcap_1toN negation {
+        result = Node.new(:CONDITIONAL_SELECTOR,
+          [
+            Node.new(:ELEMENT_NAME, ['*']),
+            Node.new(:COMBINATOR, val)
+          ]
+        )
+      }
+    | hcap_1toN {
+        result = Node.new(:CONDITIONAL_SELECTOR,
+          [Node.new(:ELEMENT_NAME, ['*']), val.first]
+        )
+      }
+    ;
+  simple_selector_1toN
+    : simple_selector combinator simple_selector_1toN {
+        result = Node.new(val[1], [val.first, val.last])
+      }
+    | simple_selector
+    ;
+  class
+    : '.' IDENT { result = Node.new(:CLASS_CONDITION, [val[1]]) }
+    ;
+  element_name
+    : namespaced_ident
+    | '*' { result = Node.new(:ELEMENT_NAME, val) }
+    ;
+  namespaced_ident
+    : namespace '|' IDENT {
+        result = Node.new(:ELEMENT_NAME,
+          [[val.first, val.last].compact.join(':')]
+        )
+      }
+    | IDENT {
+        name = @namespaces.key?('xmlns') ? "xmlns:#{val.first}" : val.first
+        result = Node.new(:ELEMENT_NAME, [name])
+      }
+    ;
+  namespace
+    : IDENT { result = val[0] }
+    |
+    ;
+  attrib
+    : LSQUARE namespaced_ident attrib_val_0or1 RSQUARE {
+        result = Node.new(:ATTRIBUTE_CONDITION,
+          [val[1]] + (val[2] || [])
+        )
+      }
+    | LSQUARE function attrib_val_0or1 RSQUARE {
+        result = Node.new(:ATTRIBUTE_CONDITION,
+          [val[1]] + (val[2] || [])
+        )
+      }
+    | LSQUARE NUMBER RSQUARE {
+        # Non standard, but hpricot supports it.
+        result = Node.new(:PSEUDO_CLASS,
+          [Node.new(:FUNCTION, ['nth-child(', val[1]])]
+        )
+      }
+    ;
+  function
+    : FUNCTION RPAREN {
+        result = Node.new(:FUNCTION, [val.first.strip])
+      }
+    | FUNCTION expr RPAREN {
+        result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
+      }
+    | FUNCTION an_plus_b RPAREN {
+        result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
+      }
+    | NOT expr RPAREN {
+        result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
+      }
+    | HAS selector RPAREN {
+        result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
+      }
+    ;
+  expr
+    : NUMBER COMMA expr { result = [val.first, val.last] }
+    | STRING COMMA expr { result = [val.first, val.last] }
+    | IDENT COMMA expr { result = [val.first, val.last] }
+    | NUMBER
+    | STRING
+    | IDENT                             # even, odd
+      {
+        if val[0] == 'even'
+          val = ["2","n","+","0"]
+          result = Node.new(:AN_PLUS_B, val)
+        elsif val[0] == 'odd'
+          val = ["2","n","+","1"]
+          result = Node.new(:AN_PLUS_B, val)
+        else
+          # This is not CSS standard.  It allows us to support this:
+          # assert_xpath("//a[foo(., @href)]", @parser.parse('a:foo(@href)'))
+          # assert_xpath("//a[foo(., @a, b)]", @parser.parse('a:foo(@a, b)'))
+          # assert_xpath("//a[foo(., a, 10)]", @parser.parse('a:foo(a, 10)'))
+          result = val
+        end
+      }
+    ;
+  an_plus_b
+    : NUMBER IDENT PLUS NUMBER          # 5n+3 -5n+3
+      {
+        if val[1] == 'n'
+          result = Node.new(:AN_PLUS_B, val)
+        else
+          raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
+        end
+      }
+    | IDENT PLUS NUMBER {               # n+3, -n+3
+        if val[0] == 'n'
+          val.unshift("1")
+          result = Node.new(:AN_PLUS_B, val)
+        elsif val[0] == '-n'
+          val[0] = 'n'
+          val.unshift("-1")
+          result = Node.new(:AN_PLUS_B, val)
+        else
+          raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
+        end
+      }
+    | NUMBER IDENT                      # 5n, -5n
+      {
+        if val[1] == 'n'
+          val << "+"
+          val << "0"
+          result = Node.new(:AN_PLUS_B, val)
+        else
+          raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
+        end
+      }
+    ;
+  pseudo
+    : ':' function {
+        result = Node.new(:PSEUDO_CLASS, [val[1]])
+      }
+    | ':' IDENT { result = Node.new(:PSEUDO_CLASS, [val[1]]) }
+    ;
+  hcap_0toN
+    : hcap_1toN
+    |
+    ;
+  hcap_1toN
+    : attribute_id hcap_1toN {
+        result = Node.new(:COMBINATOR, val)
+      }
+    | class hcap_1toN {
+        result = Node.new(:COMBINATOR, val)
+      }
+    | attrib hcap_1toN {
+        result = Node.new(:COMBINATOR, val)
+      }
+    | pseudo hcap_1toN {
+        result = Node.new(:COMBINATOR, val)
+      }
+    | attribute_id
+    | class
+    | attrib
+    | pseudo
+    ;
+  attribute_id
+    : HASH { result = Node.new(:ID, val) }
+    ;
+  attrib_val_0or1
+    : eql_incl_dash IDENT { result = [val.first, val[1]] }
+    | eql_incl_dash STRING { result = [val.first, val[1]] }
+    |
+    ;
+  eql_incl_dash
+    : EQUAL           { result = :equal }
+    | PREFIXMATCH     { result = :prefix_match }
+    | SUFFIXMATCH     { result = :suffix_match }
+    | SUBSTRINGMATCH  { result = :substring_match }
+    | NOT_EQUAL       { result = :not_equal }
+    | INCLUDES        { result = :includes }
+    | DASHMATCH       { result = :dash_match }
+    ;
+  negation
+    : NOT negation_arg RPAREN {
+        result = Node.new(:NOT, [val[1]])
+      }
+    ;
+  negation_arg
+    : element_name
+    | element_name hcap_1toN
+    | hcap_1toN
+    ;
+end
+
+---- header
+
+require 'nokogiri/css/parser_extras'
+

+ 91 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/parser_extras.rb

@@ -0,0 +1,91 @@
+require 'thread'
+
+module Nokogiri
+  module CSS
+    class Parser < Racc::Parser
+      @cache_on = true
+      @cache    = {}
+      @mutex    = Mutex.new
+
+      class << self
+        # Turn on CSS parse caching
+        attr_accessor :cache_on
+        alias :cache_on? :cache_on
+        alias :set_cache :cache_on=
+
+        # Get the css selector in +string+ from the cache
+        def [] string
+          return unless @cache_on
+          @mutex.synchronize { @cache[string] }
+        end
+
+        # Set the css selector in +string+ in the cache to +value+
+        def []= string, value
+          return value unless @cache_on
+          @mutex.synchronize { @cache[string] = value }
+        end
+
+        # Clear the cache
+        def clear_cache
+          @mutex.synchronize { @cache = {} }
+        end
+
+        # Execute +block+ without cache
+        def without_cache &block
+          tmp = @cache_on
+          @cache_on = false
+          block.call
+          @cache_on = tmp
+        end
+
+        ###
+        # Parse this CSS selector in +selector+.  Returns an AST.
+        def parse selector
+          @warned ||= false
+          unless @warned
+            $stderr.puts('Nokogiri::CSS::Parser.parse is deprecated, call Nokogiri::CSS.parse(), this will be removed August 1st or version 1.4.0 (whichever is first)')
+            @warned = true
+          end
+          new.parse selector
+        end
+      end
+
+      # Create a new CSS parser with respect to +namespaces+
+      def initialize namespaces = {}
+        @tokenizer  = Tokenizer.new
+        @namespaces = namespaces
+        super()
+      end
+
+      def parse string
+        @tokenizer.scan_setup string
+        do_parse
+      end
+
+      def next_token
+        @tokenizer.next_token
+      end
+
+      # Get the xpath for +string+ using +options+
+      def xpath_for string, options={}
+        key = "#{string}#{options[:ns]}#{options[:prefix]}"
+        v = self.class[key]
+        return v if v
+
+        args = [
+          options[:prefix] || '//',
+          options[:visitor] || XPathVisitor.new
+        ]
+        self.class[key] = parse(string).map { |ast|
+          ast.to_xpath(*args)
+        }
+      end
+
+      # On CSS parser error, raise an exception
+      def on_error error_token_id, error_value, value_stack
+        after = value_stack.compact.last
+        raise SyntaxError.new("unexpected '#{error_value}' after '#{after}'")
+      end
+    end
+  end
+end

+ 7 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/syntax_error.rb

@@ -0,0 +1,7 @@
+require 'nokogiri/syntax_error'
+module Nokogiri
+  module CSS
+    class SyntaxError < ::Nokogiri::SyntaxError
+    end
+  end
+end

+ 152 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/tokenizer.rb

@@ -0,0 +1,152 @@
+#--
+# DO NOT MODIFY!!!!
+# This file is automatically generated by rex 1.0.5
+# from lexical definition file "lib/nokogiri/css/tokenizer.rex".
+#++
+
+module Nokogiri
+module CSS
+class Tokenizer # :nodoc:
+  require 'strscan'
+
+  class ScanError < StandardError ; end
+
+  attr_reader   :lineno
+  attr_reader   :filename
+  attr_accessor :state
+
+  def scan_setup(str)
+    @ss = StringScanner.new(str)
+    @lineno =  1
+    @state  = nil
+  end
+
+  def action
+    yield
+  end
+
+  def scan_str(str)
+    scan_setup(str)
+    do_parse
+  end
+  alias :scan :scan_str
+
+  def load_file( filename )
+    @filename = filename
+    open(filename, "r") do |f|
+      scan_setup(f.read)
+    end
+  end
+
+  def scan_file( filename )
+    load_file(filename)
+    do_parse
+  end
+
+
+  def next_token
+    return if @ss.eos?
+    
+    # skips empty actions
+    until token = _next_token or @ss.eos?; end
+    token
+  end
+
+  def _next_token
+    text = @ss.peek(1)
+    @lineno  +=  1  if text == "\n"
+    token = case @state
+    when nil
+      case
+      when (text = @ss.scan(/has\([\s]*/))
+         action { [:HAS, text] }
+
+      when (text = @ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])*\([\s]*/))
+         action { [:FUNCTION, text] }
+
+      when (text = @ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])*/))
+         action { [:IDENT, text] }
+
+      when (text = @ss.scan(/\#([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])+/))
+         action { [:HASH, text] }
+
+      when (text = @ss.scan(/[\s]*~=[\s]*/))
+         action { [:INCLUDES, text] }
+
+      when (text = @ss.scan(/[\s]*\|=[\s]*/))
+         action { [:DASHMATCH, text] }
+
+      when (text = @ss.scan(/[\s]*\^=[\s]*/))
+         action { [:PREFIXMATCH, text] }
+
+      when (text = @ss.scan(/[\s]*\$=[\s]*/))
+         action { [:SUFFIXMATCH, text] }
+
+      when (text = @ss.scan(/[\s]*\*=[\s]*/))
+         action { [:SUBSTRINGMATCH, text] }
+
+      when (text = @ss.scan(/[\s]*!=[\s]*/))
+         action { [:NOT_EQUAL, text] }
+
+      when (text = @ss.scan(/[\s]*=[\s]*/))
+         action { [:EQUAL, text] }
+
+      when (text = @ss.scan(/[\s]*\)/))
+         action { [:RPAREN, text] }
+
+      when (text = @ss.scan(/[\s]*\[[\s]*/))
+         action { [:LSQUARE, text] }
+
+      when (text = @ss.scan(/[\s]*\]/))
+         action { [:RSQUARE, text] }
+
+      when (text = @ss.scan(/[\s]*\+[\s]*/))
+         action { [:PLUS, text] }
+
+      when (text = @ss.scan(/[\s]*>[\s]*/))
+         action { [:GREATER, text] }
+
+      when (text = @ss.scan(/[\s]*,[\s]*/))
+         action { [:COMMA, text] }
+
+      when (text = @ss.scan(/[\s]*~[\s]*/))
+         action { [:TILDE, text] }
+
+      when (text = @ss.scan(/\:not\([\s]*/))
+         action { [:NOT, text] }
+
+      when (text = @ss.scan(/-?([0-9]+|[0-9]*\.[0-9]+)/))
+         action { [:NUMBER, text] }
+
+      when (text = @ss.scan(/[\s]*\/\/[\s]*/))
+         action { [:DOUBLESLASH, text] }
+
+      when (text = @ss.scan(/[\s]*\/[\s]*/))
+         action { [:SLASH, text] }
+
+      when (text = @ss.scan(/U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})?/))
+         action {[:UNICODE_RANGE, text] }
+
+      when (text = @ss.scan(/[\s]+/))
+         action { [:S, text] }
+
+      when (text = @ss.scan(/"([^\n\r\f"]|\n|\r\n|\r|\f|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])*"|'([^\n\r\f']|\n|\r\n|\r|\f|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])*'/))
+         action { [:STRING, text] }
+
+      when (text = @ss.scan(/./))
+         action { [text, text] }
+
+      else
+        text = @ss.string[@ss.pos .. -1]
+        raise  ScanError, "can not match: '" + text + "'"
+      end  # if
+
+    else
+      raise  ScanError, "undefined state: '" + state.to_s + "'"
+    end  # case state
+    token
+  end  # def _next_token
+
+end # class
+end
+end

+ 55 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/tokenizer.rex

@@ -0,0 +1,55 @@
+module Nokogiri
+module CSS
+class Tokenizer # :nodoc:
+
+macro
+  nl        \n|\r\n|\r|\f
+  w         [\s]*
+  nonascii  [^\0-\177]
+  num       -?([0-9]+|[0-9]*\.[0-9]+)
+  unicode   \\[0-9A-Fa-f]{1,6}(\r\n|[\s])?
+
+  escape    {unicode}|\\[^\n\r\f0-9A-Fa-f]
+  nmchar    [_A-Za-z0-9-]|{nonascii}|{escape}
+  nmstart   [_A-Za-z]|{nonascii}|{escape}
+  ident     [-@]?({nmstart})({nmchar})*
+  name      ({nmchar})+
+  string1   "([^\n\r\f"]|{nl}|{nonascii}|{escape})*"
+  string2   '([^\n\r\f']|{nl}|{nonascii}|{escape})*'
+  string    {string1}|{string2}
+
+rule
+
+# [:state]  pattern  [actions]
+
+            has\({w}         { [:HAS, text] }
+            {ident}\({w}     { [:FUNCTION, text] }
+            {ident}          { [:IDENT, text] }
+            \#{name}         { [:HASH, text] }
+            {w}~={w}         { [:INCLUDES, text] }
+            {w}\|={w}        { [:DASHMATCH, text] }
+            {w}\^={w}        { [:PREFIXMATCH, text] }
+            {w}\$={w}        { [:SUFFIXMATCH, text] }
+            {w}\*={w}        { [:SUBSTRINGMATCH, text] }
+            {w}!={w}         { [:NOT_EQUAL, text] }
+            {w}={w}          { [:EQUAL, text] }
+            {w}\)            { [:RPAREN, text] }
+            {w}\[{w}         { [:LSQUARE, text] }
+            {w}\]            { [:RSQUARE, text] }
+            {w}\+{w}         { [:PLUS, text] }
+            {w}>{w}          { [:GREATER, text] }
+            {w},{w}          { [:COMMA, text] }
+            {w}~{w}          { [:TILDE, text] }
+            \:not\({w}       { [:NOT, text] }
+            {num}            { [:NUMBER, text] }
+            {w}\/\/{w}       { [:DOUBLESLASH, text] }
+            {w}\/{w}         { [:SLASH, text] }
+            
+            U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})?  {[:UNICODE_RANGE, text] }
+            
+            [\s]+            { [:S, text] }
+            {string}         { [:STRING, text] }
+            .                { [text, text] }
+end
+end
+end

+ 171 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/css/xpath_visitor.rb

@@ -0,0 +1,171 @@
+module Nokogiri
+  module CSS
+    class XPathVisitor # :nodoc:
+      def visit_function node
+        #  note that nth-child and nth-last-child are preprocessed in css/node.rb.
+        msg = :"visit_function_#{node.value.first.gsub(/[(]/, '')}"
+        return self.send(msg, node) if self.respond_to?(msg)
+
+        case node.value.first
+        when /^text\(/
+          'child::text()'
+        when /^self\(/
+          "self::#{node.value[1]}"
+        when /^eq\(/
+          "position() = #{node.value[1]}"
+        when /^(nth|nth-of-type|nth-child)\(/
+          if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :AN_PLUS_B
+            an_plus_b(node.value[1])
+          else
+            "position() = #{node.value[1]}"
+          end
+        when /^(nth-last-child|nth-last-of-type)\(/
+          if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :AN_PLUS_B
+            an_plus_b(node.value[1], :last => true)
+          else
+            index = node.value[1].to_i - 1
+            index == 0 ? "position() = last()" : "position() = last() - #{index}"
+          end
+        when /^(first|first-of-type)\(/
+          "position() = 1"
+        when /^(last|last-of-type)\(/
+          "position() = last()"
+        when /^contains\(/
+          "contains(., #{node.value[1]})"
+        when /^gt\(/
+          "position() > #{node.value[1]}"
+        when /^only-child\(/
+          "last() = 1"
+        when /^comment\(/
+          "comment()"
+        when /^has\(/
+          node.value[1].accept(self)
+        else
+          args = ['.'] + node.value[1..-1]
+          "#{node.value.first}#{args.join(', ')})"
+        end
+      end
+
+      def visit_not node
+        child = node.value.first
+        if :ELEMENT_NAME == child.type
+          "not(self::#{child.accept(self)})"
+        else
+          "not(#{child.accept(self)})"
+        end
+      end
+
+      def visit_id node
+        node.value.first =~ /^#(.*)$/
+        "@id = '#{$1}'"
+      end
+
+      def visit_attribute_condition node
+         attribute = if (node.value.first.type == :FUNCTION) or (node.value.first.value.first =~ /::/)
+                       ''
+                     else
+                       '@'
+                     end
+        attribute += node.value.first.accept(self)
+
+        # Support non-standard css
+        attribute.gsub!(/^@@/, '@')
+
+        return attribute unless node.value.length == 3
+
+        value = node.value.last
+        value = "'#{value}'" if value !~ /^['"]/
+
+        case node.value[1]
+        when :equal
+          attribute + " = " + "#{value}"
+        when :not_equal
+          attribute + " != " + "#{value}"
+        when :substring_match
+          "contains(#{attribute}, #{value})"
+        when :prefix_match
+          "starts-with(#{attribute}, #{value})"
+        when :dash_match
+          "#{attribute} = #{value} or starts-with(#{attribute}, concat(#{value}, '-'))"
+        when :includes
+          "contains(concat(\" \", #{attribute}, \" \"),concat(\" \", #{value}, \" \"))"
+        when :suffix_match
+          "substring(#{attribute}, string-length(#{attribute}) - " +
+            "string-length(#{value}) + 1, string-length(#{value})) = #{value}"
+        else
+          attribute + " #{node.value[1]} " + "#{value}"
+        end
+      end
+
+      def visit_pseudo_class node
+        if node.value.first.is_a?(Nokogiri::CSS::Node) and node.value.first.type == :FUNCTION
+          node.value.first.accept(self)
+        else
+          msg = :"visit_pseudo_class_#{node.value.first.gsub(/[(]/, '')}"
+          return self.send(msg, node) if self.respond_to?(msg)
+
+          case node.value.first
+          when "first", "first-child" then "position() = 1"
+          when "last", "last-child" then "position() = last()"
+          when "first-of-type" then "position() = 1"
+          when "last-of-type" then "position() = last()"
+          when "only-of-type" then "last() = 1"
+          when "empty" then "not(node())"
+          when "parent" then "node()"
+          when "root" then "not(parent::*)"
+          else
+            node.value.first + "(.)"
+          end
+        end
+      end
+
+      def visit_class_condition node
+        "contains(concat(' ', @class, ' '), ' #{node.value.first} ')"
+      end
+
+      {
+        'combinator'                => ' and ',
+        'direct_adjacent_selector'  => "/following-sibling::*[1]/self::",
+        'preceding_selector'        => "/following-sibling::",
+        'descendant_selector'       => '//',
+        'child_selector'            => '/',
+      }.each do |k,v|
+        class_eval %{
+          def visit_#{k} node
+            "\#{node.value.first.accept(self)}#{v}\#{node.value.last.accept(self)}"
+          end
+        }
+      end
+
+      def visit_conditional_selector node
+        node.value.first.accept(self) + '[' +
+        node.value.last.accept(self) + ']'
+      end
+
+      def visit_element_name node
+        node.value.first
+      end
+
+      def accept node
+        node.accept(self)
+      end
+
+    private
+      def an_plus_b node, options={}
+        raise ArgumentError, "expected an+b node to contain 4 tokens, but is #{node.value.inspect}" unless node.value.size == 4
+
+        a = node.value[0].to_i
+        b = node.value[3].to_i
+        position = options[:last] ? "(last()-position()+1)" : "position()"
+
+        if (b == 0)
+          return "(#{position} mod #{a}) = 0"
+        else
+          compare = (a < 0) ? "<=" : ">="
+          return "(#{position} #{compare} #{b}) and (((#{position}-#{b}) mod #{a.abs}) = 0)"
+        end
+      end
+
+    end
+  end
+end

+ 35 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/decorators/slop.rb

@@ -0,0 +1,35 @@
+module Nokogiri
+  module Decorators
+    ###
+    # The Slop decorator implements method missing such that a methods may be
+    # used instead of XPath or CSS.  See Nokogiri.Slop
+    module Slop
+      ###
+      # look for node with +name+.  See Nokogiri.Slop
+      def method_missing name, *args, &block
+        prefix = implied_xpath_context
+
+        if args.empty?
+          list = xpath("#{prefix}#{name.to_s.sub(/^_/, '')}")
+        elsif args.first.is_a? Hash
+          hash = args.first
+          if hash[:css]
+            list = css("#{name}#{hash[:css]}")
+          elsif hash[:xpath]
+            conds = Array(hash[:xpath]).join(' and ')
+            list = xpath("#{prefix}#{name}[#{conds}]")
+          end
+        else
+          CSS::Parser.without_cache do
+            list = xpath(
+              *CSS.xpath_for("#{name}#{args.first}", :prefix => prefix)
+            )
+          end
+        end
+
+        super if list.empty?
+        list.length == 1 ? list.first : list
+      end
+    end
+  end
+end

+ 37 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html.rb

@@ -0,0 +1,37 @@
+require 'nokogiri/html/entity_lookup'
+require 'nokogiri/html/document'
+require 'nokogiri/html/document_fragment'
+require 'nokogiri/html/sax/parser_context'
+require 'nokogiri/html/sax/parser'
+require 'nokogiri/html/sax/push_parser'
+require 'nokogiri/html/element_description'
+require 'nokogiri/html/element_description_defaults'
+
+module Nokogiri
+  class << self
+    ###
+    # Parse HTML.  Convenience method for Nokogiri::HTML::Document.parse
+    def HTML thing, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_HTML, &block
+      Nokogiri::HTML::Document.parse(thing, url, encoding, options, &block)
+    end
+  end
+
+  module HTML
+    class << self
+      ###
+      # Parse HTML.  Convenience method for Nokogiri::HTML::Document.parse
+      def parse thing, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_HTML, &block
+        Document.parse(thing, url, encoding, options, &block)
+      end
+
+      ####
+      # Parse a fragment from +string+ in to a NodeSet.
+      def fragment string, encoding = nil
+        HTML::DocumentFragment.parse string, encoding
+      end
+    end
+
+    # Instance of Nokogiri::HTML::EntityLookup
+    NamedCharacters = EntityLookup.new
+  end
+end

+ 35 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/builder.rb

@@ -0,0 +1,35 @@
+module Nokogiri
+  module HTML
+    ###
+    # Nokogiri HTML builder is used for building HTML documents.  It is very
+    # similar to the Nokogiri::XML::Builder.  In fact, you should go read the
+    # documentation for Nokogiri::XML::Builder before reading this
+    # documentation.
+    #
+    # == Synopsis:
+    #
+    # Create an HTML document with a body that has an onload attribute, and a
+    # span tag with a class of "bold" that has content of "Hello world".
+    #
+    #   builder = Nokogiri::HTML::Builder.new do |doc|
+    #     doc.html {
+    #       doc.body(:onload => 'some_func();') {
+    #         doc.span.bold {
+    #           doc.text "Hello world"
+    #         }
+    #       }
+    #     }
+    #   end
+    #   puts builder.to_html
+    #
+    # The HTML builder inherits from the XML builder, so make sure to read the
+    # Nokogiri::XML::Builder documentation.
+    class Builder < Nokogiri::XML::Builder
+      ###
+      # Convert the builder to HTML
+      def to_html
+        @doc.to_html
+      end
+    end
+  end
+end

+ 253 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/document.rb

@@ -0,0 +1,253 @@
+module Nokogiri
+  module HTML
+    class Document < Nokogiri::XML::Document
+      ###
+      # Get the meta tag encoding for this document.  If there is no meta tag,
+      # then nil is returned.
+      def meta_encoding
+        meta = meta_content_type and
+          /charset\s*=\s*([\w-]+)/i.match(meta['content'])[1]
+      end
+
+      ###
+      # Set the meta tag encoding for this document.  If there is no meta
+      # content tag, the encoding is not set.
+      def meta_encoding= encoding
+        meta = meta_content_type and
+          meta['content'] = "text/html; charset=%s" % encoding
+      end
+
+      def meta_content_type
+        css('meta[@http-equiv]').find { |node|
+          node['http-equiv'] =~ /\AContent-Type\z/i and
+            !node['content'].nil? and
+            !node['content'].empty?
+        }
+      end
+      private :meta_content_type
+
+      ###
+      # Get the title string of this document.  Return nil if there is
+      # no title tag.
+      def title
+        title = at('title') and title.inner_text
+      end
+
+      ###
+      # Set the title string of this document.  If there is no head
+      # element, the title is not set.
+      def title=(text)
+        unless title = at('title')
+          head = at('head') or return nil
+          title = Nokogiri::XML::Node.new('title', self)
+          head << title
+        end
+        title.children = XML::Text.new(text, self)
+      end
+
+      ####
+      # Serialize Node using +options+.  Save options can also be set using a
+      # block. See SaveOptions.
+      #
+      # These two statements are equivalent:
+      #
+      #  node.serialize(:encoding => 'UTF-8', :save_with => FORMAT | AS_XML)
+      #
+      # or
+      #
+      #   node.serialize(:encoding => 'UTF-8') do |config|
+      #     config.format.as_xml
+      #   end
+      #
+      def serialize options = {}
+        options[:save_with] ||= XML::Node::SaveOptions::DEFAULT_HTML
+        super
+      end
+
+      ####
+      # Create a Nokogiri::XML::DocumentFragment from +tags+
+      def fragment tags = nil
+        DocumentFragment.new(self, tags, self.root)
+      end
+
+      class << self
+        ###
+        # Parse HTML.  +string_or_io+ may be a String, or any object that
+        # responds to _read_ and _close_ such as an IO, or StringIO.
+        # +url+ is resource where this document is located.  +encoding+ is the
+        # encoding that should be used when processing the document. +options+
+        # is a number that sets options in the parser, such as
+        # Nokogiri::XML::ParseOptions::RECOVER.  See the constants in
+        # Nokogiri::XML::ParseOptions.
+        def parse string_or_io, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_HTML
+
+          options = Nokogiri::XML::ParseOptions.new(options) if Fixnum === options
+          # Give the options to the user
+          yield options if block_given?
+
+          if string_or_io.respond_to?(:encoding)
+            unless string_or_io.encoding.name == "ASCII-8BIT"
+              encoding ||= string_or_io.encoding.name
+            end
+          end
+
+          if string_or_io.respond_to?(:read)
+            url ||= string_or_io.respond_to?(:path) ? string_or_io.path : nil
+            if !encoding
+              # Libxml2's parser has poor support for encoding
+              # detection.  First, it does not recognize the HTML5
+              # style meta charset declaration.  Secondly, even if it
+              # successfully detects an encoding hint, it does not
+              # re-decode or re-parse the preceding part which may be
+              # garbled.
+              #
+              # EncodingReader aims to perform advanced encoding
+              # detection beyond what Libxml2 does, and to emulate
+              # rewinding of a stream and make Libxml2 redo parsing
+              # from the start when an encoding hint is found.
+              string_or_io = EncodingReader.new(string_or_io)
+              begin
+                return read_io(string_or_io, url, encoding, options.to_i)
+              rescue EncodingFound => e
+                encoding = e.found_encoding
+              end
+            end
+            return read_io(string_or_io, url, encoding, options.to_i)
+          end
+
+          # read_memory pukes on empty docs
+          return new if string_or_io.nil? or string_or_io.empty?
+
+          encoding ||= EncodingReader.detect_encoding(string_or_io)
+
+          read_memory(string_or_io, url, encoding, options.to_i)
+        end
+      end
+
+      class EncodingFound < StandardError # :nodoc:
+        attr_reader :found_encoding
+
+        def initialize(encoding)
+          @found_encoding = encoding
+          super("encoding found: %s" % encoding)
+        end
+      end
+
+      class EncodingReader # :nodoc:
+        class SAXHandler < Nokogiri::XML::SAX::Document # :nodoc:
+          attr_reader :encoding
+          
+          def initialize
+            @encoding = nil
+            super()
+          end
+    
+          def start_element(name, attrs = [])
+            return unless name == 'meta'
+            attr = Hash[attrs]
+            charset = attr['charset'] and
+              @encoding = charset
+            http_equiv = attr['http-equiv'] and
+              http_equiv.match(/\AContent-Type\z/i) and
+              content = attr['content'] and
+              m = content.match(/;\s*charset\s*=\s*([\w-]+)/) and
+              @encoding = m[1]
+          end
+        end
+        
+        class JumpSAXHandler < SAXHandler
+          def initialize(jumptag)
+            @jumptag = jumptag
+            super()
+          end
+
+          def start_element(name, attrs = [])
+            super
+            throw @jumptag, @encoding if @encoding
+            throw @jumptag, nil if name =~ /\A(?:div|h1|img|p|br)\z/
+          end
+        end
+
+        def self.detect_encoding(chunk)
+          if Nokogiri.jruby? && EncodingReader.is_jruby_without_fix?
+            return EncodingReader.detect_encoding_for_jruby_without_fix(chunk)
+          end
+          m = chunk.match(/\A(<\?xml[ \t\r\n]+[^>]*>)/) and
+            return Nokogiri.XML(m[1]).encoding
+
+          if Nokogiri.jruby?
+            m = chunk.match(/(<meta\s)(.*)(charset\s*=\s*([\w-]+))(.*)/i) and
+              return m[4]
+            catch(:encoding_found) {
+              Nokogiri::HTML::SAX::Parser.new(JumpSAXHandler.new(:encoding_found.to_s)).parse(chunk)
+              nil
+            }
+          else
+            handler = SAXHandler.new
+            parser = Nokogiri::HTML::SAX::PushParser.new(handler)
+            parser << chunk rescue Nokogiri::SyntaxError
+            handler.encoding
+          end
+        end
+
+        def self.is_jruby_without_fix?
+          JRUBY_VERSION.split('.').join.to_i < 165
+        end
+
+        def self.detect_encoding_for_jruby_without_fix(chunk)
+          m = chunk.match(/\A(<\?xml[ \t\r\n]+[^>]*>)/) and
+            return Nokogiri.XML(m[1]).encoding
+
+          m = chunk.match(/(<meta\s)(.*)(charset\s*=\s*([\w-]+))(.*)/i) and
+            return m[4]
+
+          catch(:encoding_found) {
+            Nokogiri::HTML::SAX::Parser.new(JumpSAXHandler.new(:encoding_found.to_s)).parse(chunk)
+            nil
+          }
+        rescue Nokogiri::SyntaxError, RuntimeError
+          # Ignore parser errors that nokogiri may raise
+          nil
+        end
+
+        def initialize(io)
+          @io = io
+          @firstchunk = nil
+          @encoding_found = nil
+        end
+
+        # This method is used by the C extension so that
+        # Nokogiri::HTML::Document#read_io() does not leak memory when
+        # EncodingFound is raised.
+        attr_reader :encoding_found
+
+        def read(len)
+          # no support for a call without len
+
+          if !@firstchunk
+            @firstchunk = @io.read(len) or return nil
+
+            # This implementation expects that the first call from
+            # htmlReadIO() is made with a length long enough (~1KB) to
+            # achieve advanced encoding detection.
+            if encoding = EncodingReader.detect_encoding(@firstchunk)
+              # The first chunk is stored for the next read in retry.
+              raise @encoding_found = EncodingFound.new(encoding)
+            end
+          end
+          @encoding_found = nil
+
+          ret = @firstchunk.slice!(0, len)
+          if (len -= ret.length) > 0
+            rest = @io.read(len) and ret << rest
+          end
+          if ret.empty?
+            nil
+          else
+            ret
+          end
+        end
+      end
+    end
+  end
+end

+ 41 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/document_fragment.rb

@@ -0,0 +1,41 @@
+module Nokogiri
+  module HTML
+    class DocumentFragment < Nokogiri::XML::DocumentFragment
+      attr_accessor :errors
+
+      ####
+      # Create a Nokogiri::XML::DocumentFragment from +tags+, using +encoding+
+      def self.parse tags, encoding = nil
+        doc = HTML::Document.new
+
+        encoding ||= tags.respond_to?(:encoding) ? tags.encoding.name : 'UTF-8'
+        doc.encoding = encoding
+
+        new(doc, tags)
+      end
+
+      def initialize document, tags = nil, ctx = nil
+        return self unless tags
+
+        if ctx
+          preexisting_errors = document.errors.dup
+          node_set = ctx.parse("<div>#{tags}</div>")
+          node_set.first.children.each { |child| child.parent = self } unless node_set.empty?
+          self.errors = document.errors - preexisting_errors
+        else
+          # This is a horrible hack, but I don't care
+          if tags.strip =~ /^<body/i
+            path = "/html/body"
+          else
+            path = "/html/body/node()"
+          end
+
+          temp_doc = HTML::Document.parse "<html><body>#{tags}", nil, document.encoding
+          temp_doc.xpath(path).each { |child| child.parent = self }
+          self.errors = temp_doc.errors
+        end
+        children
+      end
+    end
+  end
+end

+ 23 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/element_description.rb

@@ -0,0 +1,23 @@
+module Nokogiri
+  module HTML
+    class ElementDescription
+      ###
+      # Is this element a block element?
+      def block?
+        !inline?
+      end
+
+      ###
+      # Convert this description to a string
+      def to_s
+        "#{name}: #{description}"
+      end
+
+      ###
+      # Inspection information
+      def inspect
+        "#<#{self.class.name}: #{name} #{description}>"
+      end
+    end
+  end
+end

+ 671 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/element_description_defaults.rb

@@ -0,0 +1,671 @@
+module Nokogiri
+  module HTML
+    class ElementDescription
+
+      # Methods are defined protected by method_defined? because at
+      # this point the C-library or Java library is alraedy loaded,
+      # and we don't want to clobber any methods that have been
+      # defined there.
+
+      Desc = Struct.new("HTMLElementDescription", :name,
+                        :startTag, :endTag, :saveEndTag,
+                        :empty, :depr, :dtd, :isinline,
+                        :desc,
+                        :subelts, :defaultsubelt,
+                        :attrs_opt, :attrs_depr, :attrs_req)
+
+      # This is filled in down below.
+      DefaultDescriptions = Hash.new()
+
+      def default_desc
+        DefaultDescriptions[name.downcase]
+      end
+      private :default_desc
+
+      unless method_defined? :implied_start_tag?
+        def implied_start_tag?
+          d = default_desc
+          d ? d.startTag : nil
+        end
+      end
+
+      unless method_defined? :implied_end_tag?
+        def implied_end_tag?
+          d = default_desc
+          d ? d.endTag : nil
+        end
+      end
+
+      unless method_defined? :save_end_tag?
+        def save_end_tag?
+          d = default_desc
+          d ? d.saveEndTag : nil
+        end
+      end
+
+      unless method_defined? :deprecated?
+        def deprecated?
+          d = default_desc
+          d ? d.depr : nil
+        end
+      end
+
+      unless method_defined? :description
+        def description
+          d = default_desc
+          d ? d.desc : nil
+        end
+      end
+
+      unless method_defined? :default_sub_element
+        def default_sub_element
+          d = default_desc
+          d ? d.defaultsubelt : nil
+        end
+      end
+
+      unless method_defined? :optional_attributes
+        def optional_attributes
+          d = default_desc
+          d ? d.attrs_opt : []
+        end
+      end
+
+      unless method_defined? :deprecated_attributes
+        def deprecated_attributes
+          d = default_desc
+          d ? d.attrs_depr : []
+        end
+      end
+
+      unless method_defined? :required_attributes
+        def required_attributes
+          d = default_desc
+          d ? d.attrs_req : []
+        end
+      end
+
+      ###
+      # Default Element Descriptions (HTML 4.0) copied from
+      # libxml2/HTMLparser.c and libxml2/include/libxml/HTMLparser.h
+      #
+      # The copyright notice for those files and the following list of
+      # element and attribute descriptions is reproduced here:
+      #
+      # Except where otherwise noted in the source code (e.g. the
+      # files hash.c, list.c and the trio files, which are covered by
+      # a similar licence but with different Copyright notices) all
+      # the files are:
+      #
+      #  Copyright (C) 1998-2003 Daniel Veillard.  All Rights Reserved.
+      #
+      # 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 fur- nished 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, FIT- NESS FOR A PARTICULAR
+      # PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE DANIEL
+      # VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+      # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+      # FROM, OUT OF OR IN CON- NECTION WITH THE SOFTWARE OR THE USE
+      # OR OTHER DEALINGS IN THE SOFTWARE.
+
+      # Except as contained in this notice, the name of Daniel
+      # Veillard shall not be used in advertising or otherwise to
+      # promote the sale, use or other deal- ings in this Software
+      # without prior written authorization from him.
+
+      # Attributes defined and categorized
+      FONTSTYLE = ["tt", "i", "b", "u", "s", "strike", "big", "small"]
+      PHRASE = ['em', 'strong', 'dfn', 'code', 'samp',
+                'kbd', 'var', 'cite', 'abbr', 'acronym']
+      SPECIAL = ['a', 'img', 'applet', 'embed', 'object', 'font','basefont',
+                 'br', 'script', 'map', 'q', 'sub', 'sup', 'span', 'bdo',
+                 'iframe']
+      PCDATA = []
+      HEADING = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']
+      LIST = ['ul', 'ol', 'dir', 'menu']
+      FORMCTRL = ['input', 'select', 'textarea', 'label', 'button']
+      BLOCK = [HEADING, LIST, 'pre', 'p', 'dl', 'div', 'center', 'noscript',
+               'noframes', 'blockquote', 'form', 'isindex', 'hr', 'table',
+               'fieldset', 'address']
+      INLINE = [PCDATA, FONTSTYLE, PHRASE, SPECIAL, FORMCTRL]
+      FLOW = [BLOCK, INLINE]
+      MODIFIER = []
+      EMPTY = []
+
+      HTML_FLOW = FLOW
+      HTML_INLINE = INLINE
+      HTML_PCDATA = PCDATA
+      HTML_CDATA = HTML_PCDATA
+
+      COREATTRS = ['id', 'class', 'style', 'title']
+      I18N = ['lang', 'dir']
+      EVENTS = ['onclick', 'ondblclick', 'onmousedown', 'onmouseup',
+                'onmouseover', 'onmouseout', 'onkeypress', 'onkeydown',
+                'onkeyup']
+      ATTRS = [COREATTRS, I18N,EVENTS]
+      CELLHALIGN = ['align', 'char', 'charoff']
+      CELLVALIGN = ['valign']
+
+      HTML_ATTRS = ATTRS
+      CORE_I18N_ATTRS = [COREATTRS, I18N]
+      CORE_ATTRS = COREATTRS
+      I18N_ATTRS = I18N
+
+
+      A_ATTRS = [ATTRS, 'charset', 'type', 'name',
+                 'href', 'hreflang', 'rel', 'rev', 'accesskey', 'shape',
+                 'coords', 'tabindex', 'onfocus', 'onblur']
+      TARGET_ATTR = ['target']
+      ROWS_COLS_ATTR = ['rows', 'cols']
+      ALT_ATTR = ['alt']
+      SRC_ALT_ATTRS = ['src', 'alt']
+      HREF_ATTRS = ['href']
+      CLEAR_ATTRS = ['clear']
+      INLINE_P = [INLINE, 'p']
+
+      FLOW_PARAM = [FLOW, 'param']
+      APPLET_ATTRS = [COREATTRS , 'codebase',
+                      'archive', 'alt', 'name', 'height', 'width', 'align',
+                      'hspace', 'vspace']
+      AREA_ATTRS = ['shape', 'coords', 'href', 'nohref',
+                    'tabindex', 'accesskey', 'onfocus', 'onblur']
+      BASEFONT_ATTRS = ['id', 'size', 'color', 'face']
+      QUOTE_ATTRS = [ATTRS, 'cite']
+      BODY_CONTENTS = [FLOW, 'ins', 'del']
+      BODY_ATTRS = [ATTRS, 'onload', 'onunload']
+      BODY_DEPR = ['background', 'bgcolor', 'text',
+                   'link', 'vlink', 'alink']
+      BUTTON_ATTRS = [ATTRS, 'name', 'value', 'type',
+                      'disabled', 'tabindex', 'accesskey', 'onfocus', 'onblur']
+
+
+      COL_ATTRS = [ATTRS, 'span', 'width', CELLHALIGN, CELLVALIGN]
+      COL_ELT = ['col']
+      EDIT_ATTRS = [ATTRS, 'datetime', 'cite']
+      COMPACT_ATTRS = [ATTRS, 'compact']
+      DL_CONTENTS = ['dt', 'dd']
+      COMPACT_ATTR = ['compact']
+      LABEL_ATTR = ['label']
+      FIELDSET_CONTENTS = [FLOW, 'legend' ]
+      FONT_ATTRS = [COREATTRS, I18N, 'size', 'color', 'face' ]
+      FORM_CONTENTS = [HEADING, LIST, INLINE, 'pre', 'p', 'div', 'center',
+                       'noscript', 'noframes', 'blockquote', 'isindex', 'hr',
+                       'table', 'fieldset', 'address']
+      FORM_ATTRS = [ATTRS, 'method', 'enctype', 'accept', 'name', 'onsubmit',
+                    'onreset', 'accept-charset']
+      FRAME_ATTRS = [COREATTRS, 'longdesc', 'name', 'src', 'frameborder',
+                     'marginwidth', 'marginheight', 'noresize', 'scrolling' ]
+      FRAMESET_ATTRS = [COREATTRS, 'rows', 'cols', 'onload', 'onunload']
+      FRAMESET_CONTENTS = ['frameset', 'frame', 'noframes']
+      HEAD_ATTRS = [I18N, 'profile']
+      HEAD_CONTENTS = ['title', 'isindex', 'base', 'script', 'style', 'meta',
+                       'link', 'object']
+      HR_DEPR = ['align', 'noshade', 'size', 'width']
+      VERSION_ATTR = ['version']
+      HTML_CONTENT = ['head', 'body', 'frameset']
+      IFRAME_ATTRS = [COREATTRS, 'longdesc', 'name', 'src', 'frameborder',
+                      'marginwidth', 'marginheight', 'scrolling', 'align',
+                      'height', 'width']
+      IMG_ATTRS = [ATTRS, 'longdesc', 'name', 'height', 'width', 'usemap',
+                   'ismap']
+      EMBED_ATTRS = [COREATTRS, 'align', 'alt', 'border', 'code', 'codebase',
+                     'frameborder', 'height', 'hidden', 'hspace', 'name',
+                     'palette', 'pluginspace', 'pluginurl', 'src', 'type',
+                     'units', 'vspace', 'width']
+      INPUT_ATTRS = [ATTRS, 'type', 'name', 'value', 'checked', 'disabled',
+                     'readonly', 'size', 'maxlength', 'src', 'alt', 'usemap',
+                     'ismap', 'tabindex', 'accesskey', 'onfocus', 'onblur',
+                     'onselect', 'onchange', 'accept']
+      PROMPT_ATTRS = [COREATTRS, I18N, 'prompt']
+      LABEL_ATTRS = [ATTRS, 'for', 'accesskey', 'onfocus', 'onblur']
+      LEGEND_ATTRS = [ATTRS, 'accesskey']
+      ALIGN_ATTR = ['align']
+      LINK_ATTRS = [ATTRS, 'charset', 'href', 'hreflang', 'type', 'rel', 'rev',
+                    'media']
+      MAP_CONTENTS = [BLOCK, 'area']
+      NAME_ATTR = ['name']
+      ACTION_ATTR = ['action']
+      BLOCKLI_ELT = [BLOCK, 'li']
+      META_ATTRS = [I18N, 'http-equiv', 'name', 'scheme']
+      CONTENT_ATTR = ['content']
+      TYPE_ATTR = ['type']
+      NOFRAMES_CONTENT = ['body', FLOW, MODIFIER]
+      OBJECT_CONTENTS = [FLOW, 'param']
+      OBJECT_ATTRS = [ATTRS, 'declare', 'classid', 'codebase', 'data', 'type',
+                      'codetype', 'archive', 'standby', 'height', 'width',
+                      'usemap', 'name', 'tabindex']
+      OBJECT_DEPR = ['align', 'border', 'hspace', 'vspace']
+      OL_ATTRS = ['type', 'compact', 'start']
+      OPTION_ELT = ['option']
+      OPTGROUP_ATTRS = [ATTRS, 'disabled']
+      OPTION_ATTRS = [ATTRS, 'disabled', 'label', 'selected', 'value']
+      PARAM_ATTRS = ['id', 'value', 'valuetype', 'type']
+      WIDTH_ATTR = ['width']
+      PRE_CONTENT = [PHRASE, 'tt', 'i', 'b', 'u', 's', 'strike', 'a', 'br',
+                     'script', 'map', 'q', 'span', 'bdo', 'iframe']
+      SCRIPT_ATTRS = ['charset', 'src', 'defer', 'event', 'for']
+      LANGUAGE_ATTR = ['language']
+      SELECT_CONTENT = ['optgroup', 'option']
+      SELECT_ATTRS = [ATTRS, 'name', 'size', 'multiple', 'disabled', 'tabindex',
+                      'onfocus', 'onblur', 'onchange']
+      STYLE_ATTRS = [I18N, 'media', 'title']
+      TABLE_ATTRS = [ATTRS, 'summary', 'width', 'border', 'frame', 'rules',
+                     'cellspacing', 'cellpadding', 'datapagesize']
+      TABLE_DEPR = ['align', 'bgcolor']
+      TABLE_CONTENTS = ['caption', 'col', 'colgroup', 'thead', 'tfoot', 'tbody',
+                        'tr']
+      TR_ELT = ['tr']
+      TALIGN_ATTRS = [ATTRS, CELLHALIGN, CELLVALIGN]
+      TH_TD_DEPR = ['nowrap', 'bgcolor', 'width', 'height']
+      TH_TD_ATTR = [ATTRS, 'abbr', 'axis', 'headers', 'scope', 'rowspan',
+                    'colspan', CELLHALIGN, CELLVALIGN]
+      TEXTAREA_ATTRS = [ATTRS, 'name', 'disabled', 'readonly', 'tabindex',
+                        'accesskey', 'onfocus', 'onblur', 'onselect',
+                        'onchange']
+      TR_CONTENTS = ['th', 'td']
+      BGCOLOR_ATTR = ['bgcolor']
+      LI_ELT = ['li']
+      UL_DEPR = ['type', 'compact']
+      DIR_ATTR = ['dir']
+
+      [
+       ['a', false, false, false, false, false, :any, true,
+        'anchor ',
+        HTML_INLINE, nil, A_ATTRS, TARGET_ATTR, []
+       ],
+       ['abbr', false, false, false, false, false, :any, true,
+        'abbreviated form',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['acronym', false, false, false, false, false, :any, true, '',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['address', false, false, false, false, false, :any, false,
+        'information on author',
+        INLINE_P , nil, HTML_ATTRS, [], []
+       ],
+       ['applet', false, false, false, false, true, :loose, true,
+        'java applet ',
+        FLOW_PARAM, nil, [], APPLET_ATTRS, []
+       ],
+       ['area', false, true, true, true, false, :any, false,
+        'client-side image map area ',
+        EMPTY, nil, AREA_ATTRS, TARGET_ATTR, ALT_ATTR
+       ],
+       ['b', false, true, false, false, false, :any, true,
+        'bold text style',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['base', false, true, true, true, false, :any, false,
+        'document base uri ',
+        EMPTY, nil, [], TARGET_ATTR, HREF_ATTRS
+       ],
+       ['basefont', false, true, true, true, true, :loose, true,
+        'base font size ',
+        EMPTY, nil, [], BASEFONT_ATTRS, []
+       ],
+       ['bdo', false, false, false, false, false, :any, true,
+        'i18n bidi over-ride ',
+        HTML_INLINE, nil, CORE_I18N_ATTRS, [], DIR_ATTR
+       ],
+       ['big', false, true, false, false, false, :any, true,
+        'large text style',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['blockquote', false, false, false, false, false, :any, false,
+        'long quotation ',
+        HTML_FLOW, nil, QUOTE_ATTRS, [], []
+       ],
+       ['body', true, true, false, false, false, :any, false,
+        'document body ',
+        BODY_CONTENTS, 'div', BODY_ATTRS, BODY_DEPR, []
+       ],
+       ['br', false, true, true, true, false, :any, true,
+        'forced line break ',
+        EMPTY, nil, CORE_ATTRS, CLEAR_ATTRS, []
+       ],
+       ['button', false, false, false, false, false, :any, true,
+        'push button ',
+        [HTML_FLOW, MODIFIER], nil, BUTTON_ATTRS, [], []
+       ],
+       ['caption', false, false, false, false, false, :any, false,
+        'table caption ',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['center', false, true, false, false, true, :loose, false,
+        'shorthand for div align=center ',
+        HTML_FLOW, nil, [], HTML_ATTRS, []
+       ],
+       ['cite', false, false, false, false, false, :any, true, 'citation',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['code', false, false, false, false, false, :any, true,
+        'computer code fragment',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['col', false, true, true, true, false, :any, false, 'table column ',
+        EMPTY, nil, COL_ATTRS, [], []
+       ],
+       ['colgroup', false, true, false, false, false, :any, false,
+        'table column group ',
+        COL_ELT, 'col', COL_ATTRS, [], []
+       ],
+       ['dd', false, true, false, false, false, :any, false,
+        'definition description ',
+        HTML_FLOW, nil, HTML_ATTRS, [], []
+       ],
+       ['del', false, false, false, false, false, :any, true,
+        'deleted text ',
+        HTML_FLOW, nil, EDIT_ATTRS, [], []
+       ],
+       ['dfn', false, false, false, false, false, :any, true,
+        'instance definition',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['dir', false, false, false, false, true, :loose, false,
+        'directory list',
+        BLOCKLI_ELT, 'li', [], COMPACT_ATTRS, []
+       ],
+       ['div', false, false, false, false, false, :any, false,
+        'generic language/style container',
+        HTML_FLOW, nil, HTML_ATTRS, ALIGN_ATTR, []
+       ],
+       ['dl', false, false, false, false, false, :any, false,
+        'definition list ',
+        DL_CONTENTS, 'dd', HTML_ATTRS, COMPACT_ATTR, []
+       ],
+       ['dt', false, true, false, false, false, :any, false,
+        'definition term ',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['em', false, true, false, false, false, :any, true,
+        'emphasis',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['embed', false, true, false, false, true, :loose, true,
+        'generic embedded object ',
+        EMPTY, nil, EMBED_ATTRS, [], []
+       ],
+       ['fieldset', false, false, false, false, false, :any, false,
+        'form control group ',
+        FIELDSET_CONTENTS, nil, HTML_ATTRS, [], []
+       ],
+       ['font', false, true, false, false, true, :loose, true,
+        'local change to font ',
+        HTML_INLINE, nil, [], FONT_ATTRS, []
+       ],
+       ['form', false, false, false, false, false, :any, false,
+        'interactive form ',
+        FORM_CONTENTS, 'fieldset', FORM_ATTRS, TARGET_ATTR, ACTION_ATTR
+       ],
+       ['frame', false, true, true, true, false, :frameset, false,
+        'subwindow ',
+        EMPTY, nil, [], FRAME_ATTRS, []
+       ],
+       ['frameset', false, false, false, false, false, :frameset, false,
+        'window subdivision',
+        FRAMESET_CONTENTS, 'noframes', [], FRAMESET_ATTRS, []
+       ],
+       ['htrue', false, false, false, false, false, :any, false,
+        'heading ',
+        HTML_INLINE, nil, HTML_ATTRS, ALIGN_ATTR, []
+       ],
+       ['htrue', false, false, false, false, false, :any, false,
+        'heading ',
+        HTML_INLINE, nil, HTML_ATTRS, ALIGN_ATTR, []
+       ],
+       ['htrue', false, false, false, false, false, :any, false,
+        'heading ',
+        HTML_INLINE, nil, HTML_ATTRS, ALIGN_ATTR, []
+       ],
+       ['h4', false, false, false, false, false, :any, false,
+        'heading ',
+        HTML_INLINE, nil, HTML_ATTRS, ALIGN_ATTR, []
+       ],
+       ['h5', false, false, false, false, false, :any, false,
+        'heading ',
+        HTML_INLINE, nil, HTML_ATTRS, ALIGN_ATTR, []
+       ],
+       ['h6', false, false, false, false, false, :any, false,
+        'heading ',
+        HTML_INLINE, nil, HTML_ATTRS, ALIGN_ATTR, []
+       ],
+       ['head', true, true, false, false, false, :any, false,
+        'document head ',
+        HEAD_CONTENTS, nil, HEAD_ATTRS, [], []
+       ],
+       ['hr', false, true, true, true, false, :any, false,
+        'horizontal rule ',
+        EMPTY, nil, HTML_ATTRS, HR_DEPR, []
+       ],
+       ['html', true, true, false, false, false, :any, false,
+        'document root element ',
+        HTML_CONTENT, nil, I18N_ATTRS, VERSION_ATTR, []
+       ],
+       ['i', false, true, false, false, false, :any, true,
+        'italic text style',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['iframe', false, false, false, false, false, :any, true,
+        'inline subwindow ',
+        HTML_FLOW, nil, [], IFRAME_ATTRS, []
+       ],
+       ['img', false, true, true, true, false, :any, true,
+        'embedded image ',
+        EMPTY, nil, IMG_ATTRS, ALIGN_ATTR, SRC_ALT_ATTRS
+       ],
+       ['input', false, true, true, true, false, :any, true,
+        'form control ',
+        EMPTY, nil, INPUT_ATTRS, ALIGN_ATTR, []
+       ],
+       ['ins', false, false, false, false, false, :any, true,
+        'inserted text',
+        HTML_FLOW, nil, EDIT_ATTRS, [], []
+       ],
+       ['isindex', false, true, true, true, true, :loose, false,
+        'single line prompt ',
+        EMPTY, nil, [], PROMPT_ATTRS, []
+       ],
+       ['kbd', false, false, false, false, false, :any, true,
+        'text to be entered by the user',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['label', false, false, false, false, false, :any, true,
+        'form field label text ',
+        [HTML_INLINE, MODIFIER], nil, LABEL_ATTRS, [], []
+       ],
+       ['legend', false, false, false, false, false, :any, false,
+        'fieldset legend ',
+        HTML_INLINE, nil, LEGEND_ATTRS, ALIGN_ATTR, []
+       ],
+       ['li', false, true, true, false, false, :any, false,
+        'list item ',
+        HTML_FLOW, nil, HTML_ATTRS, [], []
+       ],
+       ['link', false, true, true, true, false, :any, false,
+        'a media-independent link ',
+        EMPTY, nil, LINK_ATTRS, TARGET_ATTR, []
+       ],
+       ['map', false, false, false, false, false, :any, true,
+        'client-side image map ',
+        MAP_CONTENTS, nil, HTML_ATTRS, [], NAME_ATTR
+       ],
+       ['menu', false, false, false, false, true, :loose, false,
+        'menu list ',
+        BLOCKLI_ELT, nil, [], COMPACT_ATTRS, []
+       ],
+       ['meta', false, true, true, true, false, :any, false,
+        'generic metainformation ',
+        EMPTY, nil, META_ATTRS, [], CONTENT_ATTR
+       ],
+       ['noframes', false, false, false, false, false, :frameset, false,
+        'alternate content container for non frame-based rendering ',
+        NOFRAMES_CONTENT, 'body', HTML_ATTRS, [], []
+       ],
+       ['noscript', false, false, false, false, false, :any, false,
+        'alternate content container for non script-based rendering ',
+        HTML_FLOW, 'div', HTML_ATTRS, [], []
+       ],
+       ['object', false, false, false, false, false, :any, true,
+        'generic embedded object ',
+        OBJECT_CONTENTS, 'div', OBJECT_ATTRS, OBJECT_DEPR, []
+       ],
+       ['ol', false, false, false, false, false, :any, false,
+        'ordered list ',
+        LI_ELT, 'li', HTML_ATTRS, OL_ATTRS, []
+       ],
+       ['optgroup', false, false, false, false, false, :any, false,
+        'option group ',
+        OPTION_ELT, 'option', OPTGROUP_ATTRS, [], LABEL_ATTR
+       ],
+       ['option', false, true, false, false, false, :any, false,
+        'selectable choice ',
+        HTML_PCDATA, nil, OPTION_ATTRS, [], []
+       ],
+       ['p', false, true, false, false, false, :any, false,
+        'paragraph ',
+        HTML_INLINE, nil, HTML_ATTRS, ALIGN_ATTR, []
+       ],
+       ['param', false, true, true, true, false, :any, false,
+        'named property value ',
+        EMPTY, nil, PARAM_ATTRS, [], NAME_ATTR
+       ],
+       ['pre', false, false, false, false, false, :any, false,
+        'preformatted text ',
+        PRE_CONTENT, nil, HTML_ATTRS, WIDTH_ATTR, []
+       ],
+       ['q', false, false, false, false, false, :any, true,
+        'short inline quotation ',
+        HTML_INLINE, nil, QUOTE_ATTRS, [], []
+       ],
+       ['s', false, true, false, false, true, :loose, true,
+        'strike-through text style',
+        HTML_INLINE, nil, [], HTML_ATTRS, []
+       ],
+       ['samp', false, false, false, false, false, :any, true,
+        'sample program output, scripts, etc.',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['script', false, false, false, false, false, :any, true,
+        'script statements ',
+        HTML_CDATA, nil, SCRIPT_ATTRS, LANGUAGE_ATTR, TYPE_ATTR
+       ],
+       ['select', false, false, false, false, false, :any, true,
+        'option selector ',
+        SELECT_CONTENT, nil, SELECT_ATTRS, [], []
+       ],
+       ['small', false, true, false, false, false, :any, true,
+        'small text style',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['span', false, false, false, false, false, :any, true,
+        'generic language/style container ',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['strike', false, true, false, false, true, :loose, true,
+        'strike-through text',
+        HTML_INLINE, nil, [], HTML_ATTRS, []
+       ],
+       ['strong', false, true, false, false, false, :any, true,
+        'strong emphasis',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['style', false, false, false, false, false, :any, false,
+        'style info ',
+        HTML_CDATA, nil, STYLE_ATTRS, [], TYPE_ATTR
+       ],
+       ['sub', false, true, false, false, false, :any, true,
+        'subscript',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['sup', false, true, false, false, false, :any, true,
+        'superscript ',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['table', false, false, false, false, false, :any, false,
+        '',
+        TABLE_CONTENTS, 'tr', TABLE_ATTRS, TABLE_DEPR, []
+       ],
+       ['tbody', true, false, false, false, false, :any, false,
+        'table body ',
+        TR_ELT, 'tr', TALIGN_ATTRS, [], []
+       ],
+       ['td', false, false, false, false, false, :any, false,
+        'table data cell',
+        HTML_FLOW, nil, TH_TD_ATTR, TH_TD_DEPR, []
+       ],
+       ['textarea', false, false, false, false, false, :any, true,
+        'multi-line text field ',
+        HTML_PCDATA, nil, TEXTAREA_ATTRS, [], ROWS_COLS_ATTR
+       ],
+       ['tfoot', false, true, false, false, false, :any, false,
+        'table footer ',
+        TR_ELT, 'tr', TALIGN_ATTRS, [], []
+       ],
+       ['th', false, true, false, false, false, :any, false,
+        'table header cell',
+        HTML_FLOW, nil, TH_TD_ATTR, TH_TD_DEPR, []
+       ],
+       ['thead', false, true, false, false, false, :any, false,
+        'table header ',
+        TR_ELT, 'tr', TALIGN_ATTRS, [], []
+       ],
+       ['title', false, false, false, false, false, :any, false,
+        'document title ',
+        HTML_PCDATA, nil, I18N_ATTRS, [], []
+       ],
+       ['tr', false, false, false, false, false, :any, false,
+        'table row ',
+        TR_CONTENTS, 'td', TALIGN_ATTRS, BGCOLOR_ATTR, []
+       ],
+       ['tt', false, true, false, false, false, :any, true,
+        'teletype or monospaced text style',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ],
+       ['u', false, true, false, false, true, :loose, true,
+        'underlined text style',
+        HTML_INLINE, nil, [], HTML_ATTRS, []
+       ],
+       ['ul', false, false, false, false, false, :any, false,
+        'unordered list ',
+        LI_ELT, 'li', HTML_ATTRS, UL_DEPR, []
+       ],
+       ['var', false, false, false, false, false, :any, true,
+        'instance of a variable or program argument',
+        HTML_INLINE, nil, HTML_ATTRS, [], []
+       ]
+      ].each do |descriptor|
+        name = descriptor[0]
+
+        begin
+        d = Desc.new(*descriptor)
+
+        # flatten all the attribute lists (Ruby1.9, *[a,b,c] can be
+        # used to flatten a literal list, but not in Ruby1.8).
+        d[:subelts] = d[:subelts].flatten
+        d[:attrs_opt] = d[:attrs_opt].flatten
+        d[:attrs_depr] = d[:attrs_depr].flatten
+          d[:attrs_req] = d[:attrs_req].flatten
+        rescue => e
+            p name
+          raise e
+        end
+
+        DefaultDescriptions[name] = d
+      end
+    end
+  end
+end

+ 13 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/entity_lookup.rb

@@ -0,0 +1,13 @@
+module Nokogiri
+  module HTML
+    class EntityDescription < Struct.new(:value, :name, :description); end
+
+    class EntityLookup
+      ###
+      # Look up entity with +name+
+      def [] name
+        (val = get(name)) && val.value
+      end
+    end
+  end
+end

+ 52 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/sax/parser.rb

@@ -0,0 +1,52 @@
+module Nokogiri
+  module HTML
+    ###
+    # Nokogiri lets you write a SAX parser to process HTML but get HTML
+    # correction features.
+    #
+    # See Nokogiri::HTML::SAX::Parser for a basic example of using a
+    # SAX parser with HTML.
+    #
+    # For more information on SAX parsers, see Nokogiri::XML::SAX
+    module SAX
+      ###
+      # This class lets you perform SAX style parsing on HTML with HTML
+      # error correction.
+      #
+      # Here is a basic usage example:
+      #
+      #   class MyDoc < Nokogiri::XML::SAX::Document
+      #     def start_element name, attributes = []
+      #       puts "found a #{name}"
+      #     end
+      #   end
+      #
+      #   parser = Nokogiri::HTML::SAX::Parser.new(MyDoc.new)
+      #   parser.parse(File.read(ARGV[0], 'rb'))
+      #
+      # For more information on SAX parsers, see Nokogiri::XML::SAX
+      class Parser < Nokogiri::XML::SAX::Parser
+        ###
+        # Parse html stored in +data+ using +encoding+
+        def parse_memory data, encoding = 'UTF-8'
+          raise ArgumentError unless data
+          return unless data.length > 0
+          ctx = ParserContext.memory(data, encoding)
+          yield ctx if block_given?
+          ctx.parse_with self
+        end
+
+        ###
+        # Parse a file with +filename+
+        def parse_file filename, encoding = 'UTF-8'
+          raise ArgumentError unless filename
+          raise Errno::ENOENT unless File.exists?(filename)
+          raise Errno::EISDIR if File.directory?(filename)
+          ctx = ParserContext.file(filename, encoding)
+          yield ctx if block_given?
+          ctx.parse_with self
+        end
+      end
+    end
+  end
+end

+ 16 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/sax/parser_context.rb

@@ -0,0 +1,16 @@
+module Nokogiri
+  module HTML
+    module SAX
+      ###
+      # Context for HTML SAX parsers.  This class is usually not instantiated
+      # by the user.  Instead, you should be looking at
+      # Nokogiri::HTML::SAX::Parser
+      class ParserContext < Nokogiri::XML::SAX::ParserContext
+        def self.new thing, encoding = 'UTF-8'
+          [:read, :close].all? { |x| thing.respond_to?(x) } ?  super :
+            memory(thing, encoding)
+        end
+      end
+    end
+  end
+end

+ 16 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/html/sax/push_parser.rb

@@ -0,0 +1,16 @@
+module Nokogiri
+  module HTML
+    module SAX
+      class PushParser
+        def initialize(doc = XML::SAX::Document.new, file_name = nil, encoding = 'UTF-8')
+          @document = doc
+          @encoding = encoding
+          @sax_parser = HTML::SAX::Parser.new(doc, @encoding)
+
+          ## Create our push parser context
+          initialize_native(@sax_parser, file_name, @encoding)
+        end
+      end
+    end
+  end
+end

BIN
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/nokogiri.jar


+ 4 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/syntax_error.rb

@@ -0,0 +1,4 @@
+module Nokogiri
+  class SyntaxError < ::StandardError
+  end
+end

+ 88 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/version.rb

@@ -0,0 +1,88 @@
+module Nokogiri
+  # The version of Nokogiri you are using
+  VERSION = '1.5.2'
+
+  class VersionInfo # :nodoc:
+    def jruby?
+      ::JRUBY_VERSION if RUBY_PLATFORM == "java"
+    end
+
+    def engine
+      defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'mri'
+    end
+
+    def loaded_parser_version
+      LIBXML_PARSER_VERSION.scan(/^(.*)(..)(..)$/).first.collect{ |j|
+        j.to_i
+      }.join(".")
+    end
+
+    def compiled_parser_version
+      LIBXML_VERSION
+    end
+
+    def libxml2?
+      defined?(LIBXML_VERSION)
+    end
+
+    def warnings
+      return [] unless libxml2?
+
+      if compiled_parser_version != loaded_parser_version
+        ["Nokogiri was built against LibXML version #{compiled_parser_version}, but has dynamically loaded #{loaded_parser_version}"]
+      else
+        []
+      end
+    end
+
+    def to_hash
+      hash_info = {}
+      hash_info['warnings']              = []
+      hash_info['nokogiri']              = Nokogiri::VERSION
+      hash_info['ruby']                  = {}
+      hash_info['ruby']['version']       = ::RUBY_VERSION
+      hash_info['ruby']['platform']      = ::RUBY_PLATFORM
+      hash_info['ruby']['description']   = ::RUBY_DESCRIPTION
+      hash_info['ruby']['engine']        = engine
+      hash_info['ruby']['jruby']         = jruby? if jruby?
+
+      if libxml2?
+        hash_info['libxml']              = {}
+        hash_info['libxml']['binding']   = 'extension'
+        hash_info['libxml']['compiled']  = compiled_parser_version
+        hash_info['libxml']['loaded']    = loaded_parser_version
+        hash_info['warnings']            = warnings
+      end
+
+      hash_info
+    end
+
+    def to_markdown
+      begin
+        require 'psych'
+      rescue LoadError
+      end
+      require 'yaml'
+      "# Nokogiri (#{Nokogiri::VERSION})\n" +
+      YAML.dump(to_hash).each_line.map { |line| "    #{line}" }.join
+    end
+
+    # FIXME: maybe switch to singleton?
+    @@instance = new
+    @@instance.warnings.each do |warning|
+      warn "WARNING: #{warning}"
+    end
+    def self.instance; @@instance; end
+  end
+
+  # More complete version information about libxml
+  VERSION_INFO = VersionInfo.instance.to_hash
+
+  def self.uses_libxml? # :nodoc:
+    VersionInfo.instance.libxml2?
+  end
+
+  def self.jruby? # :nodoc:
+    VersionInfo.instance.jruby?
+  end
+end

+ 73 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml.rb

@@ -0,0 +1,73 @@
+require 'nokogiri/xml/pp'
+require 'nokogiri/xml/parse_options'
+require 'nokogiri/xml/sax'
+require 'nokogiri/xml/node'
+require 'nokogiri/xml/attribute_decl'
+require 'nokogiri/xml/element_decl'
+require 'nokogiri/xml/element_content'
+require 'nokogiri/xml/character_data'
+require 'nokogiri/xml/namespace'
+require 'nokogiri/xml/attr'
+require 'nokogiri/xml/dtd'
+require 'nokogiri/xml/cdata'
+require 'nokogiri/xml/text'
+require 'nokogiri/xml/document'
+require 'nokogiri/xml/document_fragment'
+require 'nokogiri/xml/processing_instruction'
+require 'nokogiri/xml/node_set'
+require 'nokogiri/xml/syntax_error'
+require 'nokogiri/xml/xpath'
+require 'nokogiri/xml/xpath_context'
+require 'nokogiri/xml/builder'
+require 'nokogiri/xml/reader'
+require 'nokogiri/xml/notation'
+require 'nokogiri/xml/entity_decl'
+require 'nokogiri/xml/schema'
+require 'nokogiri/xml/relax_ng'
+
+module Nokogiri
+  class << self
+    ###
+    # Parse XML.  Convenience method for Nokogiri::XML::Document.parse
+    def XML thing, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_XML, &block
+      Nokogiri::XML::Document.parse(thing, url, encoding, options, &block)
+    end
+  end
+
+  module XML
+    # Original C14N 1.0 spec canonicalization
+    XML_C14N_1_0 =       0
+    # Exclusive C14N 1.0 spec canonicalization
+    XML_C14N_EXCLUSIVE_1_0 =     1
+    # C14N 1.1 spec canonicalization
+    XML_C14N_1_1 = 2
+    class << self
+      ###
+      # Parse an XML document using the Nokogiri::XML::Reader API.  See
+      # Nokogiri::XML::Reader for mor information
+      def Reader string_or_io, url = nil, encoding = nil, options = ParseOptions::STRICT
+
+        options = Nokogiri::XML::ParseOptions.new(options) if Fixnum === options
+        # Give the options to the user
+        yield options if block_given?
+
+        if string_or_io.respond_to? :read
+          return Reader.from_io(string_or_io, url, encoding, options.to_i)
+        end
+        Reader.from_memory(string_or_io, url, encoding, options.to_i)
+      end
+
+      ###
+      # Parse XML.  Convenience method for Nokogiri::XML::Document.parse
+      def parse thing, url = nil, encoding = nil, options = ParseOptions::DEFAULT_XML, &block
+        Document.parse(thing, url, encoding, options, &block)
+      end
+
+      ####
+      # Parse a fragment from +string+ in to a NodeSet.
+      def fragment string
+        XML::DocumentFragment.parse(string)
+      end
+    end
+  end
+end

+ 14 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/attr.rb

@@ -0,0 +1,14 @@
+module Nokogiri
+  module XML
+    class Attr < Node
+      alias :value :content
+      alias :to_s :content
+      alias :content= :value=
+
+      private
+      def inspect_attributes
+        [:name, :namespace, :value]
+      end
+    end
+  end
+end

+ 18 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/attribute_decl.rb

@@ -0,0 +1,18 @@
+module Nokogiri
+  module XML
+    ###
+    # Represents an attribute declaration in a DTD
+    class AttributeDecl < Nokogiri::XML::Node
+      undef_method :attribute_nodes
+      undef_method :attributes
+      undef_method :content
+      undef_method :namespace
+      undef_method :namespace_definitions
+      undef_method :line if method_defined?(:line)
+
+      def inspect
+        "#<#{self.class.name}:#{sprintf("0x%x", object_id)} #{to_s.inspect}>"
+      end
+    end
+  end
+end

+ 431 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/builder.rb

@@ -0,0 +1,431 @@
+module Nokogiri
+  module XML
+    ###
+    # Nokogiri builder can be used for building XML and HTML documents.
+    #
+    # == Synopsis:
+    #
+    #   builder = Nokogiri::XML::Builder.new do |xml|
+    #     xml.root {
+    #       xml.products {
+    #         xml.widget {
+    #           xml.id_ "10"
+    #           xml.name "Awesome widget"
+    #         }
+    #       }
+    #     }
+    #   end
+    #   puts builder.to_xml
+    #
+    # Will output:
+    #
+    #   <?xml version="1.0"?>
+    #   <root>
+    #     <products>
+    #       <widget>
+    #         <id>10</id>
+    #         <name>Awesome widget</name>
+    #       </widget>
+    #     </products>
+    #   </root>
+    #
+    #
+    # === Builder scope
+    #
+    # The builder allows two forms.  When the builder is supplied with a block
+    # that has a parameter, the outside scope is maintained.  This means you
+    # can access variables that are outside your builder.  If you don't need
+    # outside scope, you can use the builder without the "xml" prefix like
+    # this:
+    #
+    #   builder = Nokogiri::XML::Builder.new do
+    #     root {
+    #       products {
+    #         widget {
+    #           id_ "10"
+    #           name "Awesome widget"
+    #         }
+    #       }
+    #     }
+    #   end
+    #
+    # == Special Tags
+    #
+    # The builder works by taking advantage of method_missing.  Unfortunately
+    # some methods are defined in ruby that are difficult or dangerous to
+    # remove.  You may want to create tags with the name "type", "class", and
+    # "id" for example.  In that case, you can use an underscore to
+    # disambiguate your tag name from the method call.
+    #
+    # Here is an example of using the underscore to disambiguate tag names from
+    # ruby methods:
+    #
+    #   @objects = [Object.new, Object.new, Object.new]
+    #
+    #   builder = Nokogiri::XML::Builder.new do |xml|
+    #     xml.root {
+    #       xml.objects {
+    #         @objects.each do |o|
+    #           xml.object {
+    #             xml.type_   o.type
+    #             xml.class_  o.class.name
+    #             xml.id_     o.id
+    #           }
+    #         end
+    #       }
+    #     }
+    #   end
+    #   puts builder.to_xml
+    #
+    # The underscore may be used with any tag name, and the last underscore
+    # will just be removed.  This code will output the following XML:
+    #
+    #   <?xml version="1.0"?>
+    #   <root>
+    #     <objects>
+    #       <object>
+    #         <type>Object</type>
+    #         <class>Object</class>
+    #         <id>48390</id>
+    #       </object>
+    #       <object>
+    #         <type>Object</type>
+    #         <class>Object</class>
+    #         <id>48380</id>
+    #       </object>
+    #       <object>
+    #         <type>Object</type>
+    #         <class>Object</class>
+    #         <id>48370</id>
+    #       </object>
+    #     </objects>
+    #   </root>
+    #
+    # == Tag Attributes
+    #
+    # Tag attributes may be supplied as method arguments.  Here is our
+    # previous example, but using attributes rather than tags:
+    #
+    #   @objects = [Object.new, Object.new, Object.new]
+    #
+    #   builder = Nokogiri::XML::Builder.new do |xml|
+    #     xml.root {
+    #       xml.objects {
+    #         @objects.each do |o|
+    #           xml.object(:type => o.type, :class => o.class, :id => o.id)
+    #         end
+    #       }
+    #     }
+    #   end
+    #   puts builder.to_xml
+    #
+    # === Tag Attribute Short Cuts
+    #
+    # A couple attribute short cuts are available when building tags.  The
+    # short cuts are available by special method calls when building a tag.
+    #
+    # This example builds an "object" tag with the class attribute "classy"
+    # and the id of "thing":
+    #
+    #   builder = Nokogiri::XML::Builder.new do |xml|
+    #     xml.root {
+    #       xml.objects {
+    #         xml.object.classy.thing!
+    #       }
+    #     }
+    #   end
+    #   puts builder.to_xml
+    #
+    # Which will output:
+    #
+    #   <?xml version="1.0"?>
+    #   <root>
+    #     <objects>
+    #       <object class="classy" id="thing"/>
+    #     </objects>
+    #   </root>
+    #
+    # All other options are still supported with this syntax, including
+    # blocks and extra tag attributes.
+    #
+    # == Namespaces
+    #
+    # Namespaces are added similarly to attributes.  Nokogiri::XML::Builder
+    # assumes that when an attribute starts with "xmlns", it is meant to be
+    # a namespace:
+    #
+    #   builder = Nokogiri::XML::Builder.new { |xml|
+    #     xml.root('xmlns' => 'default', 'xmlns:foo' => 'bar') do
+    #       xml.tenderlove
+    #     end
+    #   }
+    #   puts builder.to_xml
+    #
+    # Will output XML like this:
+    #
+    #   <?xml version="1.0"?>
+    #   <root xmlns:foo="bar" xmlns="default">
+    #     <tenderlove/>
+    #   </root>
+    #
+    # === Referencing declared namespaces
+    #
+    # Tags that reference non-default namespaces (i.e. a tag "foo:bar") can be
+    # built by using the Nokogiri::XML::Builder#[] method.
+    #
+    # For example:
+    #
+    #   builder = Nokogiri::XML::Builder.new do |xml|
+    #     xml.root('xmlns:foo' => 'bar') {
+    #       xml.objects {
+    #         xml['foo'].object.classy.thing!
+    #       }
+    #     }
+    #   end
+    #   puts builder.to_xml
+    #
+    # Will output this XML:
+    #
+    #   <?xml version="1.0"?>
+    #   <root xmlns:foo="bar">
+    #     <objects>
+    #       <foo:object class="classy" id="thing"/>
+    #     </objects>
+    #   </root>
+    #
+    # Note the "foo:object" tag.
+    #
+    # == Document Types
+    #
+    # To create a document type (DTD), access use the Builder#doc method to get
+    # the current context document.  Then call Node#create_internal_subset to
+    # create the DTD node.
+    #
+    # For example, this Ruby:
+    #
+    #   builder = Nokogiri::XML::Builder.new do |xml|
+    #     xml.doc.create_internal_subset(
+    #       'html',
+    #       "-//W3C//DTD HTML 4.01 Transitional//EN",
+    #       "http://www.w3.org/TR/html4/loose.dtd"
+    #     )
+    #     xml.root do
+    #       xml.foo
+    #     end
+    #   end
+    #   
+    #   puts builder.to_xml
+    #
+    # Will output this xml:
+    #
+    #   <?xml version="1.0"?>
+    #   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+    #   <root>
+    #     <foo/>
+    #   </root>
+    #
+    class Builder
+      # The current Document object being built
+      attr_accessor :doc
+
+      # The parent of the current node being built
+      attr_accessor :parent
+
+      # A context object for use when the block has no arguments
+      attr_accessor :context
+
+      attr_accessor :arity # :nodoc:
+
+      ###
+      # Create a builder with an existing root object.  This is for use when
+      # you have an existing document that you would like to augment with
+      # builder methods.  The builder context created will start with the
+      # given +root+ node.
+      #
+      # For example:
+      #
+      #   doc = Nokogiri::XML(open('somedoc.xml'))
+      #   Nokogiri::XML::Builder.with(doc.at('some_tag')) do |xml|
+      #     # ... Use normal builder methods here ...
+      #     xml.awesome # add the "awesome" tag below "some_tag"
+      #   end
+      #
+      def self.with root, &block
+        new({}, root, &block)
+      end
+
+      ###
+      # Create a new Builder object.  +options+ are sent to the top level
+      # Document that is being built.
+      #
+      # Building a document with a particular encoding for example:
+      #
+      #   Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
+      #     ...
+      #   end
+      def initialize options = {}, root = nil, &block
+
+        if root
+          @doc    = root.document
+          @parent = root
+        else
+          namespace     = self.class.name.split('::')
+          namespace[-1] = 'Document'
+          @doc          = eval(namespace.join('::')).new
+          @parent       = @doc
+        end
+
+        @context  = nil
+        @arity    = nil
+        @ns       = nil
+
+        options.each do |k,v|
+          @doc.send(:"#{k}=", v)
+        end
+
+        return unless block_given?
+
+        @arity = block.arity
+        if @arity <= 0
+          @context = eval('self', block.binding)
+          instance_eval(&block)
+        else
+          yield self
+        end
+
+        @parent = @doc
+      end
+
+      ###
+      # Create a Text Node with content of +string+
+      def text string
+        insert @doc.create_text_node(string)
+      end
+
+      ###
+      # Create a CDATA Node with content of +string+
+      def cdata string
+        insert doc.create_cdata(string)
+      end
+
+      ###
+      # Create a Comment Node with content of +string+
+      def comment string
+        insert doc.create_comment(string)
+      end
+
+      ###
+      # Build a tag that is associated with namespace +ns+.  Raises an
+      # ArgumentError if +ns+ has not been defined higher in the tree.
+      def [] ns
+        @ns = @parent.namespace_definitions.find { |x| x.prefix == ns.to_s }
+        return self if @ns
+
+        @parent.ancestors.each do |a|
+          next if a == doc
+          @ns = a.namespace_definitions.find { |x| x.prefix == ns.to_s }
+          return self if @ns
+        end
+
+        raise ArgumentError, "Namespace #{ns} has not been defined"
+      end
+
+      ###
+      # Convert this Builder object to XML
+      def to_xml(*args)
+        if Nokogiri.jruby?
+          options = args.first.is_a?(Hash) ? args.shift : {}
+          if !options[:save_with]
+            options[:save_with] = Node::SaveOptions::AS_BUILDER
+          end
+          args.insert(0, options)
+        end
+        @doc.to_xml(*args)
+      end
+
+      ###
+      # Append the given raw XML +string+ to the document
+      def << string
+        @doc.fragment(string).children.each { |x| insert(x) }
+      end
+
+      def method_missing method, *args, &block # :nodoc:
+        if @context && @context.respond_to?(method)
+          @context.send(method, *args, &block)
+        else
+          node = @doc.create_element(method.to_s.sub(/[_!]$/, ''),*args) { |n|
+            # Set up the namespace
+            if @ns
+              n.namespace = @ns
+              @ns = nil
+            end
+          }
+          insert(node, &block)
+        end
+      end
+
+      private
+      ###
+      # Insert +node+ as a child of the current Node
+      def insert(node, &block)
+        node.parent = @parent
+        if block_given?
+          old_parent = @parent
+          @parent    = node
+          @arity ||= block.arity
+          if @arity <= 0
+            instance_eval(&block)
+          else
+            block.call(self)
+          end
+          @parent = old_parent
+        end
+        NodeBuilder.new(node, self)
+      end
+
+      class NodeBuilder # :nodoc:
+        def initialize node, doc_builder
+          @node = node
+          @doc_builder = doc_builder
+        end
+
+        def []= k, v
+          @node[k] = v
+        end
+
+        def [] k
+          @node[k]
+        end
+
+        def method_missing(method, *args, &block)
+          opts = args.last.is_a?(Hash) ? args.pop : {}
+          case method.to_s
+          when /^(.*)!$/
+            @node['id'] = $1
+            @node.content = args.first if args.first
+          when /^(.*)=/
+            @node[$1] = args.first
+          else
+            @node['class'] =
+              ((@node['class'] || '').split(/\s/) + [method.to_s]).join(' ')
+            @node.content = args.first if args.first
+          end
+
+          # Assign any extra options
+          opts.each do |k,v|
+            @node[k.to_s] = ((@node[k.to_s] || '').split(/\s/) + [v]).join(' ')
+          end
+
+          if block_given?
+            old_parent = @doc_builder.parent
+            @doc_builder.parent = @node
+            value = @doc_builder.instance_eval(&block)
+            @doc_builder.parent = old_parent
+            return value
+          end
+          self
+        end
+      end
+    end
+  end
+end

+ 11 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/cdata.rb

@@ -0,0 +1,11 @@
+module Nokogiri
+  module XML
+    class CDATA < Nokogiri::XML::Text
+      ###
+      # Get the name of this CDATA node
+      def name
+        '#cdata-section'
+      end
+    end
+  end
+end

+ 7 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/character_data.rb

@@ -0,0 +1,7 @@
+module Nokogiri
+  module XML
+    class CharacterData < Nokogiri::XML::Node
+      include Nokogiri::XML::PP::CharacterData
+    end
+  end
+end

+ 249 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/document.rb

@@ -0,0 +1,249 @@
+module Nokogiri
+  module XML
+    ##
+    # Nokogiri::XML::Document is the main entry point for dealing with
+    # XML documents.  The Document is created by parsing an XML document.
+    # See Nokogiri.XML()
+    #
+    # For searching a Document, see Nokogiri::XML::Node#css and
+    # Nokogiri::XML::Node#xpath
+    class Document < Nokogiri::XML::Node
+      # I'm ignoring unicode characters here.
+      # See http://www.w3.org/TR/REC-xml-names/#ns-decl for more details.
+      NCNAME_START_CHAR = "A-Za-z_"
+      NCNAME_CHAR       = NCNAME_START_CHAR + "\\-.0-9"
+      NCNAME_RE         = /^xmlns(:[#{NCNAME_START_CHAR}][#{NCNAME_CHAR}]*)?$/
+
+      ##
+      # Parse an XML file.  +string_or_io+ may be a String, or any object that
+      # responds to _read_ and _close_ such as an IO, or StringIO.
+      # +url+ is resource where this document is located.  +encoding+ is the
+      # encoding that should be used when processing the document. +options+
+      # is a number that sets options in the parser, such as
+      # Nokogiri::XML::ParseOptions::RECOVER.  See the constants in
+      # Nokogiri::XML::ParseOptions.
+      def self.parse string_or_io, url = nil, encoding = nil, options = ParseOptions::DEFAULT_XML, &block
+        options = Nokogiri::XML::ParseOptions.new(options) if Fixnum === options
+        # Give the options to the user
+        yield options if block_given?
+
+        doc = if string_or_io.respond_to?(:read)
+          url ||= string_or_io.respond_to?(:path) ? string_or_io.path : nil
+          read_io(string_or_io, url, encoding, options.to_i)
+        else
+          # read_memory pukes on empty docs
+          return new if string_or_io.nil? or string_or_io.empty?
+          read_memory(string_or_io, url, encoding, options.to_i)
+        end
+
+        # do xinclude processing
+        doc.do_xinclude(options) if options.xinclude?
+
+        return doc
+      end
+
+      # A list of Nokogiri::XML::SyntaxError found when parsing a document
+      attr_accessor :errors
+
+      def initialize *args # :nodoc:
+        @errors     = []
+        @decorators = nil
+      end
+
+      ##
+      # Create an element with +name+, and optionally setting the content and attributes.
+      #
+      #   doc.create_element "div" # <div></div>
+      #   doc.create_element "div", :class => "container" # <div class='container'></div>
+      #   doc.create_element "div", "contents" # <div>contents</div>
+      #   doc.create_element "div", "contents", :class => "container" # <div class='container'>contents</div>
+      #   doc.create_element "div" { |node| node['class'] = "container" } # <div class='container'></div>
+      #
+      def create_element name, *args, &block
+        elm = Nokogiri::XML::Element.new(name, self, &block)
+        args.each do |arg|
+          case arg
+          when Hash
+            arg.each { |k,v|
+              key = k.to_s
+              if key =~ NCNAME_RE
+                ns_name = key.split(":", 2)[1]
+                elm.add_namespace_definition ns_name, v
+                next
+              end
+              elm[k.to_s] = v.to_s
+            }
+          else
+            elm.content = arg
+          end
+        end
+        elm
+      end
+
+      # Create a Text Node with +string+
+      def create_text_node string, &block
+        Nokogiri::XML::Text.new string.to_s, self, &block
+      end
+
+      # Create a CDATA Node containing +string+
+      def create_cdata string, &block
+        Nokogiri::XML::CDATA.new self, string.to_s, &block
+      end
+
+      # Create a Comment Node containing +string+
+      def create_comment string, &block
+        Nokogiri::XML::Comment.new self, string.to_s, &block
+      end
+
+      # The name of this document.  Always returns "document"
+      def name
+        'document'
+      end
+
+      # A reference to +self+
+      def document
+        self
+      end
+
+      ##
+      # Recursively get all namespaces from this node and its subtree and
+      # return them as a hash.
+      #
+      # For example, given this document:
+      #
+      #   <root xmlns:foo="bar">
+      #     <bar xmlns:hello="world" />
+      #   </root>
+      #
+      # This method will return:
+      #
+      #   { 'xmlns:foo' => 'bar', 'xmlns:hello' => 'world' }
+      #
+      # WARNING: this method will clobber duplicate names in the keys.
+      # For example, given this document:
+      #
+      #   <root xmlns:foo="bar">
+      #     <bar xmlns:foo="baz" />
+      #   </root>
+      #
+      # The hash returned will look like this: { 'xmlns:foo' => 'bar' }
+      #
+      # Non-prefixed default namespaces (as in "xmlns=") are not included
+      # in the hash.
+      #
+      # Note this is a very expensive operation in current implementation, as it
+      # traverses the entire graph, and also has to bring each node accross the
+      # libxml bridge into a ruby object.
+      def collect_namespaces
+        ns = {}
+        traverse { |j| ns.merge!(j.namespaces) }
+        ns
+      end
+
+      # Get the list of decorators given +key+
+      def decorators key
+        @decorators ||= Hash.new
+        @decorators[key] ||= []
+      end
+
+      ##
+      # Validate this Document against it's DTD.  Returns a list of errors on
+      # the document or +nil+ when there is no DTD.
+      def validate
+        return nil unless internal_subset
+        internal_subset.validate self
+      end
+
+      ##
+      # Explore a document with shortcut methods. See Nokogiri::Slop for details.
+      #
+      # Note that any nodes that have been instantiated before #slop!
+      # is called will not be decorated with sloppy behavior. So, if you're in
+      # irb, the preferred idiom is:
+      #
+      #   irb> doc = Nokogiri::Slop my_markup
+      #
+      # and not
+      #
+      #   irb> doc = Nokogiri::HTML my_markup
+      #   ... followed by irb's implicit inspect (and therefore instantiation of every node) ...
+      #   irb> doc.slop!
+      #   ... which does absolutely nothing.
+      #
+      def slop!
+        unless decorators(XML::Node).include? Nokogiri::Decorators::Slop
+          decorators(XML::Node) << Nokogiri::Decorators::Slop
+          decorate!
+        end
+
+        self
+      end
+
+      ##
+      # Apply any decorators to +node+
+      def decorate node
+        return unless @decorators
+        @decorators.each { |klass,list|
+          next unless node.is_a?(klass)
+          list.each { |moodule| node.extend(moodule) }
+        }
+      end
+
+      alias :to_xml :serialize
+      alias :clone :dup
+
+      # Get the hash of namespaces on the root Nokogiri::XML::Node
+      def namespaces
+        root ? root.namespaces : {}
+      end
+
+      ##
+      # Create a Nokogiri::XML::DocumentFragment from +tags+
+      # Returns an empty fragment if +tags+ is nil.
+      def fragment tags = nil
+        DocumentFragment.new(self, tags, self.root)
+      end
+
+      undef_method :swap, :parent, :namespace, :default_namespace=
+      undef_method :add_namespace_definition, :attributes
+      undef_method :namespace_definitions, :line, :add_namespace
+
+      def add_child node_or_tags
+        raise "Document already has a root node" if root
+        node_or_tags = coerce(node_or_tags)
+        if node_or_tags.is_a?(XML::NodeSet)
+          raise "Document cannot have multiple root nodes" if node_or_tags.size > 1
+          super(node_or_tags.first)
+        else
+          super
+        end
+      end
+      alias :<< :add_child
+
+      ##
+      # +JRuby+
+      # Wraps Java's org.w3c.dom.document and returns Nokogiri::XML::Document
+      def self.wrap document
+        raise "JRuby only method" unless Nokogiri.jruby?
+        return wrapJavaDocument(document)
+      end
+
+      ##
+      # +JRuby+
+      # Returns Java's org.w3c.dom.document of this Document.
+      def to_java
+        raise "JRuby only method" unless Nokogiri.jruby?
+        return toJavaDocument()
+      end
+
+      private
+      def implied_xpath_context
+        "/"
+      end
+
+      def inspect_attributes
+        [:name, :children]
+      end
+    end
+  end
+end

+ 103 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/document_fragment.rb

@@ -0,0 +1,103 @@
+module Nokogiri
+  module XML
+    class DocumentFragment < Nokogiri::XML::Node
+      ##
+      #  Create a new DocumentFragment from +tags+.
+      #
+      #  If +ctx+ is present, it is used as a context node for the
+      #  subtree created, e.g., namespaces will be resolved relative
+      #  to +ctx+.
+      def initialize document, tags = nil, ctx = nil
+        return self unless tags
+
+        children = if ctx
+                     # Fix for issue#490
+                     if Nokogiri.jruby?
+                       ctx.parse("<root>#{tags}</root>").xpath("/root/node()")
+                     else
+                       ctx.parse(tags)
+                     end
+                   else
+                     XML::Document.parse("<root>#{tags}</root>") \
+                       .xpath("/root/node()")
+                   end
+        children.each { |child| child.parent = self }
+      end
+
+      ###
+      # return the name for DocumentFragment
+      def name
+        '#document-fragment'
+      end
+
+      ###
+      # Convert this DocumentFragment to a string
+      def to_s
+        children.to_s
+      end
+
+      ###
+      # Convert this DocumentFragment to html
+      # See Nokogiri::XML::NodeSet#to_html
+      def to_html *args
+        if Nokogiri.jruby?
+          options = args.first.is_a?(Hash) ? args.shift : {}
+          if !options[:save_with]
+            options[:save_with] = Node::SaveOptions::NO_DECLARATION | Node::SaveOptions::NO_EMPTY_TAGS | Node::SaveOptions::AS_HTML
+          end
+          args.insert(0, options)
+        end
+        children.to_html(*args)
+      end
+
+      ###
+      # Convert this DocumentFragment to xhtml
+      # See Nokogiri::XML::NodeSet#to_xhtml
+      def to_xhtml *args
+        if Nokogiri.jruby?
+          options = args.first.is_a?(Hash) ? args.shift : {}
+          if !options[:save_with]
+            options[:save_with] = Node::SaveOptions::NO_DECLARATION | Node::SaveOptions::NO_EMPTY_TAGS | Node::SaveOptions::AS_XHTML
+          end
+          args.insert(0, options)
+        end
+        children.to_xhtml(*args)
+      end
+
+      ###
+      # Convert this DocumentFragment to xml
+      # See Nokogiri::XML::NodeSet#to_xml
+      def to_xml *args
+        children.to_xml(*args)
+      end
+
+      ###
+      # Search this fragment.  See Nokogiri::XML::Node#css
+      def css *args
+        if children.any?
+          children.css(*args)
+        else
+          NodeSet.new(document)
+        end
+      end
+
+      alias :serialize :to_s
+
+      class << self
+        ####
+        # Create a Nokogiri::XML::DocumentFragment from +tags+
+        def parse tags
+          self.new(XML::Document.new, tags)
+        end
+      end
+
+      private
+
+      def coerce data
+        return super unless String === data
+
+        document.fragment(data).children
+      end
+    end
+  end
+end

+ 22 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/dtd.rb

@@ -0,0 +1,22 @@
+module Nokogiri
+  module XML
+    class DTD < Nokogiri::XML::Node
+      undef_method :attribute_nodes
+      undef_method :values
+      undef_method :content
+      undef_method :namespace
+      undef_method :namespace_definitions
+      undef_method :line if method_defined?(:line)
+
+      def keys
+        attributes.keys
+      end
+
+      def each &block
+        attributes.each { |key, value|
+          block.call([key, value])
+        }
+      end
+    end
+  end
+end

+ 36 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/element_content.rb

@@ -0,0 +1,36 @@
+module Nokogiri
+  module XML
+    ###
+    # Represents the allowed content in an Element Declaration inside a DTD:
+    #
+    #   <?xml version="1.0"?><?TEST-STYLE PIDATA?>
+    #   <!DOCTYPE staff SYSTEM "staff.dtd" [
+    #      <!ELEMENT div1 (head, (p | list | note)*, div2*)>
+    #   ]>
+    #   </root>
+    #
+    # ElementContent represents the tree inside the <!ELEMENT> tag shown above
+    # that lists the possible content for the div1 tag.
+    class ElementContent
+      # Possible definitions of type
+      PCDATA  = 1
+      ELEMENT = 2
+      SEQ     = 3
+      OR      = 4
+
+      # Possible content occurrences
+      ONCE    = 1
+      OPT     = 2
+      MULT    = 3
+      PLUS    = 4
+
+      attr_reader :document
+
+      ###
+      # Get the children of this ElementContent node
+      def children
+        [c1, c2].compact
+      end
+    end
+  end
+end

+ 13 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/element_decl.rb

@@ -0,0 +1,13 @@
+module Nokogiri
+  module XML
+    class ElementDecl < Nokogiri::XML::Node
+      undef_method :namespace
+      undef_method :namespace_definitions
+      undef_method :line if method_defined?(:line)
+
+      def inspect
+        "#<#{self.class.name}:#{sprintf("0x%x", object_id)} #{to_s.inspect}>"
+      end
+    end
+  end
+end

+ 19 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/entity_decl.rb

@@ -0,0 +1,19 @@
+module Nokogiri
+  module XML
+    class EntityDecl < Nokogiri::XML::Node
+      undef_method :attribute_nodes
+      undef_method :attributes
+      undef_method :namespace
+      undef_method :namespace_definitions
+      undef_method :line if method_defined?(:line)
+
+      def self.new name, doc, *args
+        doc.create_entity(name, *args)
+      end
+
+      def inspect
+        "#<#{self.class.name}:#{sprintf("0x%x", object_id)} #{to_s.inspect}>"
+      end
+    end
+  end
+end

+ 13 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/namespace.rb

@@ -0,0 +1,13 @@
+module Nokogiri
+  module XML
+    class Namespace
+      include Nokogiri::XML::PP::Node
+      attr_reader :document
+
+      private
+      def inspect_attributes
+        [:prefix, :href]
+      end
+    end
+  end
+end

+ 946 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/node.rb

@@ -0,0 +1,946 @@
+require 'stringio'
+require 'nokogiri/xml/node/save_options'
+
+module Nokogiri
+  module XML
+    ####
+    # Nokogiri::XML::Node is your window to the fun filled world of dealing
+    # with XML and HTML tags.  A Nokogiri::XML::Node may be treated similarly
+    # to a hash with regard to attributes.  For example (from irb):
+    #
+    #   irb(main):004:0> node
+    #   => <a href="#foo" id="link">link</a>
+    #   irb(main):005:0> node['href']
+    #   => "#foo"
+    #   irb(main):006:0> node.keys
+    #   => ["href", "id"]
+    #   irb(main):007:0> node.values
+    #   => ["#foo", "link"]
+    #   irb(main):008:0> node['class'] = 'green'
+    #   => "green"
+    #   irb(main):009:0> node
+    #   => <a href="#foo" id="link" class="green">link</a>
+    #   irb(main):010:0>
+    #
+    # See Nokogiri::XML::Node#[] and Nokogiri::XML#[]= for more information.
+    #
+    # Nokogiri::XML::Node also has methods that let you move around your
+    # tree.  For navigating your tree, see:
+    #
+    # * Nokogiri::XML::Node#parent
+    # * Nokogiri::XML::Node#children
+    # * Nokogiri::XML::Node#next
+    # * Nokogiri::XML::Node#previous
+    #
+    # You may search this node's subtree using Node#xpath and Node#css
+    class Node
+      include Nokogiri::XML::PP::Node
+      include Enumerable
+
+      # Element node type, see Nokogiri::XML::Node#element?
+      ELEMENT_NODE =       1
+      # Attribute node type
+      ATTRIBUTE_NODE =     2
+      # Text node type, see Nokogiri::XML::Node#text?
+      TEXT_NODE =          3
+      # CDATA node type, see Nokogiri::XML::Node#cdata?
+      CDATA_SECTION_NODE = 4
+      # Entity reference node type
+      ENTITY_REF_NODE =    5
+      # Entity node type
+      ENTITY_NODE =        6
+      # PI node type
+      PI_NODE =            7
+      # Comment node type, see Nokogiri::XML::Node#comment?
+      COMMENT_NODE =       8
+      # Document node type, see Nokogiri::XML::Node#xml?
+      DOCUMENT_NODE =      9
+      # Document type node type
+      DOCUMENT_TYPE_NODE = 10
+      # Document fragment node type
+      DOCUMENT_FRAG_NODE = 11
+      # Notation node type
+      NOTATION_NODE =      12
+      # HTML document node type, see Nokogiri::XML::Node#html?
+      HTML_DOCUMENT_NODE = 13
+      # DTD node type
+      DTD_NODE =           14
+      # Element declaration type
+      ELEMENT_DECL =       15
+      # Attribute declaration type
+      ATTRIBUTE_DECL =     16
+      # Entity declaration type
+      ENTITY_DECL =        17
+      # Namespace declaration type
+      NAMESPACE_DECL =     18
+      # XInclude start type
+      XINCLUDE_START =     19
+      # XInclude end type
+      XINCLUDE_END =       20
+      # DOCB document node type
+      DOCB_DOCUMENT_NODE = 21
+
+      def initialize name, document # :nodoc:
+        # ... Ya.  This is empty on purpose.
+      end
+
+      ###
+      # Decorate this node with the decorators set up in this node's Document
+      def decorate!
+        document.decorate(self)
+      end
+
+      ###
+      # Search this node for +paths+.  +paths+ can be XPath or CSS, and an
+      # optional hash of namespaces may be appended.
+      # See Node#xpath and Node#css.
+      def search *paths
+        # TODO use         paths, handler, ns, binds = extract_params(paths)
+        ns = paths.last.is_a?(Hash) ? paths.pop :
+          (document.root ? document.root.namespaces : {})
+
+        prefix = "#{implied_xpath_context}/"
+
+        xpath(*(paths.map { |path|
+          path = path.to_s
+          path =~ /^(\.\/|\/|\.\.)/ ? path : CSS.xpath_for(
+            path,
+            :prefix => prefix,
+            :ns     => ns
+          )
+        }.flatten.uniq) + [ns])
+      end
+      alias :/ :search
+
+      ###
+      # call-seq: xpath *paths, [namespace-bindings, variable-bindings, custom-handler-class]
+      #
+      # Search this node for XPath +paths+. +paths+ must be one or more XPath
+      # queries.
+      #
+      #   node.xpath('.//title')
+      #
+      # A hash of namespace bindings may be appended. For example:
+      #
+      #   node.xpath('.//foo:name', {'foo' => 'http://example.org/'})
+      #   node.xpath('.//xmlns:name', node.root.namespaces)
+      #
+      # A hash of variable bindings may also be appended to the namespace bindings. For example:
+      #
+      #   node.xpath('.//address[@domestic=$value]', nil, {:value => 'Yes'})
+      #
+      # Custom XPath functions may also be defined.  To define custom
+      # functions create a class and implement the function you want
+      # to define.  The first argument to the method will be the
+      # current matching NodeSet.  Any other arguments are ones that
+      # you pass in.  Note that this class may appear anywhere in the
+      # argument list.  For example:
+      #
+      #   node.xpath('.//title[regex(., "\w+")]', Class.new {
+      #     def regex node_set, regex
+      #       node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
+      #     end
+      #   }.new)
+      #
+      def xpath *paths
+        return NodeSet.new(document) unless document
+
+        paths, handler, ns, binds = extract_params(paths)
+
+        sets = paths.map { |path|
+          ctx = XPathContext.new(self)
+          ctx.register_namespaces(ns)
+          path = path.gsub(/\/xmlns:/,'/:') unless Nokogiri.uses_libxml?
+
+          binds.each do |key,value|
+            ctx.register_variable key.to_s, value
+          end if binds
+
+          ctx.evaluate(path, handler)
+        }
+        return sets.first if sets.length == 1
+
+        NodeSet.new(document) do |combined|
+          sets.each do |set|
+            set.each do |node|
+              combined << node
+            end
+          end
+        end
+      end
+
+      ###
+      # call-seq: css *rules, [namespace-bindings, custom-pseudo-class]
+      #
+      # Search this node for CSS +rules+. +rules+ must be one or more CSS
+      # selectors. For example:
+      #
+      #   node.css('title')
+      #   node.css('body h1.bold')
+      #   node.css('div + p.green', 'div#one')
+      #
+      # A hash of namespace bindings may be appended. For example:
+      #
+      #   node.css('bike|tire', {'bike' => 'http://schwinn.com/'})
+      #
+      # Custom CSS pseudo classes may also be defined.  To define
+      # custom pseudo classes, create a class and implement the custom
+      # pseudo class you want defined.  The first argument to the
+      # method will be the current matching NodeSet.  Any other
+      # arguments are ones that you pass in.  For example:
+      #
+      #   node.css('title:regex("\w+")', Class.new {
+      #     def regex node_set, regex
+      #       node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
+      #     end
+      #   }.new)
+      #
+      # Note that the CSS query string is case-sensitive with regards
+      # to your document type. That is, if you're looking for "H1" in
+      # an HTML document, you'll never find anything, since HTML tags
+      # will match only lowercase CSS queries. However, "H1" might be
+      # found in an XML document, where tags names are case-sensitive
+      # (e.g., "H1" is distinct from "h1").
+      #
+      def css *rules
+        rules, handler, ns, binds = extract_params(rules)
+
+        prefix = "#{implied_xpath_context}/"
+
+        rules = rules.map { |rule|
+          CSS.xpath_for(rule, :prefix => prefix, :ns => ns)
+        }.flatten.uniq + [ns, handler, binds].compact
+
+        xpath(*rules)
+      end
+
+      ###
+      # Search this node's immediate children using CSS selector +selector+
+      def > selector
+        ns = document.root.namespaces
+        xpath CSS.xpath_for(selector, :prefix => "./", :ns => ns).first
+      end
+
+      ###
+      # Search for the first occurrence of +path+.
+      #
+      # Returns nil if nothing is found, otherwise a Node.
+      def at path, ns = document.root ? document.root.namespaces : {}
+        search(path, ns).first
+      end
+      alias :% :at
+
+      ##
+      # Search this node for the first occurrence of XPath +paths+.
+      # Equivalent to <tt>xpath(paths).first</tt>
+      # See Node#xpath for more information.
+      #
+      def at_xpath *paths
+        xpath(*paths).first
+      end
+
+      ##
+      # Search this node for the first occurrence of CSS +rules+.
+      # Equivalent to <tt>css(rules).first</tt>
+      # See Node#css for more information.
+      #
+      def at_css *rules
+        css(*rules).first
+      end
+
+      ###
+      # Get the attribute value for the attribute +name+
+      def [] name
+        return nil unless key?(name.to_s)
+        get(name.to_s)
+      end
+
+      ###
+      # Set the attribute value for the attribute +name+ to +value+
+      def []= name, value
+        set name.to_s, value
+      end
+
+      ###
+      # Add +node_or_tags+ as a child of this Node.
+      # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
+      #
+      # Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
+      #
+      # Also see related method +<<+.
+      def add_child node_or_tags
+        node_or_tags = coerce(node_or_tags)
+        if node_or_tags.is_a?(XML::NodeSet)
+          node_or_tags.each { |n| add_child_node n }
+        else
+          add_child_node node_or_tags
+        end
+        node_or_tags
+      end
+
+      ###
+      # Add +node_or_tags+ as a child of this Node.
+      # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
+      #
+      # Returns self, to support chaining of calls (e.g., root << child1 << child2)
+      #
+      # Also see related method +add_child+.
+      def << node_or_tags
+        add_child node_or_tags
+        self
+      end
+      ###
+      # Insert +node_or_tags+ before this Node (as a sibling).
+      # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
+      #
+      # Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
+      #
+      # Also see related method +before+.
+      def add_previous_sibling node_or_tags
+        raise ArgumentError.new("A document may not have multiple root nodes.") if parent.is_a?(XML::Document) && !node_or_tags.is_a?(XML::ProcessingInstruction)
+
+        node_or_tags = coerce(node_or_tags)
+        if node_or_tags.is_a?(XML::NodeSet)
+          if text?
+            pivot = Nokogiri::XML::Node.new 'dummy', document
+            add_previous_sibling_node pivot
+          else
+            pivot = self
+          end
+          node_or_tags.each { |n| pivot.send :add_previous_sibling_node, n }
+          pivot.unlink if text?
+        else
+          add_previous_sibling_node node_or_tags
+        end
+        node_or_tags
+      end
+
+      ###
+      # Insert +node_or_tags+ after this Node (as a sibling).
+      # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
+      #
+      # Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
+      #
+      # Also see related method +after+.
+      def add_next_sibling node_or_tags
+        raise ArgumentError.new("A document may not have multiple root nodes.") if parent.is_a?(XML::Document)
+        
+        node_or_tags = coerce(node_or_tags)
+        if node_or_tags.is_a?(XML::NodeSet)
+          if text?
+            pivot = Nokogiri::XML::Node.new 'dummy', document
+            add_next_sibling_node pivot
+          else
+            pivot = self
+          end
+          node_or_tags.reverse_each { |n| pivot.send :add_next_sibling_node, n }
+          pivot.unlink if text?
+        else
+          add_next_sibling_node node_or_tags
+        end
+        node_or_tags
+      end
+
+      ####
+      # Insert +node_or_tags+ before this node (as a sibling).
+      # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
+      #
+      # Returns self, to support chaining of calls.
+      #
+      # Also see related method +add_previous_sibling+.
+      def before node_or_tags
+        add_previous_sibling node_or_tags
+        self
+      end
+
+      ####
+      # Insert +node_or_tags+ after this node (as a sibling).
+      # +node_or_tags+ can be a Nokogiri::XML::Node, a Nokogiri::XML::DocumentFragment, or a string containing markup.
+      #
+      # Returns self, to support chaining of calls.
+      #
+      # Also see related method +add_next_sibling+.
+      def after node_or_tags
+        add_next_sibling node_or_tags
+        self
+      end
+
+      ####
+      # Set the inner html for this Node to +node_or_tags+
+      # +node_or_tags+ can be a Nokogiri::XML::Node, a Nokogiri::XML::DocumentFragment, or a string containing markup.
+      #
+      # Returns self.
+      #
+      # Also see related method +children=+
+      def inner_html= node_or_tags
+        self.children = node_or_tags
+        self
+      end
+
+      ####
+      # Set the inner html for this Node +node_or_tags+
+      # +node_or_tags+ can be a Nokogiri::XML::Node, a Nokogiri::XML::DocumentFragment, or a string containing markup.
+      #
+      # Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
+      #
+      # Also see related method +inner_html=+
+      def children= node_or_tags
+        node_or_tags = coerce(node_or_tags)
+        children.unlink
+        if node_or_tags.is_a?(XML::NodeSet)
+          node_or_tags.each { |n| add_child_node n }
+        else
+          add_child_node node_or_tags
+        end
+        node_or_tags
+      end
+
+      ####
+      # Replace this Node with +node_or_tags+.
+      # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
+      #
+      # Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
+      #
+      # Also see related method +swap+.
+      def replace node_or_tags
+        node_or_tags = coerce(node_or_tags)
+        if node_or_tags.is_a?(XML::NodeSet)
+          if text?
+            replacee = Nokogiri::XML::Node.new 'dummy', document
+            add_previous_sibling_node replacee
+            unlink
+          else
+            replacee = self
+          end
+          node_or_tags.each { |n| replacee.add_previous_sibling n }
+          replacee.unlink
+        else
+          replace_node node_or_tags
+        end
+        node_or_tags
+      end
+
+      ####
+      # Swap this Node for +node_or_tags+
+      # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
+      #
+      # Returns self, to support chaining of calls.
+      #
+      # Also see related method +replace+.
+      def swap node_or_tags
+        replace node_or_tags
+        self
+      end
+
+      alias :next           :next_sibling
+      alias :previous       :previous_sibling
+
+      # :stopdoc:
+      # HACK: This is to work around an RDoc bug
+      alias :next=          :add_next_sibling
+      # :startdoc:
+
+      alias :previous=      :add_previous_sibling
+      alias :remove         :unlink
+      alias :get_attribute  :[]
+      alias :attr           :[]
+      alias :set_attribute  :[]=
+      alias :text           :content
+      alias :inner_text     :content
+      alias :has_attribute? :key?
+      alias :name           :node_name
+      alias :name=          :node_name=
+      alias :type           :node_type
+      alias :to_str         :text
+      alias :clone          :dup
+      alias :elements       :element_children
+
+      ####
+      # Returns a hash containing the node's attributes.  The key is
+      # the attribute name without any namespace, the value is a Nokogiri::XML::Attr
+      # representing the attribute.
+      # If you need to distinguish attributes with the same name, with different namespaces
+      # use #attribute_nodes instead.
+      def attributes
+        Hash[attribute_nodes.map { |node|
+          [node.node_name, node]
+        }]
+      end
+
+      ###
+      # Get the attribute values for this Node.
+      def values
+        attribute_nodes.map { |node| node.value }
+      end
+
+      ###
+      # Get the attribute names for this Node.
+      def keys
+        attribute_nodes.map { |node| node.node_name }
+      end
+
+      ###
+      # Iterate over each attribute name and value pair for this Node.
+      def each
+        attribute_nodes.each { |node|
+          yield [node.node_name, node.value]
+        }
+      end
+
+      ###
+      # Remove the attribute named +name+
+      def remove_attribute name
+        attributes[name].remove if key? name
+      end
+      alias :delete :remove_attribute
+
+      ###
+      # Returns true if this Node matches +selector+
+      def matches? selector
+        ancestors.last.search(selector).include?(self)
+      end
+
+      ###
+      # Create a DocumentFragment containing +tags+ that is relative to _this_
+      # context node.
+      def fragment tags
+        type = document.html? ? Nokogiri::HTML : Nokogiri::XML
+        type::DocumentFragment.new(document, tags, self)
+      end
+
+      ###
+      # Parse +string_or_io+ as a document fragment within the context of
+      # *this* node.  Returns a XML::NodeSet containing the nodes parsed from
+      # +string_or_io+.
+      def parse string_or_io, options = nil
+        options ||= (document.html? ? ParseOptions::DEFAULT_HTML : ParseOptions::DEFAULT_XML)
+        if Fixnum === options
+          options = Nokogiri::XML::ParseOptions.new(options)
+        end
+        # Give the options to the user
+        yield options if block_given?
+
+        contents = string_or_io.respond_to?(:read) ?
+          string_or_io.read :
+          string_or_io
+
+        return Nokogiri::XML::NodeSet.new(document) if contents.empty?
+
+        ##
+        # This is a horrible hack, but I don't care. See #313 for background.
+        error_count = document.errors.length
+        node_set = in_context(contents, options.to_i)
+        if node_set.empty? and document.errors.length > error_count and options.recover?
+          fragment = Nokogiri::HTML::DocumentFragment.parse contents
+          node_set = fragment.children
+        end
+        node_set
+      end
+
+      ####
+      # Set the Node's content to a Text node containing +string+. The string gets XML escaped, not interpreted as markup.
+      def content= string
+        self.native_content = encode_special_chars(string.to_s)
+      end
+
+      ###
+      # Set the parent Node for this Node
+      def parent= parent_node
+        parent_node.add_child(self)
+        parent_node
+      end
+
+      ###
+      # Returns a Hash of {prefix => value} for all namespaces on this
+      # node and its ancestors.
+      #
+      # This method returns the same namespaces as #namespace_scopes.
+      #
+      # Returns namespaces in scope for self -- those defined on self
+      # element directly or any ancestor node -- as a Hash of
+      # attribute-name/value pairs. Note that the keys in this hash
+      # XML attributes that would be used to define this namespace,
+      # such as "xmlns:prefix", not just the prefix. Default namespace
+      # set on self will be included with key "xmlns". However,
+      # default namespaces set on ancestor will NOT be, even if self
+      # has no explicit default namespace.
+      def namespaces
+        Hash[namespace_scopes.map { |nd|
+          key = ['xmlns', nd.prefix].compact.join(':')
+          if RUBY_VERSION >= '1.9' && document.encoding
+            begin
+              key.force_encoding document.encoding
+            rescue ArgumentError
+            end
+          end
+          [key, nd.href]
+        }]
+      end
+
+      # Returns true if this is a Comment
+      def comment?
+        type == COMMENT_NODE
+      end
+
+      # Returns true if this is a CDATA
+      def cdata?
+        type == CDATA_SECTION_NODE
+      end
+
+      # Returns true if this is an XML::Document node
+      def xml?
+        type == DOCUMENT_NODE
+      end
+
+      # Returns true if this is an HTML::Document node
+      def html?
+        type == HTML_DOCUMENT_NODE
+      end
+
+      # Returns true if this is a Text node
+      def text?
+        type == TEXT_NODE
+      end
+
+      # Returns true if this is a DocumentFragment
+      def fragment?
+        type == DOCUMENT_FRAG_NODE
+      end
+
+      ###
+      # Fetch the Nokogiri::HTML::ElementDescription for this node.  Returns
+      # nil on XML documents and on unknown tags.
+      def description
+        return nil if document.xml?
+        Nokogiri::HTML::ElementDescription[name]
+      end
+
+      ###
+      # Is this a read only node?
+      def read_only?
+        # According to gdome2, these are read-only node types
+        [NOTATION_NODE, ENTITY_NODE, ENTITY_DECL].include?(type)
+      end
+
+      # Returns true if this is an Element node
+      def element?
+        type == ELEMENT_NODE
+      end
+      alias :elem? :element?
+
+      ###
+      # Turn this node in to a string.  If the document is HTML, this method
+      # returns html.  If the document is XML, this method returns XML.
+      def to_s
+        document.xml? ? to_xml : to_html
+      end
+
+      # Get the inner_html for this node's Node#children
+      def inner_html *args
+        children.map { |x| x.to_html(*args) }.join
+      end
+
+      # Get the path to this node as a CSS expression
+      def css_path
+        path.split(/\//).map { |part|
+          part.length == 0 ? nil : part.gsub(/\[(\d+)\]/, ':nth-of-type(\1)')
+        }.compact.join(' > ')
+      end
+
+      ###
+      # Get a list of ancestor Node for this Node.  If +selector+ is given,
+      # the ancestors must match +selector+
+      def ancestors selector = nil
+        return NodeSet.new(document) unless respond_to?(:parent)
+        return NodeSet.new(document) unless parent
+
+        parents = [parent]
+
+        while parents.last.respond_to?(:parent)
+          break unless ctx_parent = parents.last.parent
+          parents << ctx_parent
+        end
+
+        return NodeSet.new(document, parents) unless selector
+
+        root = parents.last
+
+        NodeSet.new(document, parents.find_all { |parent|
+          root.search(selector).include?(parent)
+        })
+      end
+
+      ###
+      # Adds a default namespace supplied as a string +url+ href, to self.
+      # The consequence is as an xmlns attribute with supplied argument were
+      # present in parsed XML.  A default namespace set with this method will
+      # now show up in #attributes, but when this node is serialized to XML an
+      # "xmlns" attribute will appear. See also #namespace and #namespace=
+      def default_namespace= url
+        add_namespace_definition(nil, url)
+      end
+      alias :add_namespace :add_namespace_definition
+
+      ###
+      # Set the default namespace on this node (as would be defined with an
+      # "xmlns=" attribute in XML source), as a Namespace object +ns+. Note that
+      # a Namespace added this way will NOT be serialized as an xmlns attribute
+      # for this node. You probably want #default_namespace= instead, or perhaps
+      # #add_namespace_definition with a nil prefix argument.
+      def namespace= ns
+        return set_namespace(ns) unless ns
+
+        unless Nokogiri::XML::Namespace === ns
+          raise TypeError, "#{ns.class} can't be coerced into Nokogiri::XML::Namespace"
+        end
+        if ns.document != document
+          raise ArgumentError, 'namespace must be declared on the same document'
+        end
+
+        set_namespace ns
+      end
+
+      ####
+      # Yields self and all children to +block+ recursively.
+      def traverse &block
+        children.each{|j| j.traverse(&block) }
+        block.call(self)
+      end
+
+      ###
+      # Accept a visitor.  This method calls "visit" on +visitor+ with self.
+      def accept visitor
+        visitor.visit(self)
+      end
+
+      ###
+      # Test to see if this Node is equal to +other+
+      def == other
+        return false unless other
+        return false unless other.respond_to?(:pointer_id)
+        pointer_id == other.pointer_id
+      end
+
+      ###
+      # Serialize Node using +options+.  Save options can also be set using a
+      # block. See SaveOptions.
+      #
+      # These two statements are equivalent:
+      #
+      #  node.serialize(:encoding => 'UTF-8', :save_with => FORMAT | AS_XML)
+      #
+      # or
+      #
+      #   node.serialize(:encoding => 'UTF-8') do |config|
+      #     config.format.as_xml
+      #   end
+      #
+      def serialize *args, &block
+        options = args.first.is_a?(Hash) ? args.shift : {
+          :encoding   => args[0],
+          :save_with  => args[1]
+        }
+
+        encoding = options[:encoding] || document.encoding
+        options[:encoding] = encoding
+
+        outstring = ""
+        if encoding && outstring.respond_to?(:force_encoding)
+          outstring.force_encoding(Encoding.find(encoding))
+        end
+        io = StringIO.new(outstring)
+        write_to io, options, &block
+        io.string
+      end
+
+      ###
+      # Serialize this Node to HTML
+      #
+      #   doc.to_html
+      #
+      # See Node#write_to for a list of +options+.  For formatted output,
+      # use Node#to_xhtml instead.
+      def to_html options = {}
+        # FIXME: this is a hack around broken libxml versions
+        return dump_html if Nokogiri.uses_libxml? && %w[2 6] === LIBXML_VERSION.split('.')[0..1]
+
+        options[:save_with] |= SaveOptions::DEFAULT_HTML if options[:save_with]
+        options[:save_with] = SaveOptions::DEFAULT_HTML unless options[:save_with]
+        serialize(options)
+      end
+
+      ###
+      # Serialize this Node to XML using +options+
+      #
+      #   doc.to_xml(:indent => 5, :encoding => 'UTF-8')
+      #
+      # See Node#write_to for a list of +options+
+      def to_xml options = {}
+        options[:save_with] ||= SaveOptions::DEFAULT_XML
+        serialize(options)
+      end
+
+      ###
+      # Serialize this Node to XHTML using +options+
+      #
+      #   doc.to_xhtml(:indent => 5, :encoding => 'UTF-8')
+      #
+      # See Node#write_to for a list of +options+
+      def to_xhtml options = {}
+        # FIXME: this is a hack around broken libxml versions
+        return dump_html if Nokogiri.uses_libxml? && %w[2 6] === LIBXML_VERSION.split('.')[0..1]
+
+        options[:save_with] |= SaveOptions::DEFAULT_XHTML if options[:save_with]
+        options[:save_with] = SaveOptions::DEFAULT_XHTML unless options[:save_with]
+        serialize(options)
+      end
+
+      ###
+      # Write Node to +io+ with +options+. +options+ modify the output of
+      # this method.  Valid options are:
+      #
+      # * +:encoding+ for changing the encoding
+      # * +:indent_text+ the indentation text, defaults to one space
+      # * +:indent+ the number of +:indent_text+ to use, defaults to 2
+      # * +:save_with+ a combination of SaveOptions constants.
+      #
+      # To save with UTF-8 indented twice:
+      #
+      #   node.write_to(io, :encoding => 'UTF-8', :indent => 2)
+      #
+      # To save indented with two dashes:
+      #
+      #   node.write_to(io, :indent_text => '-', :indent => 2
+      #
+      def write_to io, *options
+        options       = options.first.is_a?(Hash) ? options.shift : {}
+        encoding      = options[:encoding] || options[0]
+        if Nokogiri.jruby?
+          save_options  = options[:save_with] || options[1]
+          indent_times  = options[:indent] || 0
+        else
+          save_options  = options[:save_with] || options[1] || SaveOptions::FORMAT
+          indent_times  = options[:indent] || 2
+        end
+        indent_text   = options[:indent_text] || ' '
+
+        config = SaveOptions.new(save_options.to_i)
+        yield config if block_given?
+
+        native_write_to(io, encoding, indent_text * indent_times, config.options)
+      end
+
+      ###
+      # Write Node as HTML to +io+ with +options+
+      #
+      # See Node#write_to for a list of +options+
+      def write_html_to io, options = {}
+        # FIXME: this is a hack around broken libxml versions
+        return (io << dump_html) if Nokogiri.uses_libxml? && %w[2 6] === LIBXML_VERSION.split('.')[0..1]
+
+        options[:save_with] ||= SaveOptions::DEFAULT_HTML
+        write_to io, options
+      end
+
+      ###
+      # Write Node as XHTML to +io+ with +options+
+      #
+      # See Node#write_to for a list of +options+
+      def write_xhtml_to io, options = {}
+        # FIXME: this is a hack around broken libxml versions
+        return (io << dump_html) if Nokogiri.uses_libxml? && %w[2 6] === LIBXML_VERSION.split('.')[0..1]
+
+        options[:save_with] ||= SaveOptions::DEFAULT_XHTML
+        write_to io, options
+      end
+
+      ###
+      # Write Node as XML to +io+ with +options+
+      #
+      #   doc.write_xml_to io, :encoding => 'UTF-8'
+      #
+      # See Node#write_to for a list of options
+      def write_xml_to io, options = {}
+        options[:save_with] ||= SaveOptions::DEFAULT_XML
+        write_to io, options
+      end
+
+      ###
+      # Compare two Node objects with respect to their Document.  Nodes from
+      # different documents cannot be compared.
+      def <=> other
+        return nil unless other.is_a?(Nokogiri::XML::Node)
+        return nil unless document == other.document
+        compare other
+      end
+
+      ###
+      # Do xinclude substitution on the subtree below node. If given a block, a
+      # Nokogiri::XML::ParseOptions object initialized from +options+, will be
+      # passed to it, allowing more convenient modification of the parser options.
+      def do_xinclude options = XML::ParseOptions::DEFAULT_XML, &block
+        options = Nokogiri::XML::ParseOptions.new(options) if Fixnum === options
+
+        # give options to user
+        yield options if block_given?
+
+        # call c extension
+        process_xincludes(options.to_i)
+      end
+
+      def canonicalize(mode=XML::XML_C14N_1_0,inclusive_namespaces=nil,with_comments=false)
+        c14n_root = self
+        document.canonicalize(mode, inclusive_namespaces, with_comments) do |node, parent|
+          tn = node.is_a?(XML::Node) ? node : parent
+          tn == c14n_root || tn.ancestors.include?(c14n_root)
+        end
+      end
+
+      private
+
+      def extract_params params # :nodoc:
+        # Pop off our custom function handler if it exists
+        handler = params.find { |param|
+          ![Hash, String, Symbol].include?(param.class)
+        }
+
+        params -= [handler] if handler
+
+        hashes = []
+        while Hash === params.last || params.last.nil?
+          hashes << params.pop
+          break if params.empty?
+        end
+
+        ns, binds = hashes.reverse
+
+        ns ||= document.root ? document.root.namespaces : {}
+
+        [params, handler, ns, binds]
+      end
+
+      def coerce data # :nodoc:
+        return data                    if data.is_a?(XML::NodeSet)
+        return data.children           if data.is_a?(XML::DocumentFragment)
+        return fragment(data).children if data.is_a?(String)
+
+        if data.is_a?(Document) || data.is_a?(XML::Attr) || !data.is_a?(XML::Node)
+          raise ArgumentError, <<-EOERR
+Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
+(You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)
+          EOERR
+        end
+
+        data
+      end
+
+      def implied_xpath_context
+        "./"
+      end
+
+      def inspect_attributes
+        [:name, :namespace, :attribute_nodes, :children]
+      end
+    end
+  end
+end

+ 61 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/node/save_options.rb

@@ -0,0 +1,61 @@
+module Nokogiri
+  module XML
+    class Node
+      ###
+      # Save options for serializing nodes
+      class SaveOptions
+        # Format serialized xml
+        FORMAT          = 1
+        # Do not include declarations
+        NO_DECLARATION  = 2
+        # Do not include empty tags
+        NO_EMPTY_TAGS   = 4
+        # Do not save XHTML
+        NO_XHTML        = 8
+        # Save as XHTML
+        AS_XHTML        = 16
+        # Save as XML
+        AS_XML          = 32
+        # Save as HTML
+        AS_HTML         = 64
+
+        if Nokogiri.jruby?
+          # Save builder created document
+          AS_BUILDER    = 128
+          # the default for XML documents
+          DEFAULT_XML  = AS_XML # https://github.com/tenderlove/nokogiri/issues/#issue/415
+          # the default for HTML document
+          DEFAULT_HTML = NO_DECLARATION | NO_EMPTY_TAGS | AS_HTML
+        else
+          # the default for XML documents
+          DEFAULT_XML  = FORMAT | AS_XML
+          # the default for HTML document
+          DEFAULT_HTML = FORMAT | NO_DECLARATION | NO_EMPTY_TAGS | AS_HTML
+        end
+        # the default for XHTML document
+        DEFAULT_XHTML = FORMAT | NO_DECLARATION | NO_EMPTY_TAGS | AS_XHTML
+
+        # Integer representation of the SaveOptions
+        attr_reader :options
+
+        # Create a new SaveOptions object with +options+
+        def initialize options = 0; @options = options; end
+
+        constants.each do |constant|
+          class_eval %{
+            def #{constant.downcase}
+              @options |= #{constant}
+              self
+            end
+
+            def #{constant.downcase}?
+              #{constant} & @options == #{constant}
+            end
+          }
+        end
+
+        alias :to_i :options
+      end
+    end
+  end
+end

+ 357 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/node_set.rb

@@ -0,0 +1,357 @@
+module Nokogiri
+  module XML
+    ####
+    # A NodeSet contains a list of Nokogiri::XML::Node objects.  Typically
+    # a NodeSet is return as a result of searching a Document via
+    # Nokogiri::XML::Node#css or Nokogiri::XML::Node#xpath
+    class NodeSet
+      include Enumerable
+
+      # The Document this NodeSet is associated with
+      attr_accessor :document
+
+      # Create a NodeSet with +document+ defaulting to +list+
+      def initialize document, list = []
+        @document = document
+        document.decorate(self)
+        list.each { |x| self << x }
+        yield self if block_given?
+      end
+
+      ###
+      # Get the first element of the NodeSet.
+      def first n = nil
+        return self[0] unless n
+        list = []
+        0.upto(n - 1) do |i|
+          list << self[i]
+        end
+        list
+      end
+
+      ###
+      # Get the last element of the NodeSet.
+      def last
+        self[length - 1]
+      end
+
+      ###
+      # Is this NodeSet empty?
+      def empty?
+        length == 0
+      end
+
+      ###
+      # Returns the index of the first node in self that is == to +node+. Returns nil if no match is found.
+      def index(node)
+        each_with_index { |member, j| return j if member == node }
+        nil
+      end
+
+      ###
+      # Insert +datum+ before the first Node in this NodeSet
+      def before datum
+        first.before datum
+      end
+
+      ###
+      # Insert +datum+ after the last Node in this NodeSet
+      def after datum
+        last.after datum
+      end
+
+      alias :<< :push
+      alias :remove :unlink
+
+      ###
+      # Search this document for +paths+
+      #
+      # For more information see Nokogiri::XML::Node#css and
+      # Nokogiri::XML::Node#xpath
+      def search *paths
+        handler = ![
+          Hash, String, Symbol
+        ].include?(paths.last.class) ? paths.pop : nil
+
+        ns = paths.last.is_a?(Hash) ? paths.pop : nil
+
+        sub_set = NodeSet.new(document)
+
+        paths.each do |path|
+          sub_set += send(
+            path =~ /^(\.\/|\/)/ ? :xpath : :css,
+            *(paths + [ns, handler]).compact
+          )
+        end
+
+        document.decorate(sub_set)
+        sub_set
+      end
+      alias :/ :search
+
+      ###
+      # Search this NodeSet for css +paths+
+      #
+      # For more information see Nokogiri::XML::Node#css
+      def css *paths
+        handler = ![
+          Hash, String, Symbol
+        ].include?(paths.last.class) ? paths.pop : nil
+
+        ns = paths.last.is_a?(Hash) ? paths.pop : nil
+
+        sub_set = NodeSet.new(document)
+
+        each do |node|
+          doc = node.document
+          search_ns = ns || (doc.root ? doc.root.namespaces : {})
+
+          xpaths = paths.map { |rule|
+            [
+              CSS.xpath_for(rule.to_s, :prefix => ".//", :ns => search_ns),
+              CSS.xpath_for(rule.to_s, :prefix => "self::", :ns => search_ns)
+            ].join(' | ')
+          }
+
+          sub_set += node.xpath(*(xpaths + [search_ns, handler].compact))
+        end
+        document.decorate(sub_set)
+        sub_set
+      end
+
+      ###
+      # Search this NodeSet for XPath +paths+
+      #
+      # For more information see Nokogiri::XML::Node#xpath
+      def xpath *paths
+        handler = ![
+          Hash, String, Symbol
+        ].include?(paths.last.class) ? paths.pop : nil
+
+        ns = paths.last.is_a?(Hash) ? paths.pop : nil
+
+        sub_set = NodeSet.new(document)
+        each do |node|
+          sub_set += node.xpath(*(paths + [ns, handler].compact))
+        end
+        document.decorate(sub_set)
+        sub_set
+      end
+
+      ###
+      # Search this NodeSet's nodes' immediate children using CSS selector +selector+
+      def > selector
+        ns = document.root.namespaces
+        xpath CSS.xpath_for(selector, :prefix => "./", :ns => ns).first
+      end
+
+      ###
+      # If path is a string, search this document for +path+ returning the
+      # first Node.  Otherwise, index in to the array with +path+.
+      def at path, ns = document.root ? document.root.namespaces : {}
+        return self[path] if path.is_a?(Numeric)
+        search(path, ns).first
+      end
+      alias :% :at
+
+      ##
+      # Search this NodeSet for the first occurrence of XPath +paths+.
+      # Equivalent to <tt>xpath(paths).first</tt>
+      # See NodeSet#xpath for more information.
+      #
+      def at_xpath *paths
+        xpath(*paths).first
+      end
+
+      ##
+      # Search this NodeSet for the first occurrence of CSS +rules+.
+      # Equivalent to <tt>css(rules).first</tt>
+      # See NodeSet#css for more information.
+      #
+      def at_css *rules
+        css(*rules).first
+      end
+
+      ###
+      # Filter this list for nodes that match +expr+
+      def filter expr
+        find_all { |node| node.matches?(expr) }
+      end
+
+      ###
+      # Append the class attribute +name+ to all Node objects in the NodeSet.
+      def add_class name
+        each do |el|
+          classes = el['class'].to_s.split(/\s+/)
+          el['class'] = classes.push(name).uniq.join " "
+        end
+        self
+      end
+
+      ###
+      # Remove the class attribute +name+ from all Node objects in the NodeSet.
+      # If +name+ is nil, remove the class attribute from all Nodes in the
+      # NodeSet.
+      def remove_class name = nil
+        each do |el|
+          if name
+            classes = el['class'].to_s.split(/\s+/)
+            if classes.empty?
+              el.delete 'class'
+            else
+              el['class'] = (classes - [name]).uniq.join " "
+            end
+          else
+            el.delete "class"
+          end
+        end
+        self
+      end
+
+      ###
+      # Set the attribute +key+ to +value+ or the return value of +blk+
+      # on all Node objects in the NodeSet.
+      def attr key, value = nil, &blk
+        unless Hash === key || key && (value || blk)
+          return first.attribute(key)
+        end
+
+        hash = key.is_a?(Hash) ? key : { key => value }
+
+        hash.each { |k,v| each { |el| el[k] = v || blk[el] } }
+
+        self
+      end
+      alias :set :attr
+      alias :attribute :attr
+
+      ###
+      # Remove the attributed named +name+ from all Node objects in the NodeSet
+      def remove_attr name
+        each { |el| el.delete name }
+        self
+      end
+
+      ###
+      # Iterate over each node, yielding  to +block+
+      def each(&block)
+        0.upto(length - 1) do |x|
+          yield self[x]
+        end
+      end
+
+      ###
+      # Get the inner text of all contained Node objects
+      def inner_text
+        collect{|j| j.inner_text}.join('')
+      end
+      alias :text :inner_text
+
+      ###
+      # Get the inner html of all contained Node objects
+      def inner_html *args
+        collect{|j| j.inner_html(*args) }.join('')
+      end
+
+      ###
+      # Wrap this NodeSet with +html+ or the results of the builder in +blk+
+      def wrap(html, &blk)
+        each do |j|
+          new_parent = document.parse(html).first
+          j.add_next_sibling(new_parent)
+          new_parent.add_child(j)
+        end
+        self
+      end
+
+      ###
+      # Convert this NodeSet to a string.
+      def to_s
+        map { |x| x.to_s }.join
+      end
+
+      ###
+      # Convert this NodeSet to HTML
+      def to_html *args
+        if Nokogiri.jruby?
+          options = args.first.is_a?(Hash) ? args.shift : {}
+          if !options[:save_with]
+            options[:save_with] = Node::SaveOptions::NO_DECLARATION | Node::SaveOptions::NO_EMPTY_TAGS | Node::SaveOptions::AS_HTML
+          end
+          args.insert(0, options)
+        end
+        map { |x| x.to_html(*args) }.join
+      end
+
+      ###
+      # Convert this NodeSet to XHTML
+      def to_xhtml *args
+        map { |x| x.to_xhtml(*args) }.join
+      end
+
+      ###
+      # Convert this NodeSet to XML
+      def to_xml *args
+        map { |x| x.to_xml(*args) }.join
+      end
+
+      alias :size :length
+      alias :to_ary :to_a
+
+      ###
+      # Removes the last element from set and returns it, or +nil+ if
+      # the set is empty
+      def pop
+        return nil if length == 0
+        delete last
+      end
+
+      ###
+      # Returns the first element of the NodeSet and removes it.  Returns
+      # +nil+ if the set is empty.
+      def shift
+        return nil if length == 0
+        delete first
+      end
+
+      ###
+      # Equality -- Two NodeSets are equal if the contain the same number
+      # of elements and if each element is equal to the corresponding
+      # element in the other NodeSet
+      def == other
+        return false unless other.is_a?(Nokogiri::XML::NodeSet)
+        return false unless length == other.length
+        each_with_index do |node, i|
+          return false unless node == other[i]
+        end
+        true
+      end
+
+      ###
+      # Returns a new NodeSet containing all the children of all the nodes in
+      # the NodeSet
+      def children
+        inject(NodeSet.new(document)) { |set, node| set += node.children }
+      end
+
+      ###
+      # Returns a new NodeSet containing all the nodes in the NodeSet
+      # in reverse order
+      def reverse
+        node_set = NodeSet.new(document)
+        (length - 1).downto(0) do |x|
+          node_set.push self[x]
+        end
+        node_set
+      end
+
+      ###
+      # Return a nicely formated string representation
+      def inspect
+        "[#{map { |c| c.inspect }.join ', '}]"
+      end
+
+      alias :+ :|
+    end
+  end
+end

+ 6 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/notation.rb

@@ -0,0 +1,6 @@
+module Nokogiri
+  module XML
+    class Notation < Struct.new(:name, :public_id, :system_id)
+    end
+  end
+end

+ 93 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/parse_options.rb

@@ -0,0 +1,93 @@
+module Nokogiri
+  module XML
+    ###
+    # Parse options for passing to Nokogiri.XML or Nokogiri.HTML
+    class ParseOptions
+      # Strict parsing
+      STRICT      = 0
+      # Recover from errors
+      RECOVER     = 1 << 0
+      # Substitute entities
+      NOENT       = 1 << 1
+      # Load external subsets
+      DTDLOAD     = 1 << 2
+      # Default DTD attributes
+      DTDATTR     = 1 << 3
+      # validate with the DTD
+      DTDVALID    = 1 << 4
+      # suppress error reports
+      NOERROR     = 1 << 5
+      # suppress warning reports
+      NOWARNING   = 1 << 6
+      # pedantic error reporting
+      PEDANTIC    = 1 << 7
+      # remove blank nodes
+      NOBLANKS    = 1 << 8
+      # use the SAX1 interface internally
+      SAX1        = 1 << 9
+      # Implement XInclude substitition
+      XINCLUDE    = 1 << 10
+      # Forbid network access
+      NONET       = 1 << 11
+      # Do not reuse the context dictionnary
+      NODICT      = 1 << 12
+      # remove redundant namespaces declarations
+      NSCLEAN     = 1 << 13
+      # merge CDATA as text nodes
+      NOCDATA     = 1 << 14
+      # do not generate XINCLUDE START/END nodes
+      NOXINCNODE  = 1 << 15
+      # compact small text nodes; no modification of the tree allowed afterwards (will possibly crash if you try to modify the tree)
+      COMPACT     = 1 << 16
+      # parse using XML-1.0 before update 5
+      OLD10       = 1 << 17
+      # do not fixup XINCLUDE xml:base uris
+      NOBASEFIX   = 1 << 18
+      # relax any hardcoded limit from the parser
+      HUGE        = 1 << 19
+
+      # the default options used for parsing XML documents
+      DEFAULT_XML  = RECOVER
+      # the default options used for parsing HTML documents
+      DEFAULT_HTML = RECOVER | NOERROR | NOWARNING | NONET
+
+      attr_accessor :options
+      def initialize options = STRICT
+        @options = options
+      end
+
+      constants.each do |constant|
+        next if constant.to_sym == :STRICT
+        class_eval %{
+          def #{constant.downcase}
+            @options |= #{constant}
+            self
+          end
+
+          def #{constant.downcase}?
+            #{constant} & @options == #{constant}
+          end
+        }
+      end
+
+      def strict
+        @options &= ~RECOVER
+        self
+      end
+
+      def strict?
+        @options & RECOVER == STRICT
+      end
+
+      alias :to_i :options
+
+      def inspect
+        options = []
+        self.class.constants.each do |k|
+          options << k.downcase if send(:"#{k.downcase}?")
+        end
+        super.sub(/>$/, " " + options.join(', ') + ">")
+      end
+    end
+  end
+end

+ 2 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/pp.rb

@@ -0,0 +1,2 @@
+require 'nokogiri/xml/pp/node'
+require 'nokogiri/xml/pp/character_data'

+ 18 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/pp/character_data.rb

@@ -0,0 +1,18 @@
+module Nokogiri
+  module XML
+    module PP
+      module CharacterData
+        def pretty_print pp # :nodoc:
+          nice_name = self.class.name.split('::').last
+          pp.group(2, "#(#{nice_name} ", ')') do
+            pp.pp text
+          end
+        end
+
+        def inspect # :nodoc:
+          "#<#{self.class.name}:#{sprintf("0x%x",object_id)} #{text.inspect}>"
+        end
+      end
+    end
+  end
+end

+ 56 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/pp/node.rb

@@ -0,0 +1,56 @@
+module Nokogiri
+  module XML
+    module PP
+      module Node
+        def inspect # :nodoc:
+          attributes = inspect_attributes.reject { |x|
+            begin
+              attribute = send x
+              !attribute || (attribute.respond_to?(:empty?) && attribute.empty?)
+            rescue NoMethodError
+              true
+            end
+          }.map { |attribute|
+            "#{attribute.to_s.sub(/_\w+/, 's')}=#{send(attribute).inspect}"
+          }.join ' '
+          "#<#{self.class.name}:#{sprintf("0x%x", object_id)} #{attributes}>"
+        end
+
+        def pretty_print pp # :nodoc:
+          nice_name = self.class.name.split('::').last
+          pp.group(2, "#(#{nice_name}:#{sprintf("0x%x", object_id)} {", '})') do
+
+            pp.breakable
+            attrs = inspect_attributes.map { |t|
+              [t, send(t)] if respond_to?(t)
+            }.compact.find_all { |x|
+              if x.last
+                if [:attribute_nodes, :children].include? x.first
+                  !x.last.empty?
+                else
+                  true
+                end
+              end
+            }
+
+            pp.seplist(attrs) do |v|
+              if [:attribute_nodes, :children].include? v.first
+                pp.group(2, "#{v.first.to_s.sub(/_\w+$/, 's')} = [", "]") do
+                  pp.breakable
+                  pp.seplist(v.last) do |item|
+                    pp.pp item
+                  end
+                end
+              else
+                pp.text "#{v.first} = "
+                pp.pp v.last
+              end
+            end
+            pp.breakable
+
+          end
+        end
+      end
+    end
+  end
+end

+ 8 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/processing_instruction.rb

@@ -0,0 +1,8 @@
+module Nokogiri
+  module XML
+    class ProcessingInstruction < Node
+      def initialize document, name, content
+      end
+    end
+  end
+end

+ 112 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/reader.rb

@@ -0,0 +1,112 @@
+module Nokogiri
+  module XML
+    ###
+    # Nokogiri::XML::Reader parses an XML document similar to the way a cursor
+    # would move.  The Reader is given an XML document, and yields nodes
+    # to an each block.
+    #
+    # Here is an example of usage:
+    #
+    #   reader = Nokogiri::XML::Reader(<<-eoxml)
+    #     <x xmlns:tenderlove='http://tenderlovemaking.com/'>
+    #       <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
+    #     </x>
+    #   eoxml
+    #
+    #   reader.each do |node|
+    #
+    #     # node is an instance of Nokogiri::XML::Reader
+    #     puts node.name
+    #
+    #   end
+    #
+    # Note that Nokogiri::XML::Reader#each can only be called once!!  Once
+    # the cursor moves through the entire document, you must parse the
+    # document again.  So make sure that you capture any information you
+    # need during the first iteration.
+    #
+    # The Reader parser is good for when you need the speed of a SAX parser,
+    # but do not want to write a Document handler.
+    class Reader
+      include Enumerable
+
+      TYPE_NONE = 0
+      # Element node type
+      TYPE_ELEMENT = 1
+      # Attribute node type
+      TYPE_ATTRIBUTE = 2
+      # Text node type
+      TYPE_TEXT = 3
+      # CDATA node type
+      TYPE_CDATA = 4
+      # Entity Reference node type
+      TYPE_ENTITY_REFERENCE = 5
+      # Entity node type
+      TYPE_ENTITY = 6
+      # PI node type
+      TYPE_PROCESSING_INSTRUCTION = 7
+      # Comment node type
+      TYPE_COMMENT = 8
+      # Document node type
+      TYPE_DOCUMENT = 9
+      # Document Type node type
+      TYPE_DOCUMENT_TYPE = 10
+      # Document Fragment node type
+      TYPE_DOCUMENT_FRAGMENT = 11
+      # Notation node type
+      TYPE_NOTATION = 12
+      # Whitespace node type
+      TYPE_WHITESPACE = 13
+      # Significant Whitespace node type
+      TYPE_SIGNIFICANT_WHITESPACE = 14
+      # Element end node type
+      TYPE_END_ELEMENT = 15
+      # Entity end node type
+      TYPE_END_ENTITY = 16
+      # XML Declaration node type
+      TYPE_XML_DECLARATION = 17
+
+      # A list of errors encountered while parsing
+      attr_accessor :errors
+
+      # The encoding for the document
+      attr_reader :encoding
+
+      # The XML source
+      attr_reader :source
+
+      alias :self_closing? :empty_element?
+
+      def initialize source, url = nil, encoding = nil # :nodoc:
+        @source   = source
+        @errors   = []
+        @encoding = encoding
+      end
+      private :initialize
+
+      ###
+      # Get a list of attributes for the current node.
+      def attributes
+        Hash[attribute_nodes.map { |node|
+          [node.name, node.to_s]
+        }].merge(namespaces || {})
+      end
+
+      ###
+      # Get a list of attributes for the current node
+      def attribute_nodes
+        nodes = attr_nodes
+        nodes.each { |v| v.instance_variable_set(:@_r, self) }
+        nodes
+      end
+
+      ###
+      # Move the cursor through the document yielding the cursor to the block
+      def each
+        while cursor = self.read
+          yield cursor
+        end
+      end
+    end
+  end
+end

+ 32 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/relax_ng.rb

@@ -0,0 +1,32 @@
+module Nokogiri
+  module XML
+    class << self
+      ###
+      # Create a new Nokogiri::XML::RelaxNG document from +string_or_io+.
+      # See Nokogiri::XML::RelaxNG for an example.
+      def RelaxNG string_or_io
+        RelaxNG.new(string_or_io)
+      end
+    end
+
+    ###
+    # Nokogiri::XML::RelaxNG is used for validating XML against a
+    # RelaxNG schema.
+    #
+    # == Synopsis
+    #
+    # Validate an XML document against a RelaxNG schema.  Loop over the errors
+    # that are returned and print them out:
+    #
+    #   schema  = Nokogiri::XML::RelaxNG(File.open(ADDRESS_SCHEMA_FILE))
+    #   doc     = Nokogiri::XML(File.open(ADDRESS_XML_FILE))
+    #
+    #   schema.validate(doc).each do |error|
+    #     puts error.message
+    #   end
+    #
+    # The list of errors are Nokogiri::XML::SyntaxError objects.
+    class RelaxNG < Nokogiri::XML::Schema
+    end
+  end
+end

+ 4 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/sax.rb

@@ -0,0 +1,4 @@
+require 'nokogiri/xml/sax/document'
+require 'nokogiri/xml/sax/parser_context'
+require 'nokogiri/xml/sax/parser'
+require 'nokogiri/xml/sax/push_parser'

+ 164 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/sax/document.rb

@@ -0,0 +1,164 @@
+module Nokogiri
+  module XML
+    ###
+    # SAX Parsers are event driven parsers.  Nokogiri provides two different
+    # event based parsers when dealing with XML.  If you want to do SAX style
+    # parsing using HTML, check out Nokogiri::HTML::SAX.
+    #
+    # The basic way a SAX style parser works is by creating a parser,
+    # telling the parser about the events we're interested in, then giving
+    # the parser some XML to process.  The parser will notify you when
+    # it encounters events your said you would like to know about.
+    #
+    # To register for events, you simply subclass Nokogiri::XML::SAX::Document,
+    # and implement the methods for which you would like notification.
+    #
+    # For example, if I want to be notified when a document ends, and when an
+    # element starts, I would write a class like this:
+    #
+    #   class MyDocument < Nokogiri::XML::SAX::Document
+    #     def end_document
+    #       puts "the document has ended"
+    #     end
+    #
+    #     def start_element name, attributes = []
+    #       puts "#{name} started"
+    #     end
+    #   end
+    #
+    # Then I would instantiate a SAX parser with this document, and feed the
+    # parser some XML
+    #
+    #   # Create a new parser
+    #   parser = Nokogiri::XML::SAX::Parser.new(MyDocument.new)
+    #
+    #   # Feed the parser some XML
+    #   parser.parse(File.read(ARGV[0], 'rb'))
+    #
+    # Now my document handler will be called when each node starts, and when
+    # then document ends.  To see what kinds of events are available, take
+    # a look at Nokogiri::XML::SAX::Document.
+    #
+    # Two SAX parsers for XML are available, a parser that reads from a string
+    # or IO object as it feels necessary, and a parser that lets you spoon
+    # feed it XML.  If you want to let Nokogiri deal with reading your XML,
+    # use the Nokogiri::XML::SAX::Parser.  If you want to have fine grain
+    # control over the XML input, use the Nokogiri::XML::SAX::PushParser.
+    module SAX
+      ###
+      # This class is used for registering types of events you are interested
+      # in handling.  All of the methods on this class are available as
+      # possible events while parsing an XML document.  To register for any
+      # particular event, just subclass this class and implement the methods
+      # you are interested in knowing about.
+      #
+      # To only be notified about start and end element events, write a class
+      # like this:
+      #
+      #   class MyDocument < Nokogiri::XML::SAX::Document
+      #     def start_element name, attrs = []
+      #       puts "#{name} started!"
+      #     end
+      #
+      #     def end_element name
+      #       puts "#{name} ended"
+      #     end
+      #   end
+      #
+      # You can use this event handler for any SAX style parser included with
+      # Nokogiri.  See Nokogiri::XML::SAX, and Nokogiri::HTML::SAX.
+      class Document
+        ###
+        # Called when an XML declaration is parsed
+        def xmldecl version, encoding, standalone
+        end
+
+        ###
+        # Called when document starts parsing
+        def start_document
+        end
+
+        ###
+        # Called when document ends parsing
+        def end_document
+        end
+
+        ###
+        # Called at the beginning of an element
+        # * +name+ is the name of the tag
+        # * +attrs+ are an assoc list of namespaces and attributes, e.g.:
+        #     [ ["xmlns:foo", "http://sample.net"], ["size", "large"] ]
+        def start_element name, attrs = []
+        end
+
+        ###
+        # Called at the end of an element
+        # +name+ is the tag name
+        def end_element name
+        end
+
+        ###
+        # Called at the beginning of an element
+        # +name+ is the element name
+        # +attrs+ is a list of attributes
+        # +prefix+ is the namespace prefix for the element
+        # +uri+ is the associated namespace URI
+        # +ns+ is a hash of namespace prefix:urls associated with the element
+        def start_element_namespace name, attrs = [], prefix = nil, uri = nil, ns = []
+          ###
+          # Deal with SAX v1 interface
+          name = [prefix, name].compact.join(':')
+          attributes = ns.map { |ns_prefix,ns_uri|
+            [['xmlns', ns_prefix].compact.join(':'), ns_uri]
+          } + attrs.map { |attr|
+            [[attr.prefix, attr.localname].compact.join(':'), attr.value]
+          }
+          start_element name, attributes
+        end
+
+        ###
+        # Called at the end of an element
+        # +name+ is the element's name
+        # +prefix+ is the namespace prefix associated with the element
+        # +uri+ is the associated namespace URI
+        def end_element_namespace name, prefix = nil, uri = nil
+          ###
+          # Deal with SAX v1 interface
+          end_element [prefix, name].compact.join(':')
+        end
+
+        ###
+        # Characters read between a tag.  This method might be called multiple
+        # times given one contiguous string of characters.
+        #
+        # +string+ contains the character data
+        def characters string
+        end
+
+        ###
+        # Called when comments are encountered
+        # +string+ contains the comment data
+        def comment string
+        end
+
+        ###
+        # Called on document warnings
+        # +string+ contains the warning
+        def warning string
+        end
+
+        ###
+        # Called on document errors
+        # +string+ contains the error
+        def error string
+        end
+
+        ###
+        # Called when cdata blocks are found
+        # +string+ contains the cdata content
+        def cdata_block string
+        end
+      end
+    end
+  end
+end

+ 115 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/sax/parser.rb

@@ -0,0 +1,115 @@
+module Nokogiri
+  module XML
+    module SAX
+      ###
+      # This parser is a SAX style parser that reads it's input as it
+      # deems necessary.  The parser takes a Nokogiri::XML::SAX::Document,
+      # an optional encoding, then given an XML input, sends messages to
+      # the Nokogiri::XML::SAX::Document.
+      #
+      # Here is an example of using this parser:
+      #
+      #   # Create a subclass of Nokogiri::XML::SAX::Document and implement
+      #   # the events we care about:
+      #   class MyDoc < Nokogiri::XML::SAX::Document
+      #     def start_element name, attrs = []
+      #       puts "starting: #{name}"
+      #     end
+      #
+      #     def end_element name
+      #       puts "ending: #{name}"
+      #     end
+      #   end
+      #
+      #   # Create our parser
+      #   parser = Nokogiri::XML::SAX::Parser.new(MyDoc.new)
+      #
+      #   # Send some XML to the parser
+      #   parser.parse(File.read(ARGV[0]))
+      #
+      # For more information about SAX parsers, see Nokogiri::XML::SAX.  Also
+      # see Nokogiri::XML::SAX::Document for the available events.
+      class Parser
+        class Attribute < Struct.new(:localname, :prefix, :uri, :value)
+        end
+
+        # Encodinds this parser supports
+        ENCODINGS = {
+          'NONE'        => 0, # No char encoding detected
+          'UTF-8'       => 1, # UTF-8
+          'UTF16LE'     => 2, # UTF-16 little endian
+          'UTF16BE'     => 3, # UTF-16 big endian
+          'UCS4LE'      => 4, # UCS-4 little endian
+          'UCS4BE'      => 5, # UCS-4 big endian
+          'EBCDIC'      => 6, # EBCDIC uh!
+          'UCS4-2143'   => 7, # UCS-4 unusual ordering
+          'UCS4-3412'   => 8, # UCS-4 unusual ordering
+          'UCS2'        => 9, # UCS-2
+          'ISO-8859-1'  => 10, # ISO-8859-1 ISO Latin 1
+          'ISO-8859-2'  => 11, # ISO-8859-2 ISO Latin 2
+          'ISO-8859-3'  => 12, # ISO-8859-3
+          'ISO-8859-4'  => 13, # ISO-8859-4
+          'ISO-8859-5'  => 14, # ISO-8859-5
+          'ISO-8859-6'  => 15, # ISO-8859-6
+          'ISO-8859-7'  => 16, # ISO-8859-7
+          'ISO-8859-8'  => 17, # ISO-8859-8
+          'ISO-8859-9'  => 18, # ISO-8859-9
+          'ISO-2022-JP' => 19, # ISO-2022-JP
+          'SHIFT-JIS'   => 20, # Shift_JIS
+          'EUC-JP'      => 21, # EUC-JP
+          'ASCII'       => 22, # pure ASCII
+        }
+
+        # The Nokogiri::XML::SAX::Document where events will be sent.
+        attr_accessor :document
+
+        # The encoding beings used for this document.
+        attr_accessor :encoding
+
+        # Create a new Parser with +doc+ and +encoding+
+        def initialize doc = Nokogiri::XML::SAX::Document.new, encoding = 'UTF-8'
+          @encoding = encoding
+          @document = doc
+          @warned   = false
+        end
+
+        ###
+        # Parse given +thing+ which may be a string containing xml, or an
+        # IO object.
+        def parse thing, &block
+          if thing.respond_to?(:read) && thing.respond_to?(:close)
+            parse_io(thing, &block)
+          else
+            parse_memory(thing, &block)
+          end
+        end
+
+        ###
+        # Parse given +io+
+        def parse_io io, encoding = 'ASCII'
+          @encoding = encoding
+          ctx = ParserContext.io(io, ENCODINGS[encoding])
+          yield ctx if block_given?
+          ctx.parse_with self
+        end
+
+        ###
+        # Parse a file with +filename+
+        def parse_file filename
+          raise ArgumentError unless filename
+          raise Errno::ENOENT unless File.exists?(filename)
+          raise Errno::EISDIR if File.directory?(filename)
+          ctx = ParserContext.file filename
+          yield ctx if block_given?
+          ctx.parse_with self
+        end
+
+        def parse_memory data
+          ctx = ParserContext.memory data
+          yield ctx if block_given?
+          ctx.parse_with self
+        end
+      end
+    end
+  end
+end

+ 16 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/sax/parser_context.rb

@@ -0,0 +1,16 @@
+module Nokogiri
+  module XML
+    module SAX
+      ###
+      # Context for XML SAX parsers.  This class is usually not instantiated
+      # by the user.  Instead, you should be looking at
+      # Nokogiri::XML::SAX::Parser
+      class ParserContext
+        def self.new thing, encoding = 'UTF-8'
+          [:read, :close].all? { |x| thing.respond_to?(x) } ?
+            io(thing, Parser::ENCODINGS[encoding]) : memory(thing)
+        end
+      end
+    end
+  end
+end

+ 60 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/sax/push_parser.rb

@@ -0,0 +1,60 @@
+module Nokogiri
+  module XML
+    module SAX
+      ###
+      # PushParser can parse a document that is fed to it manually.  It
+      # must be given a SAX::Document object which will be called with
+      # SAX events as the document is being parsed.
+      #
+      # Calling PushParser#<< writes XML to the parser, calling any SAX
+      # callbacks it can.
+      #
+      # PushParser#finish tells the parser that the document is finished
+      # and calls the end_document SAX method.
+      #
+      # Example:
+      #
+      #   parser = PushParser.new(Class.new(XML::SAX::Document) {
+      #     def start_document
+      #       puts "start document called"
+      #     end
+      #   }.new)
+      #   parser << "<div>hello<"
+      #   parser << "/div>"
+      #   parser.finish
+      class PushParser
+
+        # The Nokogiri::XML::SAX::Document on which the PushParser will be
+        # operating
+        attr_accessor :document
+
+        ###
+        # Create a new PushParser with +doc+ as the SAX Document, providing
+        # an optional +file_name+ and +encoding+
+        def initialize(doc = XML::SAX::Document.new, file_name = nil, encoding = 'UTF-8')
+          @document = doc
+          @encoding = encoding
+          @sax_parser = XML::SAX::Parser.new(doc)
+
+          ## Create our push parser context
+          initialize_native(@sax_parser, file_name)
+        end
+
+        ###
+        # Write a +chunk+ of XML to the PushParser.  Any callback methods
+        # that can be called will be called immediately.
+        def write chunk, last_chunk = false
+          native_write(chunk, last_chunk)
+        end
+        alias :<< :write
+
+        ###
+        # Finish the parsing.  This method is only necessary for
+        # Nokogiri::XML::SAX::Document#end_document to be called.
+        def finish
+          write '', true
+        end
+      end
+    end
+  end
+end

+ 63 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/schema.rb

@@ -0,0 +1,63 @@
+module Nokogiri
+  module XML
+    class << self
+      ###
+      # Create a new Nokogiri::XML::Schema object using a +string_or_io+
+      # object.
+      def Schema string_or_io
+        Schema.new(string_or_io)
+      end
+    end
+
+    ###
+    # Nokogiri::XML::Schema is used for validating XML against a schema
+    # (usually from an xsd file).
+    #
+    # == Synopsis
+    #
+    # Validate an XML document against a Schema.  Loop over the errors that
+    # are returned and print them out:
+    #
+    #   xsd = Nokogiri::XML::Schema(File.read(PO_SCHEMA_FILE))
+    #   doc = Nokogiri::XML(File.read(PO_XML_FILE))
+    #
+    #   xsd.validate(doc).each do |error|
+    #     puts error.message
+    #   end
+    #
+    # The list of errors are Nokogiri::XML::SyntaxError objects.
+    class Schema
+      # Errors while parsing the schema file
+      attr_accessor :errors
+
+      ###
+      # Create a new Nokogiri::XML::Schema object using a +string_or_io+
+      # object.
+      def self.new string_or_io
+        from_document Nokogiri::XML(string_or_io)
+      end
+
+      ###
+      # Validate +thing+ against this schema.  +thing+ can be a
+      # Nokogiri::XML::Document object, or a filename.  An Array of
+      # Nokogiri::XML::SyntaxError objects found while validating the
+      # +thing+ is returned.
+      def validate thing
+        if thing.is_a?(Nokogiri::XML::Document) 
+          validate_document(thing) 
+        elsif File.file?(thing)
+          validate_file(thing)
+        else
+          raise ArgumentError, "Must provide Nokogiri::Xml::Document or the name of an existing file"
+        end
+      end
+
+      ###
+      # Returns true if +thing+ is a valid Nokogiri::XML::Document or
+      # file.
+      def valid? thing
+        validate(thing).length == 0
+      end
+    end
+  end
+end

+ 47 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/syntax_error.rb

@@ -0,0 +1,47 @@
+module Nokogiri
+  module XML
+    ###
+    # This class provides information about XML SyntaxErrors.  These
+    # exceptions are typically stored on Nokogiri::XML::Document#errors.
+    class SyntaxError < ::Nokogiri::SyntaxError
+      attr_reader :domain
+      attr_reader :code
+      attr_reader :level
+      attr_reader :file
+      attr_reader :line
+      attr_reader :str1
+      attr_reader :str2
+      attr_reader :str3
+      attr_reader :int1
+      attr_reader :column
+
+      ###
+      # return true if this is a non error
+      def none?
+        level == 0
+      end
+
+      ###
+      # return true if this is a warning
+      def warning?
+        level == 1
+      end
+
+      ###
+      # return true if this is an error
+      def error?
+        level == 2
+      end
+
+      ###
+      # return true if this error is fatal
+      def fatal?
+        level == 3
+      end
+
+      def to_s
+        super.chomp
+      end
+    end
+  end
+end

+ 9 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/text.rb

@@ -0,0 +1,9 @@
+module Nokogiri
+  module XML
+    class Text < Nokogiri::XML::CharacterData
+      def content=(string)
+        self.native_content = string.to_s
+      end
+    end
+  end
+end

+ 10 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/xpath.rb

@@ -0,0 +1,10 @@
+require 'nokogiri/xml/xpath/syntax_error'
+
+module Nokogiri
+  module XML
+    class XPath
+      # The Nokogiri::XML::Document tied to this XPath instance
+      attr_accessor :document
+    end
+  end
+end

+ 11 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/xpath/syntax_error.rb

@@ -0,0 +1,11 @@
+module Nokogiri
+  module XML
+    class XPath
+      class SyntaxError < XML::SyntaxError
+        def to_s
+          [super.chomp, str1].compact.join(': ')
+        end
+      end
+    end
+  end
+end

+ 16 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xml/xpath_context.rb

@@ -0,0 +1,16 @@
+module Nokogiri
+  module XML
+    class XPathContext
+
+      ###
+      # Register namespaces in +namespaces+
+      def register_namespaces(namespaces)
+        namespaces.each do |k, v|
+          k = k.gsub(/.*:/,'') # strip off 'xmlns:' or 'xml:'
+          register_ns(k, v)
+        end
+      end
+
+    end
+  end
+end

+ 56 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xslt.rb

@@ -0,0 +1,56 @@
+require 'nokogiri/xslt/stylesheet'
+
+module Nokogiri
+  class << self
+    ###
+    # Create a Nokogiri::XSLT::Stylesheet with +stylesheet+.
+    #
+    # Example:
+    #
+    #   xslt = Nokogiri::XSLT(File.read(ARGV[0]))
+    #
+    def XSLT stylesheet, modules = {}
+      XSLT.parse(stylesheet, modules)
+    end
+  end
+
+  ###
+  # See Nokogiri::XSLT::Stylesheet for creating and maniuplating
+  # Stylesheet object.
+  module XSLT
+    class << self
+      ###
+      # Parse the stylesheet in +string+, register any +modules+
+      def parse string, modules = {}
+        modules.each do |url, klass|
+          XSLT.register url, klass
+	end
+
+        if Nokogiri.jruby?
+          Stylesheet.parse_stylesheet_doc(XML.parse(string), string)
+        else
+          Stylesheet.parse_stylesheet_doc(XML.parse(string))
+        end
+      end
+
+      ###
+      # Quote parameters in +params+ for stylesheet safety
+      def quote_params params
+        parray = (params.instance_of?(Hash) ? params.to_a.flatten : params).dup
+        parray.each_with_index do |v,i|
+          if i % 2 > 0
+            parray[i]=
+              if v =~ /'/
+                "concat('#{ v.gsub(/'/, %q{', "'", '}) }')"
+              else
+                "'#{v}'";
+              end
+          else
+            parray[i] = v.to_s
+          end
+        end
+        parray.flatten
+      end
+    end
+  end
+end

+ 25 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/nokogiri/xslt/stylesheet.rb

@@ -0,0 +1,25 @@
+module Nokogiri
+  module XSLT
+    ###
+    # A Stylesheet represents an XSLT Stylesheet object.  Stylesheet creation
+    # is done through Nokogiri.XSLT.  Here is an example of transforming
+    # an XML::Document with a Stylesheet:
+    #
+    #   doc   = Nokogiri::XML(File.read('some_file.xml'))
+    #   xslt  = Nokogiri::XSLT(File.read('some_transformer.xslt'))
+    #
+    #   puts xslt.transform(doc)
+    #
+    # See Nokogiri::XSLT::Stylesheet#transform for more transformation
+    # information.
+    class Stylesheet
+      ###
+      # Apply an XSLT stylesheet to an XML::Document.
+      # +params+ is an array of strings used as XSLT parameters.
+      # returns serialized document
+      def apply_to document, params = []
+        serialize(transform(document, params))
+      end
+    end
+  end
+end

BIN
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/xercesImpl.jar


+ 90 - 0
JBidwatcher/lib/jbidwatcher/nokogiri-1.5.2-java/lib/xsd/xmlparser/nokogiri.rb

@@ -0,0 +1,90 @@
+require 'nokogiri'
+
+module XSD # :nodoc:
+  module XMLParser # :nodoc:
+    ###
+    # Nokogiri XML parser for soap4r.
+    #
+    # Nokogiri may be used as the XML parser in soap4r.  Simply require
+    # 'xsd/xmlparser/nokogiri' in your soap4r applications, and soap4r
+    # will use Nokogiri as it's XML parser.  No other changes should be
+    # required to use Nokogiri as the XML parser.
+    #
+    # Example (using UW ITS Web Services):
+    #
+    #   require 'rubygems'
+    #   require 'nokogiri'
+    #   gem 'soap4r'
+    #   require 'defaultDriver'
+    #   require 'xsd/xmlparser/nokogiri'
+    #   
+    #   obj = AvlPortType.new
+    #   obj.getLatestByRoute(obj.getAgencies.first, 8).each do |bus|
+    #     p "#{bus.routeID}, #{bus.longitude}, #{bus.latitude}"
+    #   end
+    #
+    class Nokogiri < XSD::XMLParser::Parser
+      ###
+      # Create a new XSD parser with +host+ and +opt+
+      def initialize host, opt = {}
+        super
+        @parser = ::Nokogiri::XML::SAX::Parser.new(self, @charset || 'UTF-8')
+      end
+
+      ###
+      # Start parsing +string_or_readable+
+      def do_parse string_or_readable
+        @parser.parse(string_or_readable)
+      end
+
+      ###
+      # Handle the start_element event with +name+ and +attrs+
+      def start_element name, attrs = []
+        super(name, Hash[*attrs.flatten])
+      end
+
+      ###
+      # Handle the end_element event with +name+
+      def end_element name
+        super
+      end
+
+      ###
+      # Handle errors with message +msg+
+      def error msg
+        raise ParseError.new(msg)
+      end
+      alias :warning :error
+
+      ###
+      # Handle cdata_blocks containing +string+
+      def cdata_block string
+        characters string
+      end
+
+      def start_element_namespace name, attrs = [], prefix = nil, uri = nil, ns = []
+        ###
+        # Deal with SAX v1 interface
+        name = [prefix, name].compact.join(':')
+        attributes = ns.map { |ns_prefix,ns_uri|
+          [['xmlns', ns_prefix].compact.join(':'), ns_uri]
+        } + attrs.map { |attr|
+          [[attr.prefix, attr.localname].compact.join(':'), attr.value]
+        }.flatten
+        start_element name, attributes
+      end
+
+      def end_element_namespace name, prefix = nil, uri = nil
+        ###
+        # Deal with SAX v1 interface
+        end_element [prefix, name].compact.join(':')
+      end
+
+      %w{ xmldecl start_document end_document comment }.each do |name|
+        class_eval %{ def #{name}(*args); end }
+      end
+
+      add_factory(self)
+    end
+  end
+end

+ 34 - 0
JBidwatcher/lib/jbidwatcher/parser.rb

@@ -0,0 +1,34 @@
+#
+#  parser.rb
+#  MacBidwatcher
+#
+#  Created by Morgan Schweers on 7/24/11.
+#  Copyright 2011 CyberFOX Software, Inc. All rights reserved.
+#
+
+require 'nokogiri'
+
+class Parser
+  # @param page The HTML of the page to parse
+  def initialize(page)
+    @page = Nokogiri::HTML.parse(page)
+  end
+  
+  def match_set(match)
+    match_step = 0
+    result = []
+    @page.root.traverse do |node|
+      if node.text?
+        if node.text.strip.match(match[match_step])
+          result << node.text
+          match_step += 1
+          return result if match_step == match.length
+        elsif !node.text.strip.empty? && !result.empty?
+          result.clear
+          match_step = 0
+        end
+      end
+    end
+    nil
+  end
+end

+ 6 - 0
JBidwatcher/lib/jbidwatcher/run_crazy

@@ -0,0 +1,6 @@
+#!/bin/bash
+FILELOC=`dirname $0`
+JARCLASSES=$(ruby -e 'puts ARGV.reject {|x| x.include? "jruby"}.join(":")' `ls -1 $FILELOC/../*.jar`)
+export CLASSPATH=$FILELOC/../../classes:$JARCLASSES
+
+~/oss/jruby-1.7.18/bin/jruby -S rspec -I $FILELOC $@ $FILELOC/column_lookup_spec.rb

+ 6 - 0
JBidwatcher/lib/jbidwatcher/run_utils

@@ -0,0 +1,6 @@
+#!/bin/bash
+FILELOC=`dirname $0`
+JARCLASSES=$(ruby -e 'puts ARGV.reject {|x| x.include? "jruby"}.join(":")' `ls -1 $FILELOC/../*.jar`)
+CLASSPATH=$FILELOC/../../classes:$JARCLASSES
+
+java -Xmx500m -Xss2048k -Dfile.encoding=UTF-8 -Xbootclasspath/a:$FILELOC/../jruby-incomplete.jar -classpath $CLASSPATH -Djruby.home=$HOME/oss/jruby-1.7.18 -Djruby.script=jruby -Djruby.shell=/bin/sh org.jruby.Main -S rspec -I $FILELOC:$FILELOC/nokogiri-1.5.2-java/lib $@ $FILELOC/utilities_spec.rb

+ 324 - 0
JBidwatcher/lib/jbidwatcher/utilities.rb

@@ -0,0 +1,324 @@
+require 'java'
+
+java_import com.jbidwatcher.util.config.JConfig
+java_import com.cyberfox.util.platform.Path
+java_import com.jbidwatcher.util.Currency
+java_import com.jbidwatcher.util.Constants
+java_import com.jbidwatcher.util.queue.MQFactory
+java_import com.jbidwatcher.auction.AuctionEntry
+java_import com.jbidwatcher.auction.server.AuctionServerManager
+java_import com.jbidwatcher.ui.AuctionsManager
+java_import com.jbidwatcher.ui.FilterManager
+java_import com.jbidwatcher.ui.table.TableColumnController
+java_import com.jbidwatcher.ui.commands.UserActions
+java_import com.jbidwatcher.ui.commands.MenuCommand
+
+puts "Loading JBidwatcher Ruby Utilities"
+
+require 'rubygems'
+dirname = File.dirname(__FILE__)
+gems = if File.exists?(File.join(dirname, 'gems.jar')) || File.exists?('lib/jbidwatcher/gems.jar')
+  File.expand_path(File.join(dirname, 'gems.jar'))
+else
+  JConfig.java_class.class_loader.resource_as_url('lib/jbidwatcher/gems.jar').to_s
+end
+
+# This is an awful hack, but if I don't do this, Windows doesn't load active_support. :(
+class File
+  def self.realpath(x)
+    x
+  end
+end
+
+require gems
+ENV['GEM_PATH']="#{gems}!/"
+Gem.paths = ENV
+require 'digest/md5'
+require 'net/http.rb'
+require 'cgi'
+require 'nokogiri'
+require 'json'
+require 'open-uri'
+require 'ebay_parser'
+require 'time'
+require 'column_lookup'
+
+class JBidwatcherUtilities
+  MY_JBIDWATCHER_URL = "http://my.jbidwatcher.com:9876/advanced"
+
+  def test_basics
+    # Check that the basic libraries work.
+    puts "This is a test..."
+    puts Digest::MD5.hexdigest('foo')
+
+    # Check that accessing objects defined by JBidwatcher works
+    c = Currency.getCurrency("$54.98")
+    puts c.getValue
+    puts c.fullCurrencyName
+
+    puts "Done."
+  end
+
+  def about
+    MQFactory.getConcrete("user").enqueue("FAQ")
+  end
+
+  def fire(user_event)
+    MQFactory.getConcrete("user").enqueue(user_event)
+  end
+
+  def build_url(meth, hash)
+    uri = "#{MY_JBIDWATCHER_URL}/#{meth}"
+    url = URI.parse(uri)
+    [uri, url, hash.to_param]
+  end
+
+  def post(command, hash)
+    uri, url, params = build_url(command, hash)
+
+    p = Net::HTTP::Post.new(uri)
+    p.body = params
+    p.content_type = 'application/x-www-form-urlencoded'
+
+    Net::HTTP.new(url.host, url.port).start do |http|
+      http.request p
+    end
+  end
+
+  def report_exception(exception)
+    result = post "exception", {:body => exception}
+    puts result.body
+    result.body
+  end
+
+  def recognize_bidpage(entry, page)
+    puts entry.title
+    result = post "recognize", {:body => page, :user => JConfig.queryConfiguration("my.jbidwatcher.id")}
+    puts result.body
+    result.body
+  end
+
+  def browse_to(id)
+    entry = $auctions_manager.getEntry(id)
+    entry.server.showBrowser(entry)
+  end
+
+  def notify(message)
+    MQFactory.getConcrete("Swing").enqueue("NOTIFY #{message}")
+  end
+
+  def snipe(auction, amount)
+    entry = auction if(auction.respond_to? :getIdentifier)
+    entry ||= $auctions_manager.getEntry(auction)
+    amount = Currency.getCurrency(amount) unless amount.respond_to? :fullCurrencyName
+    entry.prepareSnipe(amount)
+    $filter_manager.redrawEntry(entry)
+  end
+
+  def cancel_snipe(id)
+    entry = $auctions_manager.getEntry(id)
+    entry.cancelSnipe(false)
+    $filter_manager.redrawEntry(entry)
+  end
+
+  def custom_column(column, auction)
+    @columns[column].call(auction).to_s
+  end
+
+  def add_column(name, &block)
+    $table_controller.add_column(name) unless @columns[name]
+    @columns[name] = block
+  end
+
+  def initialize
+    @columns = {}    
+  end
+
+  COMMANDS = {}
+
+  UserActions.java_class.declared_instance_methods.each do |m|
+    if m.annotation_present?(MenuCommand.java_class)
+      annotation = m.annotation(MenuCommand.java_class)
+      COMMANDS[annotation.action] = { :name => m.name.to_sym, :arity => annotation.params } if annotation.action && annotation.action != ""
+      COMMANDS[m.name.to_sym] =     { :name => m.name.to_sym, :arity => annotation.params }
+    end
+  end
+
+  TRANSLATIONS = {
+      'Add New' => 'Add',
+      'Check For Updates' => 'Check Updates',
+      'Explain Colors And Icons' => 'Help Colors'
+  }
+
+  def handle_action(action, action_manager, *params)
+    do_action = "Do#{action.gsub(' ', '')}".to_sym
+    pair = COMMANDS[action] || COMMANDS[do_action]
+
+    method = pair.nil? ? do_action : pair[:name]
+    arity = pair.nil? ? 0 : pair[:arity]
+
+    # Special case params: -1 means pass in null as the sole parameter, -2 means just the auction entry.
+    params, arity = {-1 => [[nil], 1], -2 => [[params[1]], 1]}[arity] if arity < 0
+
+    if action_manager.respond_to?(method, true)
+      params = [method] + params[0...arity]
+      action_manager.send(*params)
+    else
+      JConfig.log.logMessage "Did not know how to handle #{action}"
+    end
+  end
+
+  def load_scripts
+    script_dir = Path.getCanonicalFile "scripts","jbidwatcher",false
+    if File.exist?(script_dir) && File.directory?(script_dir)
+      sd = Dir.new script_dir
+      scripts = sd.reject do |filename|
+        script_file = File.join(script_dir, filename)
+        File.directory?(script_file) || File.extname(script_file) != '.rb'
+      end
+
+      scripts.each do |script_file|
+        require File.join(script_dir, script_file)
+      end
+    else
+      unless File.exist? script_dir
+        Dir.mkdir script_dir
+      end
+    end
+  end
+
+  def after_startup
+    require "models"
+    gixen
+    require 'active_support'
+    require 'active_support/core_ext'
+    require 'pp'
+  end
+
+  def parse(body)
+    Ebay::Parser.new(body).parse
+  end
+
+  def log(msg)
+    JConfig.log.logMessage msg
+  end
+
+  def get_update(auction_id, last_updated_at)
+    current = (Time.now.to_f*1000).to_i
+    last_int = last_updated_at.nil? ? 0 : last_updated_at.time
+    lite_url = "http://www.ebay.com/itm/ws/eBayISAPI.dll?ViewItemLite&pbv=0&item=#{auction_id}"
+    lite_url += "&lastaccessed=#{last_int}&lvr=0&dl=5&_=#{current}"
+    body = open(lite_url).read
+    result = JSON.parse(body)
+    response = result['ViewItemLiteResponse']
+
+    if response['Error'].blank?
+      item = response['Item'].first
+      end_date = item['EndDate']
+
+      ends_at = Time.parse(end_date['Time'] + ' ' + end_date['Date'])
+      cur_price = item['CurrentPrice']['MoneyStandard']
+      ended = item['IsEnded']
+      bid_count = item['BidCount']
+
+      {
+          'current_price' => cur_price,
+          'end_date' => (ends_at.to_f*1000).to_i,
+          'ended' => ended,
+          'bid_count' => bid_count
+      }
+    end
+  rescue => e
+    log e.inspect
+    return nil
+  end
+
+  def dump_hash(h)
+    pp h
+  end
+
+  def gixen
+    @gixen ||= begin
+      dirname = File.dirname(__FILE__)
+      if File.exists?(File.join(dirname, "gixen")) || File.exists?('lib/jbidwatcher/gixen')
+        $:<< File.join(dirname, "gixen")
+      else
+        $:<< JConfig.java_class.class_loader.resource_as_url('lib/jbidwatcher/gixen').to_s
+      end
+
+      require 'gixen'
+
+      server_prefix = Constants::EBAY_SERVER_NAME
+      username = JConfig.query_configuration("#{server_prefix}.user")
+      password = JConfig.query_configuration("#{server_prefix}.password")
+      Gixen.new(username, password) if username != 'default'
+    end
+  end
+
+  # This is just a dumping ground right now; I should change that soon.
+  def get_value(entry, column)
+
+  end
+end
+
+# $auction_server_manager = AuctionServerManager.getInstance
+# $auctions_manager = AuctionsManager.getInstance
+# $filter_manager = $auctions_manager.filters
+$table_controller = TableColumnController.getInstance
+JBidwatcher = JBidwatcherUtilities.new
+
+JBidwatcher.load_scripts
+
+# case TableColumnController.CUR_BID :
+#     return currentBid(aEntry);
+# case TableColumnController.SNIPE_OR_MAX : return formatSnipeAndBid(aEntry);
+# case TableColumnController.MAX : return aEntry.isBidOn() ? formatBid(aEntry, errorNote) :neverBid;
+# case TableColumnController.SNIPE :
+#     return snipeColumn(aEntry, errorNote);
+# case TableColumnController.TIME_LEFT :
+#     return timeLeftColumn(aEntry);
+# case TableColumnController.END_DATE :
+#     return endDateColumn(aEntry);
+# case TableColumnController.TITLE : return XMLElement.decodeString(aEntry.getTitle());
+# case TableColumnController.STATUS : return getEntryIcon(aEntry);
+# case TableColumnController.THUMBNAIL :
+#     return thumbnailColumn(aEntry);
+# case TableColumnController.SELLER :
+#     return aEntry.getSellerName();
+# case TableColumnController.COMMENT :
+#     String comment = aEntry.getComment();
+# return(comment==null? "" :comment);
+# case TableColumnController.BIDDER :
+#     String bidder = aEntry.getHighBidder();
+# if (bidder != null && bidder.length() != 0)
+#   return bidder;
+#   return "--";
+#   case TableColumnController.FIXED_PRICE :
+#       Currency bin = aEntry.getBuyNow();
+#   if (bin.isNull())
+#     return "--";
+#     return bin;
+#     case TableColumnController.SHIPPING_INSURANCE :
+#         Currency ship = aEntry.getShippingWithInsurance();
+#     if (ship.isNull())
+#       return "--";
+#       return ship;
+#       case TableColumnController.ITEM_LOCATION :
+#           return aEntry.getItemLocation();
+#       case TableColumnController.BIDCOUNT :
+#           if (aEntry.getNumBidders() < 0)
+#             return "(FP)";
+#             return Integer.toString(aEntry.getNumBidders());
+#             case TableColumnController.JUSTPRICE :
+#                 return aEntry.getCurrentPrice();
+#             case TableColumnController.SELLER_FEEDBACK :
+#                 return seller.getFeedback();
+#             case TableColumnController.SELLER_POSITIVE_FEEDBACK :
+#                 String fbp = seller.getPositivePercentage();
+#             return (fbp == null || fbp.length() == 0) ? "--" :fbp;
+#             case TableColumnController.CUR_TOTAL :
+#                 return priceWithShippingColumn(aEntry);
+#             case TableColumnController.SNIPE_TOTAL :
+#                 return formatTotalSnipe(aEntry, errorNote);
+#
+#

+ 32 - 0
JBidwatcher/lib/jbidwatcher/utilities_spec.rb

@@ -0,0 +1,32 @@
+require 'utilities'
+
+describe JBidwatcher do
+  it "should test okay" do
+    JBidwatcher.test_basics
+  end
+
+  it "should handle private mapped actions" do
+    class MockUserActions < Hash
+      private
+      def CancelSnipe(x, y)
+        self['cancel_snipe_called'] = true
+      end
+    end
+
+    m = Hash.new
+    def m.logMessage(x)
+      self['log_result'] = x
+    end
+    JConfig.set_logger(m)
+
+    c = "Component" # A mock swing component.
+    ae = "Auction Entry" # A mock auction entry
+
+    user_actions = MockUserActions.new
+    JBidwatcher.handle_action('Cancel Snipe', user_actions, c, ae)
+
+    # Assert that nothing was logged.
+    expect(m['log_result']).to be_nil
+    expect(user_actions['cancel_snipe_called']).to be true
+  end
+end

BIN
JBidwatcher/lib/jdesktop.jar


BIN
JBidwatcher/lib/jl1.0.1.jar


BIN
JBidwatcher/lib/jline-2.11.jar


BIN
jbidwatcher.jar → JBidwatcher/lib/jruby-incomplete.jar


BIN
JBidwatcher/lib/json_simple-1.1.jar


BIN
JBidwatcher/lib/jsoup-1.7.1.jar


BIN
JBidwatcher/lib/jsr305-1.3.9.jar


BIN
JBidwatcher/lib/l2fprod-common-fontchooser.jar


BIN
JBidwatcher/lib/mahalo.jar


Some files were not shown because too many files changed in this diff