html-pipeline-gitlab 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +2 -1
- data/html-pipeline-gitlab.gemspec +1 -0
- data/lib/html/pipeline/gitlab.rb +1 -0
- data/lib/html/pipeline/gitlab/gitlab_email_image_filter.rb +65 -0
- data/lib/html/pipeline/gitlab/version.rb +1 -1
- data/test/html/pipeline/gitlab_email_image_filter_test.rb +53 -0
- metadata +20 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c7665f2aba698a1f7b7c3c8194f572fb1bdc4bfc
|
4
|
+
data.tar.gz: 90460359d1b82321483bd0fca1ab9088507f6532
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdce34f98a7100bbea473e5ad46237ebb52d4eaafa71dec4d1c480f1711a94fde3ba218a7002fa418e8ac2c64f352fe3b5b0305f402b4644100a287fec995915
|
7
|
+
data.tar.gz: 07b1cef40313ae90d8fba3989dc0cab60f44ac8fd419b8ab9ee83fbe020689b2bdaee465dcb87c1e7504eb27d89357a915c3e9b0fd6b63856bd0d20cc4f94072
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -38,7 +38,8 @@ bundle exec rake test
|
|
38
38
|
## Filters
|
39
39
|
|
40
40
|
* `GitlabEmojiFilter` - replaces emoji references with images from
|
41
|
-
[PhantomOpenEmoji](https://github.com/Genshin/PhantomOpenEmoji)
|
41
|
+
[PhantomOpenEmoji](https://github.com/Genshin/PhantomOpenEmoji)
|
42
|
+
* `GitlabEmailImageFilter` - replaces linked images that were uploaded as attachments with inline images
|
42
43
|
|
43
44
|
## Contributing
|
44
45
|
|
data/lib/html/pipeline/gitlab.rb
CHANGED
@@ -9,6 +9,7 @@ module HTML
|
|
9
9
|
|
10
10
|
# Custom filter implementations
|
11
11
|
autoload :GitlabEmojiFilter, 'html/pipeline/gitlab/gitlab_emoji_filter'
|
12
|
+
autoload :GitlabEmailImageFilter, 'html/pipeline/gitlab/gitlab_email_image_filter'
|
12
13
|
|
13
14
|
def initialize(filters)
|
14
15
|
@filters = filters.flatten.freeze
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'RMagick'
|
3
|
+
require 'html/pipeline/filter'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module HTML
|
7
|
+
class Pipeline
|
8
|
+
class Gitlab
|
9
|
+
# HTML filter that replaces linked images with inline images in emails.
|
10
|
+
class GitlabEmailImageFilter < Filter
|
11
|
+
def call
|
12
|
+
doc.search('img').each do |img|
|
13
|
+
next if img['src'].nil?
|
14
|
+
|
15
|
+
src = img['src'].strip
|
16
|
+
next unless src.start_with?(context[:base_url])
|
17
|
+
|
18
|
+
file_path =
|
19
|
+
get_file_path(src, context[:upload_path], context[:base_url])
|
20
|
+
next unless File.file?(file_path)
|
21
|
+
encoded_image = base64_encode_image(file_path)
|
22
|
+
next unless encoded_image.present?
|
23
|
+
|
24
|
+
img['src'] = encoded_image
|
25
|
+
end
|
26
|
+
|
27
|
+
doc
|
28
|
+
end
|
29
|
+
|
30
|
+
def base64_encode_image(file_path)
|
31
|
+
img = Magick::Image.read(file_path).first
|
32
|
+
# Strip profiles and comments from file
|
33
|
+
img.strip!
|
34
|
+
if img.filesize > 100_000
|
35
|
+
img.format = 'JPG'
|
36
|
+
# Resize it to be maximum 600px * 600px.
|
37
|
+
img.resize_to_fit!(600, 600)
|
38
|
+
encoded_image = Base64.encode64(img.to_blob { self.quality = 60 })
|
39
|
+
else
|
40
|
+
encoded_image = Base64.encode64(img.to_blob)
|
41
|
+
end
|
42
|
+
|
43
|
+
"data:image/jpg;base64,#{encoded_image}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_file_path(url, upload_path, base_url)
|
47
|
+
# replace base url with location in file system
|
48
|
+
url.gsub!(base_url, '')
|
49
|
+
file_path = prevent_path_traversal(url)
|
50
|
+
File.join(upload_path, file_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
def prevent_path_traversal(file_path)
|
54
|
+
# decode the url. We don't want encoded chars in our file path
|
55
|
+
file_path = URI.decode(file_path).to_s
|
56
|
+
# remove all occurences of ".." from the url
|
57
|
+
# to prevent path traversing
|
58
|
+
file_path = file_path.gsub('..', '')
|
59
|
+
# replace unnecessary double slashes
|
60
|
+
file_path.gsub('//', '/')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'html/pipeline/gitlab'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
# Test for the GitlabEmailImageFilter class
|
6
|
+
class HTML::Pipeline::GitlabEmailImageFilterTest < Minitest::Test
|
7
|
+
GitlabEmailImageFilter = HTML::Pipeline::Gitlab::GitlabEmailImageFilter
|
8
|
+
|
9
|
+
def test_prevent_path_traversal
|
10
|
+
context = {
|
11
|
+
base_url: 'https://foo.com/namespace/project/uploads',
|
12
|
+
upload_path: '/opt/gitlab/public/uploads/namespace/project'
|
13
|
+
}
|
14
|
+
|
15
|
+
filter =
|
16
|
+
GitlabEmailImageFilter.new(
|
17
|
+
'<img src="https://foo.com/namespace/project/uploads/1234/test.jpg" />',
|
18
|
+
context)
|
19
|
+
|
20
|
+
{
|
21
|
+
'/..' => '/', '/a/../b' => '/a/b', '/a/../b/' => '/a/b/',
|
22
|
+
'/%2e.' => '/', '/a/%2E%2e/b' => '/a/b', '/a%2f%2E%2e%2Fb/' => '/a/b/',
|
23
|
+
'//' => '/', '/%2fetc%2Fpasswd' => '/etc/passwd'
|
24
|
+
}.each do |a, b|
|
25
|
+
filtered_a = filter.prevent_path_traversal(a)
|
26
|
+
assert_match filtered_a, b
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_file_path
|
31
|
+
context = {
|
32
|
+
base_url: 'https://foo.com/namespace/project/uploads',
|
33
|
+
upload_path: '/opt/gitlab/public/uploads/namespace/project'
|
34
|
+
}
|
35
|
+
|
36
|
+
img_src =
|
37
|
+
'https://foo.com/namespace/project/uploads/1234/test.jpg'
|
38
|
+
|
39
|
+
filter =
|
40
|
+
GitlabEmailImageFilter.new(
|
41
|
+
'<img src="https://foo.com/namespace/project/uploads/1234/test.jpg" />',
|
42
|
+
context)
|
43
|
+
|
44
|
+
file_path =
|
45
|
+
filter.get_file_path(img_src,
|
46
|
+
context[:upload_path],
|
47
|
+
context[:base_url])
|
48
|
+
expected_file_path =
|
49
|
+
'/opt/gitlab/public/uploads/namespace/project/1234/test.jpg'
|
50
|
+
|
51
|
+
assert_match file_path, expected_file_path
|
52
|
+
end
|
53
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: html-pipeline-gitlab
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Schilling
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-03-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -109,6 +109,20 @@ dependencies:
|
|
109
109
|
- - "~>"
|
110
110
|
- !ruby/object:Gem::Version
|
111
111
|
version: '4'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: rmagick
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
type: :runtime
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
112
126
|
description: Extension filters for html-pipeline used by GitLab
|
113
127
|
email:
|
114
128
|
- schilling.ro@gmail.com
|
@@ -124,8 +138,10 @@ files:
|
|
124
138
|
- Rakefile
|
125
139
|
- html-pipeline-gitlab.gemspec
|
126
140
|
- lib/html/pipeline/gitlab.rb
|
141
|
+
- lib/html/pipeline/gitlab/gitlab_email_image_filter.rb
|
127
142
|
- lib/html/pipeline/gitlab/gitlab_emoji_filter.rb
|
128
143
|
- lib/html/pipeline/gitlab/version.rb
|
144
|
+
- test/html/pipeline/gitlab_email_image_filter_test.rb
|
129
145
|
- test/html/pipeline/gitlab_gemoji_filter_test.rb
|
130
146
|
- test/test_helper.rb
|
131
147
|
homepage: https://gitlab.com/gitlab-org/html-pipeline-gitlab
|
@@ -153,5 +169,7 @@ signing_key:
|
|
153
169
|
specification_version: 4
|
154
170
|
summary: Extension filters for html-pipeline used by GitLab
|
155
171
|
test_files:
|
172
|
+
- test/html/pipeline/gitlab_email_image_filter_test.rb
|
156
173
|
- test/html/pipeline/gitlab_gemoji_filter_test.rb
|
157
174
|
- test/test_helper.rb
|
175
|
+
has_rdoc:
|