#!/usr/bin/ruby -w
##
## SMB Search: URI classes extender and URI::SMB class
## Copyright (c) 2007 OSS Technology Co., Japan <http://www.osstech.co.jp/>
##
## Date: 2007-07-07, since 2007-07-06
## Author: SATOH Fumiyasu
##

require 'uri/generic'

module URI
  class Generic
    alias to_str to_s
  end

  class SMB < Generic
    DEFAULT_PORT = 445
    COMPONENT = [
      :scheme,
      :userinfo, :host, :port,
      :path
    ].freeze

    def self.parse(uri)
      unless match = uri.match(%r#^([^/:]+://)(.*)$#)
	raise InvalidURIError, "bad URI(absolute but no scheme): #{uri}"
      end

      escaped = match[2].split(/\//).map do |node|
	URI.escape(node)
      end

      return URI.parse(match[1] + escaped.join('/'))
    end

    def self.build(args)
      tmp = Util::make_components_hash(self, args)
      return super(tmp)
    end

    def initialize(*arg)
      @domain = nil
      super(*arg)
    end

    def set_userinfo(user, password = nil, domain = nil)
      user_tmp, password_tmp, domain_tmp = split_userinfo(user)
      unless password
	user = user_tmp
	password = password_tmp
      end
      unless domain
	user = user_tmp
	domain = domain_tmp
      end

      @user = user
      @password = password if password
      @domain = domain if domain

      [@user, @password, @domain]
    end
    protected :set_userinfo

    def set_user(v)
      set_userinfo(v, @password, @domain)
      v
    end
    protected :set_user

    def check_domain(v, user = @user)
      if @registry || @opaque
        raise InvalidURIError, 
          "can not set domain with registry or opaque"
      end
      return v unless v

      if !user
        raise InvalidURIError,
          "domain component depends user component"
      end

      if USERINFO !~ v
        raise InvalidComponentError,
          "bad component(expected user component): #{v}"
      end

      return true
    end
    protected :check_domain

    def set_domain(v)
      @domain = v
      return v
    end
    protected :set_domain

    def split_userinfo(ui)
      return nil, nil, nil unless ui

      if match = ui.match(/^([^;]+);(.*)$/)
	domain = match[1]
	user, password = match[2].split(/:/, 2)
      else
	domain = nil
	user, password = ui.split(/:/, 2)
      end

      return user, password, domain
    end
    private :split_userinfo

    def userinfo
      v = super
      if v.nil?
	nil
      elsif @domain.nil?
	v
      else
	@domain + ';' + v
      end
    end

    def domain
      @domain
    end

    def domain=(domain)
      check_domain(domain)
      set_domain(domain)
      # returns domain
    end
  end

  @@schemes['SMB'] = SMB
end

