-
-
Notifications
You must be signed in to change notification settings - Fork 925
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/truffle-head'
- 9.4.12.0
- 9.4.11.0
- 9.4.10.0
- 9.4.9.0
- 9.4.8.0
- 9.4.7.0
- 9.4.6.0
- 9.4.5.0
- 9.4.4.0
- 9.4.3.0
- 9.4.2.0
- 9.4.1.0
- 9.4.0.0
- 9.3.15.0
- 9.3.14.0
- 9.3.13.0
- 9.3.12.0
- 9.3.11.0
- 9.3.10.0
- 9.3.9.0
- 9.3.8.0
- 9.3.7.0
- 9.3.6.0
- 9.3.5.0
- 9.3.4.0
- 9.3.3.0
- 9.3.2.0
- 9.3.1.0
- 9.3.0.0
- 9.2.21.0
- 9.2.20.1
- 9.2.20.0
- 9.2.19.0
- 9.2.18.0
- 9.2.17.0
- 9.2.16.0
- 9.2.15.0
- 9.2.14.0
- 9.2.13.0
- 9.2.12.0
- 9.2.11.1
- 9.2.11.0
- 9.2.10.0
- 9.2.9.0
- 9.2.8.0
- 9.2.7.0
- 9.2.6.0
- 9.2.5.0
- 9.2.4.1
- 9.2.4.0
- 9.2.3.0
- 9.2.2.0
- 9.2.1.0
- 9.2.0.0
- 9.1.17.0
- 9.1.16.0
- 9.1.15.0
- 9.1.14.0
- 9.1.13.0
- 9.1.12.0
- 9.1.11.0
- 9.1.10.0
- 9.1.9.0
- 9.1.8.0
- 9.1.7.0
Showing
1,009 changed files
with
189,445 additions
and
3,582 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
#!/usr/bin/env bash | ||
|
||
bin="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
root="$(dirname "$bin")" | ||
|
||
exec "$bin"/jruby -X+T "$@" | ||
exec "$root"/tool/jt.rb ruby --no-print-cmd "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
lib/ruby/stdlib/ffi/platform/sparcv9-solaris/fcntl-flock.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# This file is generated by rake. Do not edit. | ||
|
||
module Fcntl | ||
class Flock < FFI::Struct | ||
layout :l_type, :short, 0, | ||
:l_whence, :short, 2, | ||
:l_start, :off_t, 8, | ||
:l_len, :off_t, 16, | ||
:l_sysid, :int, 24, | ||
:l_pid, :int, 28, | ||
:l_pad, :int, 32 | ||
|
||
|
||
|
||
|
||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
884 changes: 884 additions & 0 deletions
884
lib/ruby/truffle/jruby-truffle-tool/lib/truffle/actionview_exclusions.yaml
Large diffs are not rendered by default.
Oops, something went wrong.
3 changes: 3 additions & 0 deletions
3
lib/ruby/truffle/jruby-truffle-tool/lib/truffle/activesupport_exclusions.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--- | ||
TimeExtMarshalingTest: | ||
- test_marshalling_preserves_fractional_seconds |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,191 @@ | ||
require_relative '../../stdlib/English' | ||
# frozen_string_literal: false | ||
# | ||
# Modified for JRuby | ||
# In JRuby, we define these aliases by default, so this file | ||
# does nothing. | ||
# | ||
# Include the English library file in a Ruby script, and you can | ||
# reference the global variables such as \VAR{\$\_} using less | ||
# cryptic names, listed in the following table.% \vref{tab:english}. | ||
# | ||
# Without 'English': | ||
# | ||
# $\ = ' -- ' | ||
# "waterbuffalo" =~ /buff/ | ||
# print $', $$, "\n" | ||
# | ||
# With English: | ||
# | ||
# require "English" | ||
# | ||
# $OUTPUT_FIELD_SEPARATOR = ' -- ' | ||
# "waterbuffalo" =~ /buff/ | ||
# print $POSTMATCH, $PID, "\n" | ||
# | ||
# Below is a full list of descriptive aliases and their associated global | ||
# variable: | ||
# | ||
# $ERROR_INFO:: $! | ||
# $ERROR_POSITION:: $@ | ||
# $FS:: $; | ||
# $FIELD_SEPARATOR:: $; | ||
# $OFS:: $, | ||
# $OUTPUT_FIELD_SEPARATOR:: $, | ||
# $RS:: $/ | ||
# $INPUT_RECORD_SEPARATOR:: $/ | ||
# $ORS:: $\ | ||
# $OUTPUT_RECORD_SEPARATOR:: $\ | ||
# $INPUT_LINE_NUMBER:: $. | ||
# $NR:: $. | ||
# $LAST_READ_LINE:: $_ | ||
# $DEFAULT_OUTPUT:: $> | ||
# $DEFAULT_INPUT:: $< | ||
# $PID:: $$ | ||
# $PROCESS_ID:: $$ | ||
# $CHILD_STATUS:: $? | ||
# $LAST_MATCH_INFO:: $~ | ||
# $IGNORECASE:: $= | ||
# $ARGV:: $* | ||
# $MATCH:: $& | ||
# $PREMATCH:: $` | ||
# $POSTMATCH:: $' | ||
# $LAST_PAREN_MATCH:: $+ | ||
# | ||
module English end if false | ||
|
||
# The exception object passed to +raise+. | ||
#alias $ERROR_INFO $! | ||
|
||
# The stack backtrace generated by the last | ||
# exception. <tt>See Kernel.caller</tt> for details. Thread local. | ||
#alias $ERROR_POSITION $@ | ||
|
||
# The default separator pattern used by <tt>String.split</tt>. May be | ||
# set from the command line using the <tt>-F</tt> flag. | ||
#alias $FS $; | ||
|
||
# The default separator pattern used by <tt>String.split</tt>. May be | ||
# set from the command line using the <tt>-F</tt> flag. | ||
#alias $FIELD_SEPARATOR $; | ||
|
||
# The separator string output between the parameters to methods such | ||
# as <tt>Kernel.print</tt> and <tt>Array.join</tt>. Defaults to +nil+, | ||
# which adds no text. | ||
#alias $OFS $, | ||
|
||
# The separator string output between the parameters to methods such | ||
# as <tt>Kernel.print</tt> and <tt>Array.join</tt>. Defaults to +nil+, | ||
# which adds no text. | ||
#alias $OUTPUT_FIELD_SEPARATOR $, | ||
|
||
# The input record separator (newline by default). This is the value | ||
# that routines such as <tt>Kernel.gets</tt> use to determine record | ||
# boundaries. If set to +nil+, +gets+ will read the entire file. | ||
#alias $RS $/ | ||
|
||
# The input record separator (newline by default). This is the value | ||
# that routines such as <tt>Kernel.gets</tt> use to determine record | ||
# boundaries. If set to +nil+, +gets+ will read the entire file. | ||
#alias $INPUT_RECORD_SEPARATOR $/ | ||
|
||
# The string appended to the output of every call to methods such as | ||
# <tt>Kernel.print</tt> and <tt>IO.write</tt>. The default value is | ||
# +nil+. | ||
#alias $ORS $\ | ||
|
||
# The string appended to the output of every call to methods such as | ||
# <tt>Kernel.print</tt> and <tt>IO.write</tt>. The default value is | ||
# +nil+. | ||
#alias $OUTPUT_RECORD_SEPARATOR $\ | ||
|
||
# The number of the last line read from the current input file. | ||
#alias $INPUT_LINE_NUMBER $. | ||
|
||
# The number of the last line read from the current input file. | ||
#alias $NR $. | ||
|
||
# The last line read by <tt>Kernel.gets</tt> or | ||
# <tt>Kernel.readline</tt>. Many string-related functions in the | ||
# +Kernel+ module operate on <tt>$_</tt> by default. The variable is | ||
# local to the current scope. Thread local. | ||
#alias $LAST_READ_LINE $_ | ||
|
||
# The destination of output for <tt>Kernel.print</tt> | ||
# and <tt>Kernel.printf</tt>. The default value is | ||
# <tt>$stdout</tt>. | ||
#alias $DEFAULT_OUTPUT $> | ||
|
||
# An object that provides access to the concatenation | ||
# of the contents of all the files | ||
# given as command-line arguments, or <tt>$stdin</tt> | ||
# (in the case where there are no | ||
# arguments). <tt>$<</tt> supports methods similar to a | ||
# +File+ object: | ||
# +inmode+, +close+, | ||
# <tt>closed?</tt>, +each+, | ||
# <tt>each_byte</tt>, <tt>each_line</tt>, | ||
# +eof+, <tt>eof?</tt>, +file+, | ||
# +filename+, +fileno+, | ||
# +getc+, +gets+, +lineno+, | ||
# <tt>lineno=</tt>, +path+, | ||
# +pos+, <tt>pos=</tt>, | ||
# +read+, +readchar+, | ||
# +readline+, +readlines+, | ||
# +rewind+, +seek+, +skip+, | ||
# +tell+, <tt>to_a</tt>, <tt>to_i</tt>, | ||
# <tt>to_io</tt>, <tt>to_s</tt>, along with the | ||
# methods in +Enumerable+. The method +file+ | ||
# returns a +File+ object for the file currently | ||
# being read. This may change as <tt>$<</tt> reads | ||
# through the files on the command line. Read only. | ||
#alias $DEFAULT_INPUT $< | ||
|
||
# The process number of the program being executed. Read only. | ||
#alias $PID $$ | ||
|
||
# The process number of the program being executed. Read only. | ||
#alias $PROCESS_ID $$ | ||
|
||
# The exit status of the last child process to terminate. Read | ||
# only. Thread local. | ||
#alias $CHILD_STATUS $? | ||
|
||
# A +MatchData+ object that encapsulates the results of a successful | ||
# pattern match. The variables <tt>$&</tt>, <tt>$`</tt>, <tt>$'</tt>, | ||
# and <tt>$1</tt> to <tt>$9</tt> are all derived from | ||
# <tt>$~</tt>. Assigning to <tt>$~</tt> changes the values of these | ||
# derived variables. This variable is local to the current | ||
# scope. | ||
#alias $LAST_MATCH_INFO $~ | ||
|
||
# If set to any value apart from +nil+ or +false+, all pattern matches | ||
# will be case insensitive, string comparisons will ignore case, and | ||
# string hash values will be case insensitive. Deprecated | ||
#alias $IGNORECASE $= | ||
|
||
# An array of strings containing the command-line | ||
# options from the invocation of the program. Options | ||
# used by the Ruby interpreter will have been | ||
# removed. Read only. Also known simply as +ARGV+. | ||
#alias $ARGV $* | ||
|
||
# The string matched by the last successful pattern | ||
# match. This variable is local to the current | ||
# scope. Read only. | ||
#alias $MATCH $& | ||
|
||
# The string preceding the match in the last | ||
# successful pattern match. This variable is local to | ||
# the current scope. Read only. | ||
#alias $PREMATCH $` | ||
|
||
# The string following the match in the last | ||
# successful pattern match. This variable is local to | ||
# the current scope. Read only. | ||
#alias $POSTMATCH $' | ||
|
||
# The contents of the highest-numbered group matched in the last | ||
# successful pattern match. Thus, in <tt>"cat" =~ /(c|a)(t|z)/</tt>, | ||
# <tt>$+</tt> will be set to "t". This variable is local to the | ||
# current scope. Read only. | ||
#alias $LAST_PAREN_MATCH $+ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,132 @@ | ||
require_relative '../../stdlib/abbrev' | ||
# frozen_string_literal: false | ||
#-- | ||
# Copyright (c) 2001,2003 Akinori MUSHA <knu@iDaemons.org> | ||
# | ||
# All rights reserved. You can redistribute and/or modify it under | ||
# the same terms as Ruby. | ||
# | ||
# $Idaemons: /home/cvs/rb/abbrev.rb,v 1.2 2001/05/30 09:37:45 knu Exp $ | ||
# $RoughId: abbrev.rb,v 1.4 2003/10/14 19:45:42 knu Exp $ | ||
# $Id$ | ||
#++ | ||
|
||
## | ||
# Calculates the set of unambiguous abbreviations for a given set of strings. | ||
# | ||
# require 'abbrev' | ||
# require 'pp' | ||
# | ||
# pp Abbrev.abbrev(['ruby']) | ||
# #=> {"ruby"=>"ruby", "rub"=>"ruby", "ru"=>"ruby", "r"=>"ruby"} | ||
# | ||
# pp Abbrev.abbrev(%w{ ruby rules }) | ||
# | ||
# _Generates:_ | ||
# { "ruby" => "ruby", | ||
# "rub" => "ruby", | ||
# "rules" => "rules", | ||
# "rule" => "rules", | ||
# "rul" => "rules" } | ||
# | ||
# It also provides an array core extension, Array#abbrev. | ||
# | ||
# pp %w{ summer winter }.abbrev | ||
# | ||
# _Generates:_ | ||
# { "summer" => "summer", | ||
# "summe" => "summer", | ||
# "summ" => "summer", | ||
# "sum" => "summer", | ||
# "su" => "summer", | ||
# "s" => "summer", | ||
# "winter" => "winter", | ||
# "winte" => "winter", | ||
# "wint" => "winter", | ||
# "win" => "winter", | ||
# "wi" => "winter", | ||
# "w" => "winter" } | ||
|
||
module Abbrev | ||
|
||
# Given a set of strings, calculate the set of unambiguous abbreviations for | ||
# those strings, and return a hash where the keys are all the possible | ||
# abbreviations and the values are the full strings. | ||
# | ||
# Thus, given +words+ is "car" and "cone", the keys pointing to "car" would | ||
# be "ca" and "car", while those pointing to "cone" would be "co", "con", and | ||
# "cone". | ||
# | ||
# require 'abbrev' | ||
# | ||
# Abbrev.abbrev(%w{ car cone }) | ||
# #=> {"ca"=>"car", "con"=>"cone", "co"=>"cone", "car"=>"car", "cone"=>"cone"} | ||
# | ||
# The optional +pattern+ parameter is a pattern or a string. Only input | ||
# strings that match the pattern or start with the string are included in the | ||
# output hash. | ||
# | ||
# Abbrev.abbrev(%w{car box cone crab}, /b/) | ||
# #=> {"box"=>"box", "bo"=>"box", "b"=>"box", "crab" => "crab"} | ||
# | ||
# Abbrev.abbrev(%w{car box cone}, 'ca') | ||
# #=> {"car"=>"car", "ca"=>"car"} | ||
def abbrev(words, pattern = nil) | ||
table = {} | ||
seen = Hash.new(0) | ||
|
||
if pattern.is_a?(String) | ||
pattern = /\A#{Regexp.quote(pattern)}/ # regard as a prefix | ||
end | ||
|
||
words.each do |word| | ||
next if word.empty? | ||
word.size.downto(1) { |len| | ||
abbrev = word[0...len] | ||
|
||
next if pattern && pattern !~ abbrev | ||
|
||
case seen[abbrev] += 1 | ||
when 1 | ||
table[abbrev] = word | ||
when 2 | ||
table.delete(abbrev) | ||
else | ||
break | ||
end | ||
} | ||
end | ||
|
||
words.each do |word| | ||
next if pattern && pattern !~ word | ||
|
||
table[word] = word | ||
end | ||
|
||
table | ||
end | ||
|
||
module_function :abbrev | ||
end | ||
|
||
class Array | ||
# Calculates the set of unambiguous abbreviations for the strings in +self+. | ||
# | ||
# require 'abbrev' | ||
# %w{ car cone }.abbrev | ||
# #=> {"car"=>"car", "ca"=>"car", "cone"=>"cone", "con"=>"cone", "co"=>"cone"} | ||
# | ||
# The optional +pattern+ parameter is a pattern or a string. Only input | ||
# strings that match the pattern or start with the string are included in the | ||
# output hash. | ||
# | ||
# %w{ fast boat day }.abbrev(/^.a/) | ||
# #=> {"fast"=>"fast", "fas"=>"fast", "fa"=>"fast", "day"=>"day", "da"=>"day"} | ||
# | ||
# Abbrev.abbrev(%w{car box cone}, "ca") | ||
# #=> {"car"=>"car", "ca"=>"car"} | ||
# | ||
# See also Abbrev.abbrev | ||
def abbrev(pattern = nil) | ||
Abbrev::abbrev(self, pattern) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,107 @@ | ||
require_relative '../../stdlib/base64' | ||
# frozen_string_literal: false | ||
# | ||
# = base64.rb: methods for base64-encoding and -decoding strings | ||
# | ||
|
||
# The Base64 module provides for the encoding (#encode64, #strict_encode64, | ||
# #urlsafe_encode64) and decoding (#decode64, #strict_decode64, | ||
# #urlsafe_decode64) of binary data using a Base64 representation. | ||
# | ||
# == Example | ||
# | ||
# A simple encoding and decoding. | ||
# | ||
# require "base64" | ||
# | ||
# enc = Base64.encode64('Send reinforcements') | ||
# # -> "U2VuZCByZWluZm9yY2VtZW50cw==\n" | ||
# plain = Base64.decode64(enc) | ||
# # -> "Send reinforcements" | ||
# | ||
# The purpose of using base64 to encode data is that it translates any | ||
# binary data into purely printable characters. | ||
|
||
module Base64 | ||
module_function | ||
|
||
# Returns the Base64-encoded version of +bin+. | ||
# This method complies with RFC 2045. | ||
# Line feeds are added to every 60 encoded characters. | ||
# | ||
# require 'base64' | ||
# Base64.encode64("Now is the time for all good coders\nto learn Ruby") | ||
# | ||
# <i>Generates:</i> | ||
# | ||
# Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g | ||
# UnVieQ== | ||
def encode64(bin) | ||
[bin].pack("m") | ||
end | ||
|
||
# Returns the Base64-decoded version of +str+. | ||
# This method complies with RFC 2045. | ||
# Characters outside the base alphabet are ignored. | ||
# | ||
# require 'base64' | ||
# str = 'VGhpcyBpcyBsaW5lIG9uZQpUaGlzIG' + | ||
# 'lzIGxpbmUgdHdvClRoaXMgaXMgbGlu' + | ||
# 'ZSB0aHJlZQpBbmQgc28gb24uLi4K' | ||
# puts Base64.decode64(str) | ||
# | ||
# <i>Generates:</i> | ||
# | ||
# This is line one | ||
# This is line two | ||
# This is line three | ||
# And so on... | ||
def decode64(str) | ||
str.unpack("m").first | ||
end | ||
|
||
# Returns the Base64-encoded version of +bin+. | ||
# This method complies with RFC 4648. | ||
# No line feeds are added. | ||
def strict_encode64(bin) | ||
[bin].pack("m0") | ||
end | ||
|
||
# Returns the Base64-decoded version of +str+. | ||
# This method complies with RFC 4648. | ||
# ArgumentError is raised if +str+ is incorrectly padded or contains | ||
# non-alphabet characters. Note that CR or LF are also rejected. | ||
def strict_decode64(str) | ||
str.unpack("m0").first | ||
end | ||
|
||
# Returns the Base64-encoded version of +bin+. | ||
# This method complies with ``Base 64 Encoding with URL and Filename Safe | ||
# Alphabet'' in RFC 4648. | ||
# The alphabet uses '-' instead of '+' and '_' instead of '/'. | ||
# Note that the result can still contain '='. | ||
# You can remove the padding by setting +padding+ as false. | ||
def urlsafe_encode64(bin, padding: true) | ||
str = strict_encode64(bin).tr("+/", "-_") | ||
str = str.delete("=") unless padding | ||
str | ||
end | ||
|
||
# Returns the Base64-decoded version of +str+. | ||
# This method complies with ``Base 64 Encoding with URL and Filename Safe | ||
# Alphabet'' in RFC 4648. | ||
# The alphabet uses '-' instead of '+' and '_' instead of '/'. | ||
# | ||
# The padding character is optional. | ||
# This method accepts both correctly-padded and unpadded input. | ||
# Note that it still rejects incorrectly-padded input. | ||
def urlsafe_decode64(str) | ||
# NOTE: RFC 4648 does say nothing about unpadded input, but says that | ||
# "the excess pad characters MAY also be ignored", so it is inferred that | ||
# unpadded input is also acceptable. | ||
str = str.tr("-_", "+/") | ||
if !str.end_with?("=") && str.length % 4 != 0 | ||
str = str.ljust((str.length + 3) & ~3, "=") | ||
end | ||
strict_decode64(str) | ||
end | ||
end |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,88 @@ | ||
require_relative '../../../stdlib/bigdecimal/jacobian' | ||
# frozen_string_literal: false | ||
# | ||
# require 'bigdecimal/jacobian' | ||
# | ||
# Provides methods to compute the Jacobian matrix of a set of equations at a | ||
# point x. In the methods below: | ||
# | ||
# f is an Object which is used to compute the Jacobian matrix of the equations. | ||
# It must provide the following methods: | ||
# | ||
# f.values(x):: returns the values of all functions at x | ||
# | ||
# f.zero:: returns 0.0 | ||
# f.one:: returns 1.0 | ||
# f.two:: returns 2.0 | ||
# f.ten:: returns 10.0 | ||
# | ||
# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal. | ||
# | ||
# x is the point at which to compute the Jacobian. | ||
# | ||
# fx is f.values(x). | ||
# | ||
module Jacobian | ||
module_function | ||
|
||
# Determines the equality of two numbers by comparing to zero, or using the epsilon value | ||
def isEqual(a,b,zero=0.0,e=1.0e-8) | ||
aa = a.abs | ||
bb = b.abs | ||
if aa == zero && bb == zero then | ||
true | ||
else | ||
if ((a-b)/(aa+bb)).abs < e then | ||
true | ||
else | ||
false | ||
end | ||
end | ||
end | ||
|
||
|
||
# Computes the derivative of f[i] at x[i]. | ||
# fx is the value of f at x. | ||
def dfdxi(f,fx,x,i) | ||
nRetry = 0 | ||
n = x.size | ||
xSave = x[i] | ||
ok = 0 | ||
ratio = f.ten*f.ten*f.ten | ||
dx = x[i].abs/ratio | ||
dx = fx[i].abs/ratio if isEqual(dx,f.zero,f.zero,f.eps) | ||
dx = f.one/f.ten if isEqual(dx,f.zero,f.zero,f.eps) | ||
until ok>0 do | ||
deriv = [] | ||
nRetry += 1 | ||
if nRetry > 100 | ||
raise "Singular Jacobian matrix. No change at x[" + i.to_s + "]" | ||
end | ||
dx = dx*f.two | ||
x[i] += dx | ||
fxNew = f.values(x) | ||
for j in 0...n do | ||
if !isEqual(fxNew[j],fx[j],f.zero,f.eps) then | ||
ok += 1 | ||
deriv <<= (fxNew[j]-fx[j])/dx | ||
else | ||
deriv <<= f.zero | ||
end | ||
end | ||
x[i] = xSave | ||
end | ||
deriv | ||
end | ||
|
||
# Computes the Jacobian of f at x. fx is the value of f at x. | ||
def jacobian(f,fx,x) | ||
n = x.size | ||
dfdx = Array.new(n*n) | ||
for i in 0...n do | ||
df = dfdxi(f,fx,x,i) | ||
for j in 0...n do | ||
dfdx[j*n+i] = df[j] | ||
end | ||
end | ||
dfdx | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,89 @@ | ||
require_relative '../../../stdlib/bigdecimal/ludcmp' | ||
# frozen_string_literal: false | ||
require 'bigdecimal' | ||
|
||
# | ||
# Solves a*x = b for x, using LU decomposition. | ||
# | ||
module LUSolve | ||
module_function | ||
|
||
# Performs LU decomposition of the n by n matrix a. | ||
def ludecomp(a,n,zero=0,one=1) | ||
prec = BigDecimal.limit(nil) | ||
ps = [] | ||
scales = [] | ||
for i in 0...n do # pick up largest(abs. val.) element in each row. | ||
ps <<= i | ||
nrmrow = zero | ||
ixn = i*n | ||
for j in 0...n do | ||
biggst = a[ixn+j].abs | ||
nrmrow = biggst if biggst>nrmrow | ||
end | ||
if nrmrow>zero then | ||
scales <<= one.div(nrmrow,prec) | ||
else | ||
raise "Singular matrix" | ||
end | ||
end | ||
n1 = n - 1 | ||
for k in 0...n1 do # Gaussian elimination with partial pivoting. | ||
biggst = zero; | ||
for i in k...n do | ||
size = a[ps[i]*n+k].abs*scales[ps[i]] | ||
if size>biggst then | ||
biggst = size | ||
pividx = i | ||
end | ||
end | ||
raise "Singular matrix" if biggst<=zero | ||
if pividx!=k then | ||
j = ps[k] | ||
ps[k] = ps[pividx] | ||
ps[pividx] = j | ||
end | ||
pivot = a[ps[k]*n+k] | ||
for i in (k+1)...n do | ||
psin = ps[i]*n | ||
a[psin+k] = mult = a[psin+k].div(pivot,prec) | ||
if mult!=zero then | ||
pskn = ps[k]*n | ||
for j in (k+1)...n do | ||
a[psin+j] -= mult.mult(a[pskn+j],prec) | ||
end | ||
end | ||
end | ||
end | ||
raise "Singular matrix" if a[ps[n1]*n+n1] == zero | ||
ps | ||
end | ||
|
||
# Solves a*x = b for x, using LU decomposition. | ||
# | ||
# a is a matrix, b is a constant vector, x is the solution vector. | ||
# | ||
# ps is the pivot, a vector which indicates the permutation of rows performed | ||
# during LU decomposition. | ||
def lusolve(a,b,ps,zero=0.0) | ||
prec = BigDecimal.limit(nil) | ||
n = ps.size | ||
x = [] | ||
for i in 0...n do | ||
dot = zero | ||
psin = ps[i]*n | ||
for j in 0...i do | ||
dot = a[psin+j].mult(x[j],prec) + dot | ||
end | ||
x <<= b[ps[i]] - dot | ||
end | ||
(n-1).downto(0) do |i2| | ||
dot = zero | ||
psin = ps[i2]*n | ||
for j in (i2+1)...n do | ||
dot = a[psin+j].mult(x[j],prec) + dot | ||
end | ||
x[i2] = (x[i2]-dot).div(a[psin+i2],prec) | ||
end | ||
x | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,246 @@ | ||
require_relative '../../../stdlib/bigdecimal/math' | ||
# frozen_string_literal: false | ||
require 'bigdecimal' | ||
require 'bigdecimal/util' | ||
|
||
# | ||
#-- | ||
# Contents: | ||
# sqrt(x, prec) | ||
# sin (x, prec) | ||
# cos (x, prec) | ||
# atan(x, prec) Note: |x|<1, x=0.9999 may not converge. | ||
# PI (prec) | ||
# E (prec) == exp(1.0,prec) | ||
# | ||
# where: | ||
# x ... BigDecimal number to be computed. | ||
# |x| must be small enough to get convergence. | ||
# prec ... Number of digits to be obtained. | ||
#++ | ||
# | ||
# Provides mathematical functions. | ||
# | ||
# Example: | ||
# | ||
# require "bigdecimal/math" | ||
# | ||
# include BigMath | ||
# | ||
# a = BigDecimal((PI(100)/2).to_s) | ||
# puts sin(a,100) # => 0.10000000000000000000......E1 | ||
# | ||
module BigMath | ||
module_function | ||
|
||
# call-seq: | ||
# sqrt(decimal, numeric) -> BigDecimal | ||
# | ||
# Computes the square root of +decimal+ to the specified number of digits of | ||
# precision, +numeric+. | ||
# | ||
# BigMath.sqrt(BigDecimal.new('2'), 16).to_s | ||
# #=> "0.1414213562373095048801688724E1" | ||
# | ||
def sqrt(x, prec) | ||
x.sqrt(prec) | ||
end | ||
|
||
# call-seq: | ||
# sin(decimal, numeric) -> BigDecimal | ||
# | ||
# Computes the sine of +decimal+ to the specified number of digits of | ||
# precision, +numeric+. | ||
# | ||
# If +decimal+ is Infinity or NaN, returns NaN. | ||
# | ||
# BigMath.sin(BigMath.PI(5)/4, 5).to_s | ||
# #=> "0.70710678118654752440082036563292800375E0" | ||
# | ||
def sin(x, prec) | ||
raise ArgumentError, "Zero or negative precision for sin" if prec <= 0 | ||
return BigDecimal("NaN") if x.infinite? || x.nan? | ||
n = prec + BigDecimal.double_fig | ||
one = BigDecimal("1") | ||
two = BigDecimal("2") | ||
x = -x if neg = x < 0 | ||
if x > (twopi = two * BigMath.PI(prec)) | ||
if x > 30 | ||
x %= twopi | ||
else | ||
x -= twopi while x > twopi | ||
end | ||
end | ||
x1 = x | ||
x2 = x.mult(x,n) | ||
sign = 1 | ||
y = x | ||
d = y | ||
i = one | ||
z = one | ||
while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) | ||
m = BigDecimal.double_fig if m < BigDecimal.double_fig | ||
sign = -sign | ||
x1 = x2.mult(x1,n) | ||
i += two | ||
z *= (i-one) * i | ||
d = sign * x1.div(z,m) | ||
y += d | ||
end | ||
neg ? -y : y | ||
end | ||
|
||
# call-seq: | ||
# cos(decimal, numeric) -> BigDecimal | ||
# | ||
# Computes the cosine of +decimal+ to the specified number of digits of | ||
# precision, +numeric+. | ||
# | ||
# If +decimal+ is Infinity or NaN, returns NaN. | ||
# | ||
# BigMath.cos(BigMath.PI(4), 16).to_s | ||
# #=> "-0.999999999999999999999999999999856613163740061349E0" | ||
# | ||
def cos(x, prec) | ||
raise ArgumentError, "Zero or negative precision for cos" if prec <= 0 | ||
return BigDecimal("NaN") if x.infinite? || x.nan? | ||
n = prec + BigDecimal.double_fig | ||
one = BigDecimal("1") | ||
two = BigDecimal("2") | ||
x = -x if x < 0 | ||
if x > (twopi = two * BigMath.PI(prec)) | ||
if x > 30 | ||
x %= twopi | ||
else | ||
x -= twopi while x > twopi | ||
end | ||
end | ||
x1 = one | ||
x2 = x.mult(x,n) | ||
sign = 1 | ||
y = one | ||
d = y | ||
i = BigDecimal("0") | ||
z = one | ||
while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) | ||
m = BigDecimal.double_fig if m < BigDecimal.double_fig | ||
sign = -sign | ||
x1 = x2.mult(x1,n) | ||
i += two | ||
z *= (i-one) * i | ||
d = sign * x1.div(z,m) | ||
y += d | ||
end | ||
y | ||
end | ||
|
||
# call-seq: | ||
# atan(decimal, numeric) -> BigDecimal | ||
# | ||
# Computes the arctangent of +decimal+ to the specified number of digits of | ||
# precision, +numeric+. | ||
# | ||
# If +decimal+ is NaN, returns NaN. | ||
# | ||
# BigMath.atan(BigDecimal.new('-1'), 16).to_s | ||
# #=> "-0.785398163397448309615660845819878471907514682065E0" | ||
# | ||
def atan(x, prec) | ||
raise ArgumentError, "Zero or negative precision for atan" if prec <= 0 | ||
return BigDecimal("NaN") if x.nan? | ||
pi = PI(prec) | ||
x = -x if neg = x < 0 | ||
return pi.div(neg ? -2 : 2, prec) if x.infinite? | ||
return pi / (neg ? -4 : 4) if x.round(prec) == 1 | ||
x = BigDecimal("1").div(x, prec) if inv = x > 1 | ||
x = (-1 + sqrt(1 + x**2, prec))/x if dbl = x > 0.5 | ||
n = prec + BigDecimal.double_fig | ||
y = x | ||
d = y | ||
t = x | ||
r = BigDecimal("3") | ||
x2 = x.mult(x,n) | ||
while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) | ||
m = BigDecimal.double_fig if m < BigDecimal.double_fig | ||
t = -t.mult(x2,n) | ||
d = t.div(r,m) | ||
y += d | ||
r += 2 | ||
end | ||
y *= 2 if dbl | ||
y = pi / 2 - y if inv | ||
y = -y if neg | ||
y | ||
end | ||
|
||
# call-seq: | ||
# PI(numeric) -> BigDecimal | ||
# | ||
# Computes the value of pi to the specified number of digits of precision, | ||
# +numeric+. | ||
# | ||
# BigMath.PI(10).to_s | ||
# #=> "0.3141592653589793238462643388813853786957412E1" | ||
# | ||
def PI(prec) | ||
raise ArgumentError, "Zero or negative precision for PI" if prec <= 0 | ||
n = prec + BigDecimal.double_fig | ||
zero = BigDecimal("0") | ||
one = BigDecimal("1") | ||
two = BigDecimal("2") | ||
|
||
m25 = BigDecimal("-0.04") | ||
m57121 = BigDecimal("-57121") | ||
|
||
pi = zero | ||
|
||
d = one | ||
k = one | ||
t = BigDecimal("-80") | ||
while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0) | ||
m = BigDecimal.double_fig if m < BigDecimal.double_fig | ||
t = t*m25 | ||
d = t.div(k,m) | ||
k = k+two | ||
pi = pi + d | ||
end | ||
|
||
d = one | ||
k = one | ||
t = BigDecimal("956") | ||
while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0) | ||
m = BigDecimal.double_fig if m < BigDecimal.double_fig | ||
t = t.div(m57121,n) | ||
d = t.div(k,m) | ||
pi = pi + d | ||
k = k+two | ||
end | ||
pi | ||
end | ||
|
||
# call-seq: | ||
# E(numeric) -> BigDecimal | ||
# | ||
# Computes e (the base of natural logarithms) to the specified number of | ||
# digits of precision, +numeric+. | ||
# | ||
# BigMath.E(10).to_s | ||
# #=> "0.271828182845904523536028752390026306410273E1" | ||
# | ||
def E(prec) | ||
raise ArgumentError, "Zero or negative precision for E" if prec <= 0 | ||
n = prec + BigDecimal.double_fig | ||
one = BigDecimal("1") | ||
y = one | ||
d = y | ||
z = one | ||
i = 0 | ||
while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) | ||
m = BigDecimal.double_fig if m < BigDecimal.double_fig | ||
i += 1 | ||
z *= i | ||
d = one.div(z,m) | ||
y += d | ||
end | ||
y | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,80 @@ | ||
require_relative '../../../stdlib/bigdecimal/newton' | ||
# frozen_string_literal: false | ||
require "bigdecimal/ludcmp" | ||
require "bigdecimal/jacobian" | ||
|
||
# | ||
# newton.rb | ||
# | ||
# Solves the nonlinear algebraic equation system f = 0 by Newton's method. | ||
# This program is not dependent on BigDecimal. | ||
# | ||
# To call: | ||
# n = nlsolve(f,x) | ||
# where n is the number of iterations required, | ||
# x is the initial value vector | ||
# f is an Object which is used to compute the values of the equations to be solved. | ||
# It must provide the following methods: | ||
# | ||
# f.values(x):: returns the values of all functions at x | ||
# | ||
# f.zero:: returns 0.0 | ||
# f.one:: returns 1.0 | ||
# f.two:: returns 2.0 | ||
# f.ten:: returns 10.0 | ||
# | ||
# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal. | ||
# | ||
# On exit, x is the solution vector. | ||
# | ||
module Newton | ||
include LUSolve | ||
include Jacobian | ||
module_function | ||
|
||
def norm(fv,zero=0.0) # :nodoc: | ||
s = zero | ||
n = fv.size | ||
for i in 0...n do | ||
s += fv[i]*fv[i] | ||
end | ||
s | ||
end | ||
|
||
# See also Newton | ||
def nlsolve(f,x) | ||
nRetry = 0 | ||
n = x.size | ||
|
||
f0 = f.values(x) | ||
zero = f.zero | ||
one = f.one | ||
two = f.two | ||
p5 = one/two | ||
d = norm(f0,zero) | ||
minfact = f.ten*f.ten*f.ten | ||
minfact = one/minfact | ||
e = f.eps | ||
while d >= e do | ||
nRetry += 1 | ||
# Not yet converged. => Compute Jacobian matrix | ||
dfdx = jacobian(f,f0,x) | ||
# Solve dfdx*dx = -f0 to estimate dx | ||
dx = lusolve(dfdx,f0,ludecomp(dfdx,n,zero,one),zero) | ||
fact = two | ||
xs = x.dup | ||
begin | ||
fact *= p5 | ||
if fact < minfact then | ||
raise "Failed to reduce function values." | ||
end | ||
for i in 0...n do | ||
x[i] = xs[i] - dx[i]*fact | ||
end | ||
f0 = f.values(x) | ||
dn = norm(f0,zero) | ||
end while(dn>=d) | ||
d = dn | ||
end | ||
nRetry | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,128 @@ | ||
require_relative '../../../stdlib/bigdecimal/util' | ||
# frozen_string_literal: false | ||
# BigDecimal extends the native Integer class to provide the #to_d method. | ||
# | ||
# When you require the BigDecimal library in your application, this methodwill | ||
# be available on Integer objects. | ||
class Integer < Numeric | ||
# call-seq: | ||
# int.to_d -> bigdecimal | ||
# | ||
# Convert +int+ to a BigDecimal and return it. | ||
# | ||
# require 'bigdecimal' | ||
# require 'bigdecimal/util' | ||
# | ||
# 42.to_d | ||
# # => #<BigDecimal:1008ef070,'0.42E2',9(36)> | ||
# | ||
def to_d | ||
BigDecimal(self) | ||
end | ||
end | ||
|
||
# BigDecimal extends the native Float class to provide the #to_d method. | ||
# | ||
# When you require BigDecimal in your application, this method will be | ||
# available on Float objects. | ||
class Float < Numeric | ||
# call-seq: | ||
# flt.to_d -> bigdecimal | ||
# | ||
# Convert +flt+ to a BigDecimal and return it. | ||
# | ||
# require 'bigdecimal' | ||
# require 'bigdecimal/util' | ||
# | ||
# 0.5.to_d | ||
# # => #<BigDecimal:1dc69e0,'0.5E0',9(18)> | ||
# | ||
def to_d(precision=nil) | ||
BigDecimal(self, precision || Float::DIG) | ||
end | ||
end | ||
|
||
# BigDecimal extends the native String class to provide the #to_d method. | ||
# | ||
# When you require BigDecimal in your application, this method will be | ||
# available on String objects. | ||
class String | ||
# call-seq: | ||
# string.to_d -> bigdecimal | ||
# | ||
# Convert +string+ to a BigDecimal and return it. | ||
# | ||
# require 'bigdecimal' | ||
# require 'bigdecimal/util' | ||
# | ||
# "0.5".to_d | ||
# # => #<BigDecimal:1dc69e0,'0.5E0',9(18)> | ||
# | ||
def to_d | ||
BigDecimal(self) | ||
end | ||
end | ||
|
||
# BigDecimal extends the native Numeric class to provide the #to_digits and | ||
# #to_d methods. | ||
# | ||
# When you require BigDecimal in your application, this method will be | ||
# available on BigDecimal objects. | ||
class BigDecimal < Numeric | ||
# call-seq: | ||
# a.to_digits -> string | ||
# | ||
# Converts a BigDecimal to a String of the form "nnnnnn.mmm". | ||
# This method is deprecated; use BigDecimal#to_s("F") instead. | ||
# | ||
# require 'bigdecimal' | ||
# require 'bigdecimal/util' | ||
# | ||
# d = BigDecimal.new("3.14") | ||
# d.to_digits | ||
# # => "3.14" | ||
def to_digits | ||
if self.nan? || self.infinite? || self.zero? | ||
self.to_s | ||
else | ||
i = self.to_i.to_s | ||
_,f,_,z = self.frac.split | ||
i + "." + ("0"*(-z)) + f | ||
end | ||
end | ||
|
||
# call-seq: | ||
# a.to_d -> bigdecimal | ||
# | ||
# Returns self. | ||
def to_d | ||
self | ||
end | ||
end | ||
|
||
# BigDecimal extends the native Rational class to provide the #to_d method. | ||
# | ||
# When you require BigDecimal in your application, this method will be | ||
# available on Rational objects. | ||
class Rational < Numeric | ||
# call-seq: | ||
# r.to_d(precision) -> bigdecimal | ||
# | ||
# Converts a Rational to a BigDecimal. | ||
# | ||
# The required +precision+ parameter is used to determine the amount of | ||
# significant digits for the result. See BigDecimal#div for more information, | ||
# as it is used along with the #denominator and the +precision+ for | ||
# parameters. | ||
# | ||
# r = (22/7.0).to_r | ||
# # => (7077085128725065/2251799813685248) | ||
# r.to_d(3) | ||
# # => #<BigDecimal:1a44d08,'0.314E1',18(36)> | ||
def to_d(precision) | ||
if precision <= 0 | ||
raise ArgumentError, "negative precision" | ||
end | ||
num = self.numerator | ||
BigDecimal(num).div(self.denominator, precision) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,296 @@ | ||
require_relative '../../stdlib/cgi' | ||
# frozen_string_literal: false | ||
# | ||
# cgi.rb - cgi support library | ||
# | ||
# Copyright (C) 2000 Network Applied Communication Laboratory, Inc. | ||
# | ||
# Copyright (C) 2000 Information-technology Promotion Agency, Japan | ||
# | ||
# Author: Wakou Aoyama <wakou@ruby-lang.org> | ||
# | ||
# Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber) | ||
# | ||
|
||
# == Overview | ||
# | ||
# The Common Gateway Interface (CGI) is a simple protocol for passing an HTTP | ||
# request from a web server to a standalone program, and returning the output | ||
# to the web browser. Basically, a CGI program is called with the parameters | ||
# of the request passed in either in the environment (GET) or via $stdin | ||
# (POST), and everything it prints to $stdout is returned to the client. | ||
# | ||
# This file holds the CGI class. This class provides functionality for | ||
# retrieving HTTP request parameters, managing cookies, and generating HTML | ||
# output. | ||
# | ||
# The file CGI::Session provides session management functionality; see that | ||
# class for more details. | ||
# | ||
# See http://www.w3.org/CGI/ for more information on the CGI protocol. | ||
# | ||
# == Introduction | ||
# | ||
# CGI is a large class, providing several categories of methods, many of which | ||
# are mixed in from other modules. Some of the documentation is in this class, | ||
# some in the modules CGI::QueryExtension and CGI::HtmlExtension. See | ||
# CGI::Cookie for specific information on handling cookies, and cgi/session.rb | ||
# (CGI::Session) for information on sessions. | ||
# | ||
# For queries, CGI provides methods to get at environmental variables, | ||
# parameters, cookies, and multipart request data. For responses, CGI provides | ||
# methods for writing output and generating HTML. | ||
# | ||
# Read on for more details. Examples are provided at the bottom. | ||
# | ||
# == Queries | ||
# | ||
# The CGI class dynamically mixes in parameter and cookie-parsing | ||
# functionality, environmental variable access, and support for | ||
# parsing multipart requests (including uploaded files) from the | ||
# CGI::QueryExtension module. | ||
# | ||
# === Environmental Variables | ||
# | ||
# The standard CGI environmental variables are available as read-only | ||
# attributes of a CGI object. The following is a list of these variables: | ||
# | ||
# | ||
# AUTH_TYPE HTTP_HOST REMOTE_IDENT | ||
# CONTENT_LENGTH HTTP_NEGOTIATE REMOTE_USER | ||
# CONTENT_TYPE HTTP_PRAGMA REQUEST_METHOD | ||
# GATEWAY_INTERFACE HTTP_REFERER SCRIPT_NAME | ||
# HTTP_ACCEPT HTTP_USER_AGENT SERVER_NAME | ||
# HTTP_ACCEPT_CHARSET PATH_INFO SERVER_PORT | ||
# HTTP_ACCEPT_ENCODING PATH_TRANSLATED SERVER_PROTOCOL | ||
# HTTP_ACCEPT_LANGUAGE QUERY_STRING SERVER_SOFTWARE | ||
# HTTP_CACHE_CONTROL REMOTE_ADDR | ||
# HTTP_FROM REMOTE_HOST | ||
# | ||
# | ||
# For each of these variables, there is a corresponding attribute with the | ||
# same name, except all lower case and without a preceding HTTP_. | ||
# +content_length+ and +server_port+ are integers; the rest are strings. | ||
# | ||
# === Parameters | ||
# | ||
# The method #params() returns a hash of all parameters in the request as | ||
# name/value-list pairs, where the value-list is an Array of one or more | ||
# values. The CGI object itself also behaves as a hash of parameter names | ||
# to values, but only returns a single value (as a String) for each | ||
# parameter name. | ||
# | ||
# For instance, suppose the request contains the parameter | ||
# "favourite_colours" with the multiple values "blue" and "green". The | ||
# following behavior would occur: | ||
# | ||
# cgi.params["favourite_colours"] # => ["blue", "green"] | ||
# cgi["favourite_colours"] # => "blue" | ||
# | ||
# If a parameter does not exist, the former method will return an empty | ||
# array, the latter an empty string. The simplest way to test for existence | ||
# of a parameter is by the #has_key? method. | ||
# | ||
# === Cookies | ||
# | ||
# HTTP Cookies are automatically parsed from the request. They are available | ||
# from the #cookies() accessor, which returns a hash from cookie name to | ||
# CGI::Cookie object. | ||
# | ||
# === Multipart requests | ||
# | ||
# If a request's method is POST and its content type is multipart/form-data, | ||
# then it may contain uploaded files. These are stored by the QueryExtension | ||
# module in the parameters of the request. The parameter name is the name | ||
# attribute of the file input field, as usual. However, the value is not | ||
# a string, but an IO object, either an IOString for small files, or a | ||
# Tempfile for larger ones. This object also has the additional singleton | ||
# methods: | ||
# | ||
# #local_path():: the path of the uploaded file on the local filesystem | ||
# #original_filename():: the name of the file on the client computer | ||
# #content_type():: the content type of the file | ||
# | ||
# == Responses | ||
# | ||
# The CGI class provides methods for sending header and content output to | ||
# the HTTP client, and mixes in methods for programmatic HTML generation | ||
# from CGI::HtmlExtension and CGI::TagMaker modules. The precise version of HTML | ||
# to use for HTML generation is specified at object creation time. | ||
# | ||
# === Writing output | ||
# | ||
# The simplest way to send output to the HTTP client is using the #out() method. | ||
# This takes the HTTP headers as a hash parameter, and the body content | ||
# via a block. The headers can be generated as a string using the #http_header() | ||
# method. The output stream can be written directly to using the #print() | ||
# method. | ||
# | ||
# === Generating HTML | ||
# | ||
# Each HTML element has a corresponding method for generating that | ||
# element as a String. The name of this method is the same as that | ||
# of the element, all lowercase. The attributes of the element are | ||
# passed in as a hash, and the body as a no-argument block that evaluates | ||
# to a String. The HTML generation module knows which elements are | ||
# always empty, and silently drops any passed-in body. It also knows | ||
# which elements require matching closing tags and which don't. However, | ||
# it does not know what attributes are legal for which elements. | ||
# | ||
# There are also some additional HTML generation methods mixed in from | ||
# the CGI::HtmlExtension module. These include individual methods for the | ||
# different types of form inputs, and methods for elements that commonly | ||
# take particular attributes where the attributes can be directly specified | ||
# as arguments, rather than via a hash. | ||
# | ||
# === Utility HTML escape and other methods like a function. | ||
# | ||
# There are some utility tool defined in cgi/util.rb . | ||
# And when include, you can use utility methods like a function. | ||
# | ||
# == Examples of use | ||
# | ||
# === Get form values | ||
# | ||
# require "cgi" | ||
# cgi = CGI.new | ||
# value = cgi['field_name'] # <== value string for 'field_name' | ||
# # if not 'field_name' included, then return "". | ||
# fields = cgi.keys # <== array of field names | ||
# | ||
# # returns true if form has 'field_name' | ||
# cgi.has_key?('field_name') | ||
# cgi.has_key?('field_name') | ||
# cgi.include?('field_name') | ||
# | ||
# CAUTION! cgi['field_name'] returned an Array with the old | ||
# cgi.rb(included in Ruby 1.6) | ||
# | ||
# === Get form values as hash | ||
# | ||
# require "cgi" | ||
# cgi = CGI.new | ||
# params = cgi.params | ||
# | ||
# cgi.params is a hash. | ||
# | ||
# cgi.params['new_field_name'] = ["value"] # add new param | ||
# cgi.params['field_name'] = ["new_value"] # change value | ||
# cgi.params.delete('field_name') # delete param | ||
# cgi.params.clear # delete all params | ||
# | ||
# | ||
# === Save form values to file | ||
# | ||
# require "pstore" | ||
# db = PStore.new("query.db") | ||
# db.transaction do | ||
# db["params"] = cgi.params | ||
# end | ||
# | ||
# | ||
# === Restore form values from file | ||
# | ||
# require "pstore" | ||
# db = PStore.new("query.db") | ||
# db.transaction do | ||
# cgi.params = db["params"] | ||
# end | ||
# | ||
# | ||
# === Get multipart form values | ||
# | ||
# require "cgi" | ||
# cgi = CGI.new | ||
# value = cgi['field_name'] # <== value string for 'field_name' | ||
# value.read # <== body of value | ||
# value.local_path # <== path to local file of value | ||
# value.original_filename # <== original filename of value | ||
# value.content_type # <== content_type of value | ||
# | ||
# and value has StringIO or Tempfile class methods. | ||
# | ||
# === Get cookie values | ||
# | ||
# require "cgi" | ||
# cgi = CGI.new | ||
# values = cgi.cookies['name'] # <== array of 'name' | ||
# # if not 'name' included, then return []. | ||
# names = cgi.cookies.keys # <== array of cookie names | ||
# | ||
# and cgi.cookies is a hash. | ||
# | ||
# === Get cookie objects | ||
# | ||
# require "cgi" | ||
# cgi = CGI.new | ||
# for name, cookie in cgi.cookies | ||
# cookie.expires = Time.now + 30 | ||
# end | ||
# cgi.out("cookie" => cgi.cookies) {"string"} | ||
# | ||
# cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... } | ||
# | ||
# require "cgi" | ||
# cgi = CGI.new | ||
# cgi.cookies['name'].expires = Time.now + 30 | ||
# cgi.out("cookie" => cgi.cookies['name']) {"string"} | ||
# | ||
# === Print http header and html string to $DEFAULT_OUTPUT ($>) | ||
# | ||
# require "cgi" | ||
# cgi = CGI.new("html4") # add HTML generation methods | ||
# cgi.out do | ||
# cgi.html do | ||
# cgi.head do | ||
# cgi.title { "TITLE" } | ||
# end + | ||
# cgi.body do | ||
# cgi.form("ACTION" => "uri") do | ||
# cgi.p do | ||
# cgi.textarea("get_text") + | ||
# cgi.br + | ||
# cgi.submit | ||
# end | ||
# end + | ||
# cgi.pre do | ||
# CGI::escapeHTML( | ||
# "params: #{cgi.params.inspect}\n" + | ||
# "cookies: #{cgi.cookies.inspect}\n" + | ||
# ENV.collect do |key, value| | ||
# "#{key} --> #{value}\n" | ||
# end.join("") | ||
# ) | ||
# end | ||
# end | ||
# end | ||
# end | ||
# | ||
# # add HTML generation methods | ||
# CGI.new("html3") # html3.2 | ||
# CGI.new("html4") # html4.01 (Strict) | ||
# CGI.new("html4Tr") # html4.01 Transitional | ||
# CGI.new("html4Fr") # html4.01 Frameset | ||
# CGI.new("html5") # html5 | ||
# | ||
# === Some utility methods | ||
# | ||
# require 'cgi/util' | ||
# CGI.escapeHTML('Usage: foo "bar" <baz>') | ||
# | ||
# | ||
# === Some utility methods like a function | ||
# | ||
# require 'cgi/util' | ||
# include CGI::Util | ||
# escapeHTML('Usage: foo "bar" <baz>') | ||
# h('Usage: foo "bar" <baz>') # alias | ||
# | ||
# | ||
|
||
class CGI | ||
end | ||
|
||
require 'cgi/core' | ||
require 'cgi/cookie' | ||
require 'cgi/util' | ||
CGI.autoload(:HtmlExtension, 'cgi/html') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,188 @@ | ||
require_relative '../../../stdlib/cgi/cookie' | ||
# frozen_string_literal: false | ||
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 | ||
# 'httponly' => 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 | ||
# httponly = cookie1.httponly | ||
# | ||
# cookie1.name = 'name' | ||
# cookie1.value = ['value1', 'value2', ...] | ||
# cookie1.path = 'path' | ||
# cookie1.domain = 'domain' | ||
# cookie1.expires = Time.now + 30 | ||
# cookie1.secure = true | ||
# cookie1.httponly = 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. | ||
# <tt>*value</tt>:: | ||
# 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. | ||
# httponly:: whether this cookie is a HttpOnly cookie or not (default to | ||
# false). HttpOnly cookies are not available to javascript. | ||
# | ||
# 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 | ||
@httponly = 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 | ||
@httponly = options["httponly"] == true | ||
|
||
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 | ||
# True if this cookie is httponly; false otherwise | ||
attr_reader :httponly | ||
|
||
# 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 | ||
|
||
# Set whether the Cookie is a httponly cookie or not. | ||
# | ||
# +val+ must be a boolean. | ||
def httponly=(val) | ||
@httponly = !!val | ||
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 | ||
buf << "; HttpOnly" if @httponly | ||
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 | ||
"#<CGI::Cookie: #{self.to_s.inspect}>" | ||
end | ||
|
||
end # class Cookie | ||
end | ||
|
||
|
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,101 @@ | ||
require_relative '../../../../stdlib/cgi/session/pstore' | ||
# frozen_string_literal: false | ||
# | ||
# 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: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,200 @@ | ||
require_relative '../../../stdlib/cgi/util' | ||
# frozen_string_literal: false | ||
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" <baz>') | ||
# # => "Usage: foo "bar" <baz>" | ||
def escapeHTML(string) | ||
string.gsub(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__) | ||
end | ||
|
||
begin | ||
require 'cgi/escape' | ||
rescue LoadError | ||
end | ||
|
||
# Unescape a string that has been HTML-escaped | ||
# CGI::unescapeHTML("Usage: foo "bar" <baz>") | ||
# # => "Usage: foo \"bar\" <baz>" | ||
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('<BR><A HREF="url"></A>', "A", "IMG") | ||
# # "<BR><A HREF="url"></A>" | ||
# | ||
# print CGI::escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"]) | ||
# # "<BR><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('<BR><A HREF="url"></A>'), "A", "IMG") | ||
# # "<BR><A HREF="url"></A>" | ||
# | ||
# print CGI::unescapeElement( | ||
# CGI::escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"]) | ||
# # "<BR><A HREF="url"></A>" | ||
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("<HTML><BODY></BODY></HTML>") | ||
# # <HTML> | ||
# # <BODY> | ||
# # </BODY> | ||
# # </HTML> | ||
# | ||
# print CGI::pretty("<HTML><BODY></BODY></HTML>", "\t") | ||
# # <HTML> | ||
# # <BODY> | ||
# # </BODY> | ||
# # </HTML> | ||
# | ||
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 |
Oops, something went wrong.