diary/mycgi.rb

305 lines
9.5 KiB
Ruby

# 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*<pre.*<\/pre>\n*/inm) {
t = "%PRE#{i}"; i += 1
preserve[t] = $&
t
}
lines = lines.gsub(/\n*<textarea.*<\/textarea>\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(
"<input class='form-control' id='day' size='2' type='text'>
<select class='form-control' id='month'><option id='item'></select>
<input class='form-control' id='year' size='4' type='text'>")
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