openfire_admin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'nokogiri'
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # OpenfireAdmin
2
+
3
+ Controll Openfire Admin by ruby. (by web scraping,
4
+ no need openfire plugins)
5
+
6
+ Openfire is real time collaboration server.
7
+ http://www.igniterealtime.org/projects/openfire/
8
+
9
+ This library is designed for Opscode chef.
10
+
11
+ spin out from the openfire-chef recipe.
12
+ https://github.com/team-lab/openfire-chef
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ gem 'openfire_admin'
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install openfire_admin
27
+
28
+ ## TODO
29
+
30
+ 1. write test.
31
+ 2. refactoring code
32
+ 3. write comment, and document.
33
+
34
+ ## Contributing
35
+
36
+ 1. Fork it
37
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
38
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
39
+ 4. Push to the branch (`git push origin my-new-feature`)
40
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,46 @@
1
+ module OpenfireAdmin
2
+ # http client ( cookie support )
3
+ class HttpClient
4
+ def initialize(url)
5
+ @cookies = {}
6
+ @url = url
7
+ requrie 'net/https' if @url.scheme == 'https'
8
+ end
9
+
10
+ def request(req)
11
+ Net::HTTP.start(@url.host, @url.port) do |http|
12
+ http.use_ssl = true if @url.scheme == 'https'
13
+ puts "#{req.method} #{req.path}" if @verbos
14
+ req['Host'] = @url.host
15
+ req['Cookie'] = @cookies.map{|k,v| "#{k}=#{v}"}.join(";") unless @cookies.empty?
16
+ res = http.request(req)
17
+ cookies = res.get_fields('Set-Cookie')
18
+ cookies.each{|str|
19
+ k,v = str[0...str.index(';')].split('=')
20
+ @cookies[k] = v
21
+ } if cookies
22
+ if @verbos
23
+ puts "#{res.code} #{res.message}"
24
+ res.each{|k,v| puts "#{k}=#{v}" }
25
+ end
26
+ def res.request
27
+ @request
28
+ end
29
+ res.instance_variable_set(:@request, req)
30
+ yield res
31
+ end
32
+ end
33
+
34
+ # post with form data
35
+ def post(path, form_data)
36
+ req = Net::HTTP::Post.new(path)
37
+ req.set_form_data(form_data)
38
+ request(req){|res| yield res }
39
+ end
40
+
41
+ # get path
42
+ def get(path)
43
+ request(Net::HTTP::Get.new(path)){|res| yield res }
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,27 @@
1
+ # openfire admin operator
2
+ module OpenfireAdmin
3
+ # unexpected response found exception
4
+ class ResponceException < Exception
5
+ attr_reader :response
6
+ def initialize(message,res)
7
+ case res
8
+ when Net::HTTPSuccess
9
+ doc = Nokogiri::HTML(res.body)
10
+ msgs = ( doc.search('.jive-error-text, .error') || [] ).map{|c| c.text.strip}
11
+ if msgs.empty?
12
+ super(message)
13
+ else
14
+ super("#{message} [#{msgs.join(' / ')}]")
15
+ end
16
+ when Net::HTTPRedirection
17
+ super("#{message} redirct to=>#{res['location']}")
18
+ when Net::HTTPNotFound
19
+ super("#{message} Not found #{res.request.path}")
20
+ else
21
+ super("#{message} res.code=#{res.code}")
22
+ end
23
+
24
+ @response = res
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,82 @@
1
+
2
+ module OpenfireAdmin
3
+ class SetupWizard
4
+ def initialize(http)
5
+ @http = http
6
+ end
7
+
8
+ def if_not_redirect message, res
9
+ raise ResponceException.new(message,res) unless res.code =="302"
10
+ raise ResponceException.new("setup already run",res) if res["location"] =~ /setup-complete.jsp$/
11
+ end
12
+
13
+ def language(locale)
14
+ @http.get("/setup/index.jsp?localeCode=#{locale}&save=Continue"){|res|
15
+ if_not_redirect "cant set locale #{locale}", res
16
+ }
17
+ self
18
+ end
19
+ def server(domain, embeddedPort=9090, securePort=9091)
20
+ @http.post("/setup/setup-host-settings.jsp",{
21
+ "continue"=>"Continue",
22
+ "domain"=>domain,
23
+ "embeddedPort" => embeddedPort,
24
+ "securePort" => securePort }) do |res|
25
+ if_not_redirect "cant set server", res
26
+ end
27
+ self
28
+ end
29
+ def database(mode="embedded")
30
+ @http.get("/setup/setup-datasource-settings.jsp?next=true&mode=#{mode}&continue=Continue") do |res|
31
+ if_not_redirect "cant set database #{mode}", res
32
+ end
33
+ self
34
+ end
35
+ def database_standard(driver,serverURL,username,password,
36
+ maxConnections=25,minConnections=5,
37
+ connectionTimeout=1.0)
38
+ database("standard")
39
+ @http.post("/setup/setup-datasource-standard.jsp",{
40
+ "connectionTimeout" => connectionTimeout.to_s,
41
+ "continue"=>"Continue",
42
+ "driver"=>driver,
43
+ "maxConnections"=>maxConnections,
44
+ "minConnections"=>minConnections,
45
+ "password"=>password,
46
+ "serverURL"=>serverURL,
47
+ "username"=>username}) do |res|
48
+ if_not_redirect "cant set standard database #{serverURL}", res
49
+ end
50
+ self
51
+ end
52
+
53
+ def profile(mode="default")
54
+ @http.post("/setup/setup-profile-settings.jsp",{
55
+ "mode" => mode,
56
+ "continue" => "Continue"
57
+ }) do |res|
58
+ if_not_redirect "cant set profile #{mode} #{res.request.body}", res
59
+ end
60
+ self
61
+ end
62
+ def admin(email,password)
63
+ # on get, server store session to admin user
64
+ @http.get("/setup/setup-admin-settings.jsp") do |res|
65
+ raise ResponceException.new("can't get admin settings", res) unless res.code == "200"
66
+ end
67
+ @http.post("/setup/setup-admin-settings.jsp",{"continue"=>"Continue",
68
+ "email"=>email,
69
+ "newPassword"=>password,
70
+ "newPasswordConfirm"=>password,
71
+ "password"=>password}) do |res|
72
+ if_not_redirect "cant set admin #{email}", res
73
+ end
74
+ self
75
+ end
76
+ def finish()
77
+ @http.get("/setup/setup-finished.jsp") do |res|
78
+ res.code == "200"
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,3 @@
1
+ module OpenfireAdmin
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,315 @@
1
+ # coding: utf-8
2
+ require 'net/http'
3
+ require "nokogiri"
4
+ require 'open-uri'
5
+ require 'openfire_admin/http_client'
6
+ require 'openfire_admin/response_exception'
7
+
8
+ # openfire admin operator
9
+ class OpenfireAdmin
10
+ NBSP = "\302\240" # Nokogiri::HTML("&nbsp;").text
11
+ attr_reader :client
12
+
13
+ # pure admin console client
14
+ class AdminClient
15
+ attr_reader :http
16
+ def initialize(loginurl)
17
+ @http = HttpClient.new(URI.parse(loginurl))
18
+ end
19
+ def login(username, pass)
20
+ @http.post( "/login.jsp" , {
21
+ "login"=> "true",
22
+ "password"=>pass,
23
+ "url"=>"/index.jsp",
24
+ "username"=>username}) do |res|
25
+ raise ResponceException.new("can't login",res) unless res.code == "302"
26
+ end
27
+ end
28
+ def remove_property(name)
29
+ @http.post('/server-properties.jsp', 'propName' => name, 'del'=>'true') do |res|
30
+ raise ResponceException.new("cant save",res) if res.code != "302" or res['location'] !~ /deletesuccess=true$/
31
+ end
32
+ end
33
+ def set_property(name, value)
34
+ @http.post('/server-properties.jsp', 'propName' => name, 'propValue'=>value.to_s, 'save'=>'Save Property') do |res|
35
+ raise ResponceException.new("cant save",res) if res.code != "302"
36
+ end
37
+ end
38
+ def get_property(name)
39
+ @http.post("/server-properties.jsp", "edit"=>"true", "propName"=>name) do |res|
40
+ ta = Nokogiri::HTML(res.body).at('textarea[name=propValue]')
41
+ raise ResponceException.new("not found textarea",res) unless ta
42
+ ta.content.to_s
43
+ end
44
+ end
45
+ def get_properties
46
+ ret = {}
47
+ @http.get("/server-properties.jsp") do |res|
48
+ raise ResponceException.new("can't read",res) unless res.code== "200"
49
+ doc = Nokogiri::HTML(res.body)
50
+ doc.search('//h1/parent::node()//table/tbody/tr[@class=""]').each do |tr|
51
+ v = tr.at('td[2] span')[:title]
52
+ v = "" if v == NBSP
53
+ ret[tr.at('td span')[:title]]= v
54
+ end
55
+ end
56
+ ret
57
+ end
58
+ def get_installed_plugins
59
+ @http.get("/plugin-admin.jsp") do |res|
60
+ doc =Nokogiri::HTML(res.body)
61
+ doc.at('h1').parent.at('table').search('tbody tr[valign=top]').map do |tr|
62
+ img = tr.at('a[href*="reloadplugin="]')
63
+ if img
64
+ {
65
+ :key => img[:href].match(/\?reloadplugin=([^"'&>]*)/)[1],
66
+ :name => tr.search('td')[1].content.gsub(NBSP,' ').strip,
67
+ :description => tr.search('td')[3].content.strip,
68
+ :version => tr.search('td')[4].content.strip
69
+ }
70
+ end
71
+ end
72
+ end
73
+ end
74
+ def create_user(username,password,name,email,isadmin=false)
75
+ params = {
76
+ "create"=>"Create User",
77
+ "email"=> email,
78
+ "name"=> name,
79
+ "password"=> password,
80
+ "passwordConfirm"=>password,
81
+ "username"=>username }
82
+ params['isadmin'] = "on" if isadmin
83
+ @http.post("/user-create.jsp", params ) do |res|
84
+ raise ResponceException.new("can't create user #{username}",res ) unless res.code == "302" and res["location"] =~ /success=true/
85
+ end
86
+ end
87
+ def delete_user(username)
88
+ @http.get("/user-delete.jsp?username=#{username}&delete=Delete+User") do |res|
89
+ raise ResponceException.new("can't delete user #{username}",res ) unless res.code == "302" and res["location"] =~ /deletesuccess=true/
90
+ end
91
+ end
92
+ def user_exists?(username)
93
+ @http.get("/user-password.jsp?username=#{username}") do |res|
94
+ res.code == "200"
95
+ end
96
+ end
97
+ def install_plugin(url)
98
+ @http.post("/dwr/exec/downloader.installPlugin.dwr",
99
+ "callCount"=>"1",
100
+ "c0-scriptName"=>"downloader",
101
+ "c0-methodName"=>"installPlugin",
102
+ "c0-id"=>"0",
103
+ "c0-param0"=>"string:#{url}",
104
+ "c0-param1"=>"string:14867746",
105
+ "xml"=>"true" ) do |res|
106
+ raise ResponceException.new("plugin install fail",res) unless res.code == "200" and res.body =~ /s0\.successfull=/
107
+ end
108
+ end
109
+ def reload_plugin(key)
110
+ @http.get("/plugin-admin.jsp?reloadplugin=#{key}") do |res|
111
+ raise ResponceException.new("cant reload",res) if res.code != "302" or res['location'] !~ /reloadsuccess=true/
112
+ end
113
+ end
114
+ def uninstall_plugin(key)
115
+ @http.get("/plugin-admin.jsp?deleteplugin=#{key}") do |res|
116
+ raise ResponceException.new("cant delete",res) if res.code != "302" or res['location'] !~ /deletesuccess=true/
117
+ end
118
+ end
119
+ def system_cache
120
+ @http.get("/system-cache.jsp") do |res|
121
+ Nokogiri::HTML(res.body).search('input[type=checkbox][name=cacheID]').map{|i|
122
+ {
123
+ :cacheID => i[:value],
124
+ :name => i.ancestors("tr").first.search("td td")[1].content.strip
125
+ }
126
+ }
127
+ end
128
+ end
129
+ def system_cache_clear(cacheID)
130
+ @http.post("/system-cache.jsp","cacheID"=>cacheID, "clear"=>"Clear") do |res|
131
+ ! Nokogiri::HTML(res.body).at("div[class='jive-success']").nil?
132
+ end
133
+ end
134
+ def setup_mode?
135
+ @http.get("/login.jsp") do |res|
136
+ res.code == "302" and res["location"] =~ %r"/setup/"
137
+ end
138
+ end
139
+ end
140
+ def setup_mode?
141
+ @client.setup_mode?
142
+ end
143
+ def setup_wizard
144
+ require File.join(File.dirname(__FILE__),"openfire_admin/setup_wizard")
145
+ SetupWizard.new(@client.http)
146
+ end
147
+
148
+ def initialize(loginurl="http://localhost:9090")
149
+ @client = AdminClient.new(loginurl)
150
+ end
151
+ def logined?
152
+ @logined
153
+ end
154
+
155
+ def login(username, password)
156
+ @client.login(username, password)
157
+ @logined = true
158
+ end
159
+
160
+ # System property map
161
+ class PropertyMap
162
+ def initialize(client)
163
+ @client = client
164
+ reload
165
+ end
166
+
167
+ def inspect
168
+ @cache.inspect
169
+ end
170
+
171
+ # get system property
172
+ def []( name )
173
+ v = @cache[name]
174
+ v = @client.get_property(name) if v.nil? and @cache.has_key?(name)
175
+ v
176
+ end
177
+
178
+ # reload cache
179
+ def reload
180
+ @cache = @client.get_properties
181
+ self
182
+ end
183
+
184
+ # remove property
185
+ def remove(name)
186
+ @client.remove_property(name)
187
+ end
188
+
189
+ # set/add property
190
+ def []=(name,value)
191
+ if value.nil?
192
+ remove(name)
193
+ else
194
+ @client.set_property(name, value)
195
+ @cache[name]=value
196
+ end
197
+ end
198
+ end
199
+
200
+ # get properties
201
+ def system_properties
202
+ PropertyMap.new(@client)
203
+ end
204
+
205
+ # cache control. this instance can clear cache.
206
+ class SystemCache
207
+ attr_reader :cacheID, :name
208
+ def initialize(client, cacheID, name)
209
+ @client = client
210
+ @cacheID = cacheID
211
+ @name = name
212
+ end
213
+ def to_s
214
+ "#<#{self.class} (#{@cacheID})#{name.inspect}>"
215
+ end
216
+ # clear cache
217
+ def clear
218
+ @client.system_cache_clear( @cacheID )
219
+ end
220
+ end
221
+
222
+ # return SystemCache array
223
+ def system_cache
224
+ @client.system_cache.map{|c| SystemCache.new( @client, c[:cacheID], c[:name] )}
225
+ end
226
+
227
+ # plugin abstract class
228
+ class Plugin
229
+ attr_accessor :name, :description, :version
230
+ attr_reader :key
231
+ def initialize(client, key)
232
+ @client = client
233
+ @key = key.downcase
234
+ end
235
+ def inspect
236
+ to_s
237
+ end
238
+ def to_s
239
+ "#<#{self.class} #{key} #{version} (#{name.inspect} #{description.inspect})>"
240
+ end
241
+ def eql?(obj)
242
+ case obj
243
+ when Plugin
244
+ self.key == obj.key
245
+ when String
246
+ self.key == obj.downcase
247
+ else
248
+ false
249
+ end
250
+ end
251
+ end
252
+
253
+ # installed plugin. this instance can uninstall and reload
254
+ class InstalledPlugin < Plugin
255
+ # reload plugin
256
+ def reload
257
+ @client.reload_plugin(key)
258
+ end
259
+
260
+ # uninstall plugin
261
+ def uninstall
262
+ @client.uninstall_plugin(key)
263
+ end
264
+ end
265
+
266
+ # available plugin. this can install
267
+ class AvailablePlugin < Plugin
268
+ attr_accessor :url
269
+
270
+ # install plugin
271
+ def install
272
+ @client.install_plugin(url)
273
+ end
274
+ end
275
+
276
+ # plugin list array. this can find plugin by key.
277
+ class PluginList < Array
278
+ def [](name)
279
+ if name.is_a?(String)
280
+ self.find{|p| p.eql? name }
281
+ else
282
+ super
283
+ end
284
+ end
285
+ end
286
+
287
+ # plugins list array of available plugins.
288
+ # if you need not installed plugins, ( self.available_plugins - self.install_plugin )
289
+ def available_plugins
290
+ ret = PluginList.new
291
+ doc = Nokogiri::XML(open("http://www.igniterealtime.org/projects/openfire/versions.jsp").read)
292
+ doc.search('plugin').each do |tr|
293
+ p = AvailablePlugin.new(@client, tr[:url].match(/\/([^\.\/]+)\.[^\/.]+$/)[1])
294
+ p.name = tr[:name]
295
+ p.description = tr[:description]
296
+ p.version = tr[:latest]
297
+ p.url = tr[:url]
298
+ ret << p
299
+ end
300
+ ret
301
+ end
302
+
303
+ # plugins list array of installed plugins
304
+ def installed_plugins
305
+ ret = PluginList.new
306
+ @client.get_installed_plugins.each{|p|
307
+ r = InstalledPlugin.new(@client, p[:key])
308
+ r.name = p[:name]
309
+ r.description = p[:description]
310
+ r.version = p[:version]
311
+ ret << r
312
+ }
313
+ ret
314
+ end
315
+ end
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/openfire_admin/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["nazoking"]
6
+ gem.email = ["nazoking@gmai.com"]
7
+ gem.description = %q{Manipurate Openfire admin console}
8
+ gem.summary = %q{}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "openfire_admin"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = OpenfireAdmin::VERSION
17
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: openfire_admin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - nazoking
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2013-10-05 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Manipurate Openfire admin console
17
+ email:
18
+ - nazoking@gmai.com
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files: []
24
+
25
+ files:
26
+ - .gitignore
27
+ - Gemfile
28
+ - LICENSE
29
+ - README.md
30
+ - Rakefile
31
+ - lib/openfire_admin.rb
32
+ - lib/openfire_admin/http_client.rb
33
+ - lib/openfire_admin/response_exception.rb
34
+ - lib/openfire_admin/setup_wizard.rb
35
+ - lib/openfire_admin/version.rb
36
+ - openfire_admin.gemspec
37
+ has_rdoc: false
38
+ homepage: ""
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.3.1
60
+ signing_key:
61
+ specification_version: 2
62
+ summary: ""
63
+ test_files: []
64
+