calc 1.0.0
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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +14 -0
- data/README.md +49 -0
- data/Rakefile +2 -0
- data/calc.gemspec +21 -0
- data/lib/calc.rb +35 -0
- data/lib/calc/version.rb +3 -0
- data/test/calc.rb +47 -0
- metadata +73 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Calc
|
2
|
+
|
3
|
+
Calc is safe, simple, pure Ruby mathematical expressions evaluator (calculator) library.
|
4
|
+
|
5
|
+
Although based on Ruby 'eval', it takes special care to sanitize the expression.
|
6
|
+
|
7
|
+
Calc supports all basic mathematical operations +, -, \*, / and the power function (through ** operator).
|
8
|
+
Calc also supports parenthesis and nesting.
|
9
|
+
Calc does NOT support advanced mathematical functions like trigonometry, logarithm, etc.
|
10
|
+
|
11
|
+
Calc plays well with Rails ActiveModel::Validations.
|
12
|
+
If the supplied expression is invalid (nil, blank, or syntax error),
|
13
|
+
it returns the expression itself verbatim,
|
14
|
+
thus allowing to handle errors via Rails validations.
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
require 'calc'
|
19
|
+
|
20
|
+
Calc.evaluate( "2 + 2" ) # => 4
|
21
|
+
|
22
|
+
Calc.evaluate( "2 * (1 + 9)" ) # => 20
|
23
|
+
|
24
|
+
Calc.evaluate( "2 ** (1.0 / 2)" ) # => 1.4142135623730951 (the square of two)
|
25
|
+
|
26
|
+
Calc.evaluate( "( ( 2 - 3 ) / 13 * ( 50 + 325.843 ) ) ** 3" ) # => -53090815.704202116
|
27
|
+
|
28
|
+
## Installation
|
29
|
+
|
30
|
+
gem install calc
|
31
|
+
|
32
|
+
## Using Bundler?
|
33
|
+
|
34
|
+
Add the following to your Gemfile:
|
35
|
+
|
36
|
+
gem 'calc'
|
37
|
+
|
38
|
+
Then run as usual:
|
39
|
+
|
40
|
+
bundle
|
41
|
+
|
42
|
+
## Calc is safe
|
43
|
+
|
44
|
+
Calc defines a white list of characters allowed in the expression to prevent code injection attacks.
|
45
|
+
All letters are outlawed as well as majority of other characters. Calc comes with tests.
|
46
|
+
|
47
|
+
## License
|
48
|
+
|
49
|
+
Copyright (C) 2010 Piotr 'Qertoip' Włodarek. Distributed under the MIT License.
|
data/Rakefile
ADDED
data/calc.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "calc/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "calc"
|
7
|
+
s.version = Calc::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Piotr 'Qertoip' Włodarek"]
|
10
|
+
s.email = ["qertoip@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/qertoip/calc"
|
12
|
+
s.summary = %q{Calculator (mathematical expressions evaluator) library for Ruby}
|
13
|
+
s.description = %q{Calc is safe, simple, pure-ruby mathematical expressions evaluator (calculator) library. Although based on Ruby 'eval', it takes special care to sanitize the expression.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "calc"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
data/lib/calc.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Calc
|
2
|
+
|
3
|
+
def self.evaluate( unsafe_expression )
|
4
|
+
return nil if unsafe_expression.nil?
|
5
|
+
|
6
|
+
safe_expression = sanitize( unsafe_expression )
|
7
|
+
|
8
|
+
return unsafe_expression if blank?( safe_expression )
|
9
|
+
|
10
|
+
begin
|
11
|
+
return eval( safe_expression )
|
12
|
+
rescue SyntaxError
|
13
|
+
# return expression verbatim so ActiveModel::Validations could take care of this
|
14
|
+
return unsafe_expression
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.evaluate_to_int( unsafe_expression )
|
19
|
+
return nil if unsafe_expression.nil?
|
20
|
+
return unsafe_expression if unsafe_expression.blank?
|
21
|
+
return evaluate( unsafe_expression ).to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def self.sanitize( unsafe_expression )
|
27
|
+
allowed_characters = Regexp.escape( '+-*/.()' )
|
28
|
+
return unsafe_expression.gsub( /[^\d#{allowed_characters}]/, '' )
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.blank?( s )
|
32
|
+
s =~ /^\s*$/
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/calc/version.rb
ADDED
data/test/calc.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.expand_path( "../../lib/calc", __FILE__ )
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class CalcTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
# .evaluate()
|
7
|
+
|
8
|
+
def test_evaluate_returns_correct_value_when_given_valid_expression
|
9
|
+
assert_equal( 2, Calc.evaluate( "1+1" ) )
|
10
|
+
assert_equal( 6, Calc.evaluate( " 3 * 2 " ) )
|
11
|
+
assert_equal( 10, Calc.evaluate( "5 * ( 1 + 1 )" ) )
|
12
|
+
assert_equal( 25, Calc.evaluate( "5 ** ( 1 + 1 )" ) )
|
13
|
+
assert_equal( 0, Calc.evaluate( "5 ** ( 1 + 1 ) / 5 - 5" ) )
|
14
|
+
assert_in_delta( 0.5, Calc.evaluate( "1.0/2" ), 0.0000001 )
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_evaluate_returns_nil_when_given_nil
|
18
|
+
assert_nil( Calc.evaluate( nil ) )
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_evaluate_returns_expression_verbatim_when_given_blank_expression
|
22
|
+
blank_expression = " \r \n "
|
23
|
+
assert_equal( blank_expression, Calc.evaluate( blank_expression ) )
|
24
|
+
assert_equal( "", Calc.evaluate( "" ) )
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_evaluate_returns_expression_verbatim_when_given_invalid_expression
|
28
|
+
invalid_expression_1 = "2//3"
|
29
|
+
assert_equal( invalid_expression_1, Calc.evaluate( invalid_expression_1 ) )
|
30
|
+
invalid_expression_2 = "2 * (5 + 4"
|
31
|
+
assert_equal( invalid_expression_2, Calc.evaluate( invalid_expression_2 ) )
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_evaluate_is_code_injection_proof
|
35
|
+
payload_1 = "raise 'evil'"
|
36
|
+
assert_nothing_raised do
|
37
|
+
Calc.evaluate( payload_1 )
|
38
|
+
end
|
39
|
+
|
40
|
+
payload_2 = "binding"
|
41
|
+
assert_equal( "binding", Calc.evaluate( payload_2 ) ) # returned verbatim - not evaled
|
42
|
+
|
43
|
+
payload_3 = "__FILE__"
|
44
|
+
assert_equal( "__FILE__", Calc.evaluate( payload_3 ) )
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: calc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- "Piotr 'Qertoip' W\xC5\x82odarek"
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-12-26 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Calc is safe, simple, pure-ruby mathematical expressions evaluator (calculator) library. Although based on Ruby 'eval', it takes special care to sanitize the expression.
|
22
|
+
email:
|
23
|
+
- qertoip@gmail.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- .gitignore
|
32
|
+
- Gemfile
|
33
|
+
- Gemfile.lock
|
34
|
+
- README.md
|
35
|
+
- Rakefile
|
36
|
+
- calc.gemspec
|
37
|
+
- lib/calc.rb
|
38
|
+
- lib/calc/version.rb
|
39
|
+
- test/calc.rb
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: http://github.com/qertoip/calc
|
42
|
+
licenses: []
|
43
|
+
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
requirements: []
|
66
|
+
|
67
|
+
rubyforge_project: calc
|
68
|
+
rubygems_version: 1.3.7
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: Calculator (mathematical expressions evaluator) library for Ruby
|
72
|
+
test_files: []
|
73
|
+
|