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.
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ .idea
3
+ *.gem
4
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in calc.gemspec
4
+ gemspec
@@ -0,0 +1,14 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ calc (1.0.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+
10
+ PLATFORMS
11
+ ruby
12
+
13
+ DEPENDENCIES
14
+ calc!
@@ -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.
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module Calc
2
+ VERSION = "1.0.0"
3
+ end
@@ -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
+