rox 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README ADDED
@@ -0,0 +1 @@
1
+ Try it out at: http://www.ox.io
@@ -0,0 +1,11 @@
1
+ require 'rox'
2
+
3
+ USER = "..."
4
+ PASSWORD = "..."
5
+ HOST = "https://ox.io"
6
+
7
+ ROX::Client.new(:host => HOST).login(USER, PASSWORD) do
8
+ |client|
9
+ # ...
10
+
11
+ end
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__)+'/rox/dependencies'
2
+ require File.dirname(__FILE__)+'/rox/rox'
3
+ require File.dirname(__FILE__)+'/rox/webconversation'
4
+ require File.dirname(__FILE__)+'/rox/client'
5
+ require File.dirname(__FILE__)+'/rox/response'
6
+ require File.dirname(__FILE__)+'/rox/exception'
7
+ require File.dirname(__FILE__)+'/rox/config_tree'
8
+ require File.dirname(__FILE__)+'/rox/folders'
9
+ require File.dirname(__FILE__)+'/rox/simple_module'
10
+
@@ -0,0 +1,78 @@
1
+ module ROX
2
+
3
+ class Client
4
+
5
+ attr_accessor :webconversation
6
+ attr_accessor :session
7
+
8
+ def initialize(options = nil)
9
+ if options
10
+ host = options[:host]
11
+ raise "Please specify an option 'host'" unless host
12
+ @webconversation = ROX::WebConversation.new(host)
13
+ end
14
+ end
15
+
16
+ def login(username, password)
17
+ response = @webconversation.get("/ajax/login", :action => :login, :name => username, :password => password)
18
+ response = ROX::Response.new(JSON.parse(response))
19
+ raise OXException.new(response) if response.error?
20
+ @session = response["session"]
21
+
22
+ if block_given?
23
+ begin
24
+ return yield(self)
25
+ ensure
26
+ logout
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ def logout
33
+ response = @webconversation.get("/ajax/login", :action => :logout, :session => session)
34
+ if(response and response != "")
35
+ response = ROX::Response.new(JSON.parse(response))
36
+ raise OXException.new(response) if response.error?
37
+ end
38
+ @session = nil
39
+ end
40
+
41
+ def logged_in?
42
+ !@session.nil?
43
+ end
44
+
45
+ def get(path, parameters = {})
46
+ parameters[:session] ||= @session
47
+ @webconversation.get(path, parameters)
48
+ end
49
+
50
+ def put(path, parameters = {})
51
+ parameters[:session] ||= @session
52
+ @webconversation.put(path, parameters)
53
+ end
54
+
55
+ def get_response(path, parameters = {})
56
+ response = ROX::Response.new(JSON.parse(get(path, parameters)))
57
+ raise ROX::OXException.new(response) if response.error?
58
+ return response;
59
+ end
60
+
61
+ def put_response(path, parameters = {})
62
+ response = ROX::Response.new(JSON.parse(put(path, parameters)))
63
+ raise ROX::OXException.new(response) if response.error?
64
+ return response
65
+ end
66
+
67
+ def in_module(moduleName, &block)
68
+ mod = self.module(moduleName)
69
+ return mod.instance_eval(&block) if block_given?
70
+ return mod
71
+ end
72
+
73
+ def module(moduleName)
74
+ ROX::SimpleModule.new("/ajax/"+moduleName.to_s, self)
75
+ end
76
+ end
77
+
78
+ end
@@ -0,0 +1,27 @@
1
+ module ROX
2
+ class ConfigTree
3
+ def initialize(client)
4
+ @client = client
5
+ end
6
+
7
+ def [](path)
8
+ return @client.get_response("/ajax/config/#{path}")["data"]
9
+ end
10
+
11
+ def []=(path, value)
12
+ @client.put("/ajax/config/#{path}", :body => value.to_json)
13
+ end
14
+
15
+ end
16
+
17
+
18
+ class Client
19
+
20
+ def config
21
+ @config ||= ROX::ConfigTree.new(self)
22
+ end
23
+
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,2 @@
1
+ require 'json'
2
+ require 'tzinfo'
@@ -0,0 +1,14 @@
1
+ module ROX
2
+
3
+ class OXException < Exception
4
+ def initialize(response)
5
+ @response = response
6
+ end
7
+
8
+ def to_s
9
+ @response.error
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,59 @@
1
+ module ROX
2
+
3
+ columns(:common) {
4
+
5
+ column(1, :id, :string)
6
+ column(2, :created_by, :string)
7
+ column(3, :modified_by, :string)
8
+ column(4, :creation_date, :time)
9
+ column(5, :last_modified, :time)
10
+ column(6, :last_modified_utc, :timestamp)
11
+ column(20, :folder_id, :string)
12
+
13
+ }
14
+
15
+ columns(:folder => :common) {
16
+
17
+ column(300, :title, :string)
18
+ column(301, :module, :string)
19
+ column(302, :type, :mappable, {1 => :private, 2 => :public, 3 => :shared, 5 => :system})
20
+ column(304, :boolean, :subfolders)
21
+ #column(305, :own_rights, :)
22
+ #column(306, :permissions, :)
23
+ column(307, :summary, :string)
24
+ column(308, :standard_folder, :boolean)
25
+ column(309, :total, :number)
26
+ column(310, :new, :number)
27
+ column(311, :unread, :number)
28
+ column(312, :deleted, :number)
29
+ column(313, :capabilities, :number)
30
+ column(314, :subscribed, :boolean)
31
+ column(315, :subscr_subflds, :boolean)
32
+ }
33
+
34
+
35
+ class Folders
36
+ def initialize(client)
37
+ @client = client
38
+ @columns = COLUMN_DEFINITIONS[:folder]
39
+ end
40
+
41
+ def root(*columns)
42
+ column_list = get_columns(*columns)
43
+ @client.get_response("/ajax/folders", :action => :root, :columns => column_list.to_s)
44
+ end
45
+
46
+ def get_columns(*columns)
47
+ @columns.sublist(*columns)
48
+ end
49
+
50
+ end
51
+
52
+
53
+ class Client
54
+ def folders
55
+ Folders.new(self)
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,29 @@
1
+ module ROX
2
+ class Response
3
+ def initialize(ox_response)
4
+ @oxresponse = ox_response
5
+ end
6
+
7
+ def error?
8
+ @oxresponse.include?('error')
9
+ end
10
+
11
+ def error
12
+ return nil unless error?
13
+ sprintf(@oxresponse['error'], *@oxresponse['error_params'])
14
+ end
15
+
16
+ def [](key)
17
+ @oxresponse[key.to_s]
18
+ end
19
+
20
+ def data
21
+ @oxresponse['data']
22
+ end
23
+
24
+ def to_s
25
+ @oxresponse.inspect
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,170 @@
1
+ module ROX
2
+
3
+ class Column
4
+
5
+ attr_accessor :number, :name, :type, :options
6
+
7
+ def initialize(number, name, type, options = nil)
8
+ @number = number
9
+ @name = name
10
+ @type = type
11
+ @options = options
12
+ end
13
+
14
+ def to_ox(client, value)
15
+ value
16
+ end
17
+
18
+ def from_ox(client, value)
19
+ value
20
+ end
21
+
22
+ end
23
+
24
+ class MappableColumn < Column
25
+ def initialize(number, name, type, options)
26
+ super(number, name, type, options)
27
+ @from_ox = options
28
+ @inverse = @from_ox.inject({}) {|memo, pair| memo[pair[1]] = pair[0]; memo} if options
29
+ end
30
+
31
+ def to_ox(client, value)
32
+ @inverse[value]
33
+ end
34
+
35
+ def from_ox(client, value)
36
+ @from_ox[value]
37
+ end
38
+
39
+ end
40
+
41
+ class TimeColumn < Column
42
+
43
+ def from_ox(client, value)
44
+ Time.at(client.config.timezone.local_to_utc(value / 1000))
45
+ end
46
+
47
+ def to_ox(client, value)
48
+ client.config.timezone.utc_to_local(value.to_i) * 1000
49
+ end
50
+
51
+ end
52
+
53
+ class DateColumn < Column
54
+
55
+ def from_ox(client, value)
56
+ Time.at(value / 1000)
57
+ end
58
+
59
+ def to_ox(client, value)
60
+ value.to_i * 1000
61
+ end
62
+
63
+ end
64
+
65
+ class ComplexColumn < Column
66
+ def initialize(number, name, type, klass)
67
+ super(number, name, type, klass)
68
+ @klass = klass
69
+ end
70
+
71
+ def from_ox(client, value)
72
+ @klass.new(value)
73
+ end
74
+
75
+ def to_ox(client, value)
76
+ value.to_ox
77
+ end
78
+ end
79
+
80
+ class ColumnList
81
+ attr_reader :columns, :ancestors
82
+
83
+ def initialize(ancestors = nil)
84
+ @ancestors = ancestors || Array.new
85
+ @columns = Hash.new
86
+ @columns_by_number = Hash.new
87
+ end
88
+
89
+ def column(number, name, type, options = nil)
90
+ case(type)
91
+ when :date
92
+ klass = DateColumn
93
+ when :time
94
+ klass = TimeColumn
95
+ when :mappable
96
+ klass = MappableColumn
97
+ when :complex
98
+ klass = ComplexColumn
99
+ else
100
+ klass = Column
101
+ end
102
+ column = klass.new(number, name, type, options)
103
+ add_column(column)
104
+ self
105
+ end
106
+
107
+ def add_column(column_def)
108
+ @columns[column_def.name] = column_def
109
+ @columns_by_number[column_def.number] = column_def
110
+ end
111
+
112
+ def [](key)
113
+ return @columns[key] if @columns.include?(key)
114
+ return @columns_by_number[key] if @columns_by_number.include?(key)
115
+ @ancestors.each do
116
+ |ancestor|
117
+ column = ancestor[key]
118
+ return column if column
119
+ end
120
+ nil
121
+ end
122
+
123
+ def sublist(*keys)
124
+ sublist = ColumnList.new
125
+ keys.each do
126
+ |key|
127
+ value = self[key]
128
+ sublist.add_column(value)
129
+ end
130
+ sublist
131
+ end
132
+
133
+ def to_s
134
+ @columns_by_number.keys.join(",")
135
+ end
136
+
137
+ end
138
+
139
+
140
+ class ColumnDefinitions
141
+
142
+ def initialize
143
+ @definitions = Hash.new
144
+ end
145
+
146
+ def columns(typedef, &block)
147
+ name = typedef
148
+ ancestors = Array.new
149
+ if(typedef.kind_of?(Hash))
150
+ name = typedef.keys.first
151
+ ancestors = [*typedef[name]].map{|ancestor| self[ancestor]}
152
+ end
153
+ column_list = ColumnList.new(ancestors)
154
+ column_list.instance_eval(&block)
155
+ @definitions[name] = column_list
156
+ end
157
+
158
+ def [](key)
159
+ @definitions[key]
160
+ end
161
+
162
+ end
163
+
164
+ COLUMN_DEFINITIONS = ColumnDefinitions.new
165
+
166
+ def self.columns(options, &block)
167
+ COLUMN_DEFINITIONS.columns(options, &block)
168
+ end
169
+
170
+ end
@@ -0,0 +1,42 @@
1
+ module ROX
2
+
3
+ class SimpleModule
4
+ def initialize(path, client)
5
+ @path = path
6
+ @client = client
7
+ end
8
+
9
+ def _get(params)
10
+ @client.get_response(@path, params)
11
+ end
12
+
13
+ def _put(params)
14
+ @client.put_response(@path, params)
15
+ end
16
+
17
+ def call(action, params)
18
+ _call(action, params)
19
+ end
20
+
21
+ def _call(action, params)
22
+ params[:action] = action
23
+ if(params[:body])
24
+ params[:body] = params[:body].to_json
25
+ _put(params)
26
+ elsif params[:body_raw]
27
+ params[:body] = params[:body_raw]
28
+ params.delete(:body_raw)
29
+ _put(params)
30
+ else
31
+ _get(params)
32
+ end
33
+ end
34
+
35
+ def method_missing(meth, *args, &block)
36
+ params = args.first || {}
37
+ _call(meth, params)
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,96 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'open-uri'
4
+
5
+ module ROX
6
+ class WebConversation
7
+ attr_accessor :cookies
8
+
9
+ def initialize(uri)
10
+ @cookies = Hash.new
11
+ @uri = URI.parse(uri)
12
+ end
13
+
14
+ def get(url, params = {})
15
+ req = Net::HTTP::Get.new(url+"?"+query(params))
16
+ res = request(req)
17
+ return res.body
18
+ end
19
+
20
+ def post(url, params = {})
21
+ stringified_params = Hash.new
22
+ params.each do
23
+ |key, value|
24
+ next if key == :body or key == 'body'
25
+ stringified_params[key.to_s] = value.to_s
26
+ end
27
+ req = Net::HTTP::Post.new(url)
28
+ req.set_form_data(stringified_params)
29
+ req.body = params[:body] || params['body']
30
+ res = request(req)
31
+ return res.body
32
+ end
33
+
34
+ def put(url, params = {})
35
+ req = Net::HTTP::Put.new(url+"?"+query(params))
36
+ req.body = params[:body] || params['body']
37
+ res = request(req)
38
+ return res.body
39
+ end
40
+
41
+ def delete(url, params = {})
42
+ req = Net::HTTP::Delete.new(url+"?"+query(params))
43
+ res = request(req)
44
+ return res.body
45
+ end
46
+
47
+ def remember_cookies(res)
48
+ setCookie = res['Set-Cookie']
49
+ return unless setCookie
50
+ cookies = setCookie.split(/\s*[,;]\s*/)
51
+
52
+ cookies.each do
53
+ |cookieDef|
54
+ if (cookieDef =~ /^(JS|open-xchange)/)
55
+ key, value = cookieDef.split(/\=/)
56
+ @cookies[key] = value
57
+ end
58
+ end
59
+ end
60
+
61
+ def add_cookies(req)
62
+ return if @cookies.empty?
63
+ cookie_string = ""
64
+ @cookies.each do
65
+ |key, value|
66
+ cookie_string << "#{key}=#{value},"
67
+ end
68
+ req["Cookie"] = cookie_string[0...cookie_string.size-1]
69
+ end
70
+
71
+ def query(params)
72
+ query = ""
73
+ params.each do
74
+ |key, value|
75
+ next if key == :body || key == 'body'
76
+ query += '&'
77
+ query += URI.escape(key.to_s)+"="+URI.escape(value.to_s)
78
+ end
79
+ query = query[1..query.size]
80
+ return query
81
+ end
82
+
83
+ def request(req)
84
+ add_cookies(req)
85
+ http_session = Net::HTTP.new(@uri.host, @uri.port)
86
+ http_session.use_ssl = @uri.scheme == "https"
87
+ res = http_session.start do
88
+ |http|
89
+ http.request(req)
90
+ end
91
+ remember_cookies(res)
92
+ return res
93
+ end
94
+
95
+ end
96
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rox
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Francisco Laguna
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-11 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: json
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: tzinfo
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ description: An Open-Xchange HTTP API client library
38
+ email: fla@synapps.de
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - lib/rox.rb
47
+ - lib/rox/client.rb
48
+ - lib/rox/config_tree.rb
49
+ - lib/rox/dependencies.rb
50
+ - lib/rox/exception.rb
51
+ - lib/rox/folders.rb
52
+ - lib/rox/response.rb
53
+ - lib/rox/rox.rb
54
+ - lib/rox/simple_module.rb
55
+ - lib/rox/webconversation.rb
56
+ - examples/workspace.rb
57
+ - README
58
+ homepage: http://www.ox.io
59
+ licenses: []
60
+
61
+ post_install_message:
62
+ rdoc_options: []
63
+
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.8.1
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: An Open-Xchange HTTP API client library
85
+ test_files: []
86
+