vagrant-trellis-cert 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github_changelog_generator +1 -1
- data/.gitignore +1 -1
- data/CHANGELOG.md +18 -1
- data/README.md +18 -33
- data/lib/vagrant-trellis-cert.rb +3 -3
- data/lib/vagrant_plugins/trellis_cert/certificate.rb +40 -0
- data/lib/vagrant_plugins/trellis_cert/command/distrust.rb +16 -5
- data/lib/vagrant_plugins/trellis_cert/command/trust.rb +19 -6
- data/lib/vagrant_plugins/trellis_cert/identity.rb +1 -1
- data/vagrant-trellis-cert.gemspec +3 -3
- metadata +9 -10
- data/lib/vagrant_plugins/trellis_cert/system.rb +0 -17
- data/lib/vagrant_plugins/trellis_cert/system/darwin.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8426ab246fa36b2b07c36c0580576787c028f4428eb27f767f726b311e348399
|
4
|
+
data.tar.gz: dc29f4b02bc9e74d5ca740dd86621b78bbe088fb501eb7f639a36a589df9be45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6a69f37d240c0aa67ea3c92fc8056823bbe0bcd19a941c98342bab2c3e3561aa00e02ace43948a4864f5e815e560aec2f93e821433c397cae651294a2403c8b
|
7
|
+
data.tar.gz: e035a9c43f9eaae751ce34a60cb4eff15d930011bd79871322744bd2d8067c6b68dd4b6ac6e34bc7e074b62eece73d909cf76ee4cf48c749f1107693a2d25e8b
|
data/.github_changelog_generator
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
unreleased=true
|
2
|
-
future-release=v0.
|
2
|
+
future-release=v0.5.0
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,22 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [v0.
|
3
|
+
## [v0.5.0](https://github.com/TypistTech/vagrant-trellis-cert/tree/v0.5.0) (2018-03-29)
|
4
|
+
[Full Changelog](https://github.com/TypistTech/vagrant-trellis-cert/compare/v0.4.0...v0.5.0)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- Download cert via ruby's openssl gem [\#41](https://github.com/TypistTech/vagrant-trellis-cert/issues/41)
|
9
|
+
|
10
|
+
**Closed issues:**
|
11
|
+
|
12
|
+
- No certificate is added to keychain [\#44](https://github.com/TypistTech/vagrant-trellis-cert/issues/44)
|
13
|
+
|
14
|
+
**Merged pull requests:**
|
15
|
+
|
16
|
+
- Download certificate via Ruby's default openssl wrapper [\#45](https://github.com/TypistTech/vagrant-trellis-cert/pull/45) ([TangRufus](https://github.com/TangRufus))
|
17
|
+
- Readme: Warn about `vagrant-triggers` stale development [\#43](https://github.com/TypistTech/vagrant-trellis-cert/pull/43) ([TangRufus](https://github.com/TangRufus))
|
18
|
+
|
19
|
+
## [v0.4.0](https://github.com/TypistTech/vagrant-trellis-cert/tree/v0.4.0) (2017-10-04)
|
4
20
|
[Full Changelog](https://github.com/TypistTech/vagrant-trellis-cert/compare/v0.3.0...v0.4.0)
|
5
21
|
|
6
22
|
**Implemented enhancements:**
|
@@ -9,6 +25,7 @@
|
|
9
25
|
|
10
26
|
**Merged pull requests:**
|
11
27
|
|
28
|
+
- Version bump 0.4.0 [\#39](https://github.com/TypistTech/vagrant-trellis-cert/pull/39) ([TangRufus](https://github.com/TangRufus))
|
12
29
|
- Add `distrust` subcommand [\#37](https://github.com/TypistTech/vagrant-trellis-cert/pull/37) ([TangRufus](https://github.com/TangRufus))
|
13
30
|
|
14
31
|
## [v0.3.0](https://github.com/TypistTech/vagrant-trellis-cert/tree/v0.3.0) (2017-09-18)
|
data/README.md
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
[![Gem](https://img.shields.io/gem/v/vagrant-trellis-cert.svg)](https://rubygems.org/gems/vagrant-trellis-cert)
|
4
4
|
[![Gem](https://img.shields.io/gem/dt/vagrant-trellis-cert.svg)](https://rubygems.org/gems/vagrant-trellis-cert)
|
5
|
-
[![Dependency Status](https://gemnasium.com/badges/github.com/TypistTech/vagrant-trellis-cert.svg)](https://gemnasium.com/github.com/TypistTech/vagrant-trellis-cert)
|
6
5
|
[![license](https://img.shields.io/github/license/TypistTech/vagrant-trellis-cert.svg)](https://github.com/TypistTech/vagrant-trellis-cert/blob/master/LICENSE)
|
7
6
|
[![Donate via PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://www.typist.tech/donate/vagrant-trellis-cert/)
|
8
7
|
[![Hire Typist Tech](https://img.shields.io/badge/Hire-Typist%20Tech-ff69b4.svg)](https://www.typist.tech/contact/)
|
@@ -13,12 +12,12 @@ Trust Trellis self-signed certificates with a single command
|
|
13
12
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
14
13
|
|
15
14
|
|
15
|
+
- [Minimum Requirements](#minimum-requirements)
|
16
16
|
- [Installation](#installation)
|
17
17
|
- [Usage](#usage)
|
18
|
-
- [
|
19
|
-
- [Limitations](#limitations)
|
18
|
+
- [It looks awesome. Where can I find some more goodies like this?](#it-looks-awesome-where-can-i-find-some-more-goodies-like-this)
|
20
19
|
- [Support!](#support)
|
21
|
-
- [Donate
|
20
|
+
- [Donate](#donate)
|
22
21
|
- [Why don't you hire me?](#why-dont-you-hire-me)
|
23
22
|
- [Want to help in other way? Want to be a sponsor?](#want-to-help-in-other-way-want-to-be-a-sponsor)
|
24
23
|
- [Feedback](#feedback)
|
@@ -29,6 +28,11 @@ Trust Trellis self-signed certificates with a single command
|
|
29
28
|
|
30
29
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
31
30
|
|
31
|
+
## Minimum Requirements
|
32
|
+
|
33
|
+
- macOS 10.13.3
|
34
|
+
- Vagrant 2.0.3
|
35
|
+
|
32
36
|
## Installation
|
33
37
|
|
34
38
|
```bash
|
@@ -57,43 +61,24 @@ $ vagrant trellis-cert trust fb90ab5
|
|
57
61
|
$ vagrant trellis-cert distrust fb90ab5
|
58
62
|
```
|
59
63
|
|
60
|
-
##
|
61
|
-
|
62
|
-
If the [vagrant-triggers](https://github.com/emyl/vagrant-triggers) plugin is installed, we can run the command on Vagrant state changes like `vagrant provision`. Add these lines into Trellis' `Vagrantfile`:
|
63
|
-
|
64
|
-
```ruby
|
65
|
-
# Vagrantfile
|
66
|
-
|
67
|
-
# Some lines of code...
|
68
|
-
|
69
|
-
Vagrant.configure('2') do |config|
|
70
|
-
# Some more lines of code later...
|
71
|
-
|
72
|
-
config.trigger.after :provision, :stdout => true do
|
73
|
-
run "vagrant trellis-cert trust"
|
74
|
-
end
|
75
|
-
|
76
|
-
config.trigger.after :destroy, :stdout => true do
|
77
|
-
run "vagrant trellis-cert distrust"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
```
|
81
|
-
|
82
|
-
## Limitations
|
83
|
-
|
84
|
-
Pull requests are welcome!
|
64
|
+
## It looks awesome. Where can I find some more goodies like this?
|
85
65
|
|
86
|
-
|
66
|
+
* Articles on Typist Tech's [blog](https://typist.tech)
|
67
|
+
* [Tang Rufus' WordPress plugins](https://profiles.wordpress.org/tangrufus#content-plugins) on wp.org
|
68
|
+
* More projects on [Typist Tech's GitHub profile](https://github.com/TypistTech)
|
69
|
+
* Stay tuned on [Typist Tech's newsletter](https://typist.tech/go/newsletter)
|
70
|
+
* Follow [Tang Rufus' Twitter account](https://twitter.com/TangRufus)
|
71
|
+
* Hire [Tang Rufus](https://typist.tech/contact) to build your next awesome site
|
87
72
|
|
88
73
|
## Support!
|
89
74
|
|
90
|
-
### Donate
|
75
|
+
### Donate
|
91
76
|
|
92
|
-
Love Vagrant Trellis Cert? Help me maintain it, a [donation here](https://
|
77
|
+
Love Vagrant Trellis Cert? Help me maintain it, a [donation here](https://typist.tech/donation/) can help with it.
|
93
78
|
|
94
79
|
### Why don't you hire me?
|
95
80
|
|
96
|
-
Ready to take freelance WordPress jobs. Contact me via the contact form [here](https://
|
81
|
+
Ready to take freelance WordPress jobs. Contact me via the contact form [here](https://typist.tech/contact/) or, via email [info@typist.tech](mailto:info@typist.tech)
|
97
82
|
|
98
83
|
### Want to help in other way? Want to be a sponsor?
|
99
84
|
|
data/lib/vagrant-trellis-cert.rb
CHANGED
@@ -8,9 +8,9 @@ end
|
|
8
8
|
|
9
9
|
# This is a sanity check to make sure no one is attempting to install
|
10
10
|
# this into an early Vagrant version.
|
11
|
-
# Requiring
|
12
|
-
if Vagrant::VERSION < '
|
13
|
-
raise 'The Vagrant Trellis Cert plugin is only compatible with Vagrant
|
11
|
+
# Requiring 2.0.3 or later because of Ruby 2.4.2
|
12
|
+
if Vagrant::VERSION < '2.0.3'
|
13
|
+
raise 'The Vagrant Trellis Cert plugin is only compatible with Vagrant 2.0.3 or later'
|
14
14
|
end
|
15
15
|
|
16
16
|
require 'vagrant_plugins/trellis_cert/identity'
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require 'openssl'
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module TrellisCert
|
8
|
+
class Certificate
|
9
|
+
def initialize(host:, tmp_dir:)
|
10
|
+
@host = host
|
11
|
+
@tmp_dir = tmp_dir
|
12
|
+
end
|
13
|
+
|
14
|
+
def download
|
15
|
+
fetch
|
16
|
+
|
17
|
+
File.open(path, 'w') do |file|
|
18
|
+
file.write(@cert.to_der)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def path
|
23
|
+
"#{@tmp_dir}/#{@host}.der"
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def fetch
|
29
|
+
tcp_client = TCPSocket.new(@host, 443)
|
30
|
+
ssl_client = OpenSSL::SSL::SSLSocket.new(tcp_client)
|
31
|
+
ssl_client.hostname = @host
|
32
|
+
ssl_client.connect
|
33
|
+
@cert = OpenSSL::X509::Certificate.new(ssl_client.peer_cert)
|
34
|
+
ensure
|
35
|
+
ssl_client.sysclose
|
36
|
+
tcp_client.close
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,21 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'vagrant_plugins/trellis_cert/ssl_config'
|
4
|
-
require 'vagrant_plugins/trellis_cert/
|
4
|
+
require 'vagrant_plugins/trellis_cert/result'
|
5
5
|
|
6
6
|
module VagrantPlugins
|
7
7
|
module TrellisCert
|
8
8
|
module Command
|
9
9
|
class Distrust < Vagrant.plugin('2', :command)
|
10
|
+
KEYCHAIN = '~/Library/Keychains/login.keychain'
|
11
|
+
|
10
12
|
def execute
|
11
13
|
_options, argv = parse_options!
|
12
14
|
|
13
15
|
@env.ui.info('Removing certificates...')
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
result =
|
18
|
-
.distrust(hosts)
|
17
|
+
ssl_config = SSLConfig.new(root_path: machine_root_path(argv))
|
18
|
+
|
19
|
+
result = distrust(ssl_config.canonicals)
|
19
20
|
|
20
21
|
result.print(ui: @env.ui)
|
21
22
|
|
@@ -43,6 +44,16 @@ module VagrantPlugins
|
|
43
44
|
return machine.env.root_path
|
44
45
|
end
|
45
46
|
end
|
47
|
+
|
48
|
+
def distrust(hosts)
|
49
|
+
Result.new.tap do |result|
|
50
|
+
hosts.map do |host|
|
51
|
+
is_success = system("security delete-certificate -c #{host} #{KEYCHAIN} >/dev/null 2>/dev/null")
|
52
|
+
|
53
|
+
result.add(host: host, is_success: is_success)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
46
57
|
end
|
47
58
|
end
|
48
59
|
end
|
@@ -1,20 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'vagrant_plugins/trellis_cert/certificate'
|
3
4
|
require 'vagrant_plugins/trellis_cert/ssl_config'
|
4
|
-
require 'vagrant_plugins/trellis_cert/
|
5
|
+
require 'vagrant_plugins/trellis_cert/result'
|
5
6
|
|
6
7
|
module VagrantPlugins
|
7
8
|
module TrellisCert
|
8
9
|
module Command
|
9
10
|
class Trust < Vagrant.plugin('2', :command)
|
11
|
+
KEYCHAIN = '~/Library/Keychains/login.keychain'
|
12
|
+
|
10
13
|
def execute
|
11
14
|
_options, argv = parse_options!
|
12
15
|
|
13
16
|
@env.ui.info('Importing certificates...')
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
result = trust(
|
18
|
+
ssl_config = SSLConfig.new(root_path: machine_root_path(argv))
|
19
|
+
|
20
|
+
result = trust(ssl_config.canonicals)
|
18
21
|
|
19
22
|
result.print(ui: @env.ui)
|
20
23
|
|
@@ -47,10 +50,20 @@ module VagrantPlugins
|
|
47
50
|
end
|
48
51
|
|
49
52
|
def trust(hosts)
|
53
|
+
result = Result.new
|
54
|
+
|
50
55
|
Dir.mktmpdir do |tmp_dir|
|
51
|
-
|
52
|
-
|
56
|
+
hosts.map do |host|
|
57
|
+
certificate = Certificate.new(host: host, tmp_dir: tmp_dir)
|
58
|
+
certificate.download
|
59
|
+
|
60
|
+
is_success = system("security add-trusted-cert -k #{KEYCHAIN} #{certificate.path} >/dev/null 2>/dev/null")
|
61
|
+
|
62
|
+
result.add(host: host, is_success: is_success)
|
63
|
+
end
|
53
64
|
end
|
65
|
+
|
66
|
+
result
|
54
67
|
end
|
55
68
|
end
|
56
69
|
end
|
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.homepage = 'https://www.typist.tech/projects/vagrant-trellis-cert'
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
17
|
-
spec.required_ruby_version = '~> 2.
|
17
|
+
spec.required_ruby_version = '~> 2.4.2'
|
18
18
|
|
19
19
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
20
20
|
f.match(%r{^(test|spec|features)/})
|
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
24
|
spec.require_paths = ['lib']
|
25
25
|
|
26
|
-
spec.add_development_dependency 'bundler', '~> 1.
|
26
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
27
27
|
spec.add_development_dependency 'rake', '~> 12.0'
|
28
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
28
|
+
spec.add_development_dependency 'rubocop', '~> 0.54.0'
|
29
29
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-trellis-cert
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tang Rufus
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2018-03-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -17,14 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '1.
|
20
|
+
version: '1.16'
|
21
21
|
type: :development
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '1.
|
27
|
+
version: '1.16'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: rake
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -45,14 +45,14 @@ dependencies:
|
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: 0.
|
48
|
+
version: 0.54.0
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: 0.
|
55
|
+
version: 0.54.0
|
56
56
|
description:
|
57
57
|
email:
|
58
58
|
- tangrufus@gmail.com
|
@@ -72,6 +72,7 @@ files:
|
|
72
72
|
- README.md
|
73
73
|
- Rakefile
|
74
74
|
- lib/vagrant-trellis-cert.rb
|
75
|
+
- lib/vagrant_plugins/trellis_cert/certificate.rb
|
75
76
|
- lib/vagrant_plugins/trellis_cert/command/distrust.rb
|
76
77
|
- lib/vagrant_plugins/trellis_cert/command/root.rb
|
77
78
|
- lib/vagrant_plugins/trellis_cert/command/trust.rb
|
@@ -80,8 +81,6 @@ files:
|
|
80
81
|
- lib/vagrant_plugins/trellis_cert/plugin.rb
|
81
82
|
- lib/vagrant_plugins/trellis_cert/result.rb
|
82
83
|
- lib/vagrant_plugins/trellis_cert/ssl_config.rb
|
83
|
-
- lib/vagrant_plugins/trellis_cert/system.rb
|
84
|
-
- lib/vagrant_plugins/trellis_cert/system/darwin.rb
|
85
84
|
- vagrant-trellis-cert.gemspec
|
86
85
|
homepage: https://www.typist.tech/projects/vagrant-trellis-cert
|
87
86
|
licenses:
|
@@ -95,7 +94,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
95
94
|
requirements:
|
96
95
|
- - "~>"
|
97
96
|
- !ruby/object:Gem::Version
|
98
|
-
version:
|
97
|
+
version: 2.4.2
|
99
98
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
99
|
requirements:
|
101
100
|
- - ">="
|
@@ -103,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
102
|
version: '0'
|
104
103
|
requirements: []
|
105
104
|
rubyforge_project:
|
106
|
-
rubygems_version: 2.6
|
105
|
+
rubygems_version: 2.7.6
|
107
106
|
signing_key:
|
108
107
|
specification_version: 4
|
109
108
|
summary: Trust all Trellis self-signed certificates with single command
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'vagrant_plugins/trellis_cert/system/darwin'
|
4
|
-
|
5
|
-
module VagrantPlugins
|
6
|
-
module TrellisCert
|
7
|
-
module System
|
8
|
-
def self.build
|
9
|
-
unless Vagrant::Util::Platform.darwin?
|
10
|
-
raise 'vagrant-trellis-cert only works on macOS. Pull requests are welcome.'
|
11
|
-
end
|
12
|
-
|
13
|
-
Darwin.new
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'vagrant_plugins/trellis_cert/result'
|
4
|
-
|
5
|
-
module VagrantPlugins
|
6
|
-
module TrellisCert
|
7
|
-
module System
|
8
|
-
class Darwin
|
9
|
-
KEYCHAIN = '~/Library/Keychains/login.keychain'
|
10
|
-
|
11
|
-
def trust(hosts:, tmp_dir:)
|
12
|
-
Result.new.tap do |result|
|
13
|
-
hosts.map do |host|
|
14
|
-
cert_path = "#{tmp_dir}/#{host}.pem"
|
15
|
-
|
16
|
-
# Download cert
|
17
|
-
system("openssl s_client -showcerts -connect #{host}:443 </dev/null 2>/dev/null | \
|
18
|
-
openssl x509 -outform PEM > #{cert_path} 2>/dev/null")
|
19
|
-
|
20
|
-
is_success = system("security add-trusted-cert -k #{KEYCHAIN} #{cert_path} >/dev/null 2>/dev/null")
|
21
|
-
|
22
|
-
result.add(host: host, is_success: is_success)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def distrust(hosts)
|
28
|
-
Result.new.tap do |result|
|
29
|
-
hosts.map do |host|
|
30
|
-
is_success = system("security delete-certificate -c #{host} #{KEYCHAIN} >/dev/null 2>/dev/null")
|
31
|
-
|
32
|
-
result.add(host: host, is_success: is_success)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|