lib/ass_launcher/enterprise/web_client.rb
# encoding: utf-8
module AssLauncher
module Enterprise
# Abstract 1C:Enterprise client. Provides {#location} method as URI
# generator for connection to
# 1C information base via web browser.
# @example (see #initialize)
# @example (see #location)
class WebClient
require 'uri'
require 'ass_launcher/enterprise/cli'
DEFAULT_OPTIONS = { disable_startup_messages: true }
DEFAULT_VERSION = '999'
# @return [URI] base uri location
attr_reader :uri
# Version for 1C:Enterprise platform
attr_reader :version
# @return [WebClient]
# @example
#
# # Get webclient usin connection string:
# connection_string =\
# AssLauncher::Support::ConnectionString.new(
# 'ws="http://host:port/infobase"')
# wc = AssLauncher::Enterprise::WebClient.new(cs.uri)
#
# #or without connection_string
# wc = AssLauncher::Enterprise::WebClient.new('http://host/path')
#
# @param uri [String URI] base infobase location
# @param version [String] version 1C:Enterprise platform.
# The {Enterprise::WebClient#cli_spec}
# depends on the {Enterprise::WebClient#version}.
# Default supposed max possable version.
# {Enterprise::WebClient::DEFAULT_VERSION}
#
def initialize(uri = '', version = DEFAULT_VERSION)
@version = Gem::Version.new(version || DEFAULT_VERSION)
@uri ||= URI(uri || '')
end
def uri=(uri)
@uri = URI(uri)
end
# @return [Cli::CliSpec]
def cli_spec
@cli_spec ||= AssLauncher::Enterprise::Cli::CliSpec.for(self)
end
# Defined run modes fo client
# @return (see Cli.defined_modes_for)
def self.run_modes
Cli.defined_modes_for(self)
end
# (see .run_modes)
def run_modes
self.class.run_modes
end
def build_args(&block)
args_builder.build_args(&block)
end
private :build_args
def args_builder
Cli::ArgumentsBuilder.new(cli_spec, run_modes[0])
end
private :args_builder
# Build URI location for connect to web infobase.
#
# We can use {Cli::ArgumentsBuilder} for
# build connection string with validation parameters on defined in
# {#cli_spec} specifications.
#
# Or we can pass parameters as +args+ array directly.
# @example
# wc = AssLauncher::Enterprise::WebClient.new('http://host/path')
#
# # Without ArgumentsBulder
# wc.location(['O', 'low', 'C', 'passed string',
# 'N', '1cuser',
# 'P', '1cpassw',
# 'Authoff', '']) #=> URI
#
# # With ArgumentsBulder
# wc.location do
# _O :Low
# _C 'passed string'
# _N '1cuser'
# _P '1cuser_password'
# wA :-
# oIDA :-
# authOff
# _L 'en'
# vL 'en'
# debuggerURL 'localhost'
# _UsePrivilegedMode
# end #=> URI
#
# @param args [Arry]
# @option options [bool] :disable_startup_messages adds or not
# '/DisableStartupMessages' flag parameter into +args+
#
def location(args = [], **options, &block)
options = DEFAULT_OPTIONS.merge options
args += ['DisableStartupMessages', '']\
if options[:disable_startup_messages]
args += build_args(&block) if block_given?
add_to_query uri.dup, args_to_query(args)
end
def add_to_query(uri, q)
if uri.query
uri.query += escape "&#{q}" if q
else
uri.query = escape "#{q}" if q
end
uri
end
private :add_to_query
def escape(s)
self.class.escape(s)
end
private :escape
# Fuckin 1C is bad understand of CGI.escape.
# From escaping exclude: =&
# and ' ' replaced on '%20'
def self.escape(string)
string.gsub(/([^ a-zA-Z0-9_.\-=&]+)/) do
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
end.gsub(' ', '%20')
end
CLI_TO_WEB_PARAM_NAME = %r{^/}
def args_to_query(args)
r = to_query(args)
r.gsub!(/&$/, '')
return nil if r.empty?
r
end
private :args_to_query
def to_query(args)
r = ''
args.each_with_index do |v, i|
next if (i + 1).even?
r << "#{v.gsub(CLI_TO_WEB_PARAM_NAME, '')}"
r << "=#{args[i + 1]}" unless args[i + 1].to_s.empty?
r << '&'
end
r
end
private :to_query
end
end
end