tzispa_helpers 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 87b4a937a075322e0d9ad944994d1a0562fbb390
4
+ data.tar.gz: 8ebb31c207fd19d5322097b6b11225aa52b22e80
5
+ SHA512:
6
+ metadata.gz: 2464f13b0caa59b90b74a3b0d30a68b784c420b2fba0f17b89ea7e9b4a33e8a4e5f50b1f54bf8dfe9e4c5f68a2190143545ce741f00fb7f80d8be5fd973179d7
7
+ data.tar.gz: b3af1a958c90c2881b842277b708c5d5490bb8f4704699ce002f1e64cb7f1105e57669702fbd737c35c80c5afa59a01249261448df7fb9c64b94afc1e7a0215b
data/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ Tzispa Helpers
2
+
3
+ ## v0.1.3
4
+ - Added mime module, code moved partially from response
5
+ - Added 2 crawler functions: crawler_to_markdown, crawler_table_to_dl
6
+
7
+ ## v0.1.2
8
+ - Added amount formatter in text helper with i18n support
9
+
10
+ ## v0.1.1
11
+ - Added exception rescue in Mail.send_smtp_mail
12
+ - Added pattern Helper
13
+ - Added web crawler helper
14
+
15
+ ## v0.1.0
16
+ - Initial release: code split from tzispa main gem
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ Tzispa Helpers
2
+
3
+ Helper modules for Tzispa framework
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open-uri'
4
+ require 'nokogiri'
5
+ require 'htmlentities'
6
+ require 'reverse_markdown'
7
+ require 'unicode_utils'
8
+ require 'redcarpet'
9
+
10
+ module Tzispa
11
+ module Helpers
12
+ module Crawler
13
+
14
+
15
+ def crawler_save_file(url, dest_file)
16
+ File.open("#{dest_file}", 'wb') do |fo|
17
+ fo.write open(url).read
18
+ end
19
+ end
20
+
21
+ def crawler_to_markdown(source)
22
+ begin
23
+ source = source.read if source.respond_to? :read
24
+ htmee = HTMLEntities.new
25
+ ReverseMarkdown.convert(htmee.decode(source).strip, unknown_tags: :bypass)
26
+ rescue Encoding::UndefinedConversionError
27
+ end
28
+ end
29
+
30
+ def crawler_table_to_dl(source, table_path, columns=2, excluded_terms=[])
31
+ String.new.tap { |content|
32
+ dt, dd = Array.new, Array.new
33
+ htmee = HTMLEntities.new
34
+ markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new)
35
+ Nokogiri::HTML(source)&.xpath(table_path).collect { |row|
36
+ dterm = htmee.decode(row.at_xpath('td[1]')&.content).strip
37
+ if dterm.length > 0 && !excluded_terms.include?(UnicodeUtils.downcase dterm)
38
+ dt << dterm
39
+ dd << (2..columns).map { |i|
40
+ ReverseMarkdown.convert(htmee.decode(row.at_xpath("td[#{i}]")&.children&.to_s || row.at_xpath("td[#{i}]")&.to_s).strip, unknown_tags: :bypass)
41
+ }.join('\n')
42
+ end
43
+ }
44
+ if dt.length > 0
45
+ content << '<dl>'
46
+ dt.zip(dd).sort.each do |idt,idd|
47
+ if idt.length > 0 && !excluded_terms.include?(UnicodeUtils.downcase idt)
48
+ content << "<dt>#{idt}</dt>"
49
+ content << "<dd>#{markdown.render idd}</dd>"
50
+ end
51
+ end
52
+ content << "</dl>"
53
+ end
54
+ }
55
+ end
56
+
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi/util'
4
+ require 'uri'
5
+
6
+ module Tzispa
7
+ module Helpers
8
+ module Html
9
+
10
+ def html_checked(value)
11
+ value ? ' checked="checked"' : String.new.freeze
12
+ end
13
+
14
+ def html_selected(value)
15
+ value ? ' selected="selected"' : String.new.freeze
16
+ end
17
+
18
+ def html_escape(str)
19
+ CGI::escapeHTML str
20
+ end
21
+
22
+ def html_unescape(str)
23
+ CGI::unescapeHTML str
24
+ end
25
+
26
+ def html_urlencode(str)
27
+ URI.escape str
28
+ end
29
+
30
+ def html_urldecode(str)
31
+ URI.unescape str
32
+ end
33
+
34
+ def html_strip(source)
35
+ source.gsub(/<\/?[^>]*>/, '')
36
+ end
37
+
38
+
39
+ #
40
+ # $Id: sanitize.rb 3 2005-04-05 12:51:14Z dwight $
41
+ #
42
+ # Copyright (c) 2005 Dwight Shih
43
+ # A derived work of the Perl version:
44
+ # Copyright (c) 2002 Brad Choate, bradchoate.com
45
+ #
46
+ # Permission is hereby granted, free of charge, to
47
+ # any person obtaining a copy of this software and
48
+ # associated documentation files (the "Software"), to
49
+ # deal in the Software without restriction, including
50
+ # without limitation the rights to use, copy, modify,
51
+ # merge, publish, distribute, sublicense, and/or sell
52
+ # copies of the Software, and to permit persons to
53
+ # whom the Software is furnished to do so, subject to
54
+ # the following conditions:
55
+ #
56
+ # The above copyright notice and this permission
57
+ # notice shall be included in all copies or
58
+ # substantial portions of the Software.
59
+ #
60
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY
61
+ # OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
62
+ # LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63
+ # FITNESS FOR A PARTICULAR PURPOSE AND
64
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
65
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
66
+ # OR OTHER LIABILITY, WHETHER IN AN ACTION OF
67
+ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
68
+ # OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
69
+ # OTHER DEALINGS IN THE SOFTWARE.
70
+ #
71
+ def html_sanitize( html, okTags='a href, b, br, i, p' )
72
+ # no closing tag necessary for these
73
+ soloTags = ["br","hr"]
74
+
75
+ # Build hash of allowed tags with allowed attributes
76
+ tags = okTags.downcase().split(',').collect!{ |s| s.split(' ') }
77
+ allowed = Hash.new
78
+ tags.each do |s|
79
+ key = s.shift
80
+ allowed[key] = s
81
+ end
82
+
83
+ # Analyze all <> elements
84
+ stack = Array.new
85
+ result = html.gsub( /(<.*?>)/m ) do | element |
86
+ if element =~ /\A<\/(\w+)/ then
87
+ # </tag>
88
+ tag = $1.downcase
89
+ if allowed.include?(tag) && stack.include?(tag) then
90
+ # If allowed and on the stack
91
+ # Then pop down the stack
92
+ top = stack.pop
93
+ out = "</#{top}>"
94
+ until top == tag do
95
+ top = stack.pop
96
+ out << "</#{top}>"
97
+ end
98
+ out
99
+ end
100
+ elsif element =~ /\A<(\w+)\s*\/>/
101
+ # <tag />
102
+ tag = $1.downcase
103
+ if allowed.include?(tag) then
104
+ "<#{tag} />"
105
+ end
106
+ elsif element =~ /\A<(\w+)/ then
107
+ # <tag ...>
108
+ tag = $1.downcase
109
+ if allowed.include?(tag) then
110
+ if ! soloTags.include?(tag) then
111
+ stack.push(tag)
112
+ end
113
+ if allowed[tag].length == 0 then
114
+ # no allowed attributes
115
+ "<#{tag}>"
116
+ else
117
+ # allowed attributes?
118
+ out = "<#{tag}"
119
+ while ( $' =~ /(\w+)=("[^"]+")/ )
120
+ attr = $1.downcase
121
+ valu = $2
122
+ if allowed[tag].include?(attr) then
123
+ out << " #{attr}=#{valu}"
124
+ end
125
+ end
126
+ out << ">"
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ # eat up unmatched leading >
133
+ while result.sub!(/\A([^<]*)>/m) { $1 } do end
134
+
135
+ # eat up unmatched trailing <
136
+ while result.sub!(/<([^>]*)\Z/m) { $1 } do end
137
+
138
+ # clean up the stack
139
+ if stack.length > 0 then
140
+ result << "</#{stack.reverse.join('></')}>"
141
+ end
142
+
143
+ result
144
+ end
145
+
146
+
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mail'
4
+
5
+ module Tzispa
6
+ module Helpers
7
+ module Mail
8
+
9
+ def send_smtp_mail(from:, to:, subject:, body:, config:, cc: nil, html: false)
10
+ begin
11
+ smtp_configuration config
12
+ mail = ::Mail.new
13
+ mail.from = from
14
+ if !to.empty?
15
+ to_addrs = to.split(';')
16
+ mail.to = to_addrs.pop
17
+ to_addrs.each { |email|
18
+ mail.to << email
19
+ }
20
+ if cc
21
+ cc_addrs = cc.split(';')
22
+ mail.cc = cc_addrs.pop
23
+ cc_addrs.each { |email|
24
+ mail.cc << email
25
+ }
26
+ end
27
+ mail.subject = subject
28
+ if html
29
+ mail.html_part do
30
+ content_type 'text/html; charset=UTF-8'
31
+ body = body
32
+ end
33
+ else
34
+ mail.body = body
35
+ end
36
+ mail.deliver
37
+ else
38
+ nil
39
+ end
40
+ rescue
41
+ nil
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def smtp_configuration(config)
48
+ if config.smtp_auth
49
+ ::Mail.defaults do
50
+ delivery_method :smtp, address: config.host, domain: config.domain,
51
+ port: config.port, authentication: config.authentication,
52
+ openssl_verify_mode: config.openssl_verify, enable_starttls_auto: config.starttls_auto,
53
+ user_name: config.user_name, password: config.password
54
+ end
55
+ else
56
+ ::Mail.defaults do
57
+ delivery_method :smtp, address: config.host, domain: config.domain,
58
+ port: config.port, openssl_verify_mode: config.openssl_verify,
59
+ enable_starttls_auto: config.starttls_auto
60
+ end
61
+ end
62
+ end
63
+
64
+
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack/mime'
4
+
5
+ module Tzispa
6
+ module Helpers
7
+ module Mime
8
+
9
+ def mime_type(type, value = nil)
10
+ return type if type.nil?
11
+ return type.to_s if type.to_s.include?('/')
12
+ type = ".#{type}" unless type.to_s[0] == ?.
13
+ return Rack::Mime.mime_type(type, nil) unless value
14
+ Rack::Mime::MIME_TYPES[type] = value
15
+ end
16
+
17
+ def mime_extension(type)
18
+ Rack::Mime::MIME_TYPES.invert[type]
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'html'
4
+
5
+ module Tzispa
6
+ module Helpers
7
+ module Pattern
8
+
9
+ include Tzispa::Helpers::Html
10
+
11
+ def pattern_select_hours(selected=nil)
12
+ selected &&= selected.to_i
13
+ Proc.new {
14
+ (0..23).map { |hour|
15
+ loop_item(
16
+ value: hour,
17
+ text: hour.to_s.rjust(2, '0'),
18
+ selected: html_selected( selected == hour )
19
+ )
20
+ }
21
+ }
22
+ end
23
+
24
+ def pattern_select_minutes(selected=nil)
25
+ selected &&= selected.to_i
26
+ Proc.new {
27
+ (0..59).map { |minute|
28
+ loop_item(
29
+ value: minute,
30
+ text: minute.to_s.rjust(2, '0'),
31
+ selected: html_selected( selected == minute )
32
+ )
33
+ }
34
+ }
35
+ end
36
+
37
+ def pattern_select_year(first, last, selected=nil, reverse=true)
38
+ selected &&= selected.to_i
39
+ Proc.new {
40
+ ryear = (first..last)
41
+ enum_year = first > last ? (ryear.first).downto(ryear.last) : (ryear.first).to(ryear.last)
42
+ enum_year.map { |year|
43
+ loop_item(
44
+ value: year,
45
+ text: year,
46
+ selected: html_selected( selected == year )
47
+ )
48
+ }
49
+ }
50
+ end
51
+
52
+
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tzispa
4
+ module Helpers
5
+ module Request
6
+
7
+ def request_data(fields)
8
+ Hash.new.tap { |data|
9
+ fields.each { |name|
10
+ macro_field = name.split('@:')
11
+ macro = macro_field.first.to_sym if macro_field.length == 2
12
+ field = macro_field.length == 2 ? macro_field.last : macro_field.first
13
+ field.split(':').tap { |fld|
14
+ src = fld.first
15
+ dest = fld.last
16
+ data[dest.to_sym] = macro ? send(macro, context.request[src]) : context.request[src]
17
+ }
18
+ }
19
+ }
20
+ end
21
+
22
+ def request_data_object(data_object:, fields:)
23
+ data_object.tap { |data|
24
+ fields.each { |name|
25
+ macro_field = name.split('@:')
26
+ macro = macro_field.first.to_sym if macro_field.length == 2
27
+ field = macro_field.length == 2 ? macro_field.last : macro_field.first
28
+ field.split(':').tap { |fld|
29
+ src = fld.first
30
+ dest = fld.last
31
+ data.send "#{dest}=".to_sym, macro ? send(macro, context.request[src]) : context.request[src]
32
+ }
33
+ }
34
+ }
35
+ end
36
+
37
+ def request_file_upload(request_file:, destination_path:, save_as: nil, keep_ext: true)
38
+ if request_file
39
+ fileext = File.extname(request_file[:filename]).downcase
40
+ filetype = request_file[:type]
41
+ save_ext = fileext if keep_ext
42
+ filename = (save_as ? "#{save_as}#{save_ext}" : request_file[:filename])
43
+ tempfile = request_file[:tempfile]
44
+ begin
45
+ dest_file = "#{destination_path}/#{filename}"
46
+ FileUtils.cp tempfile.path, dest_file
47
+ result = { name: filename, ext: fileext, path: dest_file, size: ::File.size(dest_file), type: filetype }
48
+ rescue => err
49
+ context.logger.fatal(err) if context
50
+ result = nil
51
+ ensure
52
+ tempfile.close
53
+ tempfile.unlink
54
+ end
55
+ else
56
+ result = nil
57
+ end
58
+ result
59
+ end
60
+
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require_relative 'mime'
5
+
6
+ module Tzispa
7
+ module Helpers
8
+ module Response
9
+
10
+ def self.included(base)
11
+ base.class_eval do
12
+ include Tzispa::Helpers::Mime
13
+ end
14
+ end
15
+
16
+ # Set or retrieve the response status code.
17
+ def status(value = nil)
18
+ response.status = value if value
19
+ response.status
20
+ end
21
+
22
+ # Set or retrieve the response body. When a block is given,
23
+ # evaluation is deferred until the body is read with #each.
24
+ def body(value = nil, &block)
25
+ if block_given?
26
+ def block.each; yield(call) end
27
+ response.body = block
28
+ elsif value
29
+ headers.delete 'Content-Length' unless request.head? || value.is_a?(Rack::File) || value.is_a?(Stream)
30
+ response.body = value
31
+ else
32
+ response.body
33
+ end
34
+ end
35
+
36
+ # Exit the current block, halts any further processing
37
+ # of the request, and returns the specified response.
38
+ def halt(*response)
39
+ response = response.first if response.length == 1
40
+ throw :halt, response
41
+ end
42
+
43
+ # Halt processing and redirect to the URI provided.
44
+ def redirect(uri, *args)
45
+ if env['HTTP_VERSION'] == 'HTTP/1.1' and 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"
53
+ response['Location'] = uri(uri.to_s, config.absolute_redirects?)
54
+ halt(*args)
55
+ end
56
+
57
+ # Generates the absolute URI for a given path in the app.
58
+ # Takes Rack routers and reverse proxies into account.
59
+ def uri(addr = nil, absolute = true)
60
+ return addr if addr =~ /\A[A-z][A-z0-9\+\.\-]*:/
61
+ uri = [host = String.new]
62
+ if absolute
63
+ host << "http#{'s' if request.secure?}://"
64
+ if request.forwarded? or request.port != (request.secure? ? 443 : 80)
65
+ host << request.host_with_port
66
+ else
67
+ host << request.host
68
+ end
69
+ end
70
+ uri << (addr ? addr : request.path_info).to_s
71
+ File.join uri
72
+ end
73
+
74
+ # Halt processing and return the error status provided.
75
+ def error(code, body = nil)
76
+ code, body = 500, code.to_str if code.respond_to? :to_str
77
+ response.body = body unless body.nil?
78
+ halt code
79
+ end
80
+
81
+ # Halt processing and return a 404 Not Found
82
+ def not_found(body = nil)
83
+ error 404, body
84
+ end
85
+
86
+ # Halt processing and return a 401 Unauthorized
87
+ def unauthorized(body = nil)
88
+ error 401, body
89
+ end
90
+
91
+ # Set multiple response headers with Hash.
92
+ def headers(hash = nil)
93
+ response.headers.merge! hash if hash
94
+ response.headers
95
+ end
96
+
97
+ # Set the Content-Type of the response body given a media type or file
98
+ # extension.
99
+ def content_type(type = nil, params = {})
100
+ return response['Content-Type'] unless type
101
+ default = params.delete :default
102
+ mime_type = mime_type(type) || default
103
+ fail "Unknown media type: %p" % type if mime_type.nil?
104
+ mime_type = mime_type.dup
105
+ unless params.include? :charset
106
+ params[:charset] = params.delete('charset') || config.default_encoding
107
+ end
108
+ params.delete :charset if mime_type.include? 'charset'
109
+ unless params.empty?
110
+ mime_type << (mime_type.include?(';') ? ', ' : ';')
111
+ mime_type << params.map do |key, val|
112
+ val = val.inspect if val =~ /[";,]/
113
+ "#{key}=#{val}"
114
+ end.join(', ')
115
+ end
116
+ response['Content-Type'] = mime_type
117
+ end
118
+
119
+ def attachment!(filename = nil, disposition = 'attachment')
120
+ content_disposition = disposition.to_s
121
+ content_disposition += "; filename=\"#{filename}\"; filename*=UTF-8''#{URI.escape(filename)}" if !filename.nil?
122
+ response['Content-Disposition'] = content_disposition
123
+ end
124
+
125
+ # Use the contents of the file at +path+ as the response body.
126
+ def send_file(path, opts = {})
127
+ begin
128
+ if opts[:type] or not response['Content-Type']
129
+ content_type opts[:type] || opts[:extension], :default => 'application/octet-stream'
130
+ end
131
+
132
+ disposition = opts[:disposition]
133
+ filename = opts[:filename]
134
+ disposition = 'attachment' if disposition.nil? and filename
135
+ filename = path if filename.nil?
136
+
137
+ attachment! filename, disposition
138
+ last_modified opts[:last_modified] if opts[:last_modified]
139
+
140
+ file = Rack::File.new nil
141
+ file.path = path
142
+ result = file.serving context.env
143
+ result[1].each { |k,v| response.headers[k] ||= v }
144
+ response.headers['Content-Length'] = result[1]['Content-Length']
145
+ #opts[:status] &&= Integer(opts[:status])
146
+ #halt opts[:status] || result[0], result[2]
147
+ response.status = result[0]
148
+ response.body = result[2]
149
+ rescue
150
+ not_found 'Fichero no encontrado'
151
+ end
152
+ end
153
+
154
+ # Sugar for redirect (example: redirect back)
155
+ def back
156
+ request.referer
157
+ end
158
+
159
+ # whether or not the status is set to 1xx
160
+ def informational?
161
+ response.status.between? 100, 199
162
+ end
163
+
164
+ # whether or not the status is set to 2xx
165
+ def success?
166
+ response.status.between? 200, 299
167
+ end
168
+
169
+ # whether or not the status is set to 3xx
170
+ def redirect?
171
+ response.status.between? 300, 399
172
+ end
173
+
174
+ # whether or not the status is set to 4xx
175
+ def client_error?
176
+ response.status.between? 400, 499
177
+ end
178
+
179
+ # whether or not the status is set to 5xx
180
+ def server_error?
181
+ response.status.between? 500, 599
182
+ end
183
+
184
+ # whether or not the status is set to 404
185
+ def not_found?
186
+ response.status == 404
187
+ end
188
+
189
+
190
+ class NotFound < NameError #:nodoc:
191
+ def http_status; 404 end
192
+ end
193
+
194
+
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+
5
+ module Tzispa
6
+ module Helpers
7
+ module Security
8
+
9
+
10
+ def secret(length)
11
+ alfanb = ['!', '$', '%', '&', '@', '#', '=', '_' '+', '-', '*', '/', '?', ':', ';', '.', ',',
12
+ ('a'..'z'), ('0'..'9'), ('A'..'Z')].map { |i| i.to_a }.flatten
13
+ (0...length-1).map { alfanb[rand(alfanb.length)] }.join
14
+ end
15
+
16
+ def uuid
17
+ sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
18
+ # 32 bits for "time_low"
19
+ rand(0..0xffff), rand(0..0xffff),
20
+
21
+ # 16 bits for "time_mid"
22
+ rand(0..0xffff),
23
+
24
+ # 16 bits for "time_hi_and_version",
25
+ #3 four most significant bits holds version number 4
26
+ rand(0..0x0fff) | 0x4000,
27
+
28
+ # 16 bits, 8 bits for "clk_seq_hi_res",
29
+ # 8 bits for "clk_seq_low",
30
+ # two most significant bits holds zero and one for variant DCE1.1
31
+ rand(0..0x3fff) | 0x8000,
32
+
33
+ # 48 bits for "node"
34
+ rand(0..0xffff), rand(0..0xffff), rand(0..0xffff)
35
+ )
36
+ end
37
+
38
+ def sign_array(astr, salt=nil)
39
+ sign, i = String.new, 0
40
+ astr.each { |s|
41
+ i = i + 1
42
+ sign << "#{"_"*i}#{s}"
43
+ }
44
+ sign << "**#{salt}"
45
+ Digest::SHA1.hexdigest sign
46
+ end
47
+
48
+ def hash_password(password, salt)
49
+ Digest::MD5::hexdigest "#{password}::#{salt}"
50
+ end
51
+
52
+ def hash_password?(hashed, pwd, salt)
53
+ hashed == hash_password(pwd, salt)
54
+ end
55
+
56
+
57
+ class Identity
58
+
59
+ attr_reader :id, :token
60
+
61
+ def initialize(id, secret)
62
+ @id = id
63
+ @token = generate_token id, secret
64
+ end
65
+
66
+ def valid?(secret)
67
+ @token == Identity.generate_token(@id, secret)
68
+ end
69
+
70
+ private
71
+
72
+ def self.generate_token(value, salt)
73
+ Digest::SHA1.hexdigest "___#{value}_#{salt}__token__"
74
+ end
75
+
76
+ end
77
+
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+ require 'bigdecimal'
5
+ require 'i18n'
6
+ require "unicode_utils"
7
+
8
+ module Tzispa
9
+ module Helpers
10
+ module Text
11
+
12
+ def remove_words(sentence, removable)
13
+ sentence.split.delete_if{|x| removable.include?(UnicodeUtils.downcase x)}.join(' ')
14
+ end
15
+
16
+ def remove_phrases(text, removable)
17
+ removable.each { |phrase|
18
+ text.slice! phrase
19
+ }
20
+ text
21
+ end
22
+
23
+ def remove_parenthesized_text(text)
24
+ text.gsub(/\([^\)]*\)/, '')
25
+ end
26
+
27
+ def synonymize(sentence, synonyms)
28
+ sentence.gsub(/[[:alnum:]]+/) {|word|
29
+ dwword = UnicodeUtils.downcase word
30
+ synonyms.has_key?(dwword) ? synonyms[dwword] : word
31
+ }
32
+ end
33
+
34
+ def strip_to_nil(str, transform = nil)
35
+ sstr = str.strip if str and not str.strip.empty?
36
+ case transform
37
+ when :upcase then
38
+ UnicodeUtils.upcase(sstr)
39
+ when :downcase then
40
+ UnicodeUtils.downcase(sstr)
41
+ when :titlecase then
42
+ UnicodeUtils.titlecase(sstr)
43
+ else sstr
44
+ end
45
+ end
46
+
47
+ def split_to_array(str, separator=';')
48
+ str.split(separator) if str
49
+ end
50
+
51
+ def join_to_nil(ary, separator)
52
+ ary.join(separator) if ary and not ary.empty?
53
+ end
54
+
55
+ def str_to_bool(str, strue=nil)
56
+ strue ? (strue == str) : (str == 'yes' || str == 'true')
57
+ end
58
+
59
+ def str_to_date(str, format=nil)
60
+ begin
61
+ Date.strptime(str, format || I18n.t('date.formats.default')) if str
62
+ rescue
63
+ nil
64
+ end
65
+ end
66
+
67
+ def str_to_datetime(str, format=nil)
68
+ begin
69
+ result = DateTime.strptime(str, format || I18n.t('time.formats.default'))
70
+ rescue
71
+ result = nil
72
+ end
73
+ result
74
+ end
75
+
76
+ def amount(number, options = {})
77
+ if number.nil? && options[:nil_as_dash] != false
78
+ '–'
79
+ elsif number.zero? && options[:zero_as_dash]
80
+ '–'
81
+ else
82
+ precision = options[:precision]
83
+ if precision
84
+ options[:minimum_precision] = precision
85
+ options[:maximum_precision] = precision
86
+ end
87
+
88
+ number = number.round if options[:round]
89
+ separator = options.fetch(:separator, I18n.t('number.currency.format.separator'))
90
+ delimiter = options.fetch(:delimiter, I18n.t('number.currency.format.delimiter')).to_s
91
+ minimum_precision = options[:minimum_precision] || 0
92
+ str = number.is_a?(BigDecimal) ? number.to_s('F').sub(/\.0+\z/, "") : number.to_s.sub(/\.0+\z/, "")
93
+ str =~ /\A(\-?)(\d+)(?:\.(\d+))?\z/ or raise "Could not parse number: #{number}"
94
+ sign = $1
95
+ integer = $2
96
+ fraction = ($3 || '')
97
+
98
+ if options[:maximum_precision]
99
+ fraction = fraction[0, options[:maximum_precision]] if options[:maximum_precision]
100
+ end
101
+
102
+ if minimum_precision > 0
103
+ if fraction.length > 0 || minimum_precision > 0
104
+ fraction = "#{fraction}#{'0' * [0, minimum_precision - fraction.length].max}"
105
+ end
106
+ end
107
+
108
+ # the following two lines appear to be the most performant way to add a delimiter to every thousands place in the number
109
+ integer_size = integer.size
110
+ (1..((integer_size-1) / 3)).each {|x| integer[integer_size-x*3,0] = delimiter}
111
+ str = integer.chomp(delimiter)
112
+
113
+ # add fraction
114
+ str << "#{separator}#{fraction}" if fraction.length > 0
115
+
116
+ # restore sign
117
+ str = "#{sign}#{str}"
118
+ # add unit if given
119
+ if options[:unit]
120
+ unless options[:unit_separator] == false
121
+ str << options.fetch(:unit_separator, ' ')
122
+ end
123
+ str << options[:unit]
124
+ end
125
+ str
126
+ end
127
+ end
128
+
129
+ def money_amount(number, options = {})
130
+ amount(number, options.merge(:unit => I18n.t('number.currency.format.unit'), :nil_as_dash => true, :precision => I18n.t('number.currency.format.precision')))
131
+ end
132
+
133
+ def price_amount(number, options = {})
134
+ amount(number, options.merge(:nil_as_dash => true, :precision => I18n.t('number.currency.format.precision')))
135
+ end
136
+
137
+
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tzispa
4
+ module Helpers
5
+
6
+ VERSION = '0.1.3'
7
+ NAME = 'Tzispa Helpers'
8
+ GEM_NAME = 'tzispa_helpers'
9
+
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ module Tzispa
2
+ module Helpers
3
+
4
+ require 'tzispa/helpers/version'
5
+ require 'tzispa/helpers/crawler'
6
+ require 'tzispa/helpers/html'
7
+ require 'tzispa/helpers/mail'
8
+ require 'tzispa/helpers/mime'
9
+ require 'tzispa/helpers/pattern'
10
+ require 'tzispa/helpers/request'
11
+ require 'tzispa/helpers/response'
12
+ require 'tzispa/helpers/security'
13
+ require 'tzispa/helpers/text'
14
+
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ module Tzispa
2
+ module Helpers
3
+
4
+ require 'tzispa/helpers'
5
+
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tzispa_helpers
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Juan Antonio Piñero
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mail
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: i18n
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.7'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: unicode_utils
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: htmlentities
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: reverse_markdown
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: redcarpet
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.3'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: nokogiri
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.6'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.6'
111
+ description: Module Helpers for Tzispa framework
112
+ email:
113
+ - japinero@area-integral.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - CHANGELOG.md
119
+ - README.md
120
+ - lib/tzispa/helpers.rb
121
+ - lib/tzispa/helpers/crawler.rb
122
+ - lib/tzispa/helpers/html.rb
123
+ - lib/tzispa/helpers/mail.rb
124
+ - lib/tzispa/helpers/mime.rb
125
+ - lib/tzispa/helpers/pattern.rb
126
+ - lib/tzispa/helpers/request.rb
127
+ - lib/tzispa/helpers/response.rb
128
+ - lib/tzispa/helpers/security.rb
129
+ - lib/tzispa/helpers/text.rb
130
+ - lib/tzispa/helpers/version.rb
131
+ - lib/tzispa_helpers.rb
132
+ homepage: https://www.area-integral.com
133
+ licenses:
134
+ - MIT
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '2.3'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 2.5.1
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: Helpers for Tzispa
156
+ test_files: []