# -*- coding:binary -*-
require 'spec_helper'

require 'msf/core'
require 'msf/core/exploit/http/client'

describe Msf::Exploit::Remote::HttpClient do
	subject do
		mod = Module.new
		mod.extend described_class

		mod
	end

	describe '#normalize_uri' do
		let(:expected_normalized_uri) do
			'/a/b/c'
		end

		let(:normalized_uri) do
			subject.normalize_uri(unnormalized_uri)
		end

		context "with just '/'" do
			let(:unnormalized_uri) do
				'/'
			end

			it "should be '/'" do
				unnormalized_uri.should == '/'
			end

			it "should return '/'" do
				normalized_uri.should == '/'
			end
		end

		context "with starting '/'" do
			let(:unnormalized_uri) do
				expected_normalized_uri
			end

			it "should start with '/'" do
				unnormalized_uri[0, 1].should == '/'
			end

			it "should not add another starting '/'" do
				normalized_uri.should == expected_normalized_uri
			end

			context "with multiple internal '/'" do
				let(:unnormalized_uri) do
					"/#{expected_normalized_uri.gsub("/", "////")}"
				end

				it "should remove doubled internal '/'" do
					normalized_uri.should == expected_normalized_uri
				end
			end

			context "with multiple starting '/'" do
				let(:unnormalized_uri) do
					"/#{expected_normalized_uri}"
				end

				it "should have at least 2 starting '/'" do
					unnormalized_uri[0, 2].should == '//'
				end

				it "should return with one starting '/'" do
					normalized_uri.should == expected_normalized_uri
				end
			end

			context "with trailing '/'" do
				let(:expected_normalized_uri) do
					'/a/b/c/'
				end

				let(:unnormalized_uri) do
					"#{expected_normalized_uri}/"
				end

				it "should end with '/'" do
					normalized_uri[-1, 1].should == '/'
				end

				context "with multiple trailing '/'" do
					let(:unnormalized_uri) do
						"#{expected_normalized_uri}/"
					end

					it "should have multiple trailing '/'" do
						unnormalized_uri[-2,2].should == '//'
					end

					it "should return only one trailing '/'" do
						normalized_uri.should == expected_normalized_uri
					end
				end
			end

			context "without trailing '/'" do
				let(:unnormalized_uri) do
					expected_normalized_uri
				end

				it "should not have a trailing '/'" do
					unnormalized_uri[-1, 1].should_not == '/'
				end

				it "should return original string" do
					normalized_uri.should == expected_normalized_uri
				end
			end
		end

		context "without starting '/'" do
			context "with trailing '/'" do
				let(:unnormalized_uri) do
					'a/b/c/'
				end
				let(:expected_normalized_uri) do
					'/a/b/c/'
				end

				it "should have trailing '/'" do
					unnormalized_uri[-1, 1].should == '/'
				end

				it "should add starting '/'" do
					normalized_uri[0, 1].should == '/'
				end

				it "should not remove trailing '/'" do
					normalized_uri[-1, 1].should == '/'
				end

				it 'should normalize the uri' do
					normalized_uri.should == "#{expected_normalized_uri}"
				end

				context "with multiple internal '/'" do
					let(:unnormalized_uri) do
						"/#{expected_normalized_uri.gsub("/", "////")}"
					end

					it "should remove doubled internal '/'" do
						normalized_uri.should == expected_normalized_uri
					end
				end
			end

			context "without trailing '/'" do
				let(:unnormalized_uri) do
					'a/b/c'
				end

				it "should not have trailing '/'" do
					unnormalized_uri[-1, 1].should_not == '/'
				end

				it "should add starting '/'" do
					normalized_uri[0, 1].should == '/'
				end

				it "should add trailing '/'" do
					normalized_uri[-1, 1].should_not == '/'
				end
			end
		end

		context 'with empty string' do
			let(:unnormalized_uri) do
				''
			end

			it "should be empty" do
				unnormalized_uri.should be_empty
			end

			it "should return '/'" do
				normalized_uri.should == '/'
			end
		end

		context 'with nil' do
			let(:unnormalized_uri) do
				nil
			end

			it 'should be nil' do
				unnormalized_uri.should be_nil
			end

			it "should return '/" do
				normalized_uri.should == '/'
			end
		end
	end
end
