admin_tools_ennder 1.3.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/Changelog +158 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +89 -0
  5. data/Rakefile +2 -0
  6. data/TODO +0 -0
  7. data/app/controllers/admin_dev_infos_controller.rb +46 -0
  8. data/app/controllers/admin_gems_controller.rb +24 -0
  9. data/app/controllers/admin_inflexions_controller.rb +6 -0
  10. data/app/controllers/admin_menu_controller.rb +2 -0
  11. data/app/controllers/admin_routes_controller.rb +21 -0
  12. data/app/controllers/admin_send_file_controller.rb +8 -0
  13. data/app/controllers/admin_translations_controller.rb +21 -0
  14. data/app/controllers/admin_url_infos_controller.rb +7 -0
  15. data/app/controllers/application_controller.rb +10 -0
  16. data/app/controllers/commands_controller.rb +152 -0
  17. data/app/controllers/gmm_controller.rb +27 -0
  18. data/app/controllers/processus_controller.rb +8 -0
  19. data/app/helpers/application_helper.rb +11 -0
  20. data/app/metal/metal_processus_liste.rb +13 -0
  21. data/app/models/command.rb +5 -0
  22. data/app/views/admin_dev_infos/index.html.erb +7 -0
  23. data/app/views/admin_dev_infos/show.html.erb +43 -0
  24. data/app/views/admin_gems/_gem_infos.html.erb +46 -0
  25. data/app/views/admin_gems/index.html.erb +3 -0
  26. data/app/views/admin_inflexions/index.html.erb +41 -0
  27. data/app/views/admin_menu/index.html.erb +29 -0
  28. data/app/views/admin_routes/index.html.erb +64 -0
  29. data/app/views/admin_send_file/index.html.erb +7 -0
  30. data/app/views/admin_translations/index.html.erb +128 -0
  31. data/app/views/admin_url_infos/index.html.erb +91 -0
  32. data/app/views/commands/_execute_results.html.erb +10 -0
  33. data/app/views/commands/execute.html.erb +10 -0
  34. data/app/views/commands/executed.html.erb +12 -0
  35. data/app/views/commands/index.html.erb +24 -0
  36. data/app/views/commands/new.html.erb +15 -0
  37. data/app/views/commands/show.html.erb +10 -0
  38. data/app/views/common/_error_messages.html.erb +10 -0
  39. data/app/views/common/_top_menu.html.erb +2 -0
  40. data/app/views/gmm/index.html.erb +34 -0
  41. data/app/views/processus/index.html.erb +9 -0
  42. data/config/routes.rb +75 -0
  43. data/db/migrate/20100422173622_create_commands.rb +13 -0
  44. data/db/migrate/rails_before_5/20100422173622_create_commands.rb +13 -0
  45. data/lib/admin_tools_ennder.rb +77 -0
  46. data/lib/admin_tools_ennder/engine.rb +7 -0
  47. data/lib/gtm.rb +75 -0
  48. data/lib/tasks/admin_tools_ennder_tasks.rake +11 -0
  49. data/test/admin_tools_ennder_test.rb +8 -0
  50. data/test/test_helper.rb +3 -0
  51. metadata +95 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 914697432a11230253094fb760a955bb70acf1ed48cad60666cd90c2e26a503f
4
+ data.tar.gz: 7f6c9d5c95756f9a65f55ca60307e6ca1daeda7b9e08bb62f6efb84729ee5fe7
5
+ SHA512:
6
+ metadata.gz: 4ca48d5aac8bd546ea828c500ed33cc35d9d2d753f6c892c62d6401f7172d5d2227cba82a984a9f2250f1a3b6807acbea81fd8d620c7099a7713bf952e545794
7
+ data.tar.gz: b3c1a0c5c2ed2616bd082593500674b865e7b2f7bb2ab8db250d84acfdb16b08dc9e28c4fb8150ce44cffca5492a347327034d6d0d4259b63887f03fe8abd0c5
@@ -0,0 +1,158 @@
1
+ == 1.3.20 / 2018-09-21
2
+ * commands controller : http authentication password compromission fixed
3
+ DO NOT USE previous gem versions, they can be used to execute arbitrary commands on your server !
4
+
5
+ == 1.3.19 / 2018-09-13
6
+ * commands controller : protected attributes
7
+
8
+ == 1.3.18 / 2018-09-13
9
+ * migration version = 5.0
10
+
11
+ == 1.3.17 / 2018-09-13
12
+ * migration with version if Rails 5+
13
+
14
+ == 1.3.16 / 2018-09-13
15
+ * fixed previous fix, sorry !
16
+
17
+ == 1.3.15 / 2018-09-13
18
+ * fixed before_filter renamed before_action in Rails 5.1
19
+
20
+ == 1.3.14 / 2018-04-27
21
+ * avoid 2 warnings
22
+ gems/admin_tools_ennder-1.3.12/app/controllers/commands_controller.rb:110: warning: assigned but unused variable - pid
23
+ gems/admin_tools_ennder-1.3.12/app/controllers/commands_controller.rb:110: warning: assigned but unused variable - stdin
24
+
25
+ == 1.3.13 / 2018-04-27
26
+ * removed
27
+
28
+ == 1.3.12 / 2017-03-22
29
+ * /admin/routes fixed for Rails 5
30
+
31
+ == 1.3.11 / 2017-03-21
32
+ * test with ruby 2.3
33
+
34
+ == 1.3.8 / 2016-02-04
35
+ * css id on command_result pre in action command/new
36
+
37
+ == 1.3.7 / 2016-02-03
38
+ * bugfix : command/new
39
+
40
+ == 1.3.6 / 2016-02-03
41
+ * bugfix : error messages partial
42
+
43
+ == 1.3.5 / 2016-02-03
44
+ * error messages partial
45
+
46
+ == 1.3.4 / 2016-02-03
47
+ * Compatibility : Rails 3+4
48
+
49
+ == 1.3.3 / 2014-03-16
50
+ * GMM : sort models
51
+
52
+ == 1.3.2 / 2014-02-23
53
+ * GMM : display model relations with type
54
+
55
+ == 1.3.1 / 2014-02-23
56
+ * GMM : display model relations
57
+
58
+ == 1.3.0 / 2014-02-16
59
+ * new admin page : Global Model Manipulation (GMM)
60
+
61
+ == 1.2.12 / 2011-12-22
62
+ * info version de Ruby dans le menu admin
63
+
64
+ == 1.2.11 / 2011-06-08
65
+ * Utilisation de Rails.application.routes pour Rails 3
66
+
67
+ == 1.2.10 / 2011-05-12
68
+ * Infos Urls : Rails 3 request_uri => fullpath
69
+
70
+ == 1.2.9 / 2011-03-28
71
+ * Urls liens d'admin générées par rails
72
+
73
+ == 1.2.8 / 2011-03-28
74
+ * route admin/menu
75
+ * correction annomalie route admin/gems
76
+
77
+ == 1.2.7 / 2011-03-28
78
+ * tests quasi complets
79
+ * liste Gems de l'appli pour Rails 3
80
+
81
+ == 1.2.5 / 2011-03-28
82
+ * correction anomalie menu admin_menu
83
+
84
+ == 1.2.4 / 2011-03-25
85
+ * portage à rails 3 avec un engine pour les routes
86
+
87
+ == 1.2.4 / 2011-03-24
88
+ * portage à rails 3
89
+ * tests inclus dans les applis test_gems_ennder_rails{2, 3}
90
+
91
+ == 1.2.3 / 2011-02-09
92
+ * changement mot de passe admin : execution de commandes
93
+ * titre info gems : gems chargés
94
+
95
+ == 1.2.2 / 2011-02-07
96
+ * Correction anomalie liste des chemins
97
+
98
+ == 1.2.0 / 2011-02-06
99
+ * Nouvelle page liste des gems
100
+
101
+ == 1.2.1 / 2011-02-07
102
+ * Infos liste des gems OK
103
+ * Ajout liste des chemin source des Gems
104
+
105
+ == 1.1.11 / 2011-02-05
106
+ * execute_command dans la bonne action
107
+
108
+ == 1.1.10 / 2011-02-04
109
+ * Ajout lien execute dans le show
110
+ * Ajout partiel _execute_results pour l'utiliser dans les action new et execute
111
+
112
+ == 1.1.9 / 2011-02-04
113
+ * correction erreur sur nouvelle route execute dans la vue, manquait le param commande
114
+
115
+ == 1.1.8 / 2011-02-04
116
+ * correction erreur sur nouvelle route execute dans la vue
117
+
118
+ == 1.1.7 / 2011-02-04
119
+ * correction erreur sur nouvelle route execute
120
+
121
+ == 1.1.6 / 2011-02-04
122
+ * gestion exception sur execution commande
123
+ * possibilité de réexecuter une commande
124
+
125
+ == 1.1.5 / 2011-02-04
126
+ * correction erreur sur précédente évolution
127
+
128
+ == 1.1.4 / 2011-02-03
129
+ * execution de commande, infos stderr
130
+
131
+ == 1.1.3 / 2011-01-24
132
+ * ajout mention exemple dans inflexions
133
+
134
+ == 1.1.2 / 2011-01-03
135
+ * Correction erreur dans le menu
136
+
137
+ == 1.1.1 / 2011-01-03
138
+ * Déplacement de routes_custom.rb dans lib/config
139
+
140
+ == 1.1.0 / 2011-01-03
141
+
142
+ * Ajout dynamique des nouvelles routes
143
+ * Renommage de la page admin_routes_infos en admin_routes
144
+
145
+ == 1.0.0 / 2011-01-02
146
+
147
+ * 1 major enhancement
148
+ Migration en Gem, et posé sur RubyGem
149
+
150
+ == 0.9.9 / 2010-12-31
151
+ * Posé sur GitHub
152
+ git remote add origin git@github.com:Ennder/admin_tools_ennder.git
153
+
154
+ == 0.9.0 / 2010-09-08
155
+ * Ajout de la route pour la page de menu
156
+
157
+ == 0.1.0 / 2010-05-05
158
+ * Création Plugin
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016 Ennder
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.
@@ -0,0 +1,89 @@
1
+ # admin_tools_ennder
2
+ ===========
3
+
4
+ Pages informatives de test et de développement
5
+
6
+ - DO NOT USE previous gem versions before 1.3.20, they can be used to execute arbitrary commands on your server !
7
+
8
+ Features
9
+ --------
10
+
11
+ 1. Ajoute une page de menu d'admin
12
+ 2. Ajoute tous les sous-menus de cette page
13
+
14
+ La page de menu a pour Url : /admin/menu (route automatique : **admin_menu_url**)
15
+
16
+ **Menu**
17
+
18
+ * Liste des inflexions
19
+ * Liste des traductions
20
+ * Liste des routes
21
+ * Liste des gems
22
+ <br/>
23
+ * Liste des processus du serveur
24
+ * Liste des processus du serveur (metal)
25
+ <br/>
26
+ * Infos de developpement
27
+ * Infos de l'Url courante
28
+ <br/>
29
+ * Execution de commandes shell
30
+ * Télécharger un fichier
31
+
32
+ Unsolved problems :
33
+ No tests developped
34
+
35
+ Examples
36
+ --------
37
+
38
+ <%= link_to "Menu d'administration", admin_menu_url %>
39
+
40
+ Requirements
41
+ ------------
42
+
43
+ - Rails 3 or greater
44
+ - gem Open4 pour l'execution des commandes
45
+ - a file named : config/auth_password_admin.secret in your app :
46
+ Containing the http authentication password needed for the commands controller
47
+
48
+ Install
49
+ -------
50
+
51
+ - install the gem manually
52
+ [sudo] gem install admin_tools_ennder
53
+ Or
54
+ - add id to your Gemfile
55
+ - Create a file containing the http authentication password needed for the commands controller
56
+ echo '<A PASSWORD>' >config/auth_password_admin.secret
57
+ Change <A PASSWORD> for a reliable password.
58
+
59
+ Author
60
+ ------
61
+
62
+ Original author: Ennder
63
+
64
+ License
65
+ -------
66
+
67
+ (The MIT License)
68
+
69
+ Copyright (c) 2010-2016 Ennder
70
+
71
+ Permission is hereby granted, free of charge, to any person obtaining
72
+ a copy of this software and associated documentation files (the
73
+ 'Software'), to deal in the Software without restriction, including
74
+ without limitation the rights to use, copy, modify, merge, publish,
75
+ distribute, sublicense, and/or sell copies of the Software, and to
76
+ permit persons to whom the Software is furnished to do so, subject to
77
+ the following conditions:
78
+
79
+ The above copyright notice and this permission notice shall be
80
+ included in all copies or substantial portions of the Software.
81
+
82
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
83
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
84
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
85
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
86
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
87
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
88
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
89
+
@@ -0,0 +1,2 @@
1
+ task :default => 'test:run'
2
+ task 'gem:release' => 'test:run'
data/TODO ADDED
File without changes
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+ class AdminDevInfosController < ApplicationController
3
+ def index
4
+ respond_to do |format|
5
+ format.html # index.html.erb
6
+ end
7
+ end
8
+
9
+ def show
10
+ if params[:nom_objet].blank?
11
+ flash[:notice] = 'Il faut spécifier un nom de Classe.'
12
+ redirect_to( :action => :index )
13
+
14
+ return
15
+ end
16
+
17
+ _defini = false
18
+ begin
19
+ #Exceptions enterrées
20
+ _defini = Object.const_defined?(params[:nom_objet])
21
+ rescue
22
+ end
23
+
24
+ if ! _defini
25
+ flash[:notice] = "La Classe #{params[:nom_objet]} n'existe pas."
26
+ redirect_to( :action => :index )
27
+
28
+ return
29
+ end
30
+
31
+ _La_classe = Object::const_get(params[:nom_objet])
32
+
33
+ if ! _La_classe.respond_to?(:new)
34
+ flash[:notice] = "La Classe #{_La_classe} ne fournit pas la méthode new()."
35
+ redirect_to( :action => :index )
36
+
37
+ return
38
+ end
39
+
40
+ @l_objet = _La_classe.new()
41
+
42
+ respond_to do |format|
43
+ format.html # show.html.erb
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,24 @@
1
+ if Rails::VERSION::MAJOR >= 3
2
+ require 'bundler'
3
+ end
4
+
5
+ class AdminGemsController < ApplicationController
6
+ def index
7
+ #mygems = Bundler.load.specs.map { |spec| spec.name }
8
+
9
+ if Rails::VERSION::MAJOR < 3
10
+ application_gems = Rails.configuration.gems
11
+ else
12
+ application_gems = Bundler.load.specs
13
+ end
14
+
15
+ @application_gems = application_gems.collect{|g|
16
+ [
17
+ g.name,
18
+ ( (Rails::VERSION::MAJOR < 3) ? g.requirement : g.version.to_s ) || '?'
19
+ ]
20
+ }.sort!{|a, b|
21
+ a[0] <=> b[0]
22
+ }
23
+ end
24
+ end
@@ -0,0 +1,6 @@
1
+ class AdminInflexionsController < ApplicationController
2
+ def index
3
+ @inflections_plur = ActiveSupport::Inflector.inflections.plurals
4
+ @inflections_sing = ActiveSupport::Inflector.inflections.singulars
5
+ end
6
+ end
@@ -0,0 +1,2 @@
1
+ class AdminMenuController < ApplicationController
2
+ end
@@ -0,0 +1,21 @@
1
+ class AdminRoutesController < ApplicationController
2
+ def index
3
+ if Rails::VERSION::MAJOR >= 3
4
+ all_routes = Rails.application.routes
5
+ else
6
+ all_routes = ActionController::Routing::Routes
7
+ end
8
+
9
+ if all_routes.named_routes.respond_to?(:routes)
10
+ @routes_hash = all_routes.routes
11
+ @named_routes_hash = all_routes.named_routes.routes
12
+ else
13
+ @routes_hash = all_routes.routes.to_a
14
+ @named_routes_hash = all_routes.named_routes.to_a
15
+ end
16
+
17
+ respond_to do |format|
18
+ format.html # index.html.erb
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,8 @@
1
+ class AdminSendFileController < ApplicationController
2
+ def index
3
+ end
4
+
5
+ def download
6
+ send_file params[:chemin], :type=>"video/x-msvideo", :x_sendfile=>true
7
+ end
8
+ end
@@ -0,0 +1,21 @@
1
+ # -*- coding: utf-8 -*-
2
+ class AdminTranslationsController < ApplicationController
3
+ def index
4
+ #TODO Ennder correction : Rails 3 ? I18n.backend.send(:translations) renvoie une liste vide
5
+ begin
6
+ @traductions_all = I18n.backend.send(:translations)
7
+ rescue _exception
8
+ @traductions_all = []
9
+ logger.error "échec I18n.backend.send(:translations) [#{_exception.message}]"
10
+ end
11
+ logger.debug "[#{@traductions_all.size}] traduction(s)"
12
+
13
+ @locales_list = I18n.available_locales.inject(''){ |list, l|
14
+ list << '&nbsp;&nbsp;<b>' + l.to_s + '</b>'
15
+ }
16
+
17
+ respond_to do |format|
18
+ format.html # index.html.erb
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ class AdminUrlInfosController < ApplicationController
2
+ def index
3
+ respond_to do |format|
4
+ format.html # index.html.erb
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ # Filters added to this controller apply to all controllers in the application.
2
+ # Likewise, all the methods added will be available for all controllers.
3
+
4
+ class ApplicationController < ActionController::Base
5
+ helper :all # include all helpers, all the time
6
+ protect_from_forgery # See ActionController::RequestForgeryProtection for details
7
+
8
+ # Scrub sensitive parameters from your log
9
+ # filter_parameter_logging :password
10
+ end
@@ -0,0 +1,152 @@
1
+ require "open4"
2
+
3
+ class CommandsController < ApplicationController
4
+ if respond_to?(:before_action)
5
+ before_action :authenticate_commands, except: [:index, :show, :new, :destroy]
6
+ else
7
+ before_filter :authenticate_commands, except: [:index, :show, :new, :destroy]
8
+ end
9
+
10
+ # GET /commands
11
+ # GET /commands.xml
12
+ def index
13
+ @commands_nb = Command.count
14
+ @commands = Command.all
15
+
16
+ respond_to do |format|
17
+ format.html # index.html.erb
18
+ format.xml { render :xml => @commands }
19
+ end
20
+ end
21
+
22
+ # GET /commands/1
23
+ # GET /commands/1.xml
24
+ def show
25
+ @command = Command.find(params[:id])
26
+
27
+ respond_to do |format|
28
+ format.html # show.html.erb
29
+ format.xml { render :xml => @command }
30
+ end
31
+ end
32
+
33
+ # GET /commands/new
34
+ # GET /commands/new.xml
35
+ def new
36
+ @command = Command.new
37
+
38
+ respond_to do |format|
39
+ format.html # new.html.erb
40
+ format.xml { render :xml => @command }
41
+ end
42
+ end
43
+
44
+ # POST /commands
45
+ # POST /commands.xml
46
+ def create
47
+ @command = Command.new(command_params)
48
+
49
+ respond_to do |format|
50
+ _result = @command.save
51
+ @commands_nb = Command.count
52
+ @commands = Command.all
53
+
54
+ if _result
55
+ # @command_result = %x[#{@command.execute.to_s}]
56
+ execute_command
57
+
58
+ @command = Command.new
59
+ format.html { render :action => "new" }
60
+ format.xml { render :xml => @command, :status => :created, :location => @command }
61
+ else
62
+ format.html { redirect_to(@command) }
63
+ format.xml { render :xml => @command.errors, :status => :unprocessable_entity }
64
+ end
65
+ end
66
+ end
67
+
68
+ # GET /commands/1/execute
69
+ # GET /commands/1/execute.xml
70
+ def execute
71
+ @command = Command.find(params[:id])
72
+ execute_command
73
+
74
+ respond_to do |format|
75
+ format.html { render :action => "executed" }
76
+ format.xml { render :xml => @command }
77
+ end
78
+ end
79
+
80
+ # GET /commands/1/executed
81
+ # GET /commands/1/executed.xml
82
+ def executed
83
+ @command = Command.find(params[:id])
84
+
85
+ respond_to do |format|
86
+ format.html { render :action => "execute" }
87
+ format.xml { render :xml => @command }
88
+ end
89
+ end
90
+
91
+ # DELETE /commands/1
92
+ # DELETE /commands/1.xml
93
+ def destroy
94
+ @command = Command.find(params[:id])
95
+ @command.destroy
96
+
97
+ respond_to do |format|
98
+ format.html { redirect_to(commands_url) }
99
+ format.xml { head :ok }
100
+ end
101
+ end
102
+
103
+
104
+ private
105
+
106
+ def authenticate_commands
107
+ authenticate_or_request_with_http_basic do |name, password|
108
+ auth_password_admin = nil
109
+ begin
110
+ auth_password_admin = get_auth_password_admin
111
+ rescue Exception => e
112
+ Rails.logger.error "==>commands_controller #{e.message}"
113
+ end
114
+
115
+ if auth_password_admin
116
+ name == 'admin' && password == auth_password_admin
117
+ else
118
+ false
119
+ end
120
+ end
121
+ end
122
+
123
+ def execute_command
124
+ begin
125
+ # pid, stdin
126
+ _, _, stdout, stderr = Open4::popen4 @command.execute.to_s
127
+ @command_result = stdout.read.strip
128
+ @command_error = stderr.read.strip
129
+ rescue Exception => e
130
+ @command_error = "Exception: #{e.inspect}"
131
+ end
132
+ end
133
+
134
+ def command_params
135
+ params.require(:command).permit(
136
+ :execute
137
+ )
138
+ end
139
+
140
+ def get_auth_password_admin
141
+ auth_password_file = File.join(Rails.root.to_s, 'config', 'auth_password_admin.secret')
142
+
143
+ auth_password_admin = nil
144
+ if File.readable? auth_password_file
145
+ auth_password_admin = File.read(auth_password_file).chomp
146
+ else
147
+ raise "#{auth_password_file} not found or not readable, can't check http authentification password"
148
+ end
149
+
150
+ auth_password_admin
151
+ end
152
+ end