tzispa_helpers 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []