webappsword_sdk 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 +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +24 -0
- data/README.md +67 -0
- data/Rakefile +20 -0
- data/VERSION +1 -0
- data/bin/webappsword_sdk +85 -0
- data/easy_installer-0.0.1.gem +0 -0
- data/example/Rakefile +72 -0
- data/example/additional/after_install.rb +1 -0
- data/example/additional/return_callback.rb +2 -0
- data/example/arch.zip +0 -0
- data/example/config.yml +6 -0
- data/example/files/joomla/index.php +54 -0
- data/example/installers/global.rb +2 -0
- data/example/installers/local.rb +2 -0
- data/example/validators/ftp.rb +6 -0
- data/example/validators/local.rb +0 -0
- data/lib/easy_installer.rb +4 -0
- data/lib/easy_installer/autoload.rb +28 -0
- data/lib/easy_installer/coffeescript_sandbox.rb +95 -0
- data/lib/easy_installer/config.rb +138 -0
- data/lib/easy_installer/config_validator.rb +73 -0
- data/lib/easy_installer/fake/ftp/install_helper.rb +34 -0
- data/lib/easy_installer/fake/ftp/validate_helper.rb +12 -0
- data/lib/easy_installer/fake/local/install_helper.rb +30 -0
- data/lib/easy_installer/fake/local/standart_input.yml +2 -0
- data/lib/easy_installer/fake/local/validate_helper.rb +6 -0
- data/lib/easy_installer/fake/php/validate_helper.rb +12 -0
- data/lib/easy_installer/fake/validator.rb +0 -0
- data/lib/easy_installer/fake/zip.rb +9 -0
- data/lib/easy_installer/generators/base.rb +25 -0
- data/lib/easy_installer/generators/config.rb +58 -0
- data/lib/easy_installer/install.rb +56 -0
- data/lib/easy_installer/install_helpers/result.rb +14 -0
- data/lib/easy_installer/install_helpers/template.rb +19 -0
- data/lib/easy_installer/install_helpers/zip.rb +9 -0
- data/lib/easy_installer/methods/ftp/install_helper.rb +105 -0
- data/lib/easy_installer/methods/ftp/standart_input.yml +5 -0
- data/lib/easy_installer/methods/ftp/standart_input.yml~ +5 -0
- data/lib/easy_installer/methods/ftp/validate_helper.rb +24 -0
- data/lib/easy_installer/methods/local/install_helper.rb +37 -0
- data/lib/easy_installer/methods/local/standart_input.yml +2 -0
- data/lib/easy_installer/methods/local/validate_helper.rb +4 -0
- data/lib/easy_installer/methods/sample/install_helper.rb +67 -0
- data/lib/easy_installer/methods/sample/standart_input.yml +5 -0
- data/lib/easy_installer/methods/sample/standart_input.yml~ +5 -0
- data/lib/easy_installer/methods/sample/validate_helper.rb +17 -0
- data/lib/easy_installer/modules/php/standart_input.yml +6 -0
- data/lib/easy_installer/modules/php/validate_helper.rb +47 -0
- data/lib/easy_installer/sandbox.rb +100 -0
- data/lib/easy_installer/sandbox_modules/message.rb +62 -0
- data/lib/easy_installer/steps.rb +36 -0
- data/lib/easy_installer/temp.rb +23 -0
- data/lib/easy_installer/translate.rb +70 -0
- data/lib/easy_installer/validator.rb +99 -0
- data/lib/easy_installer/validator_support_methods.rb +37 -0
- data/tests/files/additional/after_install.rb +1 -0
- data/tests/files/config.yml +10 -0
- data/tests/files/installers/global.rb +1 -0
- data/tests/files/installers/local.rb +1 -0
- data/tests/files/sample.zip +0 -0
- data/tests/files/template.erb +1 -0
- data/tests/files/translations/pl.yml +11 -0
- data/tests/files/validators/ftp.rb +3 -0
- data/tests/files/validators/local.rb +0 -0
- data/tests/files/validators/sample.rb +2 -0
- data/tests/test_config.rb +30 -0
- data/tests/test_config_validator.rb +22 -0
- data/tests/test_ftp.rb +51 -0
- data/tests/test_install.rb +19 -0
- data/tests/test_sandbox.rb +48 -0
- data/tests/test_sandbox_messages.rb +18 -0
- data/tests/test_steps.rb +19 -0
- data/tests/test_temp.rb +14 -0
- data/tests/test_template.rb +17 -0
- data/tests/test_validator.rb +31 -0
- data/tests/test_zip.rb +26 -0
- data/tests/wrong_config/config.yml +6 -0
- data/tests/wrong_config/install/global.rb +2 -0
- data/tests/wrong_config/install/local.rb +1 -0
- data/tests/wrong_config/translations/pl.yml +11 -0
- data/tests/wrong_config/validators/ftp.rb +4 -0
- data/tests/wrong_config/validators/local.rb +0 -0
- data/tests/wrong_config/validators/sample.rb +3 -0
- data/tests/~test_translator.rb +17 -0
- data/webappsword_sdk.gemspec +24 -0
- metadata +149 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.DS_Store
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
GEM
|
2
|
+
specs:
|
3
|
+
ffi (1.0.11)
|
4
|
+
guard (1.0.1)
|
5
|
+
ffi (>= 0.5.0)
|
6
|
+
thor (~> 0.14.6)
|
7
|
+
guard-test (0.4.3)
|
8
|
+
guard (>= 0.4)
|
9
|
+
test-unit (~> 2.2)
|
10
|
+
shoulda (3.0.1)
|
11
|
+
shoulda-context (~> 1.0.0)
|
12
|
+
shoulda-matchers (~> 1.0.0)
|
13
|
+
shoulda-context (1.0.0)
|
14
|
+
shoulda-matchers (1.0.0)
|
15
|
+
test-unit (2.4.8)
|
16
|
+
thor (0.14.6)
|
17
|
+
|
18
|
+
PLATFORMS
|
19
|
+
ruby
|
20
|
+
|
21
|
+
DEPENDENCIES
|
22
|
+
guard
|
23
|
+
guard-test
|
24
|
+
shoulda
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
Simple Auto-installer for Web Apps
|
2
|
+
|
3
|
+
Currently "works" example in tests/example/gui.rb
|
4
|
+
Keep waiting for new version
|
5
|
+
|
6
|
+
Structure:
|
7
|
+
===
|
8
|
+
|
9
|
+
files:
|
10
|
+
---
|
11
|
+
here should go all of external files like .zip or web app config files
|
12
|
+
install:
|
13
|
+
---
|
14
|
+
Here goes all install scripts.
|
15
|
+
translations:
|
16
|
+
---
|
17
|
+
Here goes yml files with translations in format 2_lang_char.yml
|
18
|
+
additional:
|
19
|
+
---
|
20
|
+
Additional ruby script
|
21
|
+
Validator:
|
22
|
+
---
|
23
|
+
Validator scripts for each method.
|
24
|
+
config.yml:
|
25
|
+
---
|
26
|
+
main config.
|
27
|
+
|
28
|
+
Install:
|
29
|
+
---
|
30
|
+
Here goes rb scripts responsible for installing on server. They should be named like : method.rb there is one exception global.rb this is script which is used then on different methods we make same steps.
|
31
|
+
Available methods imported from :
|
32
|
+
selected method InstallHelper
|
33
|
+
|
34
|
+
##### Example file :
|
35
|
+
|
36
|
+
**setup** # _this command initializes required values like ftp connection in ftp method_
|
37
|
+
**unzip "files/joomla.zip", "files/joomla"** #_ command unpack joomla.zip to directory "files/joomla"_
|
38
|
+
**move_directory "files/joomla", $user_input["path"].value** # _moves directory files/joomla to desired directory on remote or local machine_
|
39
|
+
**true**
|
40
|
+
translations:
|
41
|
+
-------------
|
42
|
+
should contain files with translations to GUI like en.yml or pl.yml.
|
43
|
+
additional:
|
44
|
+
-----------
|
45
|
+
Additional files which are used by installer
|
46
|
+
- finish.rb
|
47
|
+
Invoked after success installation. Available methods:
|
48
|
+
validator:
|
49
|
+
----------
|
50
|
+
validates inputs scripts are named after method for e.g. local.rb or ftp.rb.
|
51
|
+
##### How to write script :
|
52
|
+
_check :for=> Array of user_inputs names which are going to be validated, :then=> Array of user_inputs which have to be filled before function runs do
|
53
|
+
block of validating code
|
54
|
+
end_
|
55
|
+
##### available methods from :
|
56
|
+
- MethodValidateHelper
|
57
|
+
- ModuleValidateHelper
|
58
|
+
|
59
|
+
config.yml:
|
60
|
+
-----------
|
61
|
+
|
62
|
+
##### methods:
|
63
|
+
- available methods to install
|
64
|
+
##### lang:
|
65
|
+
- name of used lang
|
66
|
+
##### submodules:
|
67
|
+
- submodules available for this module
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
version = File.read("VERSION").strip
|
6
|
+
Rake::TestTask.new(:test) do |test|
|
7
|
+
test.libs << 'lib' << 'test'
|
8
|
+
test.pattern = 'tests/test_*.rb'
|
9
|
+
test.verbose = false
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Build gem files for all projects"
|
13
|
+
task :build do
|
14
|
+
sh "gem build webappsword_sdk.gemspec"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Build and install gem"
|
18
|
+
task :install => :build do
|
19
|
+
sh "gem install webappsword_sdk-#{version}.gem"
|
20
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/bin/webappsword_sdk
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'easy_installer'
|
4
|
+
require 'easy_installer/generators/config'
|
5
|
+
require 'easy_installer/generators/base'
|
6
|
+
require 'fileutils'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
def generate_tree(path)
|
10
|
+
directories = %w{
|
11
|
+
additional
|
12
|
+
files
|
13
|
+
install
|
14
|
+
validator
|
15
|
+
translations
|
16
|
+
}
|
17
|
+
Dir.mkdir(path)
|
18
|
+
directories.each{|dir| Dir.mkdir("#{path}/#{dir}") unless File.exist?("#{path}/#{dir}")}
|
19
|
+
end
|
20
|
+
|
21
|
+
def path_to_gem
|
22
|
+
gem_root = Gem.loaded_specs['easy_installer'].full_gem_path
|
23
|
+
end
|
24
|
+
#help
|
25
|
+
if ARGV[0] == "help" || ARGV.empty?
|
26
|
+
puts "Commands:"
|
27
|
+
puts "=== wizard (directory) ==="
|
28
|
+
puts "Create empty project"
|
29
|
+
puts "Example easy_installer wizard sample_project"
|
30
|
+
puts "=== validate ==="
|
31
|
+
puts "Validates config in current directory"
|
32
|
+
puts "=== pack ==="
|
33
|
+
puts "Creates package ready to upload"
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
if ARGV[0] == "examine" || ARGV[0] == "validate"
|
38
|
+
config = EasyInstaller::Config.new("config.yml")
|
39
|
+
if config.valid?
|
40
|
+
puts "Checked"
|
41
|
+
else
|
42
|
+
abort "Error while cheking"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if ARGV[0] == "wizard"
|
47
|
+
config = EasyInstaller::Generator::Config.new
|
48
|
+
unless ARGV[1]
|
49
|
+
puts "App folder:"
|
50
|
+
dir = STDIN.gets.split("\n")[0]
|
51
|
+
puts "===="
|
52
|
+
else
|
53
|
+
dir = ARGV[1]
|
54
|
+
end
|
55
|
+
FileUtils.mkdir(dir)
|
56
|
+
puts "lang:"
|
57
|
+
config.lang = STDIN.gets.split("\n")[0]
|
58
|
+
puts "===="
|
59
|
+
puts "methods separated by , :"
|
60
|
+
config.methods = STDIN.gets.split("\n")[0].gsub(" ","").split(",")
|
61
|
+
puts "===="
|
62
|
+
puts "submodules separated by ,: "
|
63
|
+
config.submodules = STDIN.gets.split("\n")[0].gsub(" ","").split(",")
|
64
|
+
config.save(File.join(dir,"config.yml"))
|
65
|
+
|
66
|
+
files = [
|
67
|
+
"additional/after_install.rb",
|
68
|
+
"additional/return_callback.rb",
|
69
|
+
"installers/global.rb"
|
70
|
+
]
|
71
|
+
config.methods.each{|method| files << "validators/#{method}.rb" << "installers/#{method}.rb"}
|
72
|
+
EasyInstaller::Generator::Base.new(dir) do |g|
|
73
|
+
g.create_directories [
|
74
|
+
"additional",
|
75
|
+
"files",
|
76
|
+
"installers",
|
77
|
+
"validators"
|
78
|
+
]
|
79
|
+
g.create_files files
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
if ARGV[0] == "install"
|
84
|
+
system("rake install")
|
85
|
+
end
|
Binary file
|
data/example/Rakefile
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require "easy_installer"
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
desc "Display all inputs"
|
7
|
+
task :inputs do
|
8
|
+
require "yaml"
|
9
|
+
config = EasyInstaller::Config.new("config.yml")
|
10
|
+
config["methods"].each do |method|
|
11
|
+
puts "------"
|
12
|
+
puts "#{method}:"
|
13
|
+
puts YAML::dump(config.required_inputs_for_method_as_tree(method))
|
14
|
+
puts "------"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Sample instalation"
|
19
|
+
task :install do
|
20
|
+
config = EasyInstaller::Config.new("config.yml")
|
21
|
+
config["methods"].each_index do |k|
|
22
|
+
puts "#{k}) #{config["methods"][k]}"
|
23
|
+
end
|
24
|
+
puts "select one:"
|
25
|
+
method = config["methods"][STDIN.gets.to_i]
|
26
|
+
config.method = method
|
27
|
+
puts "set values:"
|
28
|
+
#create inputs
|
29
|
+
inputs = {}
|
30
|
+
|
31
|
+
EasyInstaller::Steps.new(config, method)
|
32
|
+
|
33
|
+
config.required_inputs_for_method(method).each do |input|
|
34
|
+
puts "#{input}: "
|
35
|
+
inputs[input] = (STDIN.gets).split("\n")[0]
|
36
|
+
end
|
37
|
+
|
38
|
+
steps = EasyInstaller::Steps.new(config, method)
|
39
|
+
puts "Installing..."
|
40
|
+
|
41
|
+
#validate
|
42
|
+
steps.validate(inputs)
|
43
|
+
|
44
|
+
#install
|
45
|
+
puts "messages:"
|
46
|
+
steps.install(inputs).returned.messages.each do |message|
|
47
|
+
puts message
|
48
|
+
end
|
49
|
+
|
50
|
+
#after install
|
51
|
+
steps.after_install
|
52
|
+
|
53
|
+
#install finished
|
54
|
+
puts "======"
|
55
|
+
puts "Installation finished"
|
56
|
+
puts "Press enter then you finished to run callback"
|
57
|
+
STDIN.gets
|
58
|
+
steps.return_callback(inputs)
|
59
|
+
|
60
|
+
puts "Bye ;)"
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
desc "Validation"
|
65
|
+
task :validate do
|
66
|
+
config = EasyInstaller::Config.new("config.yml")
|
67
|
+
if config.valid?
|
68
|
+
puts "Checked"
|
69
|
+
else
|
70
|
+
abort "Error while cheking"
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
redirect_to "google.pl"
|
data/example/arch.zip
ADDED
Binary file
|
data/example/config.yml
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
<?php
|
2
|
+
/**
|
3
|
+
* @package Joomla.Site
|
4
|
+
* @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
|
5
|
+
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
6
|
+
*/
|
7
|
+
|
8
|
+
// Set flag that this is a parent file.
|
9
|
+
define('_JEXEC', 1);
|
10
|
+
define('DS', DIRECTORY_SEPARATOR);
|
11
|
+
|
12
|
+
if (file_exists(dirname(__FILE__) . '/defines.php')) {
|
13
|
+
include_once dirname(__FILE__) . '/defines.php';
|
14
|
+
}
|
15
|
+
|
16
|
+
if (!defined('_JDEFINES')) {
|
17
|
+
define('JPATH_BASE', dirname(__FILE__));
|
18
|
+
require_once JPATH_BASE.'/includes/defines.php';
|
19
|
+
}
|
20
|
+
|
21
|
+
require_once JPATH_BASE.'/includes/framework.php';
|
22
|
+
|
23
|
+
// Mark afterLoad in the profiler.
|
24
|
+
JDEBUG ? $_PROFILER->mark('afterLoad') : null;
|
25
|
+
|
26
|
+
// Instantiate the application.
|
27
|
+
$app = JFactory::getApplication('site');
|
28
|
+
|
29
|
+
// Initialise the application.
|
30
|
+
$app->initialise();
|
31
|
+
|
32
|
+
// Mark afterIntialise in the profiler.
|
33
|
+
JDEBUG ? $_PROFILER->mark('afterInitialise') : null;
|
34
|
+
|
35
|
+
// Route the application.
|
36
|
+
$app->route();
|
37
|
+
|
38
|
+
// Mark afterRoute in the profiler.
|
39
|
+
JDEBUG ? $_PROFILER->mark('afterRoute') : null;
|
40
|
+
|
41
|
+
// Dispatch the application.
|
42
|
+
$app->dispatch();
|
43
|
+
|
44
|
+
// Mark afterDispatch in the profiler.
|
45
|
+
JDEBUG ? $_PROFILER->mark('afterDispatch') : null;
|
46
|
+
|
47
|
+
// Render the application.
|
48
|
+
$app->render();
|
49
|
+
|
50
|
+
// Mark afterRender in the profiler.
|
51
|
+
JDEBUG ? $_PROFILER->mark('afterRender') : null;
|
52
|
+
|
53
|
+
// Return the response.
|
54
|
+
echo $app;
|
File without changes
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module EasyInstaller
|
2
|
+
autoload :Config, 'easy_installer/config'
|
3
|
+
autoload :Validator, 'easy_installer/validator'
|
4
|
+
autoload :ValidatorSupportMethods, 'easy_installer/validator_support_methods'
|
5
|
+
autoload :Checker, 'easy_installer/checker'
|
6
|
+
autoload :Input , 'easy_installer/input'
|
7
|
+
autoload :Translate, 'easy_installer/translate'
|
8
|
+
autoload :Installer, 'easy_installer/install'
|
9
|
+
autoload :Sandbox, 'easy_installer/sandbox'
|
10
|
+
autoload :Steps, 'easy_installer/steps'
|
11
|
+
autoload :Temp, 'easy_installer/temp'
|
12
|
+
|
13
|
+
module Generator
|
14
|
+
autoload :Config, 'easy_installer/generators/config'
|
15
|
+
autoload :Base, 'easy_installer/generators/base'
|
16
|
+
end
|
17
|
+
|
18
|
+
module InstallHelper
|
19
|
+
autoload :Template, 'easy_installer/install_helpers/Template'
|
20
|
+
autoload :ZipFile, 'easy_installer/install_helpers/zip'
|
21
|
+
autoload :Result, 'easy_installer/install_helpers/result'
|
22
|
+
end
|
23
|
+
|
24
|
+
class Sandbox
|
25
|
+
autoload :Message, 'easy_installer/sandbox_modules/message'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'coffee-script'
|
2
|
+
require 'v8'
|
3
|
+
module EasyInstaller
|
4
|
+
class CoffeeScriptSandbox
|
5
|
+
attr_accessor :modules
|
6
|
+
attr_accessor :helpers
|
7
|
+
attr_accessor :inputs
|
8
|
+
attr_accessor :errors
|
9
|
+
|
10
|
+
def initialize(code)
|
11
|
+
@code = code
|
12
|
+
@helpers = []
|
13
|
+
@inputs = {}
|
14
|
+
@modules = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_module(mod)
|
18
|
+
@modules << mod
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_helper(helper)
|
22
|
+
@helpers << helper
|
23
|
+
end
|
24
|
+
|
25
|
+
def eval
|
26
|
+
run = Runner.new
|
27
|
+
run.inputs = @inputs
|
28
|
+
#include modules
|
29
|
+
@modules.each do |mod|
|
30
|
+
extend mod::EvalInstanceMethods
|
31
|
+
@code = "
|
32
|
+
#{mod.beforecode}
|
33
|
+
#{@code}
|
34
|
+
#{mod.aftercode}
|
35
|
+
"
|
36
|
+
run.extend(mod::IncludedCode)
|
37
|
+
end
|
38
|
+
#include return code
|
39
|
+
@code = "
|
40
|
+
@result = []
|
41
|
+
#{@code}
|
42
|
+
@result
|
43
|
+
"
|
44
|
+
#include helpers
|
45
|
+
@helpers.each do |single_module|
|
46
|
+
run.extend single_module
|
47
|
+
end
|
48
|
+
#eval code
|
49
|
+
@code = CoffeeScript.compile @code
|
50
|
+
V8::Context.new(:with => run) do |cxt|
|
51
|
+
@returned = cxt.eval(@code)
|
52
|
+
end
|
53
|
+
@success = true
|
54
|
+
return true
|
55
|
+
end
|
56
|
+
|
57
|
+
def returned
|
58
|
+
unless @returned
|
59
|
+
raise "First eval Code"
|
60
|
+
end
|
61
|
+
Result.new(@returned, @modules)
|
62
|
+
end
|
63
|
+
|
64
|
+
def success?
|
65
|
+
@success
|
66
|
+
end
|
67
|
+
def returned_raw
|
68
|
+
unless @returned
|
69
|
+
raise "First eval Code"
|
70
|
+
end
|
71
|
+
@returned
|
72
|
+
end
|
73
|
+
|
74
|
+
class Result
|
75
|
+
def initialize(raw_result, modules)
|
76
|
+
@data = {}
|
77
|
+
@raw_result = raw_result
|
78
|
+
modules.each do |single_module|
|
79
|
+
raw_result.each do |result|
|
80
|
+
data = single_module.result_analize(result)
|
81
|
+
unless data == false
|
82
|
+
@data[single_module.name] = [] unless @data[single_module.name]
|
83
|
+
@data[single_module.name] << data
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def method_missing(method_name, *args)
|
90
|
+
@data[method_name.to_s]
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|