# SPDX-License-Identifier: Apache-2.0 # Copyright (C) 2021 OKTET Labs Ltd. All rights reserved. # # General CGI helpers # HEADER_FILE = "header.html" FOOTER_FILE = "footer.html" CURRENT_MONTH = "- Current -" # Where to place it in the months list CURRENT_MONTH_NUMBER = 0 def cgi_debug_log(msg) STDERR.puts "DEBUG: " + msg end class MyCGI < CGI # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/23950?help-en def MyCGI::pretty(string, shift = " ") i = 0; preserve = {} lines = string.gsub(/\n*\n*/inm) { t = "%PRE#{i}"; i += 1 preserve[t] = $& t } lines = lines.gsub(/\n*\n*/inm) { t = "%TEXTAREA#{i}"; i += 1 preserve[t] = $& t } lines = lines.gsub(/(?!\A)<(?:.|\n)*?>/n, "\n\\0").gsub(/<(?:.|\n)*?>(?!\n)/n, "\\0\n") end_pos = 0 while end_pos = lines.index(/^<\/(\w+)/n, end_pos) element = $1.dup start_pos = lines.rindex(/^\s*<#{element}/ni, end_pos) lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos]. gsub(/\n(?!\z)/n, "\n" + shift) + "__" end lines = lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/n, '\1') preserve.each { |t, s| lines.sub!(/#{Regexp::quote(t)}/, s) } lines end def MyCGI::list_select(list, param) param = Array.new if not param list.collect do |entry| param.include?(entry[0]) ? entry.dup.push(true) : entry end end def initialize(form_type, default_params, multiple_key, multiline_key, *args) super(*args) @form_type = form_type @tree_params = default_params @multiple_key = multiple_key @multiline_key = multiline_key self.params.each do |key, value| @tree_params = add_value(@tree_params, key, value, @multiple_key.include?(key)) end end def add_value(hash, key, value, multiple) hash = Hash.new if not hash if /^(.*?):(.*)$/ =~ key hash[$1] = add_value(hash[$1], $2, value, @multiple_key.include?($1)) elsif @multiline_key.include?(key) hash[key] = value.join else hash[key] = (multiple or value.length > 1) ? value : value[0] end hash end def hiddens(value) value.inject([]) do |res, item| res + [Amrita.a(:name => item[0], :value => item[1])] end end # Create array of pairs [name, value] from the parameters subtree def tree_flatten(keys) hash = @tree_params keys.each do |key| return [] if not hash[key] hash = hash[key] end add_flatten(keys[0..-2], keys[-1], hash) end def add_flatten(prefix, field, data) names = field ? prefix + [field] : prefix if data.is_a? Hash data.inject([]) do |res, pair| res + add_flatten(names, pair[0], pair[1]) end elsif data.is_a? Array data.inject([]) do |res, value| res << [names.join(":"), value.to_s] end else # single value [[names.join(":"), data.to_s]] end end def tree_hidden(keys) hash = @tree_params keys.each do |key| return "" if not hash[key] hash = hash[key] end add_hidden(keys[0..-2], keys[-1], hash) end def MyCGI::list_options(data, selections = nil) selection = ((selections.is_a? Array) ? selections[0] : selections).to_s data.collect do |pair| item = Amrita.a(:value => pair[0]){ pair[1] } item << Amrita.a(:selected => "selected")[0] if pair[0].to_s == selection item end end def tree_hidden_e(keys) hash = @tree_params keys.each do |key| return [] if not hash[key] hash = hash[key] end add_hidden_e(keys[0..-2], keys[-1], hash) end def add_hidden_e(prefix, field, value) if value.is_a? Hash value.inject([]) do |res, pair| res + add_hidden_e(prefix + [field], pair[0], pair[1]) end else value.inject([]) do |res, value1| res + [ Amrita.a(:name => (prefix + [field]).join(":"), :value => value1) ] end end end def add_hidden(prefix, field, value) if value.is_a?Hash value.inject("") do |res, pair| res + add_hidden(prefix + [field], pair[0], pair[1]) end else value.inject("") do |res, value1| res + hidden((prefix + [field]).join(":"), value1) end end end def MyCGI::hash2date(hash) begin value = %w(year month day).collect do |p| hash[p].is_a?(Array) ? hash[p][0] : hash[p] end value[0] = case value[0] when '$' then 9999 when '#' then Date.today.year else value[0].to_i end value[1] = case value[1] when '$' then Date::MONTHNAMES.length - 1 when CURRENT_MONTH then Date.today.month when CURRENT_MONTH_NUMBER.to_s then Date.today.month else value[1].to_i end if value[2] == '$' value[2] = 1 (Date.new(*value) >> 1) - 1 elsif value[2] == '#' value[2] = Date.today.day Date.new(*value) else value[2] = value[2].to_i Date.new(*value) end rescue ArgumentError raise "Invalid date #{hash["year"]}-#{hash["month"]}-#{hash["day"]}" end end def MyCGI::date2hash(date) { "year" => [date.year.to_s], "month" => [date.mon.to_s], "day" => [date.day.to_s] } end def MyCGI::select_date(prefix = "", value = nil, edit = false) if value == nil edit = true value = MyCGI::date2hash(Date.today) elsif value.is_a?Hash # TODO: !!!! value = { "year" => [value["year"]], "month" => [value["month"]], "day" => [value["day"]] } unless value["year"].is_a?Array edit = true else value = MyCGI::date2hash(value) end if edit template = Amrita::TemplateText.new( " ") template.asxml = true s = String.new template.expand(s, {:day => Amrita.a( :name => prefix + ":day", :value => value["day"][0]), :month => Amrita.a( :name => prefix + ":month"){ {:item => list_options( (0..(Date::MONTHNAMES.length - 1)).collect do |m| case m when CURRENT_MONTH_NUMBER then [m.to_s, CURRENT_MONTH] else [m.to_s, Date::MONTHNAMES[m]] end end, value["month"][0]) } }, :year => Amrita.a( :name => prefix + ":year", :value => value["year"][0]) }) s else d = Date.new(value["year"][0].to_i, value["month"][0].to_i, value["day"][0].to_i) sprintf("%s %s %s (%s)", value["day"][0], Date::MONTHNAMES[value["month"][0].to_i], value["year"][0], Date::ABBR_DAYNAMES[d.wday]) end end def MyCGI::select_date_e(prefix = "", value = nil, edit = false) noescape{ select_date(prefix, value, edit) } end # Assign values to the all-site common parts of the page # # @param data Hash of data for amrita template of the page def MyCGI::add_commons(data) data[:header] = noescape{ File.open(HEADER_FILE) { |f| f.read }} data[:footer] = noescape{ File.open(FOOTER_FILE) { |f| f.read }} end def MyCGI::optional(data) { :value => data } end # Create string from the 'value' that can be used # as a value of HTML DOM attribute 'id' # # @return String of proposed attribute value def MyCGI::element_id(value) id = value.to_s if id.empty? or id !~ /[A-Za-z].*/ "s" + id else id end end def MyCGI.dump(value) case value.class.to_s when "Hash" then "{" + value.collect do |key, x| "#{key} => #{dump(x)}" end.join(", ") + "}" when "String" then "\"#{value}\"" when "Array" then "[#{value.collect {|x| dump(x)}.join(",")}]" else "#{value.class}(#{value.to_s})" end end attr_accessor :form_type, :tree_params, :multiple_key private :add_value end