tzispa_helpers 0.2.2 → 0.3.0

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
  SHA1:
3
- metadata.gz: b8d9b4d815e666c509beeb5c3c5b5446302c3a5f
4
- data.tar.gz: ffd7c7ef51dcdbd5ab14078381ac1c93a5e3f23b
3
+ metadata.gz: 3e89639a5292d45bd73bb24c089a7d2e12a5af5d
4
+ data.tar.gz: a913cbe727b39b40d9e0fdf9cf893c820a42baaf
5
5
  SHA512:
6
- metadata.gz: b1702fe53fe07d1b9d5bff987f38ce1946e0a351e1d2e234441ff01462fc3dd8d9281b0eda134ab569d4950ed619dbb0ab0fa0010aa42c8df3e1bb9f18e53289
7
- data.tar.gz: fde228365de640a6f7ea82fb86b2e133872f51e4242525668f0b15a30ea4279d23b6e3578fd93056c643d585b68282707bd9b228800bcdefdab2d30a04d8ce57
6
+ metadata.gz: 45d66dc9fec88bdb30d7257a82bceb59bc3fb4746b22788e009d0d9f965a26ca041141465f82ffba50b67e0f921ac8b8d9061c9a499a06567d8f45bd5e9617b7
7
+ data.tar.gz: b0c6b9d2f8054c820ea478c3f870811c26b6719ba87b14160bb7be4a902be31a20506bfdfc3e3a2dd48c3c1bbd3472e1ca5403f69f1b7ea8477b0b75569f85cd
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  Tzispa Helpers
2
2
 
3
+ ## v0.3.0
4
+ - bug fixes
5
+ - code refactoring
6
+
3
7
  ## v0.2.2
4
8
  - unscape html request form values
5
9
  - added not_authorized alias method
@@ -1,19 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Tzispa
2
4
  module Helpers
3
5
 
4
- require 'tzispa/helpers/version'
5
- require 'tzispa/helpers/crawler'
6
+ require 'tzispa/helpers/date_time'
7
+ require 'tzispa/helpers/error_view'
6
8
  require 'tzispa/helpers/html'
7
- require 'tzispa/helpers/mail'
8
- require 'tzispa/helpers/mime'
9
9
  require 'tzispa/helpers/pattern'
10
+ require 'tzispa/helpers/provider'
10
11
  require 'tzispa/helpers/request'
12
+ require 'tzispa/helpers/requirer'
11
13
  require 'tzispa/helpers/response'
12
14
  require 'tzispa/helpers/security'
15
+ require 'tzispa/helpers/sign_requirer'
13
16
  require 'tzispa/helpers/text'
14
- require 'tzispa/helpers/provider'
15
- require 'tzispa/helpers/error_view'
16
- require 'tzispa/helpers/recaptcha'
17
+ require 'tzispa/helpers/version'
17
18
 
18
19
  end
19
20
  end
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Tzispa
2
4
  module Helpers
3
5
  module DateTime
4
6
 
5
7
  def date_months_diff(date1, date2)
6
- (date2.year - date1.year) * 12 + date2.month - date1.month - (date2.day >= date1.day ? 0 : 1)
8
+ (date2.year - date1.year) * 12 +
9
+ date2.month - date1.month - (date2.day >= date1.day ? 0 : 1)
7
10
  end
8
11
 
9
12
  def date_days_diff(date1, date2)
@@ -1,49 +1,64 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'tzispa/rig/template'
2
4
  require 'tzispa/version'
5
+ require 'tzispa/helpers/services/error_view'
3
6
 
4
7
  module Tzispa
5
8
  module Helpers
6
9
  module ErrorView
7
10
 
8
- def debug_info(exception=nil, status: 500)
9
- String.new.tap { |text|
10
- text << '<!DOCTYPE html>'
11
- text << '<html lang="es"><head>'
12
- text << '<meta charset="utf-8" />'
13
- text << '<style> html {background:#cccccc; font-family:Arial; font-size:15px; color:#555;} body {width:75%; max-width:1200px; margin:18px auto; background:#fff; border-radius:6px; padding:32px 24px;} ul{list-style:none; margin:0; padding:0;} li{font-style:italic; color:#666;} h1 {color:#2ECC71;} </style>'
14
- text << '</head><body>'
15
- text << "<h5>#{Tzispa::FRAMEWORK_NAME} #{Tzispa::VERSION}</h5>\n"
16
- if exception
17
- text << "<h1>#{exception.class.name}</h1><h3>#{exception.message}</h1>\n"
18
- text << '<ol>' + exception.backtrace.map { |trace| "<li>#{trace}</li>\n" }.join + '</ol>' if exception.respond_to?(:backtrace) && exception.backtrace
19
- else
20
- text << "<h1>Error #{status}</h1>\n"
21
- text << "Se ha producido un error inesperado al tramitar la petición"
22
- end
11
+ ERROR_HEADER = <<-ERRORHEADER
12
+ <head>
13
+ <meta charset="utf-8" />
14
+ <style> html {background:#cccccc; font-family:Arial; font-size:15px; color:#555;} body {width:75%; max-width:1200px; margin:18px auto; background:#fff; border-radius:6px; padding:32px 24px;} #main {margin:auto; } ul{list-style:none; margin:0; padding:0;} li{font-style:italic; color:#666;} h1 {color:#2ECC71;} </style>
15
+ </head>
16
+ ERRORHEADER
17
+
18
+ ERROR_PLATFORM_VERSIONS = <<-ERRORPVERSION
19
+ <h6>#{Tzispa::FRAMEWORK_NAME} #{Tzispa::VERSION}</h6>
20
+ ERRORPVERSION
21
+
22
+ def debug_info(ex = nil, status: 500)
23
+ String.new.tap do |text|
24
+ text << '<!DOCTYPE html><html lang="es">'
25
+ text << ERROR_HEADER << '<body>'
26
+ text << ERROR_PLATFORM_VERSIONS
27
+ text << if ex
28
+ srx = Tzispa::Helpers::Services::ErrorView.new ex
29
+ "<h1>#{srx.error_header}\n #{srx.error_backtrace_list}"
30
+ else
31
+ "<h1>Error #{status}</h1>\nSe ha producido un error indeterminado"
32
+ end
23
33
  text << '</body></html>'
24
- }
34
+ end
25
35
  end
26
36
 
27
37
  def error_page(domain, status: 500)
28
- begin
29
- error_file = "#{domain.path}/error/#{status}.htm"
30
- Tzispa::Rig::File.new(error_file).load!.content
31
- rescue
32
- String.new.tap { |text|
33
- text << '<!DOCTYPE html>'
34
- text << '<html lang="es"><head>'
35
- text << '<meta charset="utf-8" />'
36
- text << '<style> html {background:#cccccc; font-family:Arial; font-size:15px; color:#555;} body {width:75%; max-width:1200px; margin:18px auto; background:#fff; border-radius:6px; padding:32px 24px;} #main {margin:auto; } h1 {color:#2ECC71; font-size:4em; text-align:center;} </style>'
37
- text << '</head><body>'
38
- text << '<div id="main">'
39
- text << "<h5>#{Tzispa::FRAMEWORK_NAME} #{Tzispa::VERSION}</h5>\n"
40
- text << "<h1>Error #{status}</h1>\n"
41
- text << '</div>'
42
- text << '</body></html>'
43
- }
38
+ error_file = "#{domain.path}/error/#{status}.htm"
39
+ if (ef = Tzispa::Rig::File.new(error_file)) && ef.exist?
40
+ ef.load!.content
41
+ else
42
+ error_default
44
43
  end
45
44
  end
46
45
 
46
+ def error_log(ex)
47
+ Tzispa::Helpers::Services::ErrorView.new(ex).error_backtrace_log
48
+ end
49
+
50
+ def error_default
51
+ String.new.tap do |text|
52
+ text << '<!DOCTYPE html><html lang="es">'
53
+ text << ERROR_HEADER << '<body>'
54
+ text << '</head><body>'
55
+ text << '<div id="main">'
56
+ text << ERROR_PLATFORM_VERSIONS
57
+ text << "<h1>Error #{status}</h1>\n"
58
+ text << '</div>'
59
+ text << '</body></html>'
60
+ end
61
+ end
47
62
 
48
63
  end
49
64
  end
@@ -20,11 +20,11 @@ module Tzispa
20
20
  end
21
21
 
22
22
  def html_escape(str)
23
- CGI::escapeHTML str
23
+ CGI.escapeHTML str
24
24
  end
25
25
 
26
26
  def html_unescape(str)
27
- CGI::unescapeHTML str
27
+ CGI.unescapeHTML str
28
28
  end
29
29
 
30
30
  def html_urlencode(str)
@@ -36,10 +36,9 @@ module Tzispa
36
36
  end
37
37
 
38
38
  def html_strip(source)
39
- source.gsub(/<\/?[^>]*>/, '')
39
+ source.gsub(%r{/<\/?[^>]*>/}, '')
40
40
  end
41
41
 
42
-
43
42
  #
44
43
  # $Id: sanitize.rb 3 2005-04-05 12:51:14Z dwight $
45
44
  #
@@ -147,7 +146,6 @@ module Tzispa
147
146
  result
148
147
  end
149
148
 
150
-
151
149
  end
152
150
  end
153
151
  end
@@ -9,7 +9,7 @@ module Tzispa
9
9
  def mime_type(type, value = nil)
10
10
  return type if type.nil?
11
11
  return type.to_s if type.to_s.include?('/')
12
- type = ".#{type}" unless type.to_s[0] == ?.
12
+ type = ".#{type}" unless type.to_s[0] == '.'
13
13
  return Rack::Mime.mime_type(type, nil) unless value
14
14
  Rack::Mime::MIME_TYPES[type] = value
15
15
  end
@@ -8,49 +8,47 @@ module Tzispa
8
8
 
9
9
  include Tzispa::Helpers::Html
10
10
 
11
- def pattern_select_hours(selected=nil)
11
+ def pattern_select_hours(selected = nil)
12
12
  selected &&= selected.to_i
13
- Proc.new {
14
- (0..23).map { |hour|
13
+ proc do
14
+ (0..23).map do |hour|
15
15
  loop_item(
16
16
  value: hour,
17
17
  text: hour.to_s.rjust(2, '0'),
18
- selected: html_selected( selected == hour )
18
+ selected: html_selected(selected == hour)
19
19
  )
20
- }
21
- }
20
+ end
21
+ end
22
22
  end
23
23
 
24
- def pattern_select_minutes(selected=nil)
24
+ def pattern_select_minutes(selected = nil)
25
25
  selected &&= selected.to_i
26
- Proc.new {
27
- (0..59).map { |minute|
26
+ proc do
27
+ (0..59).map do |minute|
28
28
  loop_item(
29
29
  value: minute,
30
30
  text: minute.to_s.rjust(2, '0'),
31
- selected: html_selected( selected == minute )
31
+ selected: html_selected(selected == minute)
32
32
  )
33
- }
34
- }
33
+ end
34
+ end
35
35
  end
36
36
 
37
- def pattern_select_year(first, last, selected=nil, reverse=true)
37
+ def pattern_select_year(first, last, selected = nil)
38
38
  selected &&= selected.to_i
39
- Proc.new {
39
+ proc do
40
40
  ryear = (first..last)
41
- enum_year = first > last ? (ryear.first).downto(ryear.last) : (ryear.first).to(ryear.last)
42
- enum_year.map { |year|
41
+ enum_year = first > last ? ryear.first.downto(ryear.last) : ryear.first.to(ryear.last)
42
+ enum_year.map do |year|
43
43
  loop_item(
44
44
  value: year,
45
45
  text: year,
46
- selected: html_selected( selected == year )
46
+ selected: html_selected(selected == year)
47
47
  )
48
- }
49
- }
48
+ end
49
+ end
50
50
  end
51
51
 
52
-
53
-
54
52
  end
55
53
  end
56
54
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Tzispa
2
4
  module Helpers
3
5
  module Provider
@@ -11,13 +13,10 @@ module Tzispa
11
13
  end
12
14
 
13
15
  module ClassMethods
14
-
15
16
  def provides(*args)
16
- (@provides ||= Hash.new).tap { |prv|
17
- args&.each { |s|
18
- prv[s.to_sym] = s
19
- }
20
- }
17
+ (@provides ||= {}).tap do |prv|
18
+ args&.each { |s| prv[s.to_sym] = s }
19
+ end
21
20
  end
22
21
 
23
22
  def provides?(verb)
@@ -28,10 +27,8 @@ module Tzispa
28
27
  def provides_map(source, dest)
29
28
  provides[source] = dest
30
29
  end
31
-
32
30
  end
33
31
 
34
-
35
32
  end
36
33
  end
37
34
  end
@@ -6,59 +6,65 @@ module Tzispa
6
6
  module Helpers
7
7
  module Request
8
8
 
9
- using Tzispa::Utils
9
+ using Tzispa::Utils::TzString
10
10
 
11
11
  def request_data(fields)
12
- Hash.new.tap { |data|
13
- fields.each { |name|
12
+ {}.tap do |data|
13
+ fields.each do |name|
14
14
  macro_field = name.split('@:')
15
15
  macro = macro_field.first.to_sym if macro_field.length == 2
16
16
  field = macro_field.length == 2 ? macro_field.last : macro_field.first
17
- field.split(':').tap { |fld|
18
- src = fld.first
19
- dest = fld.last
20
- value = String == context.request[src] ? String.unescape_html(context.request[src]) : context.request[src]
21
- data[dest.to_sym] = macro ? send(macro, value) : value
22
- }
23
- }
24
- }
17
+ build_field field, macro, data
18
+ end
19
+ end
25
20
  end
26
21
 
27
22
  def request_data_object(data_object:, fields:)
28
- data_object.tap { |data|
29
- fields.each { |name|
23
+ data_object.tap do |data|
24
+ fields.each do |name|
30
25
  macro_field = name.split('@:')
31
26
  macro = macro_field.first.to_sym if macro_field.length == 2
32
27
  field = macro_field.length == 2 ? macro_field.last : macro_field.first
33
- field.split(':').tap { |fld|
34
- src = fld.first
35
- dest = fld.last
36
- value = String == context.request[src] ? String.unescape_html(context.request[src]) : context.request[src]
37
- data.send "#{dest}=".to_sym, macro ? send(macro, value) : value
38
- }
39
- }
40
- }
28
+ build_field field, macro, data
29
+ end
30
+ end
41
31
  end
42
32
 
43
33
  def request_file_upload(request_file:, destination_path:, save_as: nil, keep_ext: true)
44
- if request_file
45
- fileext = File.extname(request_file[:filename]).downcase
46
- filetype = request_file[:type]
47
- save_ext = fileext if keep_ext
48
- filename = (save_as ? "#{save_as}#{save_ext}" : request_file[:filename])
49
- tempfile = request_file[:tempfile]
50
- dest_file = "#{destination_path}/#{filename}"
51
- begin
52
- FileUtils.mkdir_p(destination_path) unless File.exists?(destination_path)
53
- FileUtils.cp tempfile.path, dest_file
54
- ensure
55
- tempfile.close
56
- tempfile.unlink
57
- end
58
- { name: filename, ext: fileext, path: dest_file, size: ::File.size(dest_file), type: filetype }
34
+ return unless request_file
35
+ fileext = File.extname(request_file[:filename]).downcase
36
+ filetype = request_file[:type]
37
+ save_ext = fileext if keep_ext
38
+ filename = (save_as ? "#{save_as}#{save_ext}" : request_file[:filename])
39
+ tempfile = request_file[:tempfile]
40
+ dest_file = "#{destination_path}/#{filename}"
41
+ begin
42
+ FileUtils.mkdir_p(destination_path) unless File.exist?(destination_path)
43
+ FileUtils.cp tempfile.path, dest_file
44
+ ensure
45
+ tempfile.close
46
+ tempfile.unlink
59
47
  end
48
+ { name: filename, ext: fileext, path: dest_file,
49
+ size: ::File.size(dest_file), type: filetype }
60
50
  end
61
51
 
52
+ def build_field(field, macro, data)
53
+ field.split(':').tap do |src, dest|
54
+ dest ||= src
55
+ value = if String == request[src]
56
+ String.unescape_html(request[src])
57
+ else
58
+ request[src]
59
+ end
60
+ value = macro ? send(macro, value) : value
61
+ if data.is_a? ::Hash
62
+ data[dest.to_sym] = value
63
+ else
64
+ data.send "#{dest}=".to_sym, value
65
+ end
66
+ end
67
+ end
62
68
 
63
69
  end
64
70
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Tzispa
2
4
  module Helpers
3
5
  module Requirer
@@ -7,7 +9,7 @@ module Tzispa
7
9
  end
8
10
 
9
11
  def required?(target, value)
10
- self.class.required? target. value
12
+ self.class.required? target, value
11
13
  end
12
14
 
13
15
  def required_valid?(target, value)
@@ -17,10 +19,10 @@ module Tzispa
17
19
  module ClassMethods
18
20
 
19
21
  def required(target, value, &block)
20
- @required ||= Hash.new
21
- (@required[target] ||= Hash.new).tap { |reqt|
22
+ @required ||= {}
23
+ (@required[target] ||= {}).tap do |reqt|
22
24
  reqt[value] = block || true
23
- }
25
+ end
24
26
  end
25
27
 
26
28
  def required?(target, value)
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'uri'
4
4
  require_relative 'mime'
5
+ require_relative 'services/send_file'
6
+ require_relative 'services/content_type'
5
7
 
6
8
  module Tzispa
7
9
  module Helpers
@@ -23,10 +25,14 @@ module Tzispa
23
25
  # evaluation is deferred until the body is read with #each.
24
26
  def body(value = nil, &block)
25
27
  if block_given?
26
- def block.each; yield(call) end
28
+ def block.each
29
+ yield(call)
30
+ end
27
31
  response.body = block
28
32
  elsif value
29
- headers.delete 'Content-Length' unless request.head? || value.is_a?(Rack::File) || value.is_a?(Stream)
33
+ headers.delete 'Content-Length' unless request.head? ||
34
+ value.is_a?(Rack::File) ||
35
+ value.is_a?(Stream)
30
36
  response.body = value
31
37
  else
32
38
  response.body
@@ -42,14 +48,7 @@ module Tzispa
42
48
 
43
49
  # Halt processing and redirect to the URI provided.
44
50
  def redirect(uri, absolute, *args)
45
- if (env['HTTP_VERSION'] == 'HTTP/1.1' || env['HTTP_VERSION'] == 'HTTP/2.0') && env["REQUEST_METHOD"] != 'GET'
46
- status 303
47
- else
48
- status 302
49
- end
50
-
51
- # According to RFC 2616 section 14.30, "the field value consists of a
52
- # single absolute URI"
51
+ status(request.allowed_http_version? && request.get? ? 303 : 302)
53
52
  response['Location'] = uri(uri.to_s, absolute)
54
53
  halt(*args)
55
54
  end
@@ -61,27 +60,30 @@ module Tzispa
61
60
  halt(*args)
62
61
  end
63
62
 
64
-
65
63
  # Generates the absolute URI for a given path in the app.
66
64
  # Takes Rack routers and reverse proxies into account.
67
65
  def uri(addr = nil, absolute = true)
68
- return addr if addr =~ /\A[A-z][A-z0-9\+\.\-]*:/
66
+ return addr if addr.match?(/\A[A-z][A-z0-9\+\.\-]*:/)
69
67
  uri = [host = String.new]
70
- if absolute
71
- host << "http#{'s' if request.secure?}://"
72
- if request.forwarded? or request.port != (request.secure? ? 443 : 80)
73
- host << request.host_with_port
74
- else
75
- host << request.host
76
- end
77
- end
68
+ host << uri_host if absolute
78
69
  uri << (addr ? addr : request.path_info).to_s
79
70
  File.join uri
80
71
  end
81
72
 
73
+ def uri_host
74
+ String.new.tap do |host|
75
+ host << "http#{'s' if request.secure?}://"
76
+ host << (uri_port? ? request.host_with_port : request.host)
77
+ end
78
+ end
79
+
80
+ def uri_port?
81
+ request.forwarded? || request.port != (request.secure? ? 443 : 80)
82
+ end
83
+
82
84
  # Halt processing and return the error status provided.
83
- def error(code, body = nil)
84
- code, body = 500, code.to_str if code.respond_to? :to_str
85
+ def error(code = 500, body = nil)
86
+ body = code.to_str if code.respond_to? :to_str
85
87
  response.body = body unless body.nil?
86
88
  halt code
87
89
  end
@@ -95,7 +97,7 @@ module Tzispa
95
97
  def unauthorized(body = nil)
96
98
  error 401, body
97
99
  end
98
- alias_method :not_authorized, :unauthorized
100
+ alias not_authorized unauthorized
99
101
 
100
102
  # Set multiple response headers with Hash.
101
103
  def headers(hash = nil)
@@ -106,55 +108,17 @@ module Tzispa
106
108
  # Set the Content-Type of the response body given a media type or file
107
109
  # extension.
108
110
  def content_type(type = nil, params = {})
109
- return response['Content-Type'] unless type
110
- default = params.delete :default
111
- mime_type = mime_type(type) || default
112
- fail "Unknown media type: %p" % type if mime_type.nil?
113
- mime_type = mime_type.dup
114
- unless params.include? :charset
115
- params[:charset] = params.delete('charset') || config.default_encoding
116
- end
117
- params.delete :charset if mime_type.include? 'charset'
118
- unless params.empty?
119
- mime_type << (mime_type.include?(';') ? ', ' : ';')
120
- mime_type << params.map do |key, val|
121
- val = val.inspect if val =~ /[";,]/
122
- "#{key}=#{val}"
123
- end.join(', ')
124
- end
125
- response['Content-Type'] = mime_type
126
- end
127
-
128
- def attachment!(filename = nil, disposition = 'attachment')
129
- content_disposition = disposition.to_s
130
- content_disposition += "; filename=\"#{filename}\"; filename*=UTF-8''#{URI.escape(filename)}" if !filename.nil?
131
- response['Content-Disposition'] = content_disposition
111
+ return if response.drop_content_info?
112
+ ct = Tzispa::Helpers::Services::ContentType.new(response,
113
+ config.default_encoding)
114
+ ct.header(type, params)
132
115
  end
133
116
 
134
117
  def send_file(path, opts = {})
135
- begin
136
- if opts[:type] or not response['Content-Type']
137
- content_type opts[:type] || opts[:extension], :default => 'application/octet-stream'
138
- end
139
-
140
- disposition = opts[:disposition]
141
- filename = opts[:filename]
142
- disposition = 'attachment' if disposition.nil? and filename
143
- filename = path if filename.nil?
144
-
145
- attachment! filename, disposition
146
- last_modified opts[:last_modified] if opts[:last_modified]
147
-
148
- file = Rack::File.new(Dir.pwd)
149
- result = file.serving(request, path)
150
-
151
- result[1].each { |k,v| response.headers[k] ||= v }
152
- response.headers['Content-Length'] = result[1]['Content-Length']
153
- response.status = result[0]
154
- response.body = result[2]
155
- rescue
156
- not_found 'Fichero no encontrado'
157
- end
118
+ not_found unless ::File.exist? path
119
+ file = Rack::File.new(Dir.pwd)
120
+ fss = Tzispa::Helpers::Services::SendFile.new response, path, opts
121
+ fss.send file.serving(request, path)
158
122
  end
159
123
 
160
124
  # Sugar for redirect (example: redirect back)
@@ -192,12 +156,16 @@ module Tzispa
192
156
  response.status == 404
193
157
  end
194
158
 
159
+ def error_500(str)
160
+ 500.tap { |_code| response.body = str if str }
161
+ end
195
162
 
196
163
  class NotFound < NameError #:nodoc:
197
- def http_status; 404 end
164
+ def http_status
165
+ 404
166
+ end
198
167
  end
199
168
 
200
-
201
169
  end
202
170
  end
203
171
  end
@@ -6,57 +6,46 @@ module Tzispa
6
6
  module Helpers
7
7
  module Security
8
8
 
9
-
10
9
  def secret(length)
11
- alfanb = (['!', '"', '·', '$', '%', '&', '/', '(', ')', '=', '?', '+',
12
- '@', '#', ',', '.', '-', ';', ':', '_', '[', ']', '>', '<', '*'] <<
13
- [('a'..'z'), ('0'..'9'), ('A'..'Z')].map { |i| i.to_a }).flatten
10
+ alfanb = (['!', '"', '·', '$', '%', '&', '/', '(', ')', '=',
11
+ '?', '+', '@', '#', ',', '.', '-', ';', ':', '_',
12
+ '[', ']', '>', '<', '*'] <<
13
+ [('a'..'z'), ('0'..'9'), ('A'..'Z')].map(&:to_a)).flatten
14
14
  (0...length).map { alfanb[rand(alfanb.length)] }.join
15
15
  end
16
16
 
17
17
  def uuid
18
- sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
19
- # 32 bits for "time_low"
20
- rand(0..0xffff), rand(0..0xffff),
21
-
22
- # 16 bits for "time_mid"
23
- rand(0..0xffff),
24
-
25
- # 16 bits for "time_hi_and_version",
26
- #3 four most significant bits holds version number 4
27
- rand(0..0x0fff) | 0x4000,
28
-
29
- # 16 bits, 8 bits for "clk_seq_hi_res",
30
- # 8 bits for "clk_seq_low",
31
- # two most significant bits holds zero and one for variant DCE1.1
32
- rand(0..0x3fff) | 0x8000,
33
-
34
- # 48 bits for "node"
35
- rand(0..0xffff), rand(0..0xffff), rand(0..0xffff)
36
- )
18
+ format('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
19
+ rand(0..0xffff),
20
+ rand(0..0xffff),
21
+ rand(0..0xffff),
22
+ rand(0..0x0fff) | 0x4000,
23
+ rand(0..0x3fff) | 0x8000,
24
+ rand(0..0xffff),
25
+ rand(0..0xffff),
26
+ rand(0..0xffff))
37
27
  end
38
28
 
39
- def sign_array(astr, salt=nil)
40
- sign, i = String.new, 0
41
- astr.each { |s|
42
- i = i + 1
43
- sign << "#{"_"*i}#{s}"
44
- }
29
+ def sign_array(astr, salt = nil)
30
+ sign = String.new
31
+ i = 0
32
+ astr.each do |s|
33
+ i += 1
34
+ sign << "#{'_' * i}#{s}"
35
+ end
45
36
  sign << "**#{salt}"
46
37
  Digest::SHA1.hexdigest sign
47
38
  end
48
39
 
49
40
  def hash_password(password, salt)
50
- Digest::MD5::hexdigest "#{password}::#{salt}"
41
+ Digest::MD5.hexdigest "#{password}::#{salt}"
51
42
  end
52
43
 
53
44
  def hash_password?(hashed, pwd, salt)
54
45
  hashed == hash_password(pwd, salt)
55
46
  end
56
47
 
57
-
58
48
  class Identity
59
-
60
49
  attr_reader :id, :token
61
50
 
62
51
  def initialize(id, secret)
@@ -68,15 +57,11 @@ module Tzispa
68
57
  @token == Identity.generate_token(@id, secret)
69
58
  end
70
59
 
71
- private
72
-
73
60
  def self.generate_token(value, salt)
74
61
  Digest::SHA1.hexdigest "___#{value}_#{salt}__token__"
75
62
  end
76
-
77
63
  end
78
64
 
79
-
80
65
  end
81
66
  end
82
67
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require 'tzispa/helpers/mime'
5
+
6
+ module Tzispa
7
+ module Helpers
8
+ module Services
9
+
10
+ class ContentType
11
+ include Tzispa::Helpers::Mime
12
+
13
+ attr_reader :response, :default_encoding
14
+
15
+ def initialize(response, default_encoding = nil)
16
+ @response = response
17
+ @default_encoding = default_encoding
18
+ end
19
+
20
+ # Set the Content-Type of the response body given a media type or file
21
+ # extension.
22
+ def header(type = nil, params = {})
23
+ return response['Content-Type'] unless type || params[:default]
24
+ default = params.delete :default
25
+ mime = mime_type(type) || default
26
+ raise "Unknown media type: #{type}" unless mime
27
+ params = charset mime, params
28
+ build mime.dup, params
29
+ end
30
+
31
+ def charset(mime, params)
32
+ unless params.include?(:charset) || mime.include?('charset')
33
+ params[:charset] = params.delete('charset') || default_encoding
34
+ end
35
+ params.delete :charset if mime.include? 'charset'
36
+ params
37
+ end
38
+
39
+ def file(type, extension = nil)
40
+ return unless response['Content-Type']
41
+ header type || extension,
42
+ default: 'application/octet-stream'
43
+ end
44
+
45
+ private
46
+
47
+ def build(mime, params)
48
+ mime if params.empty?
49
+ mime << (mime.include?(';') ? ', ' : ';')
50
+ mime << params.select { |_, val| val&.match?(/[";,]/) }
51
+ .map do |key, val|
52
+ "#{key}=#{val.inspect}"
53
+ end.join(', ')
54
+ response['Content-Type'] = mime
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tzispa
4
+ module Helpers
5
+ module Services
6
+
7
+ class ErrorView
8
+ attr_reader :exception
9
+
10
+ def initialize(exception)
11
+ @exception = exception
12
+ end
13
+
14
+ def error_header
15
+ "<h1>#{exception.class.name}</h1><h3>#{exception.message}</h3>"
16
+ end
17
+
18
+ def error_backtrace_list
19
+ return unless exception.respond_to?(:backtrace) && exception.backtrace
20
+ String.new.tap do |str|
21
+ str << '<ol>'
22
+ str << exception.backtrace.map { |trace| "<li>#{trace}</li>\n" }.join
23
+ str << '</ol>'
24
+ end
25
+ end
26
+
27
+ def error_backtrace_log
28
+ return unless exception.respond_to?(:backtrace) && exception.backtrace
29
+ String.new.tap do |str|
30
+ str << "#{exception.class.name}: #{exception}:\n"
31
+ str << exception.backtrace.join("\n")
32
+ end
33
+ end
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+
5
+ module Tzispa
6
+ module Helpers
7
+ module Services
8
+
9
+ class SendFile
10
+ attr_reader :response, :opts, :path
11
+
12
+ def initialize(response, path, opts)
13
+ @response = response
14
+ @opts = opts
15
+ @path = path
16
+ end
17
+
18
+ def content_disposition(filename = nil, disposition = 'attachment')
19
+ disposition = String.new << disposition.to_s
20
+ if filename
21
+ escaped = URI.escape(filename)
22
+ disposition << "; filename=\"#{escaped}\""
23
+ disposition << "; filename*=UTF-8''#{escaped}"
24
+ end
25
+ response['Content-Disposition'] = disposition
26
+ end
27
+
28
+ def send(result)
29
+ prepare
30
+ response.status = result[0]
31
+ if response.status.between? 200, 299
32
+ headers_set result[1]
33
+ response.body = result[2]
34
+ end
35
+ response
36
+ end
37
+
38
+ private
39
+
40
+ def prepare
41
+ content_headers
42
+ disposition = opts[:disposition]
43
+ filename = opts[:filename]
44
+ disposition = 'attachment' if disposition.nil? && filename
45
+ filename = path if filename.nil?
46
+ content_disposition filename, disposition
47
+ end
48
+
49
+ def headers_set(headers)
50
+ headers.each { |k, v| response.headers[k] ||= v }
51
+ response.headers['Content-Length'] = headers['Content-Length']
52
+ response.no_cache.cache_private if opts[:no_cache]
53
+ end
54
+
55
+ def content_headers
56
+ ct = Tzispa::Helpers::Services::ContentType.new response
57
+ ct.file opts[:type], opts[:extension]
58
+ last_modified opts[:last_modified] if opts[:last_modified]
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+ require 'tzispa/helpers/session_flash_bag'
5
+
6
+ module Tzispa
7
+ module Helpers
8
+ module Session
9
+
10
+ SESSION_LAST_ACCESS = :__last_access
11
+ SESSION_ID = :__session_id
12
+ SESSION_AUTH_USER = :__auth__user
13
+ GLOBAL_MESSAGE_FLASH = :__global_message_flash
14
+
15
+ def init_session
16
+ generate_session_id if config&.sessions&.enabled && !session?
17
+ end
18
+
19
+ def set_last_access
20
+ session[SESSION_LAST_ACCESS] = Time.now.utc.iso8601
21
+ end
22
+
23
+ def last_access
24
+ session[SESSION_LAST_ACCESS]
25
+ end
26
+
27
+ def flash
28
+ @flash ||= SessionFlashBag.new(session, GLOBAL_MESSAGE_FLASH)
29
+ end
30
+
31
+ def session?
32
+ !session[SESSION_ID].nil? && (session[SESSION_ID] == session.id)
33
+ end
34
+
35
+ def logged?
36
+ session? && login
37
+ end
38
+
39
+ def login=(user)
40
+ session[SESSION_AUTH_USER] = user unless user.nil?
41
+ end
42
+
43
+ def login
44
+ session[SESSION_AUTH_USER]
45
+ end
46
+
47
+ def logout
48
+ session.delete(SESSION_AUTH_USER)
49
+ end
50
+
51
+ def generate_session_id
52
+ SecureRandom.uuid.tap do |uuid|
53
+ session.id = uuid
54
+ session[SESSION_ID] = uuid
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'json'
5
+
6
+ module Tzispa
7
+ module Helpers
8
+ module Session
9
+
10
+ class SessionFlashBag
11
+ extend Forwardable
12
+
13
+ def_delegators :@bag, :count, :length, :size, :each
14
+
15
+ SESSION_FLASH_BAG = :__flash_bag
16
+
17
+ def initialize(session, key)
18
+ @session = session
19
+ @session_key = "#{SESSION_FLASH_BAG}_#{key}".to_sym
20
+ load!
21
+ end
22
+
23
+ def <<(value)
24
+ return unless value
25
+ bag << value
26
+ store
27
+ end
28
+
29
+ def pop
30
+ value = bag.pop
31
+ store
32
+ value
33
+ end
34
+
35
+ def pop_all
36
+ empty!
37
+ bag
38
+ end
39
+
40
+ def push(value)
41
+ bag.push value
42
+ store
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :bag, :session, :session_key
48
+
49
+ def load!
50
+ @bag = session[session_key] ? JSON.parse(session[session_key]) : []
51
+ end
52
+
53
+ def store
54
+ session[session_key] = bag.to_json
55
+ end
56
+
57
+ def empty!
58
+ session[session_key] = []
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'requirer'
2
4
 
3
5
  module Tzispa
@@ -17,9 +19,7 @@ module Tzispa
17
19
  self.class.sign_valid? self
18
20
  end
19
21
 
20
-
21
22
  module ClassMethods
22
-
23
23
  def sign_required!(&block)
24
24
  required(:router_params, :sign, &block)
25
25
  end
@@ -31,7 +31,6 @@ module Tzispa
31
31
  def sign_valid?(obj)
32
32
  required_valid? :router_params, :sign, obj
33
33
  end
34
-
35
34
  end
36
35
 
37
36
  end
@@ -3,7 +3,7 @@
3
3
  require 'date'
4
4
  require 'bigdecimal'
5
5
  require 'i18n'
6
- require "unicode_utils"
6
+ require 'unicode_utils'
7
7
  require 'cgi/util'
8
8
 
9
9
  module Tzispa
@@ -11,13 +11,11 @@ module Tzispa
11
11
  module Text
12
12
 
13
13
  def remove_words(sentence, removable)
14
- sentence.split.delete_if{|x| removable.include?(UnicodeUtils.downcase x)}.join(' ')
14
+ sentence.split.delete_if { |x| removable.include? UnicodeUtils.downcase(x) }.join(' ')
15
15
  end
16
16
 
17
17
  def remove_phrases(text, removable)
18
- removable.each { |phrase|
19
- text.slice! phrase
20
- }
18
+ removable.each { |phrase| text.slice! phrase }
21
19
  text
22
20
  end
23
21
 
@@ -26,68 +24,67 @@ module Tzispa
26
24
  end
27
25
 
28
26
  def synonymize(sentence, synonyms)
29
- sentence.gsub(/[[:alnum:]]+/) {|word|
27
+ sentence.gsub(/[[:alnum:]]+/) do |word|
30
28
  dwword = UnicodeUtils.downcase word
31
- synonyms.has_key?(dwword) ? synonyms[dwword] : word
32
- }
29
+ synonyms.key?(dwword) ? synonyms[dwword] : word
30
+ end
33
31
  end
34
32
 
35
33
  def strip_to_nil(str, transform = nil)
36
- sstr = str.strip if str and not str.strip.empty?
34
+ sstr = str.strip if str && !str.strip.empty?
37
35
  case transform
38
- when :upcase then
39
- UnicodeUtils.upcase(sstr)
40
- when :downcase then
41
- UnicodeUtils.downcase(sstr)
42
- when :titlecase then
43
- UnicodeUtils.titlecase(sstr)
44
- else sstr
36
+ when :upcase then
37
+ UnicodeUtils.upcase(sstr)
38
+ when :downcase then
39
+ UnicodeUtils.downcase(sstr)
40
+ when :titlecase then
41
+ UnicodeUtils.titlecase(sstr)
42
+ else
43
+ sstr
45
44
  end
46
45
  end
47
46
 
48
47
  def html_unscape(str)
49
- CGI::unescapeHTML(str.strip) if str && !str.strip.empty?
48
+ CGI.unescapeHTML(str.strip) if str && !str.strip.empty?
50
49
  end
51
50
 
52
- def split_to_array(str, separator=';')
53
- str.split(separator) if str
51
+ def split_to_array(str, separator = ';')
52
+ str&.split(separator)
54
53
  end
55
54
 
56
55
  def join_to_nil(ary, separator)
57
- ary.join(separator) if ary and not ary.empty?
56
+ ary.join(separator) if ary && !ary.empty?
58
57
  end
59
58
 
60
- def str_to_bool(str, strue=nil)
59
+ def str_to_bool(str, strue = nil)
61
60
  strue ? (strue == str) : (str == 'yes' || str == 'true')
62
61
  end
63
62
 
64
- def str_to_date(str, format=nil)
63
+ def str_to_date(str, format = nil)
65
64
  str = strip_to_nil str
66
65
  Date.strptime(str, format || I18n.t('date.formats.default')) if str
67
66
  end
68
67
 
69
- def str_to_datetime(str, format=nil)
68
+ def str_to_datetime(str, format = nil)
70
69
  str = strip_to_nil str
71
70
  DateTime.strptime(str, format || I18n.t('datetime.formats.default'))
72
71
  end
73
72
 
74
- def str_time_ellapsed(t_start, t_end=nil)
73
+ def str_time_ellapsed(t_start, t_end = nil)
75
74
  elapsed = (t_end || Time.now) - t_start
76
75
  seconds = elapsed % 60
77
76
  minutes = (elapsed / 60) % 60
78
77
  hours = elapsed / (60 * 60)
79
- format("%02d:%02d:%02d", hours, minutes, seconds)
78
+ format('%02d:%02d:%02d', hours, minutes, seconds)
80
79
  end
81
80
 
82
81
  def str_to_amount(str, options = {})
83
- if str && !str.strip.empty?
84
- separator = options.fetch(:separator, I18n.t('number.currency.format.separator'))
85
- precision = options.fetch(:precision, I18n.t('number.currency.format.precision'))
86
- re = Regexp.new "[^\\d\\#{separator}\\-]"
87
- str = str.gsub(re, '')
88
- str = str.gsub(separator, '.') if separator != '.'
89
- BigDecimal.new(str).round(precision).to_s('F')
90
- end
82
+ return unless !str || str.strip.empty?
83
+ separator = options.fetch(:separator, I18n.t('number.currency.format.separator'))
84
+ precision = options.fetch(:precision, I18n.t('number.currency.format.precision'))
85
+ str = str.gsub(Regexp.new("[^\\d\\#{separator}\\-]"), '')
86
+ str = str.gsub(separator, '.') if separator != '.'
87
+ BigDecimal.new(str).round(precision).to_s('F')
91
88
  end
92
89
 
93
90
  def amount(number, options = {})
@@ -106,30 +103,34 @@ module Tzispa
106
103
  separator = options.fetch(:separator, I18n.t('number.currency.format.separator'))
107
104
  delimiter = options.fetch(:delimiter, I18n.t('number.currency.format.delimiter')).to_s
108
105
  minimum_precision = options[:minimum_precision] || 0
109
- str = number.is_a?(BigDecimal) ? number.to_s('F').sub(/\.0+\z/, "") : number.to_s.sub(/\.0+\z/, "")
110
- str =~ /\A(\-?)(\d+)(?:\.(\d+))?\z/ or raise "Could not parse number: #{number}"
111
- sign = $1
112
- integer = $2
113
- fraction = ($3 || '')
106
+ str = if number.is_a?(BigDecimal)
107
+ number.to_s('F').sub(/\.0+\z/, '')
108
+ else
109
+ number.to_s.sub(/\.0+\z/, '')
110
+ end
111
+ smatch = str.match(/\A(\-?)(\d+)(?:\.(\d+))?\z/)
112
+ raise "Could not parse number: #{number}" unless smatch
113
+ sign = smatch[1]
114
+ integer = smatch[2]
115
+ fraction = (smatch[3] || '')
114
116
 
115
117
  if options[:maximum_precision]
116
118
  fraction = fraction[0, options[:maximum_precision]] if options[:maximum_precision]
117
119
  end
118
120
 
119
-
120
- if fraction.length > 0 && minimum_precision > 0
121
+ if fraction.positive? && minimum_precision.positive?
121
122
  fraction = "#{fraction}#{'0' * [0, minimum_precision - fraction.length].max}"
122
- elsif minimum_precision == 0 && fraction.length > 0 && fraction.to_i == 0
123
+ elsif minimum_precision.zero? && !fraction.empty? && fraction.to_i.zero?
123
124
  fraction = ''
124
125
  end
125
126
 
126
- # the following two lines appear to be the most performant way to add a delimiter to every thousands place in the number
127
+ # add a delimiter to every thousands place in the number
127
128
  integer_size = integer.size
128
- (1..((integer_size-1) / 3)).each {|x| integer[integer_size-x*3,0] = delimiter}
129
+ (1..((integer_size - 1) / 3)).each { |x| integer[integer_size - x * 3, 0] = delimiter }
129
130
  str = integer.chomp(delimiter)
130
131
 
131
132
  # add fraction
132
- str << "#{separator}#{fraction}" if fraction.length > 0
133
+ str << "#{separator}#{fraction}" unless fraction.empty?
133
134
 
134
135
  # restore sign
135
136
  str = "#{sign}#{str}"
@@ -145,22 +146,26 @@ module Tzispa
145
146
  end
146
147
 
147
148
  def money_amount(number, options = {})
148
- amount(number, options.merge(:unit => I18n.t('number.currency.format.unit'), :nil_as_dash => false, :precision => I18n.t('number.currency.format.precision'), minimum_precision: 0))
149
+ amount(number, options.merge(unit: I18n.t('number.currency.format.unit'),
150
+ nil_as_dash: false,
151
+ precision: I18n.t('number.currency.format.precision'),
152
+ minimum_precision: 0))
149
153
  end
150
154
 
151
155
  def price_amount(number, options = {})
152
- amount(number, options.merge(:nil_as_dash => false, :precision => I18n.t('number.currency.format.precision'), minimum_precision: 0))
156
+ amount(number, options.merge(nil_as_dash: false,
157
+ precision: I18n.t('number.currency.format.precision'),
158
+ minimum_precision: 0))
153
159
  end
154
160
 
155
161
  def starinizer(rating, star_value, max_stars)
156
- Hash.new.tap { |stars|
162
+ {}.tap do |stars|
157
163
  stars[:full] = rating / star_value
158
164
  stars[:half] = rating % star_value
159
165
  stars[:o] = max_stars - stars[:full] - stars[:half]
160
- }
166
+ end
161
167
  end
162
168
 
163
-
164
169
  end
165
170
  end
166
171
  end
@@ -3,7 +3,7 @@
3
3
  module Tzispa
4
4
  module Helpers
5
5
 
6
- VERSION = '0.2.2'
6
+ VERSION = '0.3.0'
7
7
  NAME = 'Tzispa Helpers'
8
8
  GEM_NAME = 'tzispa_helpers'
9
9
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tzispa_helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Antonio Piñero
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-13 00:00:00.000000000 Z
11
+ date: 2017-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -64,7 +64,6 @@ files:
64
64
  - lib/tzispa/helpers.rb
65
65
  - lib/tzispa/helpers/date_time.rb
66
66
  - lib/tzispa/helpers/error_view.rb
67
- - lib/tzispa/helpers/hash_trans.rb
68
67
  - lib/tzispa/helpers/html.rb
69
68
  - lib/tzispa/helpers/mime.rb
70
69
  - lib/tzispa/helpers/pattern.rb
@@ -73,6 +72,11 @@ files:
73
72
  - lib/tzispa/helpers/requirer.rb
74
73
  - lib/tzispa/helpers/response.rb
75
74
  - lib/tzispa/helpers/security.rb
75
+ - lib/tzispa/helpers/services/content_type.rb
76
+ - lib/tzispa/helpers/services/error_view.rb
77
+ - lib/tzispa/helpers/services/send_file.rb
78
+ - lib/tzispa/helpers/session.rb
79
+ - lib/tzispa/helpers/session_flash_bag.rb
76
80
  - lib/tzispa/helpers/sign_requirer.rb
77
81
  - lib/tzispa/helpers/text.rb
78
82
  - lib/tzispa/helpers/version.rb
@@ -1,18 +0,0 @@
1
- module Tzispa
2
- module Helpers
3
- module HashTrans
4
-
5
- def hash_fussion!(hash, fussion_keys={})
6
- hash.keys.each { |key|
7
- if fussion_keys.has_key?(key)
8
- hash[fussion_keys[key]] ?
9
- hash[fussion_keys[key]] += hash[key] :
10
- hash[fussion_keys[key]] = hash[key]
11
- hash.delete(key)
12
- end
13
- } unless fussion_keys.empty?
14
- end
15
-
16
- end
17
- end
18
- end