rox 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+