oos4ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.1.0 2007-09-28
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/License.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 David Calavera
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,39 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ config/hoe.rb
7
+ config/requirements.rb
8
+ lib/oos4ruby.rb
9
+ lib/oos4ruby/auth.rb
10
+ lib/oos4ruby/bean.rb
11
+ lib/oos4ruby/category.rb
12
+ lib/oos4ruby/collection.rb
13
+ lib/oos4ruby/contact.rb
14
+ lib/oos4ruby/contacts.rb
15
+ lib/oos4ruby/entry.rb
16
+ lib/oos4ruby/feed.rb
17
+ lib/oos4ruby/http_invoker.rb
18
+ lib/oos4ruby/oos.rb
19
+ lib/oos4ruby/search.rb
20
+ lib/oos4ruby/service.rb
21
+ lib/oos4ruby/site.rb
22
+ lib/oos4ruby/sites.rb
23
+ lib/oos4ruby/user.rb
24
+ lib/oos4ruby/version.rb
25
+ log/debug.log
26
+ script/destroy
27
+ script/generate
28
+ script/txt2html
29
+ setup.rb
30
+ tasks/deployment.rake
31
+ tasks/environment.rake
32
+ tasks/website.rake
33
+ test/test_helper.rb
34
+ test/test_oos4ruby.rb
35
+ website/index.html
36
+ website/index.txt
37
+ website/javascripts/rounded_corners_lite.inc.js
38
+ website/stylesheets/screen.css
39
+ website/template.rhtml
data/README.txt ADDED
@@ -0,0 +1 @@
1
+ README
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
data/config/hoe.rb ADDED
@@ -0,0 +1,70 @@
1
+ require 'oos4ruby/version'
2
+
3
+ AUTHOR = 'David Calavera' # can also be an array of Authors
4
+ EMAIL = "david.calavera@gmail.com"
5
+ DESCRIPTION = "oos4ruby is a ruby binding for the 11870 API"
6
+ GEM_NAME = 'oos4ruby' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'oos4r' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+
11
+ @config_file = "~/.rubyforge/user-config.yml"
12
+ @config = nil
13
+ RUBYFORGE_USERNAME = "unknown"
14
+ def rubyforge_username
15
+ unless @config
16
+ begin
17
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
18
+ rescue
19
+ puts <<-EOS
20
+ ERROR: No rubyforge config file found: #{@config_file}
21
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
22
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
23
+ EOS
24
+ exit
25
+ end
26
+ end
27
+ RUBYFORGE_USERNAME.replace @config["username"]
28
+ end
29
+
30
+
31
+ REV = nil
32
+ # UNCOMMENT IF REQUIRED:
33
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
34
+ VERS = Oos4ruby::VERSION::STRING + (REV ? ".#{REV}" : "")
35
+ RDOC_OPTS = ['--quiet', '--title', 'oos4ruby documentation',
36
+ "--opname", "index.html",
37
+ "--line-numbers",
38
+ "--main", "README",
39
+ "--inline-source"]
40
+
41
+ class Hoe
42
+ def extra_deps
43
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
44
+ @extra_deps
45
+ end
46
+ end
47
+
48
+ # Generate all the Rake tasks
49
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
50
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
51
+ p.author = AUTHOR
52
+ p.description = DESCRIPTION
53
+ p.email = EMAIL
54
+ p.summary = DESCRIPTION
55
+ p.url = HOMEPATH
56
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
57
+ p.test_globs = ["test/**/test_*.rb"]
58
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
59
+
60
+ # == Optional
61
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\\n\\n")
62
+ p.extra_deps = [ ['mime-types', '>=1.5'] ] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
63
+
64
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
65
+
66
+ end
67
+
68
+ CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
69
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
70
+ hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
16
+
17
+ require 'oos4ruby'
@@ -0,0 +1,39 @@
1
+ require 'digest/md5'
2
+ require 'digest/sha1'
3
+
4
+ class Auth
5
+
6
+ def initialize(username, password, method)
7
+ @username = username
8
+ @password = password
9
+ @method = method
10
+ end
11
+
12
+ def add_to(req)
13
+ wsse(req) if method?:wsse
14
+ app(req) if method?:app
15
+ end
16
+
17
+ def method?(method)
18
+ @method == method
19
+ end
20
+
21
+ private
22
+ def wsse(req)
23
+ nonce = Array.new(10){ rand(0x1000000) }.pack('I*')
24
+ nonce_b64 = [nonce].pack("m").chomp
25
+ now = Time.now.gmtime.strftime("%FT%TZ")
26
+ digest = [Digest::SHA1.digest(nonce_b64 + now + @password)].pack("m").chomp
27
+
28
+ req['Authorization'] = 'WSSE realm="11870.com", profile="UsernameToken"'
29
+ req['X-WSSE'] = %Q<UsernameToken Username="#{@username}", PasswordDigest="#{digest}", Nonce="#{nonce_b64}", Created="#{now}">
30
+ end
31
+
32
+ def app(req)
33
+ req['appToken'], req['authSign'] = @username, Digest::MD5.hexdigest( "#{@username}#{@password}" )
34
+ end
35
+
36
+ end
37
+
38
+
39
+
@@ -0,0 +1,189 @@
1
+ include Oos4ruby
2
+
3
+ module Bean
4
+ def self.append_features(base) #:nodoc:
5
+ super
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def define_el_reader(opts = {})
11
+ if !opts.empty?
12
+ opts.each_pair { |key, value|
13
+ value.each { |field_name|
14
+ define_method(field_name) do
15
+ name = field_name.to_s.gsub(/_/, '')
16
+ begin
17
+ child = @xml.child(name, key) if @xml.instance_of?Oos4ruby::Entry
18
+ child = REXML::XPath.first(@xml, name, key) if @xml.instance_of? REXML::Element
19
+ return child.text if child
20
+ rescue => e
21
+ puts e.backtrace.join("\n")
22
+ end
23
+ end
24
+ }
25
+ }
26
+ end
27
+ end
28
+
29
+ def set_variable(options = {})
30
+ if options.empty?
31
+ options.each_pair { |key, value|
32
+ class_variable_set("@@#{key.to_s}".to_sym, value)
33
+ }
34
+ end
35
+ end
36
+
37
+ def define_attr_reader(opts = {})
38
+ if !opts.empty?
39
+ opts.each_pair { |namespace, value|
40
+ if value.is_a?Array
41
+ value.each { |field|
42
+ define_method(field) do
43
+ name = field.to_s.gsub(/_/, '')
44
+ begin
45
+ attr = @xml.attribute(name, namespace) if @xml.instance_of? REXML::Element
46
+ return attr.value
47
+ rescue
48
+ #ATTRIBUTE NOT FOUND
49
+ end
50
+ end
51
+ }
52
+ elsif value.is_a?Hash
53
+ value.each_pair { |el, attr|
54
+ define_method("#{el}_#{attr}") do
55
+ el = el.to_s.gsub(/_/, '')
56
+
57
+ prefix = 'atom'
58
+ XmlNamespaces.each_pair { |name_key, name_value|
59
+ prefix = name_key if name_value.to_s == namespace.to_s
60
+ }
61
+
62
+ elem = @xml.child(el, namespace) if @xml.instance_of?Oos4ruby::Entry
63
+ elem = REXML::XPath.first(@xml, "./#{prefix}:#{el}", namespace) if @xml.instance_of?REXML::Element
64
+
65
+ if (attr.is_a?Symbol)
66
+ attr = attr.to_s.gsub(/_/, '')
67
+ begin
68
+ attr_value = elem.attribute(attr, namespace)
69
+ return attr_value.value
70
+ rescue
71
+ #ATTRIBUTE NOT FOUND
72
+ end
73
+ elsif attr.is_a?Hash
74
+ attr.each_pair { |attr_name, attr_namespace|
75
+ attr_name = attr_name.to_s.gsub(/_/, '')
76
+ begin
77
+ attr_value = elem.attribute(attr_name, attr_namespace)
78
+ return attr_value.value
79
+ rescue
80
+ #ATTRIBUTE NOT FOUND
81
+ end
82
+ }
83
+ end
84
+ end
85
+ }
86
+ end
87
+ }
88
+ end
89
+ end
90
+ end
91
+
92
+ def make_id
93
+ id = ''
94
+ 5.times { id += rand(1000000).to_s }
95
+ "Oos4ruby:11870.com,2007:#{id}"
96
+ end
97
+
98
+ def add_element(base, new_el, text, attrs = {})
99
+ el = base.add_element new_el.to_s, attrs
100
+ el.text = text
101
+ base
102
+ end
103
+
104
+ def add_category(xml, term, scheme)
105
+ xml.add_category(term.to_s, scheme)
106
+ end
107
+
108
+ def remove_category(xml, term = nil, scheme = nil)
109
+ if xml.is_a?Entry
110
+ hash = {}
111
+ hash[:term] = term if term
112
+ hash[:scheme] = scheme if scheme
113
+ cat = xml.category( hash )
114
+ xml.delete_category( cat ) if cat
115
+ elsif xml.is_a?REXML::Element
116
+ xml.delete_element c
117
+ end
118
+ end
119
+
120
+ def create_entry
121
+ entry = REXML::Element.new('entry')
122
+ entry.add_namespace AtomNamespace
123
+ XmlNamespaces.each_pair { |prefix, namespace|
124
+ unless prefix == 'atom' || prefix == 'gml'
125
+ entry.add_namespace prefix, namespace
126
+ end
127
+ }
128
+ entry
129
+ end
130
+
131
+ class BeanClass
132
+ def author
133
+ @entry.child('author/name').text
134
+ end
135
+
136
+ def to_xml
137
+ @xml.to_s
138
+ end
139
+
140
+ def to_s
141
+ @xml.to_s
142
+ end
143
+
144
+ def update!
145
+ edit_link = @xml.link('edit')
146
+
147
+ getter = HTTPInvoker.new(edit_link, @auth)
148
+
149
+ worked = getter.get
150
+ if worked
151
+ @xml = Entry.new( getter.body )
152
+ load!
153
+
154
+ putter = HTTPInvoker.new edit_link, @auth
155
+ worked = putter.put AtomEntryContentType, @xml.to_s
156
+
157
+ raise RuntimeError.new unless worked
158
+ else
159
+ raise RuntimeError.new unless worked
160
+ end
161
+ end
162
+
163
+ def delete!
164
+ edit_link = @xml.link('edit')
165
+
166
+ deleter = HTTPInvoker.new(edit_link, @auth)
167
+
168
+ worked = deleter.delete
169
+
170
+ raise RuntimeError.new unless worked
171
+ end
172
+
173
+ protected
174
+ def add_category(term, scheme)
175
+ Bean.add_category(@xml, term, scheme)
176
+ end
177
+
178
+ def update_category(new_term, new_scheme, old_term = nil, old_scheme = nil)
179
+ remove_category old_term, old_scheme
180
+ add_category new_term, new_scheme
181
+ end
182
+
183
+ def remove_category(term = nil, scheme = nil)
184
+ Bean.remove_category(@xml, term, scheme)
185
+ end
186
+
187
+ end
188
+ end
189
+
@@ -0,0 +1,28 @@
1
+ include Bean
2
+
3
+ module Oos4ruby
4
+ class Category
5
+
6
+ define_attr_reader({
7
+ AtomNamespace => [:term, :scheme],
8
+ OosNamespace => [:frecuency]
9
+ })
10
+
11
+ def initialize(term, scheme = nil)
12
+ unless term.instance_of?(REXML::Element)
13
+ @term = term
14
+ @scheme = scheme
15
+ @xml = REXML::Element.new 'category'
16
+ @xml.add_attributes 'term' => @term, 'scheme' => @scheme
17
+ else
18
+ @xml = term
19
+ end
20
+ end
21
+
22
+ def to_s
23
+ return @xml.to_s
24
+ end
25
+ end
26
+ end
27
+
28
+
@@ -0,0 +1,96 @@
1
+ module Oos4ruby
2
+ class Collection
3
+
4
+ attr_reader :entries
5
+
6
+ def initialize(feed, auth, slug = nil)
7
+ @feed = feed
8
+ @auth = auth
9
+ @slug = slug
10
+ end
11
+
12
+ def next_page?
13
+ @feed.next?
14
+ end
15
+
16
+ def previous_page?
17
+ @feed.previous?
18
+ end
19
+
20
+ def next_page
21
+ return get_page(@feed.next) if next_page?
22
+ end
23
+
24
+ def previous_page
25
+ return get_page(@feed.previous) if previous_page?
26
+ end
27
+
28
+ def next_page!
29
+ return get_page!(@feed.next)
30
+ end
31
+
32
+ def previous!
33
+ return get_page!(@feed.previous)
34
+ end
35
+
36
+ def all
37
+ all = @entries
38
+ aux = self
39
+ while aux.next_page?
40
+ next_page = aux.next_page
41
+ next_page.entries.each {|entry| all << entry}
42
+ aux = next_page
43
+ end
44
+ return all
45
+ end
46
+
47
+ def refresh!
48
+ return get_page!(@feed.self_link)
49
+ end
50
+
51
+ def to_s
52
+ @entries.join("\n")
53
+ end
54
+
55
+ def create!(opts = {})
56
+ opts[:author] = REXML::XPath.first(@feed.xml, 'author', XmlNamespaces)
57
+
58
+ new_entry = Site.dump! opts, @slug if self.instance_of?Sites
59
+ new_entry = Contact.dump! opts, @slug if self.instance_of?Contacts
60
+
61
+ poster = HTTPInvoker.new( @feed.self_link, @auth)
62
+
63
+ worked = poster.post AtomEntryContentType, "<?xml version='1.0' ?>\n" + new_entry.to_s
64
+
65
+ raise RuntimeError.new unless worked
66
+ return Site.new(poster.entry, @auth, @slug) if self.instance_of?Sites
67
+ return Contact.new(poster.entry, @auth, @slug) if self.instance_of?Contacts
68
+ end
69
+
70
+ private
71
+ def get_page(link)
72
+ getter = HTTPInvoker.new(link, @auth)
73
+ worked = getter.get
74
+
75
+ return convert(getter.body) if worked
76
+ end
77
+
78
+ def get_page!(link)
79
+ getter = HTTPInvoker.new(link, @auth)
80
+ worked = getter.get
81
+ if worked
82
+ @feed = Feed.read(getter.body)
83
+ @entries = convert(getter.body).entries
84
+ return self
85
+ end
86
+ end
87
+
88
+ def convert( body )
89
+ return Sites.new( Feed.read( body ), @auth, @slug ) if self.instance_of?(Sites)
90
+ return Contacts.new( Feed.read( body ), @auth, @slug ) if self.instance_of?(Contacts)
91
+ end
92
+
93
+ end
94
+ end
95
+
96
+
@@ -0,0 +1,72 @@
1
+
2
+ include Bean
3
+
4
+ module Oos4ruby
5
+ class Contact < BeanClass
6
+
7
+ define_el_reader AtomNamespace => [:title, :updated]
8
+
9
+ attr_writer :trusted
10
+
11
+ alias :nick :title
12
+
13
+ def initialize(xml, auth, slug)
14
+ @xml = xml
15
+ @auth = auth
16
+ @slug = slug
17
+ end
18
+
19
+ def Contact.find_by_user( auth, slug, opts = {} )
20
+ raise Oos4ruby::UnknownUser if slug.nil?
21
+
22
+ uri = CONTACTS_URL + "/#{slug}"
23
+
24
+ getter = HTTPInvoker.new(uri, auth)
25
+
26
+ worked = getter.get
27
+
28
+ Contacts.new(Feed.read(getter.body), auth, slug) if worked
29
+ end
30
+
31
+ def data
32
+ @data = User.find @auth, @xml.link('userInfo') unless @data
33
+ @data
34
+ end
35
+
36
+ def trusted?
37
+ trusted = @xml.first("./atom:category[@scheme=\"#{TRUSTED_URL}\"]")
38
+ trusted = Category.new trusted
39
+ trusted.term.downcase == 'true'
40
+ end
41
+
42
+ def Contact.dump!(opts, slug)
43
+ entry = create_entry
44
+
45
+ entry.add_element opts[:author]
46
+ add_element entry, 'updated', DateTime.now
47
+ add_element entry, 'id', make_id
48
+
49
+ add_element entry, 'title', (opts[:contact] || opts[:slug] || opts[:title])
50
+ add_element entry, 'content', ''
51
+
52
+ if opts[:trusted]
53
+ if opts[:trusted].is_a?REXML::Element
54
+ entry.add_element opts[:trusted]
55
+ else
56
+ add_category entry, opts[:trusted], TRUSTED_URL
57
+ end
58
+ end
59
+
60
+ entry
61
+ end
62
+
63
+ private
64
+ def load!
65
+ update_category @trusted, TRUSTED_URL, nil, TRUSTED_URL unless @trusted.nil?
66
+ @xml.add_child('content', nil, nil, {:type => 'html'})
67
+ end
68
+
69
+ end
70
+ end
71
+
72
+
@@ -0,0 +1,11 @@
1
+
2
+ module Oos4ruby
3
+ class Contacts < Collection
4
+ def initialize(feed, auth, slug)
5
+ super(feed, auth, slug)
6
+ @entries = feed.entries.map {|entry| Contact.new(entry, @auth, @slug) }
7
+ end
8
+ end
9
+ end
10
+
11
+
@@ -0,0 +1,91 @@
1
+
2
+ require 'rexml/document'
3
+ require 'rexml/xpath'
4
+
5
+ module Oos4ruby
6
+ class Entry
7
+
8
+ def initialize(node)
9
+ if node.class == String
10
+ @element = REXML::Document.new(node, { :raw => nil }).root
11
+ else
12
+ @element = node
13
+ end
14
+ end
15
+
16
+ def to_s
17
+ "<?xml version='1.0' ?>\n" + @element.to_s
18
+ end
19
+
20
+ def child(field, namespace = nil)
21
+ if (namespace)
22
+ thisNS = {}
23
+ prefix = 'NS'
24
+ thisNS[prefix] = namespace
25
+ else
26
+ prefix = 'atom'
27
+ thisNS = XmlNamespaces
28
+ end
29
+ return REXML::XPath.first(@element, "./#{prefix}:#{field}", thisNS)
30
+ end
31
+
32
+ def add_child(name, prefix = nil, namespace = nil, attr = {})
33
+ name = (prefix || 'atom') + ':' + name
34
+ e = REXML::Element.new( name, @element )
35
+ if prefix && namespace
36
+ e.add_namespace(prefix, namespace)
37
+ else
38
+ e.add_namespace('atom', AtomNamespace)
39
+ end
40
+ if !attr.empty?
41
+ attr.each_pair { |key, value| e.add_attribute(key.to_s, value) }
42
+ end
43
+ e
44
+ end
45
+
46
+ def category( cat )
47
+ first = true
48
+ xpath = "./atom:category["
49
+ if cat[:term]
50
+ xpath += "@term=\"#{cat[:term]}\""
51
+ first = false
52
+ end
53
+ xpath += " and " unless first
54
+ if cat[:scheme]
55
+ xpath += "@scheme=\"#{cat[:scheme]}\""
56
+ end
57
+ xpath += "]"
58
+ REXML::XPath.first(@element, xpath, XmlNamespaces)
59
+ end
60
+
61
+ def add_category(term, scheme = nil, label = nil)
62
+ c = @element.add_category(term, scheme, label)
63
+ c
64
+ end
65
+
66
+ def delete_category(c)
67
+ @element.delete_element c
68
+ end
69
+
70
+ def link(rel)
71
+ a = REXML::XPath.first(@element, "./atom:link[@rel=\"#{rel}\"]", XmlNamespaces)
72
+ if a
73
+ uri = URI.parse a.attributes['href']
74
+ if uri.absolute?
75
+ return uri
76
+ else
77
+ return URI.parse(OOS_URL).merge(uri)
78
+ end
79
+ end
80
+ end
81
+
82
+ def match(xp)
83
+ REXML::XPath.match(@element, xp, XmlNamespaces)
84
+ end
85
+
86
+ def first(xp)
87
+ REXML::XPath.first(@element, xp, XmlNamespaces)
88
+ end
89
+
90
+ end
91
+ end