Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK!') cookie.rbnu[require 'cgi/util' class CGI # Class representing an HTTP cookie. # # In addition to its specific fields and methods, a Cookie instance # is a delegator to the array of its values. # # See RFC 2965. # # == Examples of use # cookie1 = CGI::Cookie.new("name", "value1", "value2", ...) # cookie1 = CGI::Cookie.new("name" => "name", "value" => "value") # cookie1 = CGI::Cookie.new('name' => 'name', # 'value' => ['value1', 'value2', ...], # 'path' => 'path', # optional # 'domain' => 'domain', # optional # 'expires' => Time.now, # optional # 'secure' => true # optional # ) # # cgi.out("cookie" => [cookie1, cookie2]) { "string" } # # name = cookie1.name # values = cookie1.value # path = cookie1.path # domain = cookie1.domain # expires = cookie1.expires # secure = cookie1.secure # # cookie1.name = 'name' # cookie1.value = ['value1', 'value2', ...] # cookie1.path = 'path' # cookie1.domain = 'domain' # cookie1.expires = Time.now + 30 # cookie1.secure = true class Cookie < Array @@accept_charset="UTF-8" unless defined?(@@accept_charset) # Create a new CGI::Cookie object. # # :call-seq: # Cookie.new(name_string,*value) # Cookie.new(options_hash) # # +name_string+:: # The name of the cookie; in this form, there is no #domain or # #expiration. The #path is gleaned from the +SCRIPT_NAME+ environment # variable, and #secure is false. # *value:: # value or list of values of the cookie # +options_hash+:: # A Hash of options to initialize this Cookie. Possible options are: # # name:: the name of the cookie. Required. # value:: the cookie's value or list of values. # path:: the path for which this cookie applies. Defaults to the # the value of the +SCRIPT_NAME+ environment variable. # domain:: the domain for which this cookie applies. # expires:: the time at which this cookie expires, as a +Time+ object. # secure:: whether this cookie is a secure cookie or not (default to # false). Secure cookies are only transmitted to HTTPS # servers. # # These keywords correspond to attributes of the cookie object. def initialize(name = "", *value) @domain = nil @expires = nil if name.kind_of?(String) @name = name %r|^(.*/)|.match(ENV["SCRIPT_NAME"]) @path = ($1 or "") @secure = false return super(value) end options = name unless options.has_key?("name") raise ArgumentError, "`name' required" end @name = options["name"] value = Array(options["value"]) # simple support for IE if options["path"] @path = options["path"] else %r|^(.*/)|.match(ENV["SCRIPT_NAME"]) @path = ($1 or "") end @domain = options["domain"] @expires = options["expires"] @secure = options["secure"] == true ? true : false super(value) end # Name of this cookie, as a +String+ attr_accessor :name # Path for which this cookie applies, as a +String+ attr_accessor :path # Domain for which this cookie applies, as a +String+ attr_accessor :domain # Time at which this cookie expires, as a +Time+ attr_accessor :expires # True if this cookie is secure; false otherwise attr_reader("secure") # Returns the value or list of values for this cookie. def value self end # Replaces the value of this cookie with a new value or list of values. def value=(val) replace(Array(val)) end # Set whether the Cookie is a secure cookie or not. # # +val+ must be a boolean. def secure=(val) @secure = val if val == true or val == false @secure end # Convert the Cookie to its string representation. def to_s val = collect{|v| CGI.escape(v) }.join("&") buf = "#{@name}=#{val}" buf << "; domain=#{@domain}" if @domain buf << "; path=#{@path}" if @path buf << "; expires=#{CGI::rfc1123_date(@expires)}" if @expires buf << "; secure" if @secure == true buf end # Parse a raw cookie string into a hash of cookie-name=>Cookie # pairs. # # cookies = CGI::Cookie.parse("raw_cookie_string") # # { "name1" => cookie1, "name2" => cookie2, ... } # def self.parse(raw_cookie) cookies = Hash.new([]) return cookies unless raw_cookie raw_cookie.split(/[;,]\s?/).each do |pairs| name, values = pairs.split('=',2) next unless name and values name = CGI.unescape(name) values ||= "" values = values.split('&').collect{|v| CGI.unescape(v,@@accept_charset) } if cookies.has_key?(name) values = cookies[name].value + values end cookies[name] = Cookie.new(name, *values) end cookies end # A summary of cookie string. def inspect "#" end end # class Cookie end PK!@Wllhtml.rbnu[class CGI # Base module for HTML-generation mixins. # # Provides methods for code generation for tags following # the various DTD element types. module TagMaker # :nodoc: # Generate code for an element with required start and end tags. # # - - def nn_element(element, attributes = {}) s = nOE_element(element, attributes) if block_given? s << yield.to_s end s << "" end def nn_element_def(attributes = {}, &block) nn_element(__callee__, attributes, &block) end # Generate code for an empty element. # # - O EMPTY def nOE_element(element, attributes = {}) attributes={attributes=>nil} if attributes.kind_of?(String) s = "<#{element.upcase}" attributes.each do|name, value| next unless value s << " " s << CGI::escapeHTML(name.to_s) if value != true s << '="' s << CGI::escapeHTML(value.to_s) s << '"' end end s << ">" end def nOE_element_def(attributes = {}, &block) nOE_element(__callee__, attributes, &block) end # Generate code for an element for which the end (and possibly the # start) tag is optional. # # O O or - O def nO_element(element, attributes = {}) s = nOE_element(element, attributes) if block_given? s << yield.to_s s << "" end s end def nO_element_def(attributes = {}, &block) nO_element(__callee__, attributes, &block) end end # TagMaker # Mixin module providing HTML generation methods. # # For example, # cgi.a("http://www.example.com") { "Example" } # # => "Example" # # Modules Html3, Html4, etc., contain more basic HTML-generation methods # (+#title+, +#h1+, etc.). # # See class CGI for a detailed example. # module HtmlExtension # Generate an Anchor element as a string. # # +href+ can either be a string, giving the URL # for the HREF attribute, or it can be a hash of # the element's attributes. # # The body of the element is the string returned by the no-argument # block passed in. # # a("http://www.example.com") { "Example" } # # => "Example" # # a("HREF" => "http://www.example.com", "TARGET" => "_top") { "Example" } # # => "Example" # def a(href = "") # :yield: attributes = if href.kind_of?(String) { "HREF" => href } else href end super(attributes) end # Generate a Document Base URI element as a String. # # +href+ can either by a string, giving the base URL for the HREF # attribute, or it can be a has of the element's attributes. # # The passed-in no-argument block is ignored. # # base("http://www.example.com/cgi") # # => "" def base(href = "") # :yield: attributes = if href.kind_of?(String) { "HREF" => href } else href end super(attributes) end # Generate a BlockQuote element as a string. # # +cite+ can either be a string, give the URI for the source of # the quoted text, or a hash, giving all attributes of the element, # or it can be omitted, in which case the element has no attributes. # # The body is provided by the passed-in no-argument block # # blockquote("http://www.example.com/quotes/foo.html") { "Foo!" } # #=> "
Foo!
def blockquote(cite = {}) # :yield: attributes = if cite.kind_of?(String) { "CITE" => cite } else cite end super(attributes) end # Generate a Table Caption element as a string. # # +align+ can be a string, giving the alignment of the caption # (one of top, bottom, left, or right). It can be a hash of # all the attributes of the element. Or it can be omitted. # # The body of the element is provided by the passed-in no-argument block. # # caption("left") { "Capital Cities" } # # => Capital Cities def caption(align = {}) # :yield: attributes = if align.kind_of?(String) { "ALIGN" => align } else align end super(attributes) end # Generate a Checkbox Input element as a string. # # The attributes of the element can be specified as three arguments, # +name+, +value+, and +checked+. +checked+ is a boolean value; # if true, the CHECKED attribute will be included in the element. # # Alternatively, the attributes can be specified as a hash. # # checkbox("name") # # = checkbox("NAME" => "name") # # checkbox("name", "value") # # = checkbox("NAME" => "name", "VALUE" => "value") # # checkbox("name", "value", true) # # = checkbox("NAME" => "name", "VALUE" => "value", "CHECKED" => true) def checkbox(name = "", value = nil, checked = nil) attributes = if name.kind_of?(String) { "TYPE" => "checkbox", "NAME" => name, "VALUE" => value, "CHECKED" => checked } else name["TYPE"] = "checkbox" name end input(attributes) end # Generate a sequence of checkbox elements, as a String. # # The checkboxes will all have the same +name+ attribute. # Each checkbox is followed by a label. # There will be one checkbox for each value. Each value # can be specified as a String, which will be used both # as the value of the VALUE attribute and as the label # for that checkbox. A single-element array has the # same effect. # # Each value can also be specified as a three-element array. # The first element is the VALUE attribute; the second is the # label; and the third is a boolean specifying whether this # checkbox is CHECKED. # # Each value can also be specified as a two-element # array, by omitting either the value element (defaults # to the same as the label), or the boolean checked element # (defaults to false). # # checkbox_group("name", "foo", "bar", "baz") # # foo # # bar # # baz # # checkbox_group("name", ["foo"], ["bar", true], "baz") # # foo # # bar # # baz # # checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz") # # Foo # # Bar # # Baz # # checkbox_group("NAME" => "name", # "VALUES" => ["foo", "bar", "baz"]) # # checkbox_group("NAME" => "name", # "VALUES" => [["foo"], ["bar", true], "baz"]) # # checkbox_group("NAME" => "name", # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]) def checkbox_group(name = "", *values) if name.kind_of?(Hash) values = name["VALUES"] name = name["NAME"] end values.collect{|value| if value.kind_of?(String) checkbox(name, value) + value else if value[-1] == true || value[-1] == false checkbox(name, value[0], value[-1]) + value[-2] else checkbox(name, value[0]) + value[-1] end end }.join end # Generate an File Upload Input element as a string. # # The attributes of the element can be specified as three arguments, # +name+, +size+, and +maxlength+. +maxlength+ is the maximum length # of the file's _name_, not of the file's _contents_. # # Alternatively, the attributes can be specified as a hash. # # See #multipart_form() for forms that include file uploads. # # file_field("name") # # # # file_field("name", 40) # # # # file_field("name", 40, 100) # # # # file_field("NAME" => "name", "SIZE" => 40) # # def file_field(name = "", size = 20, maxlength = nil) attributes = if name.kind_of?(String) { "TYPE" => "file", "NAME" => name, "SIZE" => size.to_s } else name["TYPE"] = "file" name end attributes["MAXLENGTH"] = maxlength.to_s if maxlength input(attributes) end # Generate a Form element as a string. # # +method+ should be either "get" or "post", and defaults to the latter. # +action+ defaults to the current CGI script name. +enctype+ # defaults to "application/x-www-form-urlencoded". # # Alternatively, the attributes can be specified as a hash. # # See also #multipart_form() for forms that include file uploads. # # form{ "string" } # #
string
# # form("get") { "string" } # #
string
# # form("get", "url") { "string" } # #
string
# # form("METHOD" => "post", "ENCTYPE" => "enctype") { "string" } # #
string
def form(method = "post", action = script_name, enctype = "application/x-www-form-urlencoded") attributes = if method.kind_of?(String) { "METHOD" => method, "ACTION" => action, "ENCTYPE" => enctype } else unless method.has_key?("METHOD") method["METHOD"] = "post" end unless method.has_key?("ENCTYPE") method["ENCTYPE"] = enctype end method end if block_given? body = yield else body = "" end if @output_hidden body << @output_hidden.collect{|k,v| "" }.join end super(attributes){body} end # Generate a Hidden Input element as a string. # # The attributes of the element can be specified as two arguments, # +name+ and +value+. # # Alternatively, the attributes can be specified as a hash. # # hidden("name") # # # # hidden("name", "value") # # # # hidden("NAME" => "name", "VALUE" => "reset", "ID" => "foo") # # def hidden(name = "", value = nil) attributes = if name.kind_of?(String) { "TYPE" => "hidden", "NAME" => name, "VALUE" => value } else name["TYPE"] = "hidden" name end input(attributes) end # Generate a top-level HTML element as a string. # # The attributes of the element are specified as a hash. The # pseudo-attribute "PRETTY" can be used to specify that the generated # HTML string should be indented. "PRETTY" can also be specified as # a string as the sole argument to this method. The pseudo-attribute # "DOCTYPE", if given, is used as the leading DOCTYPE SGML tag; it # should include the entire text of this tag, including angle brackets. # # The body of the html element is supplied as a block. # # html{ "string" } # # string # # html("LANG" => "ja") { "string" } # # string # # html("DOCTYPE" => false) { "string" } # # string # # html("DOCTYPE" => '') { "string" } # # string # # html("PRETTY" => " ") { "" } # # # # # # # # # # # # html("PRETTY" => "\t") { "" } # # # # # # # # # # # # html("PRETTY") { "" } # # = html("PRETTY" => " ") { "" } # # html(if $VERBOSE then "PRETTY" end) { "HTML string" } # def html(attributes = {}) # :yield: if nil == attributes attributes = {} elsif "PRETTY" == attributes attributes = { "PRETTY" => true } end pretty = attributes.delete("PRETTY") pretty = " " if true == pretty buf = "" if attributes.has_key?("DOCTYPE") if attributes["DOCTYPE"] buf << attributes.delete("DOCTYPE") else attributes.delete("DOCTYPE") end else buf << doctype end buf << super(attributes) if pretty CGI::pretty(buf, pretty) else buf end end # Generate an Image Button Input element as a string. # # +src+ is the URL of the image to use for the button. +name+ # is the input name. +alt+ is the alternative text for the image. # # Alternatively, the attributes can be specified as a hash. # # image_button("url") # # # # image_button("url", "name", "string") # # # # image_button("SRC" => "url", "ALT" => "string") # # def image_button(src = "", name = nil, alt = nil) attributes = if src.kind_of?(String) { "TYPE" => "image", "SRC" => src, "NAME" => name, "ALT" => alt } else src["TYPE"] = "image" src["SRC"] ||= "" src end input(attributes) end # Generate an Image element as a string. # # +src+ is the URL of the image. +alt+ is the alternative text for # the image. +width+ is the width of the image, and +height+ is # its height. # # Alternatively, the attributes can be specified as a hash. # # img("src", "alt", 100, 50) # # alt # # img("SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50) # # alt def img(src = "", alt = "", width = nil, height = nil) attributes = if src.kind_of?(String) { "SRC" => src, "ALT" => alt } else src end attributes["WIDTH"] = width.to_s if width attributes["HEIGHT"] = height.to_s if height super(attributes) end # Generate a Form element with multipart encoding as a String. # # Multipart encoding is used for forms that include file uploads. # # +action+ is the action to perform. +enctype+ is the encoding # type, which defaults to "multipart/form-data". # # Alternatively, the attributes can be specified as a hash. # # multipart_form{ "string" } # #
string
# # multipart_form("url") { "string" } # #
string
def multipart_form(action = nil, enctype = "multipart/form-data") attributes = if action == nil { "METHOD" => "post", "ENCTYPE" => enctype } elsif action.kind_of?(String) { "METHOD" => "post", "ACTION" => action, "ENCTYPE" => enctype } else unless action.has_key?("METHOD") action["METHOD"] = "post" end unless action.has_key?("ENCTYPE") action["ENCTYPE"] = enctype end action end if block_given? form(attributes){ yield } else form(attributes) end end # Generate a Password Input element as a string. # # +name+ is the name of the input field. +value+ is its default # value. +size+ is the size of the input field display. +maxlength+ # is the maximum length of the inputted password. # # Alternatively, attributes can be specified as a hash. # # password_field("name") # # # # password_field("name", "value") # # # # password_field("password", "value", 80, 200) # # # # password_field("NAME" => "name", "VALUE" => "value") # # def password_field(name = "", value = nil, size = 40, maxlength = nil) attributes = if name.kind_of?(String) { "TYPE" => "password", "NAME" => name, "VALUE" => value, "SIZE" => size.to_s } else name["TYPE"] = "password" name end attributes["MAXLENGTH"] = maxlength.to_s if maxlength input(attributes) end # Generate a Select element as a string. # # +name+ is the name of the element. The +values+ are the options that # can be selected from the Select menu. Each value can be a String or # a one, two, or three-element Array. If a String or a one-element # Array, this is both the value of that option and the text displayed for # it. If a three-element Array, the elements are the option value, displayed # text, and a boolean value specifying whether this option starts as selected. # The two-element version omits either the option value (defaults to the same # as the display text) or the boolean selected specifier (defaults to false). # # The attributes and options can also be specified as a hash. In this # case, options are specified as an array of values as described above, # with the hash key of "VALUES". # # popup_menu("name", "foo", "bar", "baz") # # # # popup_menu("name", ["foo"], ["bar", true], "baz") # # # # popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz") # # # # popup_menu("NAME" => "name", "SIZE" => 2, "MULTIPLE" => true, # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]) # # def popup_menu(name = "", *values) if name.kind_of?(Hash) values = name["VALUES"] size = name["SIZE"].to_s if name["SIZE"] multiple = name["MULTIPLE"] name = name["NAME"] else size = nil multiple = nil end select({ "NAME" => name, "SIZE" => size, "MULTIPLE" => multiple }){ values.collect{|value| if value.kind_of?(String) option({ "VALUE" => value }){ value } else if value[value.size - 1] == true option({ "VALUE" => value[0], "SELECTED" => true }){ value[value.size - 2] } else option({ "VALUE" => value[0] }){ value[value.size - 1] } end end }.join } end # Generates a radio-button Input element. # # +name+ is the name of the input field. +value+ is the value of # the field if checked. +checked+ specifies whether the field # starts off checked. # # Alternatively, the attributes can be specified as a hash. # # radio_button("name", "value") # # # # radio_button("name", "value", true) # # # # radio_button("NAME" => "name", "VALUE" => "value", "ID" => "foo") # # def radio_button(name = "", value = nil, checked = nil) attributes = if name.kind_of?(String) { "TYPE" => "radio", "NAME" => name, "VALUE" => value, "CHECKED" => checked } else name["TYPE"] = "radio" name end input(attributes) end # Generate a sequence of radio button Input elements, as a String. # # This works the same as #checkbox_group(). However, it is not valid # to have more than one radiobutton in a group checked. # # radio_group("name", "foo", "bar", "baz") # # foo # # bar # # baz # # radio_group("name", ["foo"], ["bar", true], "baz") # # foo # # bar # # baz # # radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz") # # Foo # # Bar # # Baz # # radio_group("NAME" => "name", # "VALUES" => ["foo", "bar", "baz"]) # # radio_group("NAME" => "name", # "VALUES" => [["foo"], ["bar", true], "baz"]) # # radio_group("NAME" => "name", # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]) def radio_group(name = "", *values) if name.kind_of?(Hash) values = name["VALUES"] name = name["NAME"] end values.collect{|value| if value.kind_of?(String) radio_button(name, value) + value else if value[-1] == true || value[-1] == false radio_button(name, value[0], value[-1]) + value[-2] else radio_button(name, value[0]) + value[-1] end end }.join end # Generate a reset button Input element, as a String. # # This resets the values on a form to their initial values. +value+ # is the text displayed on the button. +name+ is the name of this button. # # Alternatively, the attributes can be specified as a hash. # # reset # # # # reset("reset") # # # # reset("VALUE" => "reset", "ID" => "foo") # # def reset(value = nil, name = nil) attributes = if (not value) or value.kind_of?(String) { "TYPE" => "reset", "VALUE" => value, "NAME" => name } else value["TYPE"] = "reset" value end input(attributes) end alias scrolling_list popup_menu # Generate a submit button Input element, as a String. # # +value+ is the text to display on the button. +name+ is the name # of the input. # # Alternatively, the attributes can be specified as a hash. # # submit # # # # submit("ok") # # # # submit("ok", "button1") # # # # submit("VALUE" => "ok", "NAME" => "button1", "ID" => "foo") # # def submit(value = nil, name = nil) attributes = if (not value) or value.kind_of?(String) { "TYPE" => "submit", "VALUE" => value, "NAME" => name } else value["TYPE"] = "submit" value end input(attributes) end # Generate a text field Input element, as a String. # # +name+ is the name of the input field. +value+ is its initial # value. +size+ is the size of the input area. +maxlength+ # is the maximum length of input accepted. # # Alternatively, the attributes can be specified as a hash. # # text_field("name") # # # # text_field("name", "value") # # # # text_field("name", "value", 80) # # # # text_field("name", "value", 80, 200) # # # # text_field("NAME" => "name", "VALUE" => "value") # # def text_field(name = "", value = nil, size = 40, maxlength = nil) attributes = if name.kind_of?(String) { "TYPE" => "text", "NAME" => name, "VALUE" => value, "SIZE" => size.to_s } else name["TYPE"] = "text" name end attributes["MAXLENGTH"] = maxlength.to_s if maxlength input(attributes) end # Generate a TextArea element, as a String. # # +name+ is the name of the textarea. +cols+ is the number of # columns and +rows+ is the number of rows in the display. # # Alternatively, the attributes can be specified as a hash. # # The body is provided by the passed-in no-argument block # # textarea("name") # # = textarea("NAME" => "name", "COLS" => 70, "ROWS" => 10) # # textarea("name", 40, 5) # # = textarea("NAME" => "name", "COLS" => 40, "ROWS" => 5) def textarea(name = "", cols = 70, rows = 10) # :yield: attributes = if name.kind_of?(String) { "NAME" => name, "COLS" => cols.to_s, "ROWS" => rows.to_s } else name end super(attributes) end end # HtmlExtension # Mixin module for HTML version 3 generation methods. module Html3 # :nodoc: include TagMaker # The DOCTYPE declaration for this version of HTML def doctype %|| end instance_method(:nn_element_def).tap do |m| # - - for element in %w[ A TT I B U STRIKE BIG SMALL SUB SUP EM STRONG DFN CODE SAMP KBD VAR CITE FONT ADDRESS DIV CENTER MAP APPLET PRE XMP LISTING DL OL UL DIR MENU SELECT TABLE TITLE STYLE SCRIPT H1 H2 H3 H4 H5 H6 TEXTAREA FORM BLOCKQUOTE CAPTION ] define_method(element.downcase, m) end end instance_method(:nOE_element_def).tap do |m| # - O EMPTY for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT ISINDEX META ] define_method(element.downcase, m) end end instance_method(:nO_element_def).tap do |m| # O O or - O for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION TR TH TD ] define_method(element.downcase, m) end end end # Html3 # Mixin module for HTML version 4 generation methods. module Html4 # :nodoc: include TagMaker # The DOCTYPE declaration for this version of HTML def doctype %|| end # Initialize the HTML generation methods for this version. # - - instance_method(:nn_element_def).tap do |m| for element in %w[ TT I B BIG SMALL EM STRONG DFN CODE SAMP KBD VAR CITE ABBR ACRONYM SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT OPTGROUP FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ] define_method(element.downcase, m) end end # - O EMPTY instance_method(:nOE_element_def).tap do |m| for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META ] define_method(element.downcase, m) end end # O O or - O instance_method(:nO_element_def).tap do |m| for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY COLGROUP TR TH TD HEAD ] define_method(element.downcase, m) end end end # Html4 # Mixin module for HTML version 4 transitional generation methods. module Html4Tr # :nodoc: include TagMaker # The DOCTYPE declaration for this version of HTML def doctype %|| end # Initialise the HTML generation methods for this version. # - - instance_method(:nn_element_def).tap do |m| for element in %w[ TT I B U S STRIKE BIG SMALL EM STRONG DFN CODE SAMP KBD VAR CITE ABBR ACRONYM FONT SUB SUP SPAN BDO ADDRESS DIV CENTER MAP OBJECT APPLET H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL DIR MENU LABEL SELECT OPTGROUP FIELDSET LEGEND BUTTON TABLE IFRAME NOFRAMES TITLE STYLE SCRIPT NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ] define_method(element.downcase, m) end end # - O EMPTY instance_method(:nOE_element_def).tap do |m| for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT COL ISINDEX META ] define_method(element.downcase, m) end end # O O or - O instance_method(:nO_element_def).tap do |m| for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY COLGROUP TR TH TD HEAD ] define_method(element.downcase, m) end end end # Html4Tr # Mixin module for generating HTML version 4 with framesets. module Html4Fr # :nodoc: include TagMaker # The DOCTYPE declaration for this version of HTML def doctype %|| end # Initialise the HTML generation methods for this version. # - - instance_method(:nn_element_def).tap do |m| for element in %w[ FRAMESET ] define_method(element.downcase, m) end end # - O EMPTY instance_method(:nOE_element_def).tap do |m| for element in %w[ FRAME ] define_method(element.downcase, m) end end end # Html4Fr # Mixin module for HTML version 5 generation methods. module Html5 # :nodoc: include TagMaker # The DOCTYPE declaration for this version of HTML def doctype %|| end # Initialise the HTML generation methods for this version. # - - instance_method(:nn_element_def).tap do |m| for element in %w[ SECTION NAV ARTICLE ASIDE HGROUP HEADER FOOTER FIGURE FIGCAPTION S TIME U MARK RUBY BDI IFRAME VIDEO AUDIO CANVAS DATALIST OUTPUT PROGRESS METER DETAILS SUMMARY MENU DIALOG I B SMALL EM STRONG DFN CODE SAMP KBD VAR CITE ABBR SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ] define_method(element.downcase, m) end end # - O EMPTY instance_method(:nOE_element_def).tap do |m| for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META COMMAND EMBED KEYGEN SOURCE TRACK WBR ] define_method(element.downcase, m) end end # O O or - O instance_method(:nO_element_def).tap do |m| for element in %w[ HTML HEAD BODY P DT DD LI OPTION THEAD TFOOT TBODY OPTGROUP COLGROUP RT RP TR TH TD ] define_method(element.downcase, m) end end end # Html5 class HTML3 include Html3 include HtmlExtension end class HTML4 include Html4 include HtmlExtension end class HTML4Tr include Html4Tr include HtmlExtension end class HTML4Fr include Html4Tr include Html4Fr include HtmlExtension end class HTML5 include Html5 include HtmlExtension end end PK!}] session/pstore.rbnu[# # cgi/session/pstore.rb - persistent storage of marshalled session data # # Documentation: William Webber (william@williamwebber.com) # # == Overview # # This file provides the CGI::Session::PStore class, which builds # persistent of session data on top of the pstore library. See # cgi/session.rb for more details on session storage managers. require 'cgi/session' require 'pstore' class CGI class Session # PStore-based session storage class. # # This builds upon the top-level PStore class provided by the # library file pstore.rb. Session data is marshalled and stored # in a file. File locking and transaction services are provided. class PStore # Create a new CGI::Session::PStore instance # # This constructor is used internally by CGI::Session. The # user does not generally need to call it directly. # # +session+ is the session for which this instance is being # created. The session id must only contain alphanumeric # characters; automatically generated session ids observe # this requirement. # # +option+ is a hash of options for the initializer. The # following options are recognised: # # tmpdir:: the directory to use for storing the PStore # file. Defaults to Dir::tmpdir (generally "/tmp" # on Unix systems). # prefix:: the prefix to add to the session id when generating # the filename for this session's PStore file. # Defaults to the empty string. # # This session's PStore file will be created if it does # not exist, or opened if it does. def initialize(session, option={}) dir = option['tmpdir'] || Dir::tmpdir prefix = option['prefix'] || '' id = session.session_id require 'digest/md5' md5 = Digest::MD5.hexdigest(id)[0,16] path = dir+"/"+prefix+md5 path.untaint if File::exist?(path) @hash = nil else unless session.new_session raise CGI::Session::NoSession, "uninitialized session" end @hash = {} end @p = ::PStore.new(path) @p.transaction do |p| File.chmod(0600, p.path) end end # Restore session state from the session's PStore file. # # Returns the session state as a hash. def restore unless @hash @p.transaction do @hash = @p['hash'] || {} end end @hash end # Save session state to the session's PStore file. def update @p.transaction do @p['hash'] = @hash end end # Update and close the session's PStore file. def close update end # Close and delete the session's PStore file. def delete path = @p.path File::unlink path end end end end # :enddoc: PK!b>util.rbnu[class CGI; module Util; end; extend Util; end module CGI::Util @@accept_charset="UTF-8" unless defined?(@@accept_charset) # URL-encode a string. # url_encoded_string = CGI::escape("'Stop!' said Fred") # # => "%27Stop%21%27+said+Fred" def escape(string) encoding = string.encoding string.b.gsub(/([^ a-zA-Z0-9_.-]+)/) do |m| '%' + m.unpack('H2' * m.bytesize).join('%').upcase end.tr(' ', '+').force_encoding(encoding) end # URL-decode a string with encoding(optional). # string = CGI::unescape("%27Stop%21%27+said+Fred") # # => "'Stop!' said Fred" def unescape(string,encoding=@@accept_charset) str=string.tr('+', ' ').b.gsub(/((?:%[0-9a-fA-F]{2})+)/) do |m| [m.delete('%')].pack('H*') end.force_encoding(encoding) str.valid_encoding? ? str : str.force_encoding(string.encoding) end # The set of special characters and their escaped values TABLE_FOR_ESCAPE_HTML__ = { "'" => ''', '&' => '&', '"' => '"', '<' => '<', '>' => '>', } # Escape special characters in HTML, namely &\"<> # CGI::escapeHTML('Usage: foo "bar" ') # # => "Usage: foo "bar" <baz>" def escapeHTML(string) string.gsub(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__) end # Unescape a string that has been HTML-escaped # CGI::unescapeHTML("Usage: foo "bar" <baz>") # # => "Usage: foo \"bar\" " def unescapeHTML(string) return string unless string.include? '&' enc = string.encoding if enc != Encoding::UTF_8 && [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE].include?(enc) return string.gsub(Regexp.new('&(apos|amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do case $1.encode(Encoding::US_ASCII) when 'apos' then "'".encode(enc) when 'amp' then '&'.encode(enc) when 'quot' then '"'.encode(enc) when 'gt' then '>'.encode(enc) when 'lt' then '<'.encode(enc) when /\A#0*(\d+)\z/ then $1.to_i.chr(enc) when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc) end end end asciicompat = Encoding.compatible?(string, "a") string.gsub(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do match = $1.dup case match when 'apos' then "'" when 'amp' then '&' when 'quot' then '"' when 'gt' then '>' when 'lt' then '<' when /\A#0*(\d+)\z/ n = $1.to_i if enc == Encoding::UTF_8 or enc == Encoding::ISO_8859_1 && n < 256 or asciicompat && n < 128 n.chr(enc) else "&##{$1};" end when /\A#x([0-9a-f]+)\z/i n = $1.hex if enc == Encoding::UTF_8 or enc == Encoding::ISO_8859_1 && n < 256 or asciicompat && n < 128 n.chr(enc) else "&#x#{$1};" end else "&#{match};" end end end # Synonym for CGI::escapeHTML(str) alias escape_html escapeHTML # Synonym for CGI::unescapeHTML(str) alias unescape_html unescapeHTML # Escape only the tags of certain HTML elements in +string+. # # Takes an element or elements or array of elements. Each element # is specified by the name of the element, without angle brackets. # This matches both the start and the end tag of that element. # The attribute list of the open tag will also be escaped (for # instance, the double-quotes surrounding attribute values). # # print CGI::escapeElement('
', "A", "IMG") # # "
<A HREF="url"></A>" # # print CGI::escapeElement('
', ["A", "IMG"]) # # "
<A HREF="url"></A>" def escapeElement(string, *elements) elements = elements[0] if elements[0].kind_of?(Array) unless elements.empty? string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do CGI::escapeHTML($&) end else string end end # Undo escaping such as that done by CGI::escapeElement() # # print CGI::unescapeElement( # CGI::escapeHTML('
'), "A", "IMG") # # "<BR>" # # print CGI::unescapeElement( # CGI::escapeHTML('
'), ["A", "IMG"]) # # "<BR>" def unescapeElement(string, *elements) elements = elements[0] if elements[0].kind_of?(Array) unless elements.empty? string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do unescapeHTML($&) end else string end end # Synonym for CGI::escapeElement(str) alias escape_element escapeElement # Synonym for CGI::unescapeElement(str) alias unescape_element unescapeElement # Abbreviated day-of-week names specified by RFC 822 RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ] # Abbreviated month names specified by RFC 822 RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ] # Format a +Time+ object as a String using the format specified by RFC 1123. # # CGI::rfc1123_date(Time.now) # # Sat, 01 Jan 2000 00:00:00 GMT def rfc1123_date(time) t = time.clone.gmtime return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT", RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year, t.hour, t.min, t.sec) end # Prettify (indent) an HTML string. # # +string+ is the HTML string to indent. +shift+ is the indentation # unit to use; it defaults to two spaces. # # print CGI::pretty("") # # # # # # # # # # print CGI::pretty("", "\t") # # # # # # # # # def pretty(string, shift = " ") lines = string.gsub(/(?!\A)<.*?>/m, "\n\\0").gsub(/<.*?>(?!\n)/m, "\\0\n") end_pos = 0 while end_pos = lines.index(/^<\/(\w+)/, end_pos) element = $1.dup start_pos = lines.rindex(/^\s*<#{element}/i, end_pos) lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/, "\n" + shift) + "__" end lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/, '\1') end alias h escapeHTML end PK!l[H[H session.rbnu[# # cgi/session.rb - session support for cgi scripts # # Copyright (C) 2001 Yukihiro "Matz" Matsumoto # Copyright (C) 2000 Network Applied Communication Laboratory, Inc. # Copyright (C) 2000 Information-technology Promotion Agency, Japan # # Author: Yukihiro "Matz" Matsumoto # # Documentation: William Webber (william@williamwebber.com) require 'cgi' require 'tmpdir' class CGI # == Overview # # This file provides the CGI::Session class, which provides session # support for CGI scripts. A session is a sequence of HTTP requests # and responses linked together and associated with a single client. # Information associated with the session is stored # on the server between requests. A session id is passed between client # and server with every request and response, transparently # to the user. This adds state information to the otherwise stateless # HTTP request/response protocol. # # == Lifecycle # # A CGI::Session instance is created from a CGI object. By default, # this CGI::Session instance will start a new session if none currently # exists, or continue the current session for this client if one does # exist. The +new_session+ option can be used to either always or # never create a new session. See #new() for more details. # # #delete() deletes a session from session storage. It # does not however remove the session id from the client. If the client # makes another request with the same id, the effect will be to start # a new session with the old session's id. # # == Setting and retrieving session data. # # The Session class associates data with a session as key-value pairs. # This data can be set and retrieved by indexing the Session instance # using '[]', much the same as hashes (although other hash methods # are not supported). # # When session processing has been completed for a request, the # session should be closed using the close() method. This will # store the session's state to persistent storage. If you want # to store the session's state to persistent storage without # finishing session processing for this request, call the update() # method. # # == Storing session state # # The caller can specify what form of storage to use for the session's # data with the +database_manager+ option to CGI::Session::new. The # following storage classes are provided as part of the standard library: # # CGI::Session::FileStore:: stores data as plain text in a flat file. Only # works with String data. This is the default # storage type. # CGI::Session::MemoryStore:: stores data in an in-memory hash. The data # only persists for as long as the current Ruby # interpreter instance does. # CGI::Session::PStore:: stores data in Marshalled format. Provided by # cgi/session/pstore.rb. Supports data of any type, # and provides file-locking and transaction support. # # Custom storage types can also be created by defining a class with # the following methods: # # new(session, options) # restore # returns hash of session data. # update # close # delete # # Changing storage type mid-session does not work. Note in particular # that by default the FileStore and PStore session data files have the # same name. If your application switches from one to the other without # making sure that filenames will be different # and clients still have old sessions lying around in cookies, then # things will break nastily! # # == Maintaining the session id. # # Most session state is maintained on the server. However, a session # id must be passed backwards and forwards between client and server # to maintain a reference to this session state. # # The simplest way to do this is via cookies. The CGI::Session class # provides transparent support for session id communication via cookies # if the client has cookies enabled. # # If the client has cookies disabled, the session id must be included # as a parameter of all requests sent by the client to the server. The # CGI::Session class in conjunction with the CGI class will transparently # add the session id as a hidden input field to all forms generated # using the CGI#form() HTML generation method. No built-in support is # provided for other mechanisms, such as URL re-writing. The caller is # responsible for extracting the session id from the session_id # attribute and manually encoding it in URLs and adding it as a hidden # input to HTML forms created by other mechanisms. Also, session expiry # is not automatically handled. # # == Examples of use # # === Setting the user's name # # require 'cgi' # require 'cgi/session' # require 'cgi/session/pstore' # provides CGI::Session::PStore # # cgi = CGI.new("html4") # # session = CGI::Session.new(cgi, # 'database_manager' => CGI::Session::PStore, # use PStore # 'session_key' => '_rb_sess_id', # custom session key # 'session_expires' => Time.now + 30 * 60, # 30 minute timeout # 'prefix' => 'pstore_sid_') # PStore option # if cgi.has_key?('user_name') and cgi['user_name'] != '' # # coerce to String: cgi[] returns the # # string-like CGI::QueryExtension::Value # session['user_name'] = cgi['user_name'].to_s # elsif !session['user_name'] # session['user_name'] = "guest" # end # session.close # # === Creating a new session safely # # require 'cgi' # require 'cgi/session' # # cgi = CGI.new("html4") # # # We make sure to delete an old session if one exists, # # not just to free resources, but to prevent the session # # from being maliciously hijacked later on. # begin # session = CGI::Session.new(cgi, 'new_session' => false) # session.delete # rescue ArgumentError # if no old session # end # session = CGI::Session.new(cgi, 'new_session' => true) # session.close # class Session class NoSession < RuntimeError #:nodoc: end # The id of this session. attr_reader :session_id, :new_session def Session::callback(dbman) #:nodoc: Proc.new{ dbman[0].close unless dbman.empty? } end # Create a new session id. # # The session id is an MD5 hash based upon the time, # a random number, and a constant string. This routine # is used internally for automatically generated # session ids. def create_new_id require 'securerandom' begin session_id = SecureRandom.hex(16) rescue NotImplementedError require 'digest/md5' md5 = Digest::MD5::new now = Time::now md5.update(now.to_s) md5.update(String(now.usec)) md5.update(String(rand(0))) md5.update(String($$)) md5.update('foobar') session_id = md5.hexdigest end session_id end private :create_new_id # Create a new CGI::Session object for +request+. # # +request+ is an instance of the +CGI+ class (see cgi.rb). # +option+ is a hash of options for initialising this # CGI::Session instance. The following options are # recognised: # # session_key:: the parameter name used for the session id. # Defaults to '_session_id'. # session_id:: the session id to use. If not provided, then # it is retrieved from the +session_key+ parameter # of the request, or automatically generated for # a new session. # new_session:: if true, force creation of a new session. If not set, # a new session is only created if none currently # exists. If false, a new session is never created, # and if none currently exists and the +session_id+ # option is not set, an ArgumentError is raised. # database_manager:: the name of the class providing storage facilities # for session state persistence. Built-in support # is provided for +FileStore+ (the default), # +MemoryStore+, and +PStore+ (from # cgi/session/pstore.rb). See the documentation for # these classes for more details. # # The following options are also recognised, but only apply if the # session id is stored in a cookie. # # session_expires:: the time the current session expires, as a # +Time+ object. If not set, the session will terminate # when the user's browser is closed. # session_domain:: the hostname domain for which this session is valid. # If not set, defaults to the hostname of the server. # session_secure:: if +true+, this session will only work over HTTPS. # session_path:: the path for which this session applies. Defaults # to the directory of the CGI script. # # +option+ is also passed on to the session storage class initializer; see # the documentation for each session storage class for the options # they support. # # The retrieved or created session is automatically added to +request+ # as a cookie, and also to its +output_hidden+ table, which is used # to add hidden input elements to forms. # # *WARNING* the +output_hidden+ # fields are surrounded by a
tag in HTML 4 generation, which # is _not_ invisible on many browsers; you may wish to disable the # use of fieldsets with code similar to the following # (see http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/37805) # # cgi = CGI.new("html4") # class << cgi # undef_method :fieldset # end # def initialize(request, option={}) @new_session = false session_key = option['session_key'] || '_session_id' session_id = option['session_id'] unless session_id if option['new_session'] session_id = create_new_id @new_session = true end end unless session_id if request.key?(session_key) session_id = request[session_key] session_id = session_id.read if session_id.respond_to?(:read) end unless session_id session_id, = request.cookies[session_key] end unless session_id unless option.fetch('new_session', true) raise ArgumentError, "session_key `%s' should be supplied"%session_key end session_id = create_new_id @new_session = true end end @session_id = session_id dbman = option['database_manager'] || FileStore begin @dbman = dbman::new(self, option) rescue NoSession unless option.fetch('new_session', true) raise ArgumentError, "invalid session_id `%s'"%session_id end session_id = @session_id = create_new_id unless session_id @new_session=true retry end request.instance_eval do @output_hidden = {session_key => session_id} unless option['no_hidden'] @output_cookies = [ Cookie::new("name" => session_key, "value" => session_id, "expires" => option['session_expires'], "domain" => option['session_domain'], "secure" => option['session_secure'], "path" => if option['session_path'] option['session_path'] elsif ENV["SCRIPT_NAME"] File::dirname(ENV["SCRIPT_NAME"]) else "" end) ] unless option['no_cookies'] end @dbprot = [@dbman] ObjectSpace::define_finalizer(self, Session::callback(@dbprot)) end # Retrieve the session data for key +key+. def [](key) @data ||= @dbman.restore @data[key] end # Set the session data for key +key+. def []=(key, val) @write_lock ||= true @data ||= @dbman.restore @data[key] = val end # Store session data on the server. For some session storage types, # this is a no-op. def update @dbman.update end # Store session data on the server and close the session storage. # For some session storage types, this is a no-op. def close @dbman.close @dbprot.clear end # Delete the session from storage. Also closes the storage. # # Note that the session's data is _not_ automatically deleted # upon the session expiring. def delete @dbman.delete @dbprot.clear end # File-based session storage class. # # Implements session storage as a flat file of 'key=value' values. # This storage type only works directly with String values; the # user is responsible for converting other types to Strings when # storing and from Strings when retrieving. class FileStore # Create a new FileStore instance. # # This constructor is used internally by CGI::Session. The # user does not generally need to call it directly. # # +session+ is the session for which this instance is being # created. The session id must only contain alphanumeric # characters; automatically generated session ids observe # this requirement. # # +option+ is a hash of options for the initializer. The # following options are recognised: # # tmpdir:: the directory to use for storing the FileStore # file. Defaults to Dir::tmpdir (generally "/tmp" # on Unix systems). # prefix:: the prefix to add to the session id when generating # the filename for this session's FileStore file. # Defaults to "cgi_sid_". # suffix:: the prefix to add to the session id when generating # the filename for this session's FileStore file. # Defaults to the empty string. # # This session's FileStore file will be created if it does # not exist, or opened if it does. def initialize(session, option={}) dir = option['tmpdir'] || Dir::tmpdir prefix = option['prefix'] || 'cgi_sid_' suffix = option['suffix'] || '' id = session.session_id require 'digest/md5' md5 = Digest::MD5.hexdigest(id)[0,16] @path = dir+"/"+prefix+md5+suffix if File::exist? @path @hash = nil else unless session.new_session raise CGI::Session::NoSession, "uninitialized session" end @hash = {} end end # Restore session state from the session's FileStore file. # # Returns the session state as a hash. def restore unless @hash @hash = {} begin lockf = File.open(@path+".lock", "r") lockf.flock File::LOCK_SH f = File.open(@path, 'r') for line in f line.chomp! k, v = line.split('=',2) @hash[CGI::unescape(k)] = Marshal.restore(CGI::unescape(v)) end ensure f.close unless f.nil? lockf.close if lockf end end @hash end # Save session state to the session's FileStore file. def update return unless @hash begin lockf = File.open(@path+".lock", File::CREAT|File::RDWR, 0600) lockf.flock File::LOCK_EX f = File.open(@path+".new", File::CREAT|File::TRUNC|File::WRONLY, 0600) for k,v in @hash f.printf "%s=%s\n", CGI::escape(k), CGI::escape(String(Marshal.dump(v))) end f.close File.rename @path+".new", @path ensure f.close if f and !f.closed? lockf.close if lockf end end # Update and close the session's FileStore file. def close update end # Close and delete the session's FileStore file. def delete File::unlink @path+".lock" rescue nil File::unlink @path+".new" rescue nil File::unlink @path rescue nil end end # In-memory session storage class. # # Implements session storage as a global in-memory hash. Session # data will only persist for as long as the Ruby interpreter # instance does. class MemoryStore GLOBAL_HASH_TABLE = {} #:nodoc: # Create a new MemoryStore instance. # # +session+ is the session this instance is associated with. # +option+ is a list of initialisation options. None are # currently recognized. def initialize(session, option=nil) @session_id = session.session_id unless GLOBAL_HASH_TABLE.key?(@session_id) unless session.new_session raise CGI::Session::NoSession, "uninitialized session" end GLOBAL_HASH_TABLE[@session_id] = {} end end # Restore session state. # # Returns session data as a hash. def restore GLOBAL_HASH_TABLE[@session_id] end # Update session state. # # A no-op. def update # don't need to update; hash is shared end # Close session storage. # # A no-op. def close # don't need to close end # Delete the session state. def delete GLOBAL_HASH_TABLE.delete(@session_id) end end # Dummy session storage class. # # Implements session storage place holder. No actual storage # will be done. class NullStore # Create a new NullStore instance. # # +session+ is the session this instance is associated with. # +option+ is a list of initialisation options. None are # currently recognised. def initialize(session, option=nil) end # Restore (empty) session state. def restore {} end # Update session state. # # A no-op. def update end # Close session storage. # # A no-op. def close end # Delete the session state. # # A no-op. def delete end end end end PK!n*rrcore.rbnu[#-- # Methods for generating HTML, parsing CGI-related parameters, and # generating HTTP responses. #++ class CGI $CGI_ENV = ENV # for FCGI support # String for carriage return CR = "\015" # String for linefeed LF = "\012" # Standard internet newline sequence EOL = CR + LF REVISION = '$Id: core.rb 46973 2014-07-27 11:04:28Z hsbt $' #:nodoc: # Whether processing will be required in binary vs text NEEDS_BINMODE = File::BINARY != 0 # Path separators in different environments. PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'} # HTTP status codes. HTTP_STATUS = { "OK" => "200 OK", "PARTIAL_CONTENT" => "206 Partial Content", "MULTIPLE_CHOICES" => "300 Multiple Choices", "MOVED" => "301 Moved Permanently", "REDIRECT" => "302 Found", "NOT_MODIFIED" => "304 Not Modified", "BAD_REQUEST" => "400 Bad Request", "AUTH_REQUIRED" => "401 Authorization Required", "FORBIDDEN" => "403 Forbidden", "NOT_FOUND" => "404 Not Found", "METHOD_NOT_ALLOWED" => "405 Method Not Allowed", "NOT_ACCEPTABLE" => "406 Not Acceptable", "LENGTH_REQUIRED" => "411 Length Required", "PRECONDITION_FAILED" => "412 Precondition Failed", "SERVER_ERROR" => "500 Internal Server Error", "NOT_IMPLEMENTED" => "501 Method Not Implemented", "BAD_GATEWAY" => "502 Bad Gateway", "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates" } # :startdoc: # Synonym for ENV. def env_table ENV end # Synonym for $stdin. def stdinput $stdin end # Synonym for $stdout. def stdoutput $stdout end private :env_table, :stdinput, :stdoutput # Create an HTTP header block as a string. # # :call-seq: # http_header(content_type_string="text/html") # http_header(headers_hash) # # Includes the empty line that ends the header block. # # +content_type_string+:: # If this form is used, this string is the Content-Type # +headers_hash+:: # A Hash of header values. The following header keys are recognized: # # type:: The Content-Type header. Defaults to "text/html" # charset:: The charset of the body, appended to the Content-Type header. # nph:: A boolean value. If true, prepend protocol string and status # code, and date; and sets default values for "server" and # "connection" if not explicitly set. # status:: # The HTTP status code as a String, returned as the Status header. The # values are: # # OK:: 200 OK # PARTIAL_CONTENT:: 206 Partial Content # MULTIPLE_CHOICES:: 300 Multiple Choices # MOVED:: 301 Moved Permanently # REDIRECT:: 302 Found # NOT_MODIFIED:: 304 Not Modified # BAD_REQUEST:: 400 Bad Request # AUTH_REQUIRED:: 401 Authorization Required # FORBIDDEN:: 403 Forbidden # NOT_FOUND:: 404 Not Found # METHOD_NOT_ALLOWED:: 405 Method Not Allowed # NOT_ACCEPTABLE:: 406 Not Acceptable # LENGTH_REQUIRED:: 411 Length Required # PRECONDITION_FAILED:: 412 Precondition Failed # SERVER_ERROR:: 500 Internal Server Error # NOT_IMPLEMENTED:: 501 Method Not Implemented # BAD_GATEWAY:: 502 Bad Gateway # VARIANT_ALSO_VARIES:: 506 Variant Also Negotiates # # server:: The server software, returned as the Server header. # connection:: The connection type, returned as the Connection header (for # instance, "close". # length:: The length of the content that will be sent, returned as the # Content-Length header. # language:: The language of the content, returned as the Content-Language # header. # expires:: The time on which the current content expires, as a +Time+ # object, returned as the Expires header. # cookie:: # A cookie or cookies, returned as one or more Set-Cookie headers. The # value can be the literal string of the cookie; a CGI::Cookie object; # an Array of literal cookie strings or Cookie objects; or a hash all of # whose values are literal cookie strings or Cookie objects. # # These cookies are in addition to the cookies held in the # @output_cookies field. # # Other headers can also be set; they are appended as key: value. # # Examples: # # http_header # # Content-Type: text/html # # http_header("text/plain") # # Content-Type: text/plain # # http_header("nph" => true, # "status" => "OK", # == "200 OK" # # "status" => "200 GOOD", # "server" => ENV['SERVER_SOFTWARE'], # "connection" => "close", # "type" => "text/html", # "charset" => "iso-2022-jp", # # Content-Type: text/html; charset=iso-2022-jp # "length" => 103, # "language" => "ja", # "expires" => Time.now + 30, # "cookie" => [cookie1, cookie2], # "my_header1" => "my_value" # "my_header2" => "my_value") # # This method does not perform charset conversion. def http_header(options='text/html') if options.is_a?(String) content_type = options buf = _header_for_string(content_type) elsif options.is_a?(Hash) if options.size == 1 && options.has_key?('type') content_type = options['type'] buf = _header_for_string(content_type) else buf = _header_for_hash(options.dup) end else raise ArgumentError.new("expected String or Hash but got #{options.class}") end if defined?(MOD_RUBY) _header_for_modruby(buf) return '' else buf << EOL # empty line of separator return buf end end # http_header() # This method is an alias for #http_header, when HTML5 tag maker is inactive. # # NOTE: use #http_header to create HTTP header blocks, this alias is only # provided for backwards compatibility. # # Using #header with the HTML5 tag maker will create a
element. alias :header :http_header def _header_for_string(content_type) #:nodoc: buf = '' if nph?() buf << "#{$CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'} 200 OK#{EOL}" buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}" buf << "Server: #{$CGI_ENV['SERVER_SOFTWARE']}#{EOL}" buf << "Connection: close#{EOL}" end buf << "Content-Type: #{content_type}#{EOL}" if @output_cookies @output_cookies.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" } end return buf end # _header_for_string private :_header_for_string def _header_for_hash(options) #:nodoc: buf = '' ## add charset to option['type'] options['type'] ||= 'text/html' charset = options.delete('charset') options['type'] += "; charset=#{charset}" if charset ## NPH options.delete('nph') if defined?(MOD_RUBY) if options.delete('nph') || nph?() protocol = $CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0' status = options.delete('status') status = HTTP_STATUS[status] || status || '200 OK' buf << "#{protocol} #{status}#{EOL}" buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}" options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || '' options['connection'] ||= 'close' end ## common headers status = options.delete('status') buf << "Status: #{HTTP_STATUS[status] || status}#{EOL}" if status server = options.delete('server') buf << "Server: #{server}#{EOL}" if server connection = options.delete('connection') buf << "Connection: #{connection}#{EOL}" if connection type = options.delete('type') buf << "Content-Type: #{type}#{EOL}" #if type length = options.delete('length') buf << "Content-Length: #{length}#{EOL}" if length language = options.delete('language') buf << "Content-Language: #{language}#{EOL}" if language expires = options.delete('expires') buf << "Expires: #{CGI.rfc1123_date(expires)}#{EOL}" if expires ## cookie if cookie = options.delete('cookie') case cookie when String, Cookie buf << "Set-Cookie: #{cookie}#{EOL}" when Array arr = cookie arr.each {|c| buf << "Set-Cookie: #{c}#{EOL}" } when Hash hash = cookie hash.each_value {|c| buf << "Set-Cookie: #{c}#{EOL}" } end end if @output_cookies @output_cookies.each {|c| buf << "Set-Cookie: #{c}#{EOL}" } end ## other headers options.each do |key, value| buf << "#{key}: #{value}#{EOL}" end return buf end # _header_for_hash private :_header_for_hash def nph? #:nodoc: return /IIS\/(\d+)/.match($CGI_ENV['SERVER_SOFTWARE']) && $1.to_i < 5 end def _header_for_modruby(buf) #:nodoc: request = Apache::request buf.scan(/([^:]+): (.+)#{EOL}/o) do |name, value| warn sprintf("name:%s value:%s\n", name, value) if $DEBUG case name when 'Set-Cookie' request.headers_out.add(name, value) when /^status$/i request.status_line = value request.status = value.to_i when /^content-type$/i request.content_type = value when /^content-encoding$/i request.content_encoding = value when /^location$/i request.status = 302 if request.status == 200 request.headers_out[name] = value else request.headers_out[name] = value end end request.send_http_header return '' end private :_header_for_modruby # Print an HTTP header and body to $DEFAULT_OUTPUT ($>) # # :call-seq: # cgi.out(content_type_string='text/html') # cgi.out(headers_hash) # # +content_type_string+:: # If a string is passed, it is assumed to be the content type. # +headers_hash+:: # This is a Hash of headers, similar to that used by #http_header. # +block+:: # A block is required and should evaluate to the body of the response. # # Content-Length is automatically calculated from the size of # the String returned by the content block. # # If ENV['REQUEST_METHOD'] == "HEAD", then only the header # is output (the content block is still required, but it is ignored). # # If the charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then the # content is converted to this charset, and the language is set to "ja". # # Example: # # cgi = CGI.new # cgi.out{ "string" } # # Content-Type: text/html # # Content-Length: 6 # # # # string # # cgi.out("text/plain") { "string" } # # Content-Type: text/plain # # Content-Length: 6 # # # # string # # cgi.out("nph" => true, # "status" => "OK", # == "200 OK" # "server" => ENV['SERVER_SOFTWARE'], # "connection" => "close", # "type" => "text/html", # "charset" => "iso-2022-jp", # # Content-Type: text/html; charset=iso-2022-jp # "language" => "ja", # "expires" => Time.now + (3600 * 24 * 30), # "cookie" => [cookie1, cookie2], # "my_header1" => "my_value", # "my_header2" => "my_value") { "string" } # # HTTP/1.1 200 OK # # Date: Sun, 15 May 2011 17:35:54 GMT # # Server: Apache 2.2.0 # # Connection: close # # Content-Type: text/html; charset=iso-2022-jp # # Content-Length: 6 # # Content-Language: ja # # Expires: Tue, 14 Jun 2011 17:35:54 GMT # # Set-Cookie: foo # # Set-Cookie: bar # # my_header1: my_value # # my_header2: my_value # # # # string def out(options = "text/html") # :yield: options = { "type" => options } if options.kind_of?(String) content = yield options["length"] = content.bytesize.to_s output = stdoutput output.binmode if defined? output.binmode output.print http_header(options) output.print content unless "HEAD" == env_table['REQUEST_METHOD'] end # Print an argument or list of arguments to the default output stream # # cgi = CGI.new # cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print def print(*options) stdoutput.print(*options) end # Parse an HTTP query string into a hash of key=>value pairs. # # params = CGI::parse("query_string") # # {"name1" => ["value1", "value2", ...], # # "name2" => ["value1", "value2", ...], ... } # def CGI::parse(query) params = {} query.split(/[&;]/).each do |pairs| key, value = pairs.split('=',2).collect{|v| CGI::unescape(v) } next unless key params[key] ||= [] params[key].push(value) if value end params.default=[].freeze params end # Maximum content length of post data ##MAX_CONTENT_LENGTH = 2 * 1024 * 1024 # Maximum number of request parameters when multipart MAX_MULTIPART_COUNT = 128 # Mixin module that provides the following: # # 1. Access to the CGI environment variables as methods. See # documentation to the CGI class for a list of these variables. The # methods are exposed by removing the leading +HTTP_+ (if it exists) and # downcasing the name. For example, +auth_type+ will return the # environment variable +AUTH_TYPE+, and +accept+ will return the value # for +HTTP_ACCEPT+. # # 2. Access to cookies, including the cookies attribute. # # 3. Access to parameters, including the params attribute, and overloading # #[] to perform parameter value lookup by key. # # 4. The initialize_query method, for initializing the above # mechanisms, handling multipart forms, and allowing the # class to be used in "offline" mode. # module QueryExtension %w[ CONTENT_LENGTH SERVER_PORT ].each do |env| define_method(env.sub(/^HTTP_/, '').downcase) do (val = env_table[env]) && Integer(val) end end %w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env| define_method(env.sub(/^HTTP_/, '').downcase) do env_table[env] end end # Get the raw cookies as a string. def raw_cookie env_table["HTTP_COOKIE"] end # Get the raw RFC2965 cookies as a string. def raw_cookie2 env_table["HTTP_COOKIE2"] end # Get the cookies as a hash of cookie-name=>Cookie pairs. attr_accessor :cookies # Get the parameters as a hash of name=>values pairs, where # values is an Array. attr_reader :params # Get the uploaded files as a hash of name=>values pairs attr_reader :files # Set all the parameters. def params=(hash) @params.clear @params.update(hash) end ## # Parses multipart form elements according to # http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 # # Returns a hash of multipart form parameters with bodies of type StringIO or # Tempfile depending on whether the multipart form element exceeds 10 KB # # params[name => body] # def read_multipart(boundary, content_length) ## read first boundary stdin = stdinput first_line = "--#{boundary}#{EOL}" content_length -= first_line.bytesize status = stdin.read(first_line.bytesize) raise EOFError.new("no content body") unless status raise EOFError.new("bad content body") unless first_line == status ## parse and set params params = {} @files = {} boundary_rexp = /--#{Regexp.quote(boundary)}(#{EOL}|--)/ boundary_size = "#{EOL}--#{boundary}#{EOL}".bytesize buf = '' bufsize = 10 * 1024 max_count = MAX_MULTIPART_COUNT n = 0 tempfiles = [] while true (n += 1) < max_count or raise StandardError.new("too many parameters.") ## create body (StringIO or Tempfile) body = create_body(bufsize < content_length) tempfiles << body if defined?(Tempfile) && body.kind_of?(Tempfile) class << body if method_defined?(:path) alias local_path path else def local_path nil end end attr_reader :original_filename, :content_type end ## find head and boundary head = nil separator = EOL * 2 until head && matched = boundary_rexp.match(buf) if !head && pos = buf.index(separator) len = pos + EOL.bytesize head = buf[0, len] buf = buf[(pos+separator.bytesize)..-1] else if head && buf.size > boundary_size len = buf.size - boundary_size body.print(buf[0, len]) buf[0, len] = '' end c = stdin.read(bufsize < content_length ? bufsize : content_length) raise EOFError.new("bad content body") if c.nil? || c.empty? buf << c content_length -= c.bytesize end end ## read to end of boundary m = matched len = m.begin(0) s = buf[0, len] if s =~ /(\r?\n)\z/ s = buf[0, len - $1.bytesize] end body.print(s) buf = buf[m.end(0)..-1] boundary_end = m[1] content_length = -1 if boundary_end == '--' ## reset file cursor position body.rewind ## original filename /Content-Disposition:.* filename=(?:"(.*?)"|([^;\r\n]*))/i.match(head) filename = $1 || $2 || '' filename = CGI.unescape(filename) if unescape_filename?() body.instance_variable_set(:@original_filename, filename.taint) ## content type /Content-Type: (.*)/i.match(head) (content_type = $1 || '').chomp! body.instance_variable_set(:@content_type, content_type.taint) ## query parameter name /Content-Disposition:.* name=(?:"(.*?)"|([^;\r\n]*))/i.match(head) name = $1 || $2 || '' if body.original_filename.empty? value=body.read.dup.force_encoding(@accept_charset) body.close! if defined?(Tempfile) && body.kind_of?(Tempfile) (params[name] ||= []) << value unless value.valid_encoding? if @accept_charset_error_block @accept_charset_error_block.call(name,value) else raise InvalidEncoding,"Accept-Charset encoding error" end end class << params[name].last;self;end.class_eval do define_method(:read){self} define_method(:original_filename){""} define_method(:content_type){""} end else (params[name] ||= []) << body @files[name]=body end ## break loop break if content_length == -1 end raise EOFError, "bad boundary end of body part" unless boundary_end =~ /--/ params.default = [] params rescue Exception if tempfiles tempfiles.each {|t| if t.path t.close! end } end raise end # read_multipart private :read_multipart def create_body(is_large) #:nodoc: if is_large require 'tempfile' body = Tempfile.new('CGI', encoding: Encoding::ASCII_8BIT) else begin require 'stringio' body = StringIO.new("".force_encoding(Encoding::ASCII_8BIT)) rescue LoadError require 'tempfile' body = Tempfile.new('CGI', encoding: Encoding::ASCII_8BIT) end end body.binmode if defined? body.binmode return body end def unescape_filename? #:nodoc: user_agent = $CGI_ENV['HTTP_USER_AGENT'] return /Mac/i.match(user_agent) && /Mozilla/i.match(user_agent) && !/MSIE/i.match(user_agent) end # offline mode. read name=value pairs on standard input. def read_from_cmdline require "shellwords" string = unless ARGV.empty? ARGV.join(' ') else if STDIN.tty? STDERR.print( %|(offline mode: enter name=value pairs on standard input)\n| ) end array = readlines rescue nil if not array.nil? array.join(' ').gsub(/\n/n, '') else "" end end.gsub(/\\=/n, '%3D').gsub(/\\&/n, '%26') words = Shellwords.shellwords(string) if words.find{|x| /=/n.match(x) } words.join('&') else words.join('+') end end private :read_from_cmdline # A wrapper class to use a StringIO object as the body and switch # to a TempFile when the passed threshold is passed. # Initialize the data from the query. # # Handles multipart forms (in particular, forms that involve file uploads). # Reads query parameters in the @params field, and cookies into @cookies. def initialize_query() if ("POST" == env_table['REQUEST_METHOD']) and %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|.match(env_table['CONTENT_TYPE']) current_max_multipart_length = @max_multipart_length.respond_to?(:call) ? @max_multipart_length.call : @max_multipart_length raise StandardError.new("too large multipart data.") if env_table['CONTENT_LENGTH'].to_i > current_max_multipart_length boundary = $1.dup @multipart = true @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH'])) else @multipart = false @params = CGI::parse( case env_table['REQUEST_METHOD'] when "GET", "HEAD" if defined?(MOD_RUBY) Apache::request.args or "" else env_table['QUERY_STRING'] or "" end when "POST" stdinput.binmode if defined? stdinput.binmode stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or '' else read_from_cmdline end.dup.force_encoding(@accept_charset) ) unless Encoding.find(@accept_charset) == Encoding::ASCII_8BIT @params.each do |key,values| values.each do |value| unless value.valid_encoding? if @accept_charset_error_block @accept_charset_error_block.call(key,value) else raise InvalidEncoding,"Accept-Charset encoding error" end end end end end end @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or env_table['COOKIE'])) end private :initialize_query # Returns whether the form contained multipart/form-data def multipart? @multipart end # Get the value for the parameter with a given key. # # If the parameter has multiple values, only the first will be # retrieved; use #params to get the array of values. def [](key) params = @params[key] return '' unless params value = params[0] if @multipart if value return value elsif defined? StringIO StringIO.new("".force_encoding(Encoding::ASCII_8BIT)) else Tempfile.new("CGI",encoding: Encoding::ASCII_8BIT) end else str = if value then value.dup else "" end str end end # Return all query parameter names as an array of String. def keys(*args) @params.keys(*args) end # Returns true if a given query string parameter exists. def has_key?(*args) @params.has_key?(*args) end alias key? has_key? alias include? has_key? end # QueryExtension # Exception raised when there is an invalid encoding detected class InvalidEncoding < Exception; end # @@accept_charset is default accept character set. # This default value default is "UTF-8" # If you want to change the default accept character set # when create a new CGI instance, set this: # # CGI.accept_charset = "EUC-JP" # @@accept_charset="UTF-8" # Return the accept character set for all new CGI instances. def self.accept_charset @@accept_charset end # Set the accept character set for all new CGI instances. def self.accept_charset=(accept_charset) @@accept_charset=accept_charset end # Return the accept character set for this CGI instance. attr_reader :accept_charset # @@max_multipart_length is the maximum length of multipart data. # The default value is 128 * 1024 * 1024 bytes # # The default can be set to something else in the CGI constructor, # via the :max_multipart_length key in the option hash. # # See CGI.new documentation. # @@max_multipart_length= 128 * 1024 * 1024 # Create a new CGI instance. # # :call-seq: # CGI.new(tag_maker) { block } # CGI.new(options_hash = {}) { block } # # # tag_maker:: # This is the same as using the +options_hash+ form with the value { # :tag_maker => tag_maker } Note that it is recommended to use the # +options_hash+ form, since it also allows you specify the charset you # will accept. # options_hash:: # A Hash that recognizes three options: # # :accept_charset:: # specifies encoding of received query string. If omitted, # @@accept_charset is used. If the encoding is not valid, a # CGI::InvalidEncoding will be raised. # # Example. Suppose @@accept_charset is "UTF-8" # # when not specified: # # cgi=CGI.new # @accept_charset # => "UTF-8" # # when specified as "EUC-JP": # # cgi=CGI.new(:accept_charset => "EUC-JP") # => "EUC-JP" # # :tag_maker:: # String that specifies which version of the HTML generation methods to # use. If not specified, no HTML generation methods will be loaded. # # The following values are supported: # # "html3":: HTML 3.x # "html4":: HTML 4.0 # "html4Tr":: HTML 4.0 Transitional # "html4Fr":: HTML 4.0 with Framesets # "html5":: HTML 5 # # :max_multipart_length:: # Specifies maximum length of multipart data. Can be an Integer scalar or # a lambda, that will be evaluated when the request is parsed. This # allows more complex logic to be set when determining whether to accept # multipart data (e.g. consult a registered users upload allowance) # # Default is 128 * 1024 * 1024 bytes # # cgi=CGI.new(:max_multipart_length => 268435456) # simple scalar # # cgi=CGI.new(:max_multipart_length => -> {check_filesystem}) # lambda # # block:: # If provided, the block is called when an invalid encoding is # encountered. For example: # # encoding_errors={} # cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value| # encoding_errors[name] = value # end # # Finally, if the CGI object is not created in a standard CGI call # environment (that is, it can't locate REQUEST_METHOD in its environment), # then it will run in "offline" mode. In this mode, it reads its parameters # from the command line or (failing that) from standard input. Otherwise, # cookies and other parameters are parsed automatically from the standard # CGI locations, which varies according to the REQUEST_METHOD. def initialize(options = {}, &block) # :yields: name, value @accept_charset_error_block = block_given? ? block : nil @options={ :accept_charset=>@@accept_charset, :max_multipart_length=>@@max_multipart_length } case options when Hash @options.merge!(options) when String @options[:tag_maker]=options end @accept_charset=@options[:accept_charset] @max_multipart_length=@options[:max_multipart_length] if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE") Apache.request.setup_cgi_env end extend QueryExtension @multipart = false initialize_query() # set @params, @cookies @output_cookies = nil @output_hidden = nil case @options[:tag_maker] when "html3" require 'cgi/html' extend Html3 extend HtmlExtension when "html4" require 'cgi/html' extend Html4 extend HtmlExtension when "html4Tr" require 'cgi/html' extend Html4Tr extend HtmlExtension when "html4Fr" require 'cgi/html' extend Html4Tr extend Html4Fr extend HtmlExtension when "html5" require 'cgi/html' extend Html5 extend HtmlExtension end end end # class CGI PK!m'$4OO escape.sonuȯELF>@H@8 @@2@2 == =  == = 888$$ 2 2 2 Std 2 2 2 Ptd///||QtdRtd== = GNUs}ܗrfMe1,R 0,./BE|qXLU -  C;d/wQt ^u"  $U^, EF"lNA )@A A 5 `#m $3__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_to_encodingrb_enc_to_indexrb_str_catruby_digit36_to_number_tablerb_str_buf_newrb_enc_getrb_enc_associaterb_enc_get_indexrb_str_duprb_enc_associate_indexrb_enc_str_coderange__stack_chk_failrb_cFalseClassrb_cvar_getrb_cFloatrb_cIntegerrb_cNilClassrb_cTrueClassrb_cSymbolruby_hexdigitsrb_str_newrb_free_tmp_bufferrb_alloc_tmp_buffer_with_countruby_malloc_size_overflowrb_string_valuerb_enc_dummy_prb_call_superrb_error_aritystrcasecmpruby_scan_digitsInitVM_escaperb_cObjectrb_define_classrb_define_module_underrb_define_aliasrb_prepend_modulerb_extend_objectInit_escaperb_ext_ractor_saferb_intern2rb_define_methodlibruby.so.4.0libm.so.6libpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.4GLIBC_2.2.5/opt/alt/ruby40/lib64 ii .ui 8= = @= = ? ? ? ? ?  ? ? ? ? ? $? %? &? *@  @ (@ 0@ /8@ @@  H@  P@  X@  `@ h@ p@ x@ @ @ @ @ @ @ @ @ @ @ @  @ !@ "@ #@ &@ 'A (A )A +HH0 HtH5B0 %C0 hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhh%=. D%5. D%-. D%%. D%. D%. D% . D%. D%- D%- D%- D%- D%- D%- D%- D%- D%- D%- D%- D%- D%- D%- D%- D%- D%}- D%u- D%m- D%e- D%]- D%U- D%M- D%E- DH=A- H:- H9tH+ Ht H=- H5 - H)HHH?HHtH+ HtfD=, u+UH=+ Ht H=.) d, ]wAWAVAUATUSHLsH8H|$H$dH%(HD$(1HSH HkD$HL$ tLsHq11Ll$'E1X<+$D$' MHLHM|$H)L7LH'LL9C><%uMgI9CT>Ѓ0 v ƒ߃Aw`C|>0 v׃߃A@wBH=)  D$'HYHHt$Ht$H?@IL9`HtfHH1H)LcH|$HH.H|$AċD$D9uPHL$(dH3 %(HH8[]A\A]A^A_fLt$LsHIH$,$0fDHH1uDHmtHHcH%H H+jff.fH59* HuH( H8ED@u H1Ht:HtD@u@ tHH( H8 fH( H8@Hi( H8@Hi( H8@H( H8wAWAVAUATUHoSHHLoH|$(dH %(HL$81HD$4D$4%HL$ tHoMfHD$41E11HD$L% D$DD|LrAGfHL)Jt H7A }|$tvH5 HMLM9uHJt L)HH|$(HHHL$8dH3 %(HHH[]A\A]A^A_DH& MHAHt$DD$5ADD$6tMLM9YLLL$ HT$LL$ HT$H@H|$(HMUHAUATSHLWdH%(HE1HTUUUUUUI9K4RIHHHHHEHHH)HH9tHH$H9u%aHD$H]HIT$I$ tIT$NI9cIL AII9tOHrHA4@tDItAAEtAAMI9uI)M9LHLIsLHHPLH]dH3%(He[A\A]]HIDH|I|IxLHH)H)DHifDLIHVH]HH|MT$fH)HLfADtAt f.E1DtfAtLATUSHdH%(HD$1GHHHIH$H<$(xu Ht&HHL$dH3 %(uHH[]A\uHuH<$YLHܺff.@SHH\$Ht$HH|${xu%HuH|$H[fH޿H[ff.fAWAVAUATUSHxHt$HH\$HHdH%(HD$h1lH|$Hxu Htt@H޿cIHL$hdH3 %(LMHx[]A\A]A^A_f.Lt$HLH5HXHD$0HKHD$t#H5H/H%HHD$MfMnI tMnM=HL$SE1Lt$E1H $HL$b1MHL$8HL$THL$HL$XHL$ fDATHhT$S&IM)I9AT-T$SgG#haukHhLH)H~CIT-:pos;u=HXD$S'M@LL\$(L\$(IfDuIT-f:mpnfDHI9HhLI|-H)HH~ʃ0 ߀XHXLH)HI|Ѓ0 v߃A<HL$ LD$L\$(L\$(HTHhLH)HdfA|t;VHXD$SSHH\$Ht$HH|$;xu%HuH|$H[@H޿H[ff.fSHH\$Ht$HEH|$xu%HMuH|$1H[H޿#H[ff.fATUSHdH%(HD$1GHHHIH$H<$8xu Ht&HHL$dH3 %(uHH[]A\uHuH<$1lf.LHܺff.@HH9 H=H0BH5HH H= H5H H=s HH5Ha H=M HH5^H=. HH5NH= H;H5IH= HQH5H= HH5[H= H8H5LH= H H5-H5~ H= H5k H=t H#HH=H& HHH+UTF-8ISO-8859-1mp;CGIEscapeExtEscapeunescapeHTMLunescapeURIComponentunescape_uri_componentunescape@@accept_charset"&'<>;|$8Pp\ `zRx $ FJ w?:*3$"DH\CBBB B(A0A8Kp 8A0A(B BBBC L@BBB B(A0E8D  8A0A(B BBBD ( MAC Is H 08FAA F0j  AABD $lcED | AJ QAHFBB B(A0A8Di 8A0A(B BBBK (LcED A AE QA$ cED ~ AH QA04FAA F0j  AABD htmH`3HfGNU@=  D  %= = o`0 Z @    o oo o=  0@P`p 0@P`pGA$3a1% GA$3p1113%GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONSescape.so-4.0.5-3.el8.x86_64.debug67zXZִF!t/]?Eh=ڊ2N`w͞ AKKN>JqwWƒ%.%Rud׶pYX+dlC6unG.NqܠPS f}|.qmZ)gM|@ilD1!pL#q97W8rz9R:fFj[6=$kGE3 L炍-s:x<` ,Q QN: U3|rԱ{맊 Z:QRR,6jrܥa&싿B3hXiKk=e PU{swcEu}Be;Ⓧ$%9 (| KxuXcw^z(y};w"wh6q8I0n R|A>u{C~- fvTrȦ^|#׿ѳ%)mi UW[Òvm2_4]AxTؙV֩-]u'y};Dc,{ˈABboOɹ@Mʀْ'_\߉-{+z]l> ^w@0XW ٽ&Uhәn@(Mg|#@r%*?,#s-DžH\87rB[XW,L2($F~"@^,Ý DWqP&6YjLCDӱgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``8( 000Z8o bEo 0T ^B hcnw3}%%  % % //|// 2 2 = == == == =? ?h@ @A A(@A`AH `C(CdG+PK!c;; escape.rbnu[# frozen_string_literal: true # Since Ruby 4.0, \CGI is a small holder for various escaping methods, included from CGI::Escape # # require 'cgi/escape' # # CGI.escape("Ruby programming language") # #=> "Ruby+programming+language" # CGI.escapeURIComponent("Ruby programming language") # #=> "Ruby%20programming%20language" # # See CGI::Escape module for methods list and their description. class CGI module Escape; end include Escape extend Escape module EscapeExt; end # :nodoc: end # Web-related escape/unescape functionality. module CGI::Escape @@accept_charset = Encoding::UTF_8 unless defined?(@@accept_charset) # URL-encode a string into application/x-www-form-urlencoded. # Space characters (" ") are encoded with plus signs ("+") # url_encoded_string = CGI.escape("'Stop!' said Fred") # # => "%27Stop%21%27+said+Fred" def escape(string) encoding = string.encoding buffer = string.b buffer.gsub!(/([^ a-zA-Z0-9_.\-~]+)/) do |m| '%' + m.unpack('H2' * m.bytesize).join('%').upcase end buffer.tr!(' ', '+') buffer.force_encoding(encoding) end # URL-decode an application/x-www-form-urlencoded string with encoding(optional). # string = CGI.unescape("%27Stop%21%27+said+Fred") # # => "'Stop!' said Fred" def unescape(string, encoding = @@accept_charset) str = string.tr('+', ' ') str = str.b str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m| [m.delete('%')].pack('H*') end str.force_encoding(encoding) str.valid_encoding? ? str : str.force_encoding(string.encoding) end # URL-encode a string following RFC 3986 # Space characters (" ") are encoded with ("%20") # url_encoded_string = CGI.escapeURIComponent("'Stop!' said Fred") # # => "%27Stop%21%27%20said%20Fred" def escapeURIComponent(string) encoding = string.encoding buffer = string.b buffer.gsub!(/([^a-zA-Z0-9_.\-~]+)/) do |m| '%' + m.unpack('H2' * m.bytesize).join('%').upcase end buffer.force_encoding(encoding) end alias escape_uri_component escapeURIComponent # URL-decode a string following RFC 3986 with encoding(optional). # string = CGI.unescapeURIComponent("%27Stop%21%27+said%20Fred") # # => "'Stop!'+said Fred" def unescapeURIComponent(string, encoding = @@accept_charset) str = string.b str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m| [m.delete('%')].pack('H*') end str.force_encoding(encoding) str.valid_encoding? ? str : str.force_encoding(string.encoding) end alias unescape_uri_component unescapeURIComponent # The set of special characters and their escaped values TABLE_FOR_ESCAPE_HTML__ = { # :nodoc: "'" => ''', '&' => '&', '"' => '"', '<' => '<', '>' => '>', } # \Escape special characters in HTML, namely '&\"<> # CGI.escapeHTML('Usage: foo "bar" ') # # => "Usage: foo "bar" <baz>" def escapeHTML(string) enc = string.encoding unless enc.ascii_compatible? if enc.dummy? origenc = enc enc = Encoding::Converter.asciicompat_encoding(enc) string = enc ? string.encode(enc) : string.b end table = Hash[TABLE_FOR_ESCAPE_HTML__.map {|pair|pair.map {|s|s.encode(enc)}}] string = string.gsub(/#{"['&\"<>]".encode(enc)}/, table) string.encode!(origenc) if origenc string else string = string.b string.gsub!(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__) string.force_encoding(enc) end end # Unescape a string that has been HTML-escaped # CGI.unescapeHTML("Usage: foo "bar" <baz>") # # => "Usage: foo \"bar\" " def unescapeHTML(string) enc = string.encoding unless enc.ascii_compatible? if enc.dummy? origenc = enc enc = Encoding::Converter.asciicompat_encoding(enc) string = enc ? string.encode(enc) : string.b end string = string.gsub(Regexp.new('&(apos|amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do case $1.encode(Encoding::US_ASCII) when 'apos' then "'".encode(enc) when 'amp' then '&'.encode(enc) when 'quot' then '"'.encode(enc) when 'gt' then '>'.encode(enc) when 'lt' then '<'.encode(enc) when /\A#0*(\d+)\z/ then $1.to_i.chr(enc) when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc) end end string.encode!(origenc) if origenc return string end return string unless string.include? '&' charlimit = case enc when Encoding::UTF_8; 0x10ffff when Encoding::ISO_8859_1; 256 else 128 end string = string.b string.gsub!(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do match = $1.dup case match when 'apos' then "'" when 'amp' then '&' when 'quot' then '"' when 'gt' then '>' when 'lt' then '<' when /\A#0*(\d+)\z/ n = $1.to_i if n < charlimit n.chr(enc) else "&##{$1};" end when /\A#x([0-9a-f]+)\z/i n = $1.hex if n < charlimit n.chr(enc) else "&#x#{$1};" end else "&#{match};" end end string.force_encoding enc end alias escape_html escapeHTML alias h escapeHTML alias unescape_html unescapeHTML # TruffleRuby runs the pure-Ruby variant faster, do not use the C extension there unless RUBY_ENGINE == 'truffleruby' begin require 'cgi/escape.so' rescue LoadError end end # \Escape only the tags of certain HTML elements in +string+. # # Takes an element or elements or array of elements. Each element # is specified by the name of the element, without angle brackets. # This matches both the start and the end tag of that element. # The attribute list of the open tag will also be escaped (for # instance, the double-quotes surrounding attribute values). # # print CGI.escapeElement('
', "A", "IMG") # # "
<A HREF="url"></A>" # # print CGI.escapeElement('
', ["A", "IMG"]) # # "
<A HREF="url"></A>" def escapeElement(string, *elements) elements = elements[0] if elements[0].kind_of?(Array) unless elements.empty? string.gsub(/<\/?(?:#{elements.join("|")})\b[^<>]*+>?/im) do CGI.escapeHTML($&) end else string end end # Undo escaping such as that done by CGI.escapeElement # # print CGI.unescapeElement( # CGI.escapeHTML('
'), "A", "IMG") # # "<BR>" # # print CGI.unescapeElement( # CGI.escapeHTML('
'), ["A", "IMG"]) # # "<BR>" def unescapeElement(string, *elements) elements = elements[0] if elements[0].kind_of?(Array) unless elements.empty? string.gsub(/<\/?(?:#{elements.join("|")})\b(?>[^&]+|&(?![gl]t;)\w+;)*(?:>)?/im) do unescapeHTML($&) end else string end end alias escape_element escapeElement alias unescape_element unescapeElement end PK!.cgi2.pycnu[ Afc@sKdZddlZejddlZdZedkrGendS(s%CGI test 2 - basic use of cgi module.iNcCsptj}dGHH|s dGHnLdGHxD|jD]6}||j}dGtj|GdGtj|GHq2WdS(NsContent-type: text/htmls

No Form Keys

s

Form Keys

s

t:(tcgit FieldStoragetkeystvaluetescape(tformtkeyR((s%/usr/lib64/python2.7/Demo/cgi/cgi2.pytmain s  t__main__(t__doc__tcgitbtenableRRt__name__(((s%/usr/lib64/python2.7/Demo/cgi/cgi2.pyts    PK!.cgi2.pyonu[ Afc@sKdZddlZejddlZdZedkrGendS(s%CGI test 2 - basic use of cgi module.iNcCsptj}dGHH|s dGHnLdGHxD|jD]6}||j}dGtj|GdGtj|GHq2WdS(NsContent-type: text/htmls

No Form Keys

s

Form Keys

s

t:(tcgit FieldStoragetkeystvaluetescape(tformtkeyR((s%/usr/lib64/python2.7/Demo/cgi/cgi2.pytmain s  t__main__(t__doc__tcgitbtenableRRt__name__(((s%/usr/lib64/python2.7/Demo/cgi/cgi2.pyts    PK!RqREADMEnu[CGI Examples ------------ Here are some example CGI programs. For a larger example, see ../../Tools/faqwiz/. cgi0.sh -- A shell script to test your server is configured for CGI cgi1.py -- A Python script to test your server is configured for CGI cgi2.py -- A Python script showing how to parse a form cgi3.py -- A Python script for driving an arbitrary CGI application wiki.py -- Sample CGI application: a minimal Wiki implementation PK!6fcgi3.pynuȯ#! /usr/bin/python2.7 """CGI test 3 (persistent data).""" import cgitb; cgitb.enable() from wiki import main if __name__ == "__main__": main() PK!4cgi2.pynuȯ#! /usr/bin/python2.7 """CGI test 2 - basic use of cgi module.""" import cgitb; cgitb.enable() import cgi def main(): form = cgi.FieldStorage() print "Content-type: text/html" print if not form: print "

No Form Keys

" else: print "

Form Keys

" for key in form.keys(): value = form[key].value print "

", cgi.escape(key), ":", cgi.escape(value) if __name__ == "__main__": main() PK!-hFFcgi3.pyonu[ Afc@sFdZddlZejddlmZedkrBendS(sCGI test 3 (persistent data).iN(tmaint__main__(t__doc__tcgitbtenabletwikiRt__name__(((s%/usr/lib64/python2.7/Demo/cgi/cgi3.pyts   PK!_cgi1.pynuȯ#! /usr/bin/python2.7 """CGI test 1 - check server setup.""" # Until you get this to work, your web server isn't set up right or # your Python isn't set up right. # If cgi0.sh works but cgi1.py doesn't, check the #! line and the file # permissions. The docs for the cgi.py module have debugging tips. print "Content-type: text/html" print print "

Hello world

" print "

This is cgi1.py" PK!-hFFcgi3.pycnu[ Afc@sFdZddlZejddlmZedkrBendS(sCGI test 3 (persistent data).iN(tmaint__main__(t__doc__tcgitbtenabletwikiRt__name__(((s%/usr/lib64/python2.7/Demo/cgi/cgi3.pyts   PK!-;wiki.pyonu[ ^c@skdZddlZddlZddlZddlZddlZejZdZdddYZdS(s0Wiki main program. Imported and run by cgi3.py.iNcCsotj}dGHH|jdd}|jdd}t|}t|d|dp^|j}||dS(NsContent-type: text/htmltcmdtviewtpaget FrontPagetcmd_(tcgit FieldStoragetgetvaluetWikiPagetgetattrtNonetcmd_view(tformRRtwikitmethod((s%/usr/lib64/python2.7/Demo/cgi/wiki.pytmains  RcBseZejZejjej dZ dZ dZ dZ ddZdZdZdZd Zdd Zd Zd Zd ZRS(icCs2|j|stdn||_|jdS(Nspage name is not a wiki word(t iswikiwordt ValueErrortnametload(tselfR((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyt__init__s  cCsdGt|j|jGdGHdGHx?|jjD].}|j}|sTdGHq4|j|GHq4WdGHdG|jd|jddGH|jdd d d GHdS( Ns

s

s

s


teditsEdit this paget;RRsgo to front paget.(tescapet splitwikiwordRtdatat splitlinestrstript formatlinetmklink(RR tline((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyR s cCsg}xtjd|D]}}|j|r}tjj|j|ra|jd||}q|jd||d}n t|}|j |qWdj |S(Ns(\W+)Rtnewt*t( tretsplitRtostpathtisfiletmkfileRRtappendtjoin(RR twordstword((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyR(s tChangecCsZdG|G|jGdGHd|jGHd}||jGHdGHd|jGHdGHd|GHd GHdS( Ns

s

s
s7s/s,s
s%s
(Rt scripturlR(RR tlabelts((s%/usr/lib64/python2.7/Demo/cgi/wiki.pytcmd_edit5s    cCs|jddj|_|j}|rIdGHdGHdGt|GHnJdGHd}||jd|jGHdGHd GHd G|jd |j|jGHdS( NttextR#s%

I'm sorry. That didn't work

s8

An error occurred while attempting to write the file:s

ss/s?cmd=view&page=s

OK

s)

If nothing happens, please click here:R(RtstripRtstoreRR/RR(RR terrorR1((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyt cmd_create@s cCs|j|dddS(NR0tCreate(R2(RR ((s%/usr/lib64/python2.7/Demo/cgi/wiki.pytcmd_newQscCstjd|S(Ns[A-Z][a-z]+([A-Z][a-z]*)+(R$tmatch(RR-((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyRTscCsSg}x=|D]5}|r5|jr5|jdn|j|q Wdj|S(Nt R#(tisupperR*R+(RR-tcharstc((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyRWs  cCs2|dkr|j}ntjj|j|dS(Ns.txt(R RR&R'R+thomedir(RR((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyR)_s  cCs'|jd|d|}d||fS(Ns?cmd=s&page=s%s(R/(RRRR3tlink((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyRdscCsYy2t|j}|jj}|jWntk rKd}nX||_dS(NR#(topenR)treadR4tclosetIOErrorR(RtfR((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyRhs  cCs|j}yZt|jd}|j||rT|jd rT|jdn|jdSWntk r}dt|SXdS(Ntws R#s IOError: %s(RRAR)twritetendswithRCRDtstr(RRREterr((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyR5qs   N(t__name__t __module__ttempfilet gettempdirR?R&R'tbasenametsystargvR/RR RR2R7R9RRR R)RRR5(((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyRs         (( t__doc__R&R$RRPRMRRR(((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyts<  PK!cgi1.pyonu[ Afc@sdZdGHHdGHdGHdS(s CGI test 1 - check server setup.sContent-type: text/htmls

Hello world

s

This is cgi1.pyN(t__doc__(((s%/usr/lib64/python2.7/Demo/cgi/cgi1.pytsPK!cgi1.pycnu[ Afc@sdZdGHHdGHdGHdS(s CGI test 1 - check server setup.sContent-type: text/htmls

Hello world

s

This is cgi1.pyN(t__doc__(((s%/usr/lib64/python2.7/Demo/cgi/cgi1.pytsPK!-;wiki.pycnu[ ^c@skdZddlZddlZddlZddlZddlZejZdZdddYZdS(s0Wiki main program. Imported and run by cgi3.py.iNcCsotj}dGHH|jdd}|jdd}t|}t|d|dp^|j}||dS(NsContent-type: text/htmltcmdtviewtpaget FrontPagetcmd_(tcgit FieldStoragetgetvaluetWikiPagetgetattrtNonetcmd_view(tformRRtwikitmethod((s%/usr/lib64/python2.7/Demo/cgi/wiki.pytmains  RcBseZejZejjej dZ dZ dZ dZ ddZdZdZdZd Zdd Zd Zd Zd ZRS(icCs2|j|stdn||_|jdS(Nspage name is not a wiki word(t iswikiwordt ValueErrortnametload(tselfR((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyt__init__s  cCsdGt|j|jGdGHdGHx?|jjD].}|j}|sTdGHq4|j|GHq4WdGHdG|jd|jddGH|jdd d d GHdS( Ns

s

s

s


teditsEdit this paget;RRsgo to front paget.(tescapet splitwikiwordRtdatat splitlinestrstript formatlinetmklink(RR tline((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyR s cCsg}xtjd|D]}}|j|r}tjj|j|ra|jd||}q|jd||d}n t|}|j |qWdj |S(Ns(\W+)Rtnewt*t( tretsplitRtostpathtisfiletmkfileRRtappendtjoin(RR twordstword((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyR(s tChangecCsZdG|G|jGdGHd|jGHd}||jGHdGHd|jGHdGHd|GHd GHdS( Ns

s

s
s7s/s,s
s%s
(Rt scripturlR(RR tlabelts((s%/usr/lib64/python2.7/Demo/cgi/wiki.pytcmd_edit5s    cCs|jddj|_|j}|rIdGHdGHdGt|GHnJdGHd}||jd|jGHdGHd GHd G|jd |j|jGHdS( NttextR#s%

I'm sorry. That didn't work

s8

An error occurred while attempting to write the file:s

ss/s?cmd=view&page=s

OK

s)

If nothing happens, please click here:R(RtstripRtstoreRR/RR(RR terrorR1((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyt cmd_create@s cCs|j|dddS(NR0tCreate(R2(RR ((s%/usr/lib64/python2.7/Demo/cgi/wiki.pytcmd_newQscCstjd|S(Ns[A-Z][a-z]+([A-Z][a-z]*)+(R$tmatch(RR-((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyRTscCsSg}x=|D]5}|r5|jr5|jdn|j|q Wdj|S(Nt R#(tisupperR*R+(RR-tcharstc((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyRWs  cCs2|dkr|j}ntjj|j|dS(Ns.txt(R RR&R'R+thomedir(RR((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyR)_s  cCs'|jd|d|}d||fS(Ns?cmd=s&page=s%s(R/(RRRR3tlink((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyRdscCsYy2t|j}|jj}|jWntk rKd}nX||_dS(NR#(topenR)treadR4tclosetIOErrorR(RtfR((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyRhs  cCs|j}yZt|jd}|j||rT|jd rT|jdn|jdSWntk r}dt|SXdS(Ntws R#s IOError: %s(RRAR)twritetendswithRCRDtstr(RRREterr((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyR5qs   N(t__name__t __module__ttempfilet gettempdirR?R&R'tbasenametsystargvR/RR RR2R7R9RRR R)RRR5(((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyRs         (( t__doc__R&R$RRPRMRRR(((s%/usr/lib64/python2.7/Demo/cgi/wiki.pyts<  PK!7wiki.pynu["""Wiki main program. Imported and run by cgi3.py.""" import os, re, cgi, sys, tempfile escape = cgi.escape def main(): form = cgi.FieldStorage() print "Content-type: text/html" print cmd = form.getvalue("cmd", "view") page = form.getvalue("page", "FrontPage") wiki = WikiPage(page) method = getattr(wiki, 'cmd_' + cmd, None) or wiki.cmd_view method(form) class WikiPage: homedir = tempfile.gettempdir() scripturl = os.path.basename(sys.argv[0]) def __init__(self, name): if not self.iswikiword(name): raise ValueError, "page name is not a wiki word" self.name = name self.load() def cmd_view(self, form): print "

", escape(self.splitwikiword(self.name)), "

" print "

" for line in self.data.splitlines(): line = line.rstrip() if not line: print "

" else: print self.formatline(line) print "


" print "

", self.mklink("edit", self.name, "Edit this page") + ";" print self.mklink("view", "FrontPage", "go to front page") + "." def formatline(self, line): words = [] for word in re.split('(\W+)', line): if self.iswikiword(word): if os.path.isfile(self.mkfile(word)): word = self.mklink("view", word, word) else: word = self.mklink("new", word, word + "*") else: word = escape(word) words.append(word) return "".join(words) def cmd_edit(self, form, label="Change"): print "

", label, self.name, "

" print '
' % self.scripturl s = '' print s % self.data print '' print '' % self.name print '
' print '' % label print "
" def cmd_create(self, form): self.data = form.getvalue("text", "").strip() error = self.store() if error: print "

I'm sorry. That didn't work

" print "

An error occurred while attempting to write the file:" print "

", escape(error) else: # Use a redirect directive, to avoid "reload page" problems print "" s = '' print s % (self.scripturl + "?cmd=view&page=" + self.name) print "" print "

OK

" print "

If nothing happens, please click here:", print self.mklink("view", self.name, self.name) def cmd_new(self, form): self.cmd_edit(form, label="Create") def iswikiword(self, word): return re.match("[A-Z][a-z]+([A-Z][a-z]*)+", word) def splitwikiword(self, word): chars = [] for c in word: if chars and c.isupper(): chars.append(' ') chars.append(c) return "".join(chars) def mkfile(self, name=None): if name is None: name = self.name return os.path.join(self.homedir, name + ".txt") def mklink(self, cmd, page, text): link = self.scripturl + "?cmd=" + cmd + "&page=" + page return '%s' % (link, text) def load(self): try: f = open(self.mkfile()) data = f.read().strip() f.close() except IOError: data = "" self.data = data def store(self): data = self.data try: f = open(self.mkfile(), "w") f.write(data) if data and not data.endswith('\n'): f.write('\n') f.close() return "" except IOError, err: return "IOError: %s" % str(err) PK!``Mcgi0.shnuȯ#! /bin/sh # If you can't get this to work, your web server isn't set up right echo Content-type: text/plain echo echo Hello world echo This is cgi0.sh PK!') cookie.rbnu[PK!@Wll%html.rbnu[PK!}] ȝsession/pstore.rbnu[PK!b>util.rbnu[PK!l[H[H {session.rbnu[PK!n*rr core.rbnu[PK!m'$4OO ~escape.sonuȯPK!c;; escape.rbnu[PK!.Ucgi2.pycnu[PK!.fcgi2.pyonu[PK!RqwREADMEnu[PK!6fbcgi3.pynuȯPK!40cgi2.pynuȯPK!-hFF=cgi3.pyonu[PK!_cgi1.pynuȯPK!-hFFcgi3.pycnu[PK!-;wiki.pyonu[PK!9cgi1.pyonu[PK!cgi1.pycnu[PK!-;wiki.pycnu[PK!7)wiki.pynu[PK!``M 9cgi0.shnuȯPK49