tool_pouch 0.0.34

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ module ToolPouch::Mathema
2
+ def self.tax_for_amount(amount, region, options={})
3
+ options.reverse_merge!(:time => Time.now)
4
+
5
+ case region
6
+ when 'quebec' then get_quebec_taxes(amount, options)
7
+ else []
8
+ end
9
+ end
10
+
11
+ def self.get_quebec_taxes(amount, options={})
12
+ options.reverse_merge!(:time => Time.now)
13
+
14
+ gst = { :id => 'gst', :nature => 'tax', :rate => 0.05 }
15
+ qst = { :id => 'qst', :nature => 'tax' }
16
+
17
+ qst[:rate] = case
18
+ when options[:time] < Time.parse('2012-01-01') then 0.085
19
+ else 0.095
20
+ end
21
+
22
+ gst[:amount] = (amount * gst[:rate]).round
23
+ qst[:amount] = ((amount + gst[:amount]) * qst[:rate]).round
24
+
25
+ return [gst, qst]
26
+ end
27
+ end
@@ -0,0 +1,279 @@
1
+ require 'addressable/uri'
2
+
3
+ module ToolPouch::Trail
4
+ def self.build_querystring(form_data)
5
+ query_string = ''
6
+ if form_data
7
+ params = []
8
+ if not form_data.empty?
9
+ form_data.each do |d|
10
+ if d[1].is_a?(Hash)
11
+ d[1].each do |key, value|
12
+ params << "#{d[0]}[#{key}]=#{CGI.escape(CGI.unescape(value.to_s))}"
13
+ end
14
+ else
15
+ params << "#{d[0]}=#{CGI.escape(CGI.unescape(d[1].to_s))}"
16
+ end
17
+ end
18
+ end
19
+ query_string = params.sort.join('&')
20
+ end
21
+ return query_string
22
+ end
23
+
24
+ def self.directories(path)
25
+ directory = ''
26
+ if path and path.class == String
27
+ last_slash_index = path.rindex('/')
28
+
29
+ if last_slash_index.to_i > 0
30
+ directory = path[0, last_slash_index]
31
+ end
32
+ end
33
+
34
+ return directory
35
+ end
36
+
37
+ def self.extension(path)
38
+ file_extension = ''
39
+ if path
40
+ file_extension_with_dot = File.extname(path)
41
+ if not file_extension_with_dot.empty?
42
+ file_extension = file_extension_with_dot[1, file_extension_with_dot.length]
43
+ end
44
+ end
45
+ return file_extension
46
+ end
47
+
48
+ def self.filename_without_extension(path, options={})
49
+ options.reverse_merge!(:full_path => true)
50
+
51
+ filename = options[:full_path] ? path : filename_without_path(path)
52
+
53
+ return (filename and filename.rindex('.')) ? filename[0, filename.rindex('.')] : filename
54
+ end
55
+
56
+ def self.filename_without_path(path)
57
+ filename_without_path = path
58
+ if path
59
+ #Handle properly path without filename
60
+ if trailing_slash?(path)
61
+ filename_without_path = ''
62
+ else
63
+ filename_without_path = File.basename(path)
64
+ end
65
+ end
66
+ return filename_without_path
67
+ end
68
+
69
+ def self.get_domain(url)
70
+ domain = nil
71
+ if url
72
+ # add protocol so it becomes a valid URI
73
+ url = ('http://' + url) unless url =~ /^https?:\/\//
74
+
75
+ # remove %'s, which we don't need and could cause an URL to become invalid
76
+ url.gsub!('%', '')
77
+
78
+ begin
79
+ # get the host part, and remove the www. if present
80
+ domain = Addressable::URI.parse(url).host.gsub(/^www\./i, '')
81
+ rescue
82
+ ""
83
+ end
84
+ end
85
+ return domain
86
+ end
87
+
88
+ def self.get_all_files_with_extension(path, extensions=[])
89
+ extensions = [extensions] unless extensions.is_a? Array
90
+ extensions.collect!{|x| ".#{x}"}
91
+
92
+ files = []
93
+ Find.find(path) { |f| files << f if File.file?(f) and extensions.include? File.extname(f) }
94
+
95
+ return files
96
+ end
97
+
98
+ def self.get_file(root, filenames)
99
+ files = get_files(root, filenames)
100
+
101
+ return files.empty? ? nil : files.first
102
+ end
103
+
104
+ def self.get_files(root, filenames, options={})
105
+ options.reverse_merge!(:perfect_match => true)
106
+
107
+ filenames = [filenames] unless filenames.is_a? Array
108
+ root = slice_trailing_slash(root)
109
+ files = []
110
+
111
+ Find.find(root) do |f|
112
+ if options[:perfect_match]
113
+ files << f.gsub(root + '/', '') if File.file?(f) and filenames.include?(filename_without_path(f))
114
+ else
115
+ found = false
116
+ filename_only = filename_without_path(f)
117
+ filenames.each{ |m| found = true if filename_only.match(/#{m}/) }
118
+ files << f.gsub(root + '/', '') if File.file?(f) and found
119
+ end
120
+ end
121
+
122
+ return files
123
+ end
124
+
125
+ def self.get_first_file_with_extension(path, extensions=[])
126
+ return get_all_files_with_extension(path, extensions).first
127
+ end
128
+
129
+ def self.get_first_match(path, value)
130
+ File.open(path) do |io|
131
+ io.each do |line|
132
+ line.chomp!
133
+ return line if line.include? value
134
+ end
135
+ end
136
+
137
+ return nil
138
+ end
139
+
140
+ def self.get_querystring(url)
141
+ raw = URI.split(url)[7]
142
+
143
+ qs = {}
144
+
145
+ if raw
146
+ raw.split('&').each do |full_param|
147
+ key, value = full_param.split('=')
148
+ qs[key] = value
149
+ end
150
+ end
151
+
152
+ return qs
153
+ end
154
+
155
+ def self.get_section(url, options={})
156
+ section = nil
157
+ if url
158
+ if options[:base_path]
159
+ section = url.gsub(options[:base_path] + '/', '').split('/')[0]
160
+ else
161
+ section = url.split('/')[-1, 1].to_s
162
+ end
163
+
164
+ # Remove format if it was specified
165
+ section = File.basename(section, '.*')
166
+ end
167
+
168
+ return section
169
+ end
170
+
171
+ def self.is_file_with_extension?(path)
172
+ file_with_extension = false
173
+ if path
174
+ extension = File.extname(path)
175
+ if extension and not extension.empty?
176
+ file_with_extension = true
177
+ end
178
+ end
179
+ return file_with_extension
180
+ end
181
+
182
+ def self.is_url?(path)
183
+ return (path.to_s.include?('http://') or path.to_s.include?('https://')) ? true : false
184
+ end
185
+
186
+ def self.last_directory(path)
187
+ path += 'dummystring' if trailing_slash?(path)
188
+
189
+ return path.split('/')[-2, 1]
190
+ end
191
+
192
+ def self.open_and_merge(directories, options={})
193
+ options.reverse_merge!(:extensions => '')
194
+
195
+ directories = [directories] if not directories.is_a? Array
196
+
197
+ case options[:extensions]
198
+ when 'yml' then content = HashTree.new
199
+ else content = []
200
+ end
201
+
202
+ directories.each do |directory|
203
+ Find.find(directory) do |p|
204
+ next unless File.file?(p)
205
+
206
+ case options[:extensions]
207
+ when 'yml' then content.merge(yml_content(p))
208
+ when 'xml' then content << File.open(p, "r").readlines.join
209
+ end
210
+ end
211
+ end
212
+
213
+ case options[:extensions]
214
+ when 'yml' then content.get
215
+ else return content.join("\n")
216
+ end
217
+ end
218
+
219
+ def self.order_querystring_alpha(url)
220
+ ordered_url = url
221
+ if url and not url.strip.empty?
222
+ qs = URI.split(url)[7]
223
+
224
+ if qs
225
+ ordered_url = url.split('?')[0] + '?'
226
+ parameters = qs.split('&')
227
+ escaped_parameters = []
228
+ # Escape each parameter to ensure coherence with build_query_string
229
+ for parameter in parameters
230
+ name_value = parameter.split('=')
231
+ if name_value.size == 2
232
+ escaped_value = CGI.escape(CGI.unescape(name_value[1]))
233
+ escaped_parameters << "#{name_value[0]}=#{escaped_value}"
234
+ else
235
+ escaped_parameters << "#{name_value[0]}"
236
+ end
237
+ end
238
+ ordered_url << escaped_parameters.sort.join('&')
239
+ return ordered_url
240
+ end
241
+ end
242
+ return url
243
+ end
244
+
245
+ def self.partial_exists?(partial_short_path)
246
+ short_path = partial_short_path.split('/')
247
+ short_path[short_path.length-1] = '_' + short_path.last
248
+ return File.exists?(RAILS_ROOT + '/app/views' + short_path.join('/') + '.html.erb')
249
+ end
250
+
251
+ def self.refresh_file_content(path, content)
252
+ FileUtils.mkdir_p directories(path)
253
+ FileUtils.rm(path) if File.exists?(path)
254
+ File.open(path, 'w') {|f| f.write(content) }
255
+ end
256
+
257
+ def self.slice_trailing_slash(path)
258
+ return (trailing_slash?(path)) ? path.chop : path
259
+ end
260
+
261
+ def self.strip_scheme(uri)
262
+ uri.sub(/^#{Addressable::URI.parse(URI.encode(uri)).scheme}:\/\//,"")
263
+ end
264
+
265
+ def self.trailing_slash?(path)
266
+ trailing_slash = false
267
+ if path and path.length > 0
268
+ if path.slice(-1,1) == '/'
269
+ trailing_slash = true
270
+ end
271
+ end
272
+
273
+ return trailing_slash
274
+ end
275
+
276
+ def self.yml_content(file)
277
+ return YAML.load_file(file)
278
+ end
279
+ end
@@ -0,0 +1,98 @@
1
+ require "addressable/uri"
2
+
3
+ #*************************************************************************************
4
+ # TOCOMMENT
5
+ #*************************************************************************************
6
+ module ToolPouch::Transistor
7
+ def self.get(raw_url, options={})
8
+ raw_url += '?' + ToolPouch::Trail.build_querystring(options.delete(:params)) if options[:params]
9
+
10
+ return send_request(:get, raw_url, options)
11
+ end
12
+
13
+ def self.get_head(url)
14
+ begin
15
+ uri = parse_uri(url)
16
+ res = Net::HTTP.start(uri.host, uri.port)
17
+ rescue
18
+ return false
19
+ end
20
+
21
+ return (res and res.head(url) ? res.head(url) : false)
22
+ end
23
+
24
+ def self.parse_uri(uri)
25
+ parsed_uri = Addressable::URI.parse(uri)
26
+ parsed_uri.port = 443 if parsed_uri.scheme == 'https'
27
+
28
+ return parsed_uri
29
+ end
30
+
31
+ def self.post(raw_url, options={})
32
+ send_request(:post, raw_url, options)
33
+ end
34
+
35
+ def self.send_request(method, raw_url, options={})
36
+ options.reverse_merge!(body: nil, content_type: nil, login: nil, params: {}, password: nil, timeout: nil)
37
+
38
+ url = parse_uri raw_url
39
+
40
+ request = "Net::HTTP::#{method.to_s.camelize}".constantize.new(url.request_uri)
41
+ request.basic_auth(options[:login], options[:password]) if options[:login]
42
+ request.body = options[:body] if options[:body]
43
+ request.content_type = options[:content_type] if options[:content_type]
44
+ request.set_form_data(options[:params]) if not options[:params].empty?
45
+
46
+ return start_net_http(url, request, timeout: options[:timeout])
47
+ end
48
+
49
+ def self.start_net_http(url, request, options={})
50
+ http = Net::HTTP.new(url.host, url.port)
51
+
52
+ if http
53
+ http.use_ssl = (url.scheme == 'https')
54
+ http.read_timeout = options[:timeout] if options[:timeout]
55
+
56
+ return http.start { |r| r.request(request) }
57
+ end
58
+
59
+ return nil
60
+ end
61
+
62
+ #*************************************************************************************
63
+ # Digest communication module
64
+ #*************************************************************************************
65
+ module Digest
66
+ def self.delete(url, password, form_data={})
67
+ form_data['_method'] = 'delete'
68
+
69
+ return post_request_digest(url, password, form_data)
70
+ end
71
+
72
+ def self.get(url, password)
73
+ url_digest = ToolPouch::Locksmith.build_digest_request(url, password)
74
+
75
+ if url_digest
76
+ uri = parse_uri url_digest
77
+
78
+ return Net::HTTP.get_response(uri) if uri
79
+ end
80
+
81
+ return nil
82
+ end
83
+
84
+ def self.post(url, password, form_data={})
85
+ url << ('?' + ToolPouch::Trail.build_querystring(form_data)) if not form_data.empty?
86
+
87
+ url_digest = ToolPouch::Locksmith.build_digest_request(url, password)
88
+
89
+ return Net::HTTP.post_form(parse_uri(url_digest), ToolPouch::Trail.get_querystring(url_digest))
90
+ end
91
+
92
+ def self.put(url, password, form_data={})
93
+ form_data['_method'] = 'put'
94
+
95
+ return post(url, password, form_data)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,3 @@
1
+ module ToolPouch
2
+ VERSION = "0.0.34"
3
+ end
@@ -0,0 +1,3 @@
1
+ require 'tool_pouch'
2
+
3
+ Time.zone = 'Eastern Time (US & Canada)'
@@ -0,0 +1,12 @@
1
+ require "spec_helper"
2
+
3
+ describe ToolPouch::Krono do
4
+ describe '#is_iso8601?' do
5
+ it "recognizes valid date" do
6
+ ToolPouch::Krono.is_iso8601?('2000-01-01T00:00:00-05:00').should be_true
7
+ ToolPouch::Krono.is_iso8601?('1900-01-01T00:00:00-05:00').should be_true
8
+ ToolPouch::Krono.is_iso8601?('1800-01-01T00:00:00-05:00').should be_true
9
+ ToolPouch::Krono.is_iso8601?('1700-01-01T00:00:00-05:00').should be_true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,105 @@
1
+ require "spec_helper"
2
+ require 'addressable/uri'
3
+
4
+ describe ToolPouch::Locksmith do
5
+ let (:password) {'ThiZizAS3cr3T'}
6
+
7
+ describe 'digesting an URL' do
8
+ it "works without an URL authority" do
9
+ url = "/home"
10
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password)
11
+
12
+ ToolPouch::Locksmith.check_digest_request(digested_url, password).should be_true
13
+ end
14
+
15
+ it "works without an URL query" do
16
+ url = "http://example.org"
17
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password)
18
+
19
+ ToolPouch::Locksmith.check_digest_request(digested_url, password).should be_true
20
+ end
21
+
22
+ it "works regardless of the scheme use (http vs https)" do
23
+ url = "https://example.org"
24
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password)
25
+ digested_url.gsub! /https:\/\//, 'http://'
26
+
27
+ ToolPouch::Locksmith.check_digest_request(digested_url, password).should be_true
28
+ end
29
+
30
+ it "allows specifying a lifespan" do
31
+ url = "http://example.org"
32
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password, 30.seconds)
33
+
34
+ ToolPouch::Locksmith.check_digest_request(digested_url, password).should be_true
35
+ end
36
+
37
+ it "works with an URL query" do
38
+ url = "http://example.org?key=value"
39
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password)
40
+
41
+ ToolPouch::Locksmith.check_digest_request(digested_url, password).should be_true
42
+ end
43
+
44
+ it "orders the query parameters" do
45
+ url = "http://example.org?b=1&c=1&a=1"
46
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password)
47
+
48
+ digested_url.should match /http:\/\/example.org\?a=1&b=1&c=1/
49
+ end
50
+
51
+ it "works regardless of the orders of URL query parameters" do
52
+ url = "http://example.org?b=1&c=1&a=1"
53
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password)
54
+ digested_url_with_different_orders = digested_url.gsub /a=1&b=1&c=1/, 'c=1&a=1&b=1'
55
+
56
+ ToolPouch::Locksmith.check_digest_request(digested_url_with_different_orders, password).should be_true
57
+ end
58
+
59
+ it "works regardless of using percent encoded characters or real characters in the query" do
60
+ url = "http://example.org?key=%C3%97"
61
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password)
62
+ unescaped_digested_url = digested_url.gsub /%C3%97/, '×'
63
+ ToolPouch::Locksmith.check_digest_request(unescaped_digested_url, password).should be_true
64
+
65
+ url = "http://example.org?key=×"
66
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password)
67
+ escaped_digested_url = digested_url.gsub /×/, '%C3%97'
68
+ ToolPouch::Locksmith.check_digest_request(escaped_digested_url, password).should be_true
69
+ end
70
+
71
+ it "does not allow token hacking" do
72
+ url = "http://example.org?key=value"
73
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password)
74
+ hacked_url = digested_url.gsub /token=/, 'token=X'
75
+
76
+ ToolPouch::Locksmith.check_digest_request(hacked_url, password).should be_false
77
+ end
78
+
79
+ it "does not allow an expired URL" do
80
+ url = "http://example.org"
81
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password, 2.seconds)
82
+ sleep 3
83
+
84
+ ToolPouch::Locksmith.check_digest_request(digested_url, password).should be_false
85
+ end
86
+
87
+ it "works regardless of the port used" do
88
+ url = "https://example.org:443"
89
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password)
90
+ digested_url.gsub! /:443/, ''
91
+ ToolPouch::Locksmith.check_digest_request(digested_url, password).should be_true
92
+
93
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password)
94
+ digested_url.gsub! /:443/, ':80'
95
+ ToolPouch::Locksmith.check_digest_request(digested_url, password).should be_true
96
+ end
97
+
98
+ it "keeps the port in the generated URL" do
99
+ url = "https://example.org:443"
100
+ digested_url = ToolPouch::Locksmith.build_digest_request(url, password)
101
+ digested_url.should match /:443/
102
+ end
103
+ end
104
+
105
+ end