From cee9fb6c958a1b9d52c1fe28f3f6d6d108ab96b8 Mon Sep 17 00:00:00 2001 From: Kaspar Schiess Date: Thu, 30 Dec 2010 13:12:28 +0100 Subject: [PATCH 1/5] + A gemfile for quickstarting an interested developer. --- Gemfile | 10 ++++++++++ Gemfile.lock | 29 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 Gemfile create mode 100644 Gemfile.lock diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..f10ce04 --- /dev/null +++ b/Gemfile @@ -0,0 +1,10 @@ +source "http://rubygems.org" + +gem 'hoe' +gem 'hoe-git' + +group :development do + gem 'metaid' + gem 'rspec' + gem 'flexmock' +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..0d8c43b --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,29 @@ +GEM + remote: http://rubygems.org/ + specs: + diff-lcs (1.1.2) + flexmock (0.8.11) + hoe (2.8.0) + rake (>= 0.8.7) + hoe-git (1.3.0) + hoe (>= 2.2.0) + metaid (1.0) + rake (0.8.7) + rspec (2.3.0) + rspec-core (~> 2.3.0) + rspec-expectations (~> 2.3.0) + rspec-mocks (~> 2.3.0) + rspec-core (2.3.1) + rspec-expectations (2.3.0) + diff-lcs (~> 1.1.2) + rspec-mocks (2.3.0) + +PLATFORMS + ruby + +DEPENDENCIES + flexmock + hoe + hoe-git + metaid + rspec From a696aa89a0410c538fc98f6b8db7336638127015 Mon Sep 17 00:00:00 2001 From: Jamstah Date: Tue, 21 Dec 2010 17:56:32 +0000 Subject: [PATCH 2/5] Add a method to escape filter strings, and some convenience method for creating some common filter patterns, that are automatically escaped. --- lib/net/ldap/filter.rb | 42 ++++++++++++++++++++++++++++++++++++++++++ test/test_filter.rb | 7 +++++++ 2 files changed, 49 insertions(+) diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 8eec9f0..23a88f2 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -79,6 +79,8 @@ class Net::LDAP::Filter # mail value containing the substring "anderson": # # f = Net::LDAP::Filter.eq("mail", "*anderson*") + # + # This filter does not perform any escaping def eq(attribute, value) new(:eq, attribute, value) end @@ -136,10 +138,44 @@ class Net::LDAP::Filter # Creates a Filter object indicating that a particular attribute value # is either not present or does not match a particular string; see # Filter::eq for more information. + # + # This filter does not perform any escaping def ne(attribute, value) new(:ne, attribute, value) end + ## + # Creates a Filter object indicating that the value of a particular + # attribute must match a particular string. The attribute value is + # escaped, so the "*" character is interpreted literally. + def equals(attribute, value) + new(:eq, attribute, escape(value)) + end + + ## + # Creates a Filter object indicating that the value of a particular + # attribute must begin with a particular string. The attribute value is + # escaped, so the "*" character is interpreted literally. + def begins(attribute, value) + new(:eq, attribute, escape(value) + "*") + end + + ## + # Creates a Filter object indicating that the value of a particular + # attribute must end with a particular string. The attribute value is + # escaped, so the "*" character is interpreted literally. + def ends(attribute, value) + new(:eq, attribute, "*" + escape(value)) + end + + ## + # Creates a Filter object indicating that the value of a particular + # attribute must contain a particular string. The attribute value is + # escaped, so the "*" character is interpreted literally. + def contains(attribute, value) + new(:eq, attribute, "*" + escape(value) + "*") + end + ## # Creates a Filter object indicating that a particular attribute value # is greater than or equal to the specified value. @@ -207,6 +243,12 @@ class Net::LDAP::Filter alias_method :present, :present? alias_method :pres, :present? + ## + # Escape a string for use in an LDAP filter + def escape(string) + string.gsub(/[\*\(\)\\\0]/) {|s| sprintf("\\%02x", s[0]) } + end + ## # Converts an LDAP search filter in BER format to an Net::LDAP::Filter # object. The incoming BER object most likely came to us by parsing an diff --git a/test/test_filter.rb b/test/test_filter.rb index 88495f1..c7214a7 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -24,6 +24,13 @@ class TestFilter < Test::Unit::TestCase assert_equal("(uid=george *)", Filter.eq("uid", "george *").to_s) end + def test_convenience_filters + assert_equal("(uid=\\2a)", Filter.equals("uid", "*").to_s) + assert_equal("(uid=\\28*)", Filter.begins("uid", "(").to_s) + assert_equal("(uid=*\\29)", Filter.ends("uid", ")").to_s) + assert_equal("(uid=*\\5c*)", Filter.contains("uid", "\\").to_s) + end + def test_c2 assert_equal("(uid=george *)", Filter.from_rfc2254("uid=george *").to_rfc2254) From 36904e208a8048253c34c55ed9766b4080555ea6 Mon Sep 17 00:00:00 2001 From: Kaspar Schiess Date: Thu, 30 Dec 2010 13:44:17 +0100 Subject: [PATCH 3/5] + Rewrote tests as specs. Ruby1.9 compatible escape code. --- lib/net/ldap/filter.rb | 21 ++++++++++++++++++++- spec/unit/ldap/filter_spec.rb | 32 +++++++++++++++++++++++++++++++- test/test_filter.rb | 7 ------- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 23a88f2..4e8aec8 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -1,3 +1,4 @@ +# Encoding: UTF-8 # Copyright (C) 2006 by Francis Cianfrocca and other contributors. All # Rights Reserved. # @@ -243,10 +244,28 @@ class Net::LDAP::Filter alias_method :present, :present? alias_method :pres, :present? + # http://tools.ietf.org/html/rfc4515 lists these exceptions from UTF1 + # charset for filters. All of the following must be escaped in any normal + # string using a single backslash ('\') as escape. + # + ESCAPES = { + '!' => '21', # EXCLAMATION = %x21 ; exclamation mark ("!") + '&' => '26', # AMPERSAND = %x26 ; ampersand (or AND symbol) ("&") + '*' => '2A', # ASTERISK = %x2A ; asterisk ("*") + ':' => '3A', # COLON = %x3A ; colon (":") + '|' => '7C', # VERTBAR = %x7C ; vertical bar (or pipe) ("|") + '~' => '7E', # TILDE = %x7E ; tilde ("~") + } + # Compiled character class regexp using the keys from the above hash. + ESCAPE_RE = Regexp.new( + "[" + + ESCAPES.keys.map { |e| Regexp.escape(e) }.join + + "]") + ## # Escape a string for use in an LDAP filter def escape(string) - string.gsub(/[\*\(\)\\\0]/) {|s| sprintf("\\%02x", s[0]) } + string.gsub(ESCAPE_RE) { |char| "\\" + ESCAPES[char] } end ## diff --git a/spec/unit/ldap/filter_spec.rb b/spec/unit/ldap/filter_spec.rb index fac0c28..623f032 100644 --- a/spec/unit/ldap/filter_spec.rb +++ b/spec/unit/ldap/filter_spec.rb @@ -49,5 +49,35 @@ describe Net::LDAP::Filter do Net::LDAP::Filter.construct("uid=O'Keefe").to_rfc2254.should == "(uid=O'Keefe)" end end - + + describe "convenience filter constructors" do + def eq(attribute, value) + described_class.eq(attribute, value) + end + describe "<- .equals(attr, val)" do + it "should delegate to .eq with escaping" do + described_class.equals('dn', 'f*oo').should == eq('dn', 'f\2Aoo') + end + end + describe "<- .begins(attr, val)" do + it "should delegate to .eq with escaping" do + described_class.begins('dn', 'f*oo').should == eq('dn', 'f\2Aoo*') + end + end + describe "<- .ends(attr, val)" do + it "should delegate to .eq with escaping" do + described_class.ends('dn', 'f*oo').should == eq('dn', '*f\2Aoo') + end + end + describe "<- .contains(attr, val)" do + it "should delegate to .eq with escaping" do + described_class.contains('dn', 'f*oo').should == eq('dn', '*f\2Aoo*') + end + end + end + describe "<- .escape(str)" do + it "should escape !, &, *, :, | and ~" do + Net::LDAP::Filter.escape('!&*:|~').should == "\\21\\26\\2A\\3A\\7C\\7E" + end + end end \ No newline at end of file diff --git a/test/test_filter.rb b/test/test_filter.rb index c7214a7..88495f1 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -24,13 +24,6 @@ class TestFilter < Test::Unit::TestCase assert_equal("(uid=george *)", Filter.eq("uid", "george *").to_s) end - def test_convenience_filters - assert_equal("(uid=\\2a)", Filter.equals("uid", "*").to_s) - assert_equal("(uid=\\28*)", Filter.begins("uid", "(").to_s) - assert_equal("(uid=*\\29)", Filter.ends("uid", ")").to_s) - assert_equal("(uid=*\\5c*)", Filter.contains("uid", "\\").to_s) - end - def test_c2 assert_equal("(uid=george *)", Filter.from_rfc2254("uid=george *").to_rfc2254) From 9a0da07f73c19c068abcf1c4539bc2a177aab5b3 Mon Sep 17 00:00:00 2001 From: Kaspar Schiess Date: Thu, 30 Dec 2010 13:46:06 +0100 Subject: [PATCH 4/5] + Upgrades our code to a recent rspec --- Gemfile | 2 +- Gemfile.lock | 2 +- spec/spec_helper.rb | 3 +-- spec/unit/ber/ber_spec.rb | 7 ++++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Gemfile b/Gemfile index f10ce04..f284314 100644 --- a/Gemfile +++ b/Gemfile @@ -5,6 +5,6 @@ gem 'hoe-git' group :development do gem 'metaid' - gem 'rspec' + gem 'rspec', '~> 2.0' gem 'flexmock' end diff --git a/Gemfile.lock b/Gemfile.lock index 0d8c43b..96a7b25 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -26,4 +26,4 @@ DEPENDENCIES hoe hoe-git metaid - rspec + rspec (~> 2.0) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f6c63bc..5079537 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,6 +1,5 @@ require 'net/ldap' -require 'rubygems' -Spec::Runner.configure do |config| +RSpec.configure do |config| config.mock_with :flexmock end diff --git a/spec/unit/ber/ber_spec.rb b/spec/unit/ber/ber_spec.rb index 9506122..33be2fd 100644 --- a/spec/unit/ber/ber_spec.rb +++ b/spec/unit/ber/ber_spec.rb @@ -4,12 +4,13 @@ require 'net/ber' require 'net/ldap' describe "BER encoding of" do - def properly_encode_and_decode - simple_matcher('properly encode and decode') do |given| + + RSpec::Matchers.define :properly_encode_and_decode do + match do |given| given.to_ber.read_ber.should == given end end - + context "arrays" do it "should properly encode/decode []" do [].should properly_encode_and_decode From 5bc73d3aa3aa83f810a48bfa60502b1a281dab3d Mon Sep 17 00:00:00 2001 From: Kaspar Schiess Date: Thu, 30 Dec 2010 13:46:32 +0100 Subject: [PATCH 5/5] . ignoring .rspec (useful to force autotest into spec mode) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a323762..993ac60 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.rspec spec/ldap.yml .rvmrc *.gemspec