ruby-net-text 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 13d187b33206cde3d60845489921d5193f573198009e06e6870b3d81fc370692
4
- data.tar.gz: 3979773503767a22dcb0923cacb5c841456aeecfef113a3c6fbb6382c9b898b7
3
+ metadata.gz: bf06a0fb93555a7705a8ab92e7380dcc98134721b24a1f578251667b0a7a973a
4
+ data.tar.gz: c96bc45c9d21310f93a2b9f77ed6194d1539741b58e9ba1d713f3e68779e7505
5
5
  SHA512:
6
- metadata.gz: 942e564ad60a43ce4ef6306c7e73b0962c065c606e34a9fbab269bccd6900b87a5a1d4bd13a28384f02128e9d167648e152b029f547ac20998e633ff9fafd329
7
- data.tar.gz: 5349d6752b31dd637c44158528dcf6489cb71a3d6aaba80df9afde7572c579419e8dd44a6729ca92e01089d20c33bd1b6daa9230db97fb76c26a801363ab3ee1
6
+ metadata.gz: 586165ce218f116cb6a2214a4deff76fc250a241b8ab2a92e91a6caa42d8202a38b1b2262b583a7444a1d260023716b4527191de800f90ea83ff226d6821284a
7
+ data.tar.gz: 982663ef31a62ddca0941eef34b8e227670d97b0c6674116a5b5927f5547f8e1c6e2d6df23b972cece6a9ea07263e543c5f806e0c0bc0488b7bb52f4df80b84e
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gemini
4
+ # Contains specific method to parse text/gemini documents.
5
+ module GmiParser
6
+ private
7
+
8
+ def parse_meta
9
+ header = { status: @status, meta: @meta, mimetype: nil }
10
+ return header unless body_permitted?
11
+ mime = { lang: nil, charset: 'utf-8', format: nil }
12
+ raw_meta = meta.split(';').map(&:strip)
13
+ header[:mimetype] = raw_meta.shift
14
+ return header unless raw_meta.any?
15
+ raw_meta.map { |m| m.split('=') }.each do |opt|
16
+ key = opt[0].downcase.to_sym
17
+ next unless mime.has_key? key
18
+ mime[key] = opt[1].downcase
19
+ end
20
+ header.merge(mime)
21
+ end
22
+
23
+ def parse_preformatted_block(line, buf)
24
+ cur_block = { meta: line[3..].chomp, content: '' }
25
+ while (line = buf.gets)
26
+ if line.start_with?('```')
27
+ @preformatted_blocks << cur_block
28
+ break
29
+ end
30
+ cur_block[:content] += line
31
+ end
32
+ end
33
+
34
+ def parse_link(line)
35
+ m = line.strip.match(/\A=>\s*([^\s]+)(?:\s*(.+))?\z/)
36
+ return if m.nil?
37
+ begin
38
+ uri = URI(m[1])
39
+ rescue URI::InvalidURIError
40
+ return
41
+ end
42
+ uri = @uri.merge(uri) if @uri && uri.is_a?(URI::Generic)
43
+ @links << { uri: uri, label: m[2]&.chomp }
44
+ end
45
+
46
+ def parse_body
47
+ buf = StringIO.new(@body)
48
+ while (line = buf.gets)
49
+ if line.start_with?('```')
50
+ parse_preformatted_block(line, buf)
51
+ elsif line.start_with?('=>')
52
+ parse_link(line)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gemini
4
+ # Contains specific method to correctly display Gemini texts
5
+ module ReflowText
6
+ private
7
+
8
+ def reflow_line_cut_index(line)
9
+ possible_cut = [
10
+ line.rindex(' ') || 0,
11
+ line.rindex('­') || 0,
12
+ line.rindex('-') || 0
13
+ ].sort
14
+ possible_cut.reverse!
15
+ possible_cut[0]
16
+ end
17
+
18
+ def reflow_line_prefix(line)
19
+ m = line.match(/\A([*#>]+ )/)
20
+ return '' unless m
21
+ # Each quote line should begin with the quote mark
22
+ return m[1] if m[1].start_with?('>')
23
+ ' ' * m[1].length
24
+ end
25
+
26
+ def reflow_text_line(line, mono_block_open, length)
27
+ line.strip!
28
+ if mono_block_open || line.start_with?('=>') || line.length < length
29
+ return [line]
30
+ end
31
+ output = []
32
+ prefix = reflow_line_prefix(line)
33
+ while line.length > length
34
+ cut_line = line[0...length]
35
+ cut_index = reflow_line_cut_index(cut_line)
36
+ break if cut_index.zero? # Better do nothing for now
37
+ output << line[0...cut_index]
38
+ line = prefix + line[cut_index + 1..]
39
+ end
40
+ output << line
41
+ end
42
+
43
+ def reformat_body(length)
44
+ unless length.is_a? Integer
45
+ raise ArgumentError, "Length must be Integer, #{length} given"
46
+ end
47
+ return @body if length.zero?
48
+ new_body = []
49
+ mono_block_open = false
50
+ buf = StringIO.new(@body)
51
+ while (line = buf.gets)
52
+ if line.start_with?('```')
53
+ mono_block_open = !mono_block_open
54
+ # Don't include code block toggle lines
55
+ next
56
+ end
57
+ new_body += reflow_text_line(line, mono_block_open, length)
58
+ end
59
+ new_body.join("\n")
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gemini
4
+ # Contains specific method to handle SSL connection
5
+ module SSL
6
+ private
7
+
8
+ def ssl_check_existing(new_cert, cert_file)
9
+ raw = File.read cert_file
10
+ saved_one = OpenSSL::X509::Certificate.new raw
11
+ return true if saved_one == new_cert
12
+ # TODO: offer some kind of recuperation
13
+ warn "#{cert_file} does not match the current host cert!"
14
+ false
15
+ end
16
+
17
+ def ssl_verify_cb(cert)
18
+ return false unless OpenSSL::SSL.verify_certificate_identity(cert, @host)
19
+ cert_file = File.expand_path("#{@certs_path}/#{@host}.pem")
20
+ return ssl_check_existing(cert, cert_file) if File.exist?(cert_file)
21
+ FileUtils.mkdir_p(File.expand_path(@certs_path))
22
+ File.open(cert_file, 'wb') { |f| f.print cert.to_pem }
23
+ true
24
+ end
25
+
26
+ def ssl_context
27
+ ssl_context = OpenSSL::SSL::SSLContext.new
28
+ ssl_context.set_params(verify_mode: OpenSSL::SSL::VERIFY_PEER)
29
+ ssl_context.min_version = OpenSSL::SSL::TLS1_2_VERSION
30
+ ssl_context.verify_hostname = true
31
+ ssl_context.ca_file = '/etc/ssl/certs/ca-certificates.crt'
32
+ ssl_context.verify_callback = lambda do |preverify_ok, store_context|
33
+ return true if preverify_ok
34
+ ssl_verify_cb store_context.current_cert
35
+ end
36
+ ssl_context
37
+ end
38
+
39
+ def init_sockets
40
+ socket = TCPSocket.new(@host, @port)
41
+ @ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
42
+ # Close underlying TCP socket with SSL socket
43
+ @ssl_socket.sync_close = true
44
+ @ssl_socket.hostname = @host # SNI
45
+ @ssl_socket.connect
46
+ end
47
+
48
+ # Closes the SSL and TCP connections.
49
+ def finish
50
+ @ssl_socket.close
51
+ end
52
+ end
53
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-net-text
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Étienne Deparis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-30 00:00:00.000000000 Z
11
+ date: 2021-04-28 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: etienne@depar.is
@@ -18,8 +18,11 @@ extra_rdoc_files: []
18
18
  files:
19
19
  - LICENSE
20
20
  - lib/net/gemini.rb
21
+ - lib/net/gemini/gmi_parser.rb
22
+ - lib/net/gemini/reflow_text.rb
21
23
  - lib/net/gemini/request.rb
22
24
  - lib/net/gemini/response.rb
25
+ - lib/net/gemini/ssl.rb
23
26
  - lib/uri/finger.rb
24
27
  - lib/uri/gemini.rb
25
28
  - lib/uri/gopher.rb
@@ -42,7 +45,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
42
45
  - !ruby/object:Gem::Version
43
46
  version: '0'
44
47
  requirements: []
45
- rubygems_version: 3.1.4
48
+ rubygems_version: 3.2.15
46
49
  signing_key:
47
50
  specification_version: 4
48
51
  summary: Gemini, Gopher, and Finger support for Net::* and URI::*