openfire_admin 0.0.1

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/.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
+