mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-16 23:30:12 +01:00
Froze the Rails gems and RedCloth into the vendor directory, so that these will be used instead of any local version of Rails which might be incompatible. Should also mean that you don't need to install RedCloth locally to make Tracks work (I'm not sure whether this also applies to Rails, and don't want to uninstall my local Rails gems to find out!)
Effectively fixes #159. git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@176 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
parent
825bad76a7
commit
c392296680
751 changed files with 94570 additions and 4 deletions
34
tracks/lib/tasks/gems.rake
Normal file
34
tracks/lib/tasks/gems.rake
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
desc "Copy third-party gems into ./lib"
|
||||
task :freeze_other_gems do
|
||||
# TODO Get this list from parsing environment.rb
|
||||
libraries = %w(redcloth)
|
||||
require 'rubygems'
|
||||
require 'find'
|
||||
|
||||
libraries.each do |library|
|
||||
library_gem = Gem.cache.search(library).sort_by { |g| g.version }.last
|
||||
puts "Freezing #{library} for #{library_gem.version}..."
|
||||
|
||||
# TODO Add dependencies to list of libraries to freeze
|
||||
#library_gem.dependencies.each { |g| libraries << g }
|
||||
|
||||
folder_for_library = "#{library_gem.name}-#{library_gem.version}"
|
||||
system "cd vendor; gem unpack -v '#{library_gem.version}' #{library_gem.name};"
|
||||
|
||||
# Copy files recursively to ./lib
|
||||
folder_for_library_with_lib = "vendor/#{folder_for_library}/lib/"
|
||||
Find.find(folder_for_library_with_lib) do |original_file|
|
||||
destination_file = "./lib/" + original_file.gsub(folder_for_library_with_lib, '')
|
||||
|
||||
if File.directory?(original_file)
|
||||
if !File.exist?(destination_file)
|
||||
Dir.mkdir destination_file
|
||||
end
|
||||
else
|
||||
File.copy original_file, destination_file
|
||||
end
|
||||
end
|
||||
|
||||
system "rm -r vendor/#{folder_for_library}"
|
||||
end
|
||||
end
|
||||
|
|
@ -525,8 +525,8 @@ div.message {
|
|||
}
|
||||
|
||||
#ErrorExplanation {
|
||||
width: 400px;
|
||||
border: 2px solid red;
|
||||
width: 335px;
|
||||
border: 2px solid #ff0000;
|
||||
padding: 7px;
|
||||
padding-bottom: 12px;
|
||||
margin-bottom: 20px;
|
||||
|
|
@ -550,8 +550,8 @@ div.message {
|
|||
}
|
||||
|
||||
#ErrorExplanation ul li {
|
||||
font-size: 12px;
|
||||
list-style: square;
|
||||
font-size: 1em;
|
||||
list-style: disc;
|
||||
}
|
||||
|
||||
ul.warning { list-style-type: circle; font-size: 1em; }
|
||||
3
tracks/vendor/RedCloth-3.0.3/bin/redcloth
vendored
Normal file
3
tracks/vendor/RedCloth-3.0.3/bin/redcloth
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/local/bin/ruby18
|
||||
require 'redcloth'
|
||||
puts RedCloth.new( ARGF.read ).to_html
|
||||
26
tracks/vendor/RedCloth-3.0.3/run-tests.rb
vendored
Normal file
26
tracks/vendor/RedCloth-3.0.3/run-tests.rb
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env ruby
|
||||
require 'lib/redcloth'
|
||||
require 'yaml'
|
||||
|
||||
Dir["tests/*.yml"].each do |testfile|
|
||||
YAML::load_documents( File.open( testfile ) ) do |doc|
|
||||
if doc['in'] and doc['out']
|
||||
red = RedCloth.new( doc['in'] )
|
||||
html = if testfile =~ /markdown/
|
||||
red.to_html( :markdown )
|
||||
else
|
||||
red.to_html
|
||||
end
|
||||
puts "---"
|
||||
|
||||
html.gsub!( /\n+/, "\n" )
|
||||
doc['out'].gsub!( /\n+/, "\n" )
|
||||
if html == doc['out']
|
||||
puts "success: true"
|
||||
else
|
||||
puts "out: "; p html
|
||||
puts "expected: "; p doc['out']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
105
tracks/vendor/RedCloth-3.0.3/tests/code.yml
vendored
Normal file
105
tracks/vendor/RedCloth-3.0.3/tests/code.yml
vendored
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
in: 'This is an empty dictionary: @{}@'
|
||||
out: '<p>This is an empty dictionary: <code>{}</code></p>'
|
||||
---
|
||||
in: |-
|
||||
Testing nested pre tags...
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
Good code here.
|
||||
|
||||
<pre>
|
||||
a = 1
|
||||
</pre>
|
||||
|
||||
Bad code here.
|
||||
|
||||
<script language="JavaScript">
|
||||
window.open( "about:blank" );
|
||||
</script>
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
out: |-
|
||||
<p>Testing nested pre tags…</p>
|
||||
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
Good code here.
|
||||
|
||||
<pre>
|
||||
a = 1
|
||||
</pre>
|
||||
|
||||
Bad code here.
|
||||
|
||||
<script language="JavaScript">
|
||||
window.open( "about:blank" );
|
||||
</script>
|
||||
</code>
|
||||
</pre>
|
||||
---
|
||||
in: |-
|
||||
<pre>
|
||||
*** test
|
||||
</pre>
|
||||
out: |-
|
||||
<pre>
|
||||
*** test
|
||||
</pre>
|
||||
---
|
||||
in: |-
|
||||
<notextile>
|
||||
*** test
|
||||
</notextile>
|
||||
out: |-
|
||||
*** test
|
||||
---
|
||||
in: '*this <span></span> is strong*'
|
||||
out: '<p><strong>this <span></span> is strong</strong></p>'
|
||||
---
|
||||
in: '*this <span>test</span> is strong*'
|
||||
out: '<p><strong>this <span>test</span> is strong</strong></p>'
|
||||
---
|
||||
in: <pre class="code"> __inline__</pre>
|
||||
out: <pre class="code"> __inline__</pre>
|
||||
---
|
||||
in: |-
|
||||
* @foo@
|
||||
* @bar@
|
||||
* and @x@ is also.
|
||||
out: "<ul>\n\t<li><code>foo</code></li>\n\t\t<li><code>bar</code></li>\n\t\t<li>and <code>x</code> is also.</li>\n\t</ul>"
|
||||
---
|
||||
in: |-
|
||||
<pre class="code"> <hello> </pre>
|
||||
<pre class="code"> <hello> </pre>
|
||||
out: |-
|
||||
<pre class="code"> <hello> </pre>
|
||||
<pre class="code"> <hello> </pre>
|
||||
---
|
||||
in: |
|
||||
Test of Markdown-style indented code.
|
||||
|
||||
a = [1, 2, 3]
|
||||
a.each do |x|
|
||||
puts "test number", x,
|
||||
"and more!"
|
||||
end
|
||||
|
||||
Paragraph 2.
|
||||
|
||||
Paragraph 3.
|
||||
out: |-
|
||||
<p>Test of Markdown-style indented code.</p>
|
||||
|
||||
<pre><code>a = [1, 2, 3]
|
||||
a.each do |x|
|
||||
puts "test number", x,
|
||||
"and more!"
|
||||
end</code></pre>
|
||||
|
||||
<p>Paragraph 2.</p>
|
||||
|
||||
<p>Paragraph 3.</p>
|
||||
171
tracks/vendor/RedCloth-3.0.3/tests/images.yml
vendored
Normal file
171
tracks/vendor/RedCloth-3.0.3/tests/images.yml
vendored
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
---
|
||||
in: This is an !image.jpg!
|
||||
out: <p>This is an <img src="image.jpg" alt="" /></p>
|
||||
---
|
||||
in: This is an !image.jpg(with alt text)!
|
||||
out: <p>This is an <img src="image.jpg" title="with alt text" alt="with alt text" /></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!
|
||||
out: <p>This is an <img src="http://example.com/i/image.jpg" alt="" /></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg#a1!
|
||||
out: <p>This is an <img src="http://example.com/i/image.jpg#a1" alt="" /></p>
|
||||
---
|
||||
in: This is an !image.jpg!.
|
||||
out: <p>This is an <img src="image.jpg" alt="" />.</p>
|
||||
---
|
||||
in: This is an !image.jpg(with alt text)!.
|
||||
out: <p>This is an <img src="image.jpg" title="with alt text" alt="with alt text" />.</p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!.
|
||||
out: <p>This is an <img src="http://example.com/i/image.jpg" alt="" />.</p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg#a1!.
|
||||
out: <p>This is an <img src="http://example.com/i/image.jpg#a1" alt="" />.</p>
|
||||
---
|
||||
in: This is not an image!!!
|
||||
out: <p>This is not an image!!!</p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:#1
|
||||
out: <p>This is an <a href="#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:#a
|
||||
out: <p>This is an <a href="#a"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:#a1
|
||||
out: <p>This is an <a href="#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:#a10
|
||||
out: <p>This is an <a href="#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:index.html
|
||||
out: <p>This is an <a href="index.html"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:index.html#1
|
||||
out: <p>This is an <a href="index.html#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:index.html#a1
|
||||
out: <p>This is an <a href="index.html#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:index.html#a10
|
||||
out: <p>This is an <a href="index.html#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar
|
||||
out: <p>This is an <a href="index.html?foo=bar"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar#1
|
||||
out: <p>This is an <a href="index.html?foo=bar#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar#a
|
||||
out: <p>This is an <a href="index.html?foo=bar#a"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar#a1
|
||||
out: <p>This is an <a href="index.html?foo=bar#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar#a10
|
||||
out: <p>This is an <a href="index.html?foo=bar#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/
|
||||
out: <p>This is an <a href="http://example.com/"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/#1
|
||||
out: <p>This is an <a href="http://example.com/#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/#a
|
||||
out: <p>This is an <a href="http://example.com/#a"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/#a1
|
||||
out: <p>This is an <a href="http://example.com/#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/#a10
|
||||
out: <p>This is an <a href="http://example.com/#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html
|
||||
out: <p>This is an <a href="http://example.com/index.html"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html#1
|
||||
out: <p>This is an <a href="http://example.com/index.html#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html#a
|
||||
out: <p>This is an <a href="http://example.com/index.html#a"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html#a1
|
||||
out: <p>This is an <a href="http://example.com/index.html#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html#a10
|
||||
out: <p>This is an <a href="http://example.com/index.html#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar#1
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar#a
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar#a"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar#a1
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar#a10
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#1
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a1
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a10
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b.
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b"><img src="http://example.com/i/image.jpg" alt="" /></a>.</p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#1.
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#1"><img src="http://example.com/i/image.jpg" alt="" /></a>.</p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a.
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a"><img src="http://example.com/i/image.jpg" alt="" /></a>.</p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a1.
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a1"><img src="http://example.com/i/image.jpg" alt="" /></a>.</p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a10.
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a10"><img src="http://example.com/i/image.jpg" alt="" /></a>.</p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b, but this is not.
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b"><img src="http://example.com/i/image.jpg" alt="" /></a>, but this is not.</p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#1, but this is not.
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#1"><img src="http://example.com/i/image.jpg" alt="" /></a>, but this is not.</p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a, but this is not.
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a"><img src="http://example.com/i/image.jpg" alt="" /></a>, but this is not.</p>
|
||||
---
|
||||
in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a1, but this is not.
|
||||
out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a1"><img src="http://example.com/i/image.jpg" alt="" /></a>, but this is not.</p>
|
||||
---
|
||||
in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a10) This is not.
|
||||
out: <p>(This is an <a href="http://example.com/index.html?foo=bar&a=b#a10"><img src="http://example.com/i/image.jpg" alt="" /></a>) This is not.</p>
|
||||
---
|
||||
in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b) This is not.
|
||||
out: <p>(This is an <a href="http://example.com/index.html?foo=bar&a=b"><img src="http://example.com/i/image.jpg" alt="" /></a>) This is not.</p>
|
||||
---
|
||||
in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#1) This is not.
|
||||
out: <p>(This is an <a href="http://example.com/index.html?foo=bar&a=b#1"><img src="http://example.com/i/image.jpg" alt="" /></a>) This is not.</p>
|
||||
---
|
||||
in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a) This is not.
|
||||
out: <p>(This is an <a href="http://example.com/index.html?foo=bar&a=b#a"><img src="http://example.com/i/image.jpg" alt="" /></a>) This is not.</p>
|
||||
---
|
||||
in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a1) This is not.
|
||||
out: <p>(This is an <a href="http://example.com/index.html?foo=bar&a=b#a1"><img src="http://example.com/i/image.jpg" alt="" /></a>) This is not.</p>
|
||||
---
|
||||
in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a10) This is not.
|
||||
out: <p>(This is an <a href="http://example.com/index.html?foo=bar&a=b#a10"><img src="http://example.com/i/image.jpg" alt="" /></a>) This is not.</p>
|
||||
39
tracks/vendor/RedCloth-3.0.3/tests/instiki.yml
vendored
Normal file
39
tracks/vendor/RedCloth-3.0.3/tests/instiki.yml
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
--- # Bugs filed at http://www.instiki.org/show/BugReports
|
||||
in: |-
|
||||
_Hi, <span class="newWikiWord">Joe Bob<a href="../show/JoeBob">?</a></span>, this should all be in italic!_
|
||||
out: |-
|
||||
<p><em>Hi, <span class="newWikiWord">Joe Bob<a href="../show/JoeBob">?</a></span>, this should all be in italic!</em></p>
|
||||
---
|
||||
in: '*this <span>span</span> is strong*'
|
||||
out: '<p><strong>this <span>span</span> is strong</strong></p>'
|
||||
---
|
||||
in: '*this <span>Camel Thing<a href="../show/CamelThing">?</a></span> is strong*'
|
||||
out: '<p><strong>this <span>Camel Thing<a href="../show/CamelThing">?</a></span> is strong</strong></p>'
|
||||
---
|
||||
in: '_this <span>span</span> is italic_'
|
||||
out: '<p><em>this <span>span</span> is italic</em></p>'
|
||||
---
|
||||
in: '%{color:red}nested span because of <span><span class="newWikiWord">Camel Word<a href="../show/CamelWord">?</a></span></span>%'
|
||||
out: '<p><span style="color:red;">nested span because of <span><span class="newWikiWord">Camel Word<a href="../show/CamelWord">?</a></span></span></span></p>'
|
||||
---
|
||||
in: |-
|
||||
h2. Version History
|
||||
|
||||
* "Version
|
||||
0.0":http://www.threewordslong.com/render-0-8-9b.patch - Early version using MD5 hashes.
|
||||
* "Version
|
||||
0.1":http://www.threewordslong.com/chunk-0-1.patch.gz - First cut of new system. Much cleaner.
|
||||
* "Version 0.2":http://www.threewordslong.com/chunk-0-2.patch.gz - Fixed problem with "authors" page and some tests.
|
||||
out: |-
|
||||
<h2>Version History</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="http://www.threewordslong.com/render-0-8-9b.patch">Version
|
||||
0.0</a> – Early version using <span class="caps">MD5</span> hashes.</li>
|
||||
<li><a href="http://www.threewordslong.com/chunk-0-1.patch.gz">Version
|
||||
0.1</a> – First cut of new system. Much cleaner.</li>
|
||||
<li><a href="http://www.threewordslong.com/chunk-0-2.patch.gz">Version 0.2</a> – Fixed problem with “authors” page and some tests.</li>
|
||||
</ul>
|
||||
---
|
||||
in: "--richSeymour --whyTheLuckyStiff"
|
||||
out: "<p>—richSeymour—whyTheLuckyStiff</p>"
|
||||
155
tracks/vendor/RedCloth-3.0.3/tests/links.yml
vendored
Normal file
155
tracks/vendor/RedCloth-3.0.3/tests/links.yml
vendored
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
---
|
||||
in: '"link text":#1'
|
||||
out: <p><a href="#1">link text</a></p>
|
||||
---
|
||||
in: '"link text":#a'
|
||||
out: <p><a href="#a">link text</a></p>
|
||||
---
|
||||
in: '"link text":#a1'
|
||||
out: <p><a href="#a1">link text</a></p>
|
||||
---
|
||||
in: '"link text":#a10'
|
||||
out: <p><a href="#a10">link text</a></p>
|
||||
---
|
||||
in: '"link text":index.html'
|
||||
out: <p><a href="index.html">link text</a></p>
|
||||
---
|
||||
in: '"link text":index.html#1'
|
||||
out: <p><a href="index.html#1">link text</a></p>
|
||||
---
|
||||
in: '"link text":index.html#a'
|
||||
out: <p><a href="index.html#a">link text</a></p>
|
||||
---
|
||||
in: '"link text":index.html#a1'
|
||||
out: <p><a href="index.html#a1">link text</a></p>
|
||||
---
|
||||
in: '"link text":index.html#a10'
|
||||
out: <p><a href="index.html#a10">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/'
|
||||
out: <p><a href="http://example.com/">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/#1'
|
||||
out: <p><a href="http://example.com/#1">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/#a'
|
||||
out: <p><a href="http://example.com/#a">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/#a1'
|
||||
out: <p><a href="http://example.com/#a1">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/#a10'
|
||||
out: <p><a href="http://example.com/#a10">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/index.html'
|
||||
out: <p><a href="http://example.com/index.html">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/index.html#a'
|
||||
out: <p><a href="http://example.com/index.html#a">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/index.html#1'
|
||||
out: <p><a href="http://example.com/index.html#1">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/index.html#a1'
|
||||
out: <p><a href="http://example.com/index.html#a1">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/index.html#a10'
|
||||
out: <p><a href="http://example.com/index.html#a10">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/?foo=bar'
|
||||
out: <p><a href="http://example.com/?foo=bar">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/?foo=bar#a'
|
||||
out: <p><a href="http://example.com/?foo=bar#a">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/?foo=bar#1'
|
||||
out: <p><a href="http://example.com/?foo=bar#1">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/?foo=bar#a1'
|
||||
out: <p><a href="http://example.com/?foo=bar#a1">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/?foo=bar#a10'
|
||||
out: <p><a href="http://example.com/?foo=bar#a10">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/?foo=bar&a=b'
|
||||
out: <p><a href="http://example.com/?foo=bar&a=b">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/?foo=bar&a=b#1'
|
||||
out: <p><a href="http://example.com/?foo=bar&a=b#1">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/?foo=bar&a=b#a'
|
||||
out: <p><a href="http://example.com/?foo=bar&a=b#a">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/?foo=bar&a=b#a1'
|
||||
out: <p><a href="http://example.com/?foo=bar&a=b#a1">link text</a></p>
|
||||
---
|
||||
in: '"link text":http://example.com/?foo=bar&a=b#a10'
|
||||
out: <p><a href="http://example.com/?foo=bar&a=b#a10">link text</a></p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/'
|
||||
out: <p>This is a <a href="http://example.com/">link</a></p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/.'
|
||||
out: <p>This is a <a href="http://example.com/">link</a>.</p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/index.html.'
|
||||
out: <p>This is a <a href="http://example.com/index.html">link</a>.</p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/index.html#a.'
|
||||
out: <p>This is a <a href="http://example.com/index.html#a">link</a>.</p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/index.html#1.'
|
||||
out: <p>This is a <a href="http://example.com/index.html#1">link</a>.</p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/index.html#a1.'
|
||||
out: <p>This is a <a href="http://example.com/index.html#a1">link</a>.</p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/index.html#a10.'
|
||||
out: <p>This is a <a href="http://example.com/index.html#a10">link</a>.</p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/?foo=bar.'
|
||||
out: <p>This is a <a href="http://example.com/?foo=bar">link</a>.</p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/?foo=bar#1.'
|
||||
out: <p>This is a <a href="http://example.com/?foo=bar#1">link</a>.</p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/?foo=bar#a.'
|
||||
out: <p>This is a <a href="http://example.com/?foo=bar#a">link</a>.</p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/?foo=bar#a1.'
|
||||
out: <p>This is a <a href="http://example.com/?foo=bar#a1">link</a>.</p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/?foo=bar#a10.'
|
||||
out: <p>This is a <a href="http://example.com/?foo=bar#a10">link</a>.</p>
|
||||
---
|
||||
in: 'This is a "link":http://example.com/?foo=bar#a10, but this is not.'
|
||||
out: <p>This is a <a href="http://example.com/?foo=bar#a10">link</a>, but this is not.</p>
|
||||
---
|
||||
in: '(This is a "link":http://example.com/?foo=bar#a10) but this is not.'
|
||||
out: <p>(This is a <a href="http://example.com/?foo=bar#a10">link</a>) but this is not.</p>
|
||||
---
|
||||
in: '"link text(link title)":http://example.com/'
|
||||
out: <p><a href="http://example.com/" title="link title">link text</a></p>
|
||||
# ---
|
||||
# in: '"link text(link title) ":http://example.com/'
|
||||
# out: <p>“link text(link title) “:http://example.com/</p>
|
||||
# comments: this is a real test and should pass
|
||||
---
|
||||
in: '"(link) text(link title)":http://example.com/'
|
||||
out: <p><a href="http://example.com/" class="link" title="link title"> text</a></p>
|
||||
comments: link text can not contain parentheses
|
||||
---
|
||||
in: '"Dive Into XML":http://www.xml.com/pub/au/164'
|
||||
out: <p><a href="http://www.xml.com/pub/au/164">Dive Into <span class="caps">XML</span></a></p>
|
||||
---
|
||||
in: '"Lab Exercises":../lab/exercises/exercises.html.'
|
||||
out: <p><a href="../lab/exercises/exercises.html">Lab Exercises</a>.</p>
|
||||
---
|
||||
in: 'Go to "discuss":http://www.dreammoods.com/cgibin/cutecast/cutecast.pl?forum=1&thread=26627 to discuss.'
|
||||
out: <p>Go to <a href="http://www.dreammoods.com/cgibin/cutecast/cutecast.pl?forum=1&thread=26627">discuss</a> to discuss.</p>
|
||||
---
|
||||
in: '* "rubylang":http://www.ruby-lang.org/en/'
|
||||
out: "<ul>\n\t<li><a href=\"http://www.ruby-lang.org/en/\">rubylang</a></li>\n\t</ul>"
|
||||
---
|
||||
in: 'The ION coding style document found at "IONCodingStyleGuide.doc":http://perforce:8081/@md=d&cd=//&c=82E@//depot/systest/system/main/pub/doc/IONCodingStyleGuide.doc?ac=22 codifies a couple of rules to ensure reasonably consistent code and documentation of libraries in ION. Test text'
|
||||
out: <p>The <span class="caps">ION</span> coding style document found at <a href="http://perforce:8081/@md=d&cd=//&c=82E@//depot/systest/system/main/pub/doc/IONCodingStyleGuide.doc?ac=22">IONCodingStyleGuide.doc</a> codifies a couple of rules to ensure reasonably consistent code and documentation of libraries in <span class="caps">ION</span>. Test text</p>
|
||||
77
tracks/vendor/RedCloth-3.0.3/tests/lists.yml
vendored
Normal file
77
tracks/vendor/RedCloth-3.0.3/tests/lists.yml
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
--- # Bret Pettichord, Thanks.
|
||||
in: |-
|
||||
* first line
|
||||
* second
|
||||
line
|
||||
* third line
|
||||
out: |-
|
||||
<ul>
|
||||
<li>first line</li>
|
||||
<li>second
|
||||
line</li>
|
||||
<li>third line</li>
|
||||
</ul>
|
||||
---
|
||||
in: |-
|
||||
p. start
|
||||
|
||||
* one
|
||||
and one
|
||||
* two
|
||||
and two
|
||||
* three
|
||||
|
||||
p. end
|
||||
out: |-
|
||||
<p>start</p>
|
||||
<ul>
|
||||
<li>one
|
||||
and one</li>
|
||||
<li>two
|
||||
and two</li>
|
||||
<li>three</li>
|
||||
</ul>
|
||||
|
||||
<p>end</p>
|
||||
---
|
||||
in: |-
|
||||
Funky:
|
||||
|
||||
* Testing
|
||||
*# number
|
||||
*##* bullet
|
||||
*# number
|
||||
*# number
|
||||
yeah number
|
||||
#* bullet
|
||||
*** okay
|
||||
****# what
|
||||
|
||||
|
||||
out: |-
|
||||
<p>Funky:</p>
|
||||
<ul>
|
||||
<li>Testing
|
||||
<ol>
|
||||
<li>number
|
||||
<ul>
|
||||
<li>bullet</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>number</li>
|
||||
<li>number
|
||||
yeah number</li>
|
||||
<ul>
|
||||
<li>bullet
|
||||
<ul>
|
||||
<li>okay
|
||||
<ol>
|
||||
<li>what</li>
|
||||
</ul></li>
|
||||
</ol></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ol>
|
||||
---
|
||||
in: "* command run: @time ruby run-tests.rb > toto@"
|
||||
out: "<ul>\n\t<li>command run: <code>time ruby run-tests.rb > toto</code></li>\n\t</ul>"
|
||||
218
tracks/vendor/RedCloth-3.0.3/tests/markdown.yml
vendored
Normal file
218
tracks/vendor/RedCloth-3.0.3/tests/markdown.yml
vendored
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
in: |
|
||||
This is a regular paragraph.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>Foo</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
This is another regular paragraph.
|
||||
out: |-
|
||||
<p>This is a regular paragraph.</p>
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>Foo</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>This is another regular paragraph.</p>
|
||||
---
|
||||
in: '"Larry Bird":http://images.google.com/images?num=30&q=larry+bird'
|
||||
out: '<p>"Larry Bird":http://images.google.com/images?num=30&q=larry+bird</p>'
|
||||
---
|
||||
in: '©'
|
||||
out: <p>©</p>
|
||||
---
|
||||
in: AT&T
|
||||
out: <p>AT&T</p>
|
||||
|
||||
# We don't do this.
|
||||
# ---
|
||||
# in: 4 < 5
|
||||
# out: 4 < 5
|
||||
---
|
||||
in: |
|
||||
This is an H1
|
||||
=============
|
||||
|
||||
This is an H2
|
||||
-------------
|
||||
out: |-
|
||||
<h1>This is an H1</h1>
|
||||
|
||||
<h2>This is an H2</h2>
|
||||
---
|
||||
in: |
|
||||
# This is an H1
|
||||
|
||||
## This is an H2
|
||||
|
||||
###### This is an H6
|
||||
out: |-
|
||||
<h1>This is an H1</h1>
|
||||
|
||||
<h2>This is an H2</h2>
|
||||
|
||||
<h6>This is an H6</h6>
|
||||
---
|
||||
in: |
|
||||
> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
|
||||
> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
|
||||
> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
|
||||
>
|
||||
> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
|
||||
> id sem consectetuer libero luctus adipiscing.
|
||||
out: |-
|
||||
<blockquote>
|
||||
<p>This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
|
||||
consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
|
||||
Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.</p>
|
||||
|
||||
<p>Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
|
||||
id sem consectetuer libero luctus adipiscing.</p>
|
||||
|
||||
</blockquote>
|
||||
---
|
||||
in: |
|
||||
> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
|
||||
consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
|
||||
Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
|
||||
>
|
||||
> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
|
||||
id sem consectetuer libero luctus adipiscing.
|
||||
out: |-
|
||||
<blockquote>
|
||||
<p>This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
|
||||
consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
|
||||
Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.</p>
|
||||
|
||||
<p>Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
|
||||
id sem consectetuer libero luctus adipiscing.</p>
|
||||
|
||||
</blockquote>
|
||||
---
|
||||
in: |
|
||||
> This is the first level of quoting.
|
||||
>
|
||||
> > This is nested blockquote.
|
||||
>
|
||||
> Back to the first level.
|
||||
out: |-
|
||||
<blockquote>
|
||||
<p>This is the first level of quoting.</p>
|
||||
<blockquote>
|
||||
<p>This is nested blockquote.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
|
||||
|
||||
<p>Back to the first level.</p>
|
||||
|
||||
</blockquote>
|
||||
---
|
||||
in: |
|
||||
> ## This is a header.
|
||||
>
|
||||
> 1. This is the first list item.
|
||||
> 2. This is the second list item.
|
||||
>
|
||||
> Here's some example code:
|
||||
>
|
||||
> return shell_exec("echo $input | $markdown_script");
|
||||
out: |-
|
||||
<blockquote>
|
||||
<h2>This is a header.</h2>
|
||||
|
||||
|
||||
|
||||
<p>1. This is the first list item.
|
||||
2. This is the second list item.</p>
|
||||
|
||||
<p>Here's some example code:</p>
|
||||
<pre><code>return shell_exec("echo $input | $markdown_script");</code></pre>
|
||||
|
||||
</blockquote>
|
||||
---
|
||||
in: |
|
||||
* * *
|
||||
|
||||
***
|
||||
|
||||
*****
|
||||
|
||||
- - -
|
||||
|
||||
---------------------------------------
|
||||
|
||||
_ _ _
|
||||
out: |-
|
||||
<hr />
|
||||
|
||||
<hr />
|
||||
|
||||
<hr />
|
||||
|
||||
<hr />
|
||||
|
||||
<hr />
|
||||
|
||||
<hr />
|
||||
---
|
||||
in: |
|
||||
This is [an example](http://example.com/ "Title") inline link.
|
||||
|
||||
[This link](http://example.net/) has no title attribute.
|
||||
out: |-
|
||||
<p>This is <a href="http://example.com/" title="Title">an example</a> inline link.</p>
|
||||
|
||||
<p><a href="http://example.net/">This link</a> has no title attribute.</p>
|
||||
---
|
||||
in: See my [About](/about/) page for details.
|
||||
out: <p>See my <a href="/about/">About</a> page for details.</p>
|
||||
---
|
||||
in: |
|
||||
This is [an example][id] reference-style link.
|
||||
|
||||
This is [an example] [id] reference-style link.
|
||||
|
||||
[id]: http://example.com/ "Optional Title Here"
|
||||
out: |-
|
||||
<p>This is <a href="http://example.com/" title="Optional Title Here">an example</a> reference-style link.</p>
|
||||
|
||||
<p>This is <a href="http://example.com/" title="Optional Title Here">an example</a> reference-style link.</p>
|
||||
---
|
||||
in: |
|
||||
[Google][]
|
||||
[Google]: http://google.com/
|
||||
out: <p><a href="http://google.com/">Google</a></p>
|
||||
---
|
||||
in: |
|
||||
Visit [Daring Fireball][] for more information.
|
||||
[Daring Fireball]: http://daringfireball.net/
|
||||
out: <p>Visit <a href="http://daringfireball.net/">Daring Fireball</a> for more information.</p>
|
||||
---
|
||||
in: |
|
||||
I get 10 times more traffic from [Google] [1] than from
|
||||
[Yahoo] [2] or [MSN] [3].
|
||||
|
||||
[1]: http://google.com/ "Google"
|
||||
[2]: http://search.yahoo.com/ "Yahoo Search"
|
||||
[3]: http://search.msn.com/ "MSN Search"
|
||||
|
||||
out: |-
|
||||
<p>I get 10 times more traffic from <a href="http://google.com/" title="Google">Google</a> than from
|
||||
<a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
|
||||
---
|
||||
in: |
|
||||
I get 10 times more traffic from [Google][] than from
|
||||
[Yahoo][] or [MSN][].
|
||||
|
||||
[google]: http://google.com/ "Google"
|
||||
[yahoo]: http://search.yahoo.com/ "Yahoo Search"
|
||||
[msn]: http://search.msn.com/ "MSN Search"
|
||||
out: |-
|
||||
<p>I get 10 times more traffic from <a href="http://google.com/" title="Google">Google</a> than from
|
||||
<a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
|
||||
64
tracks/vendor/RedCloth-3.0.3/tests/poignant.yml
vendored
Normal file
64
tracks/vendor/RedCloth-3.0.3/tests/poignant.yml
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
--- # Tests from the (Poignant Guide)
|
||||
in: >
|
||||
h3. False
|
||||
|
||||
|
||||
!<i/blix-neg.gif(Shape of a cat.)!
|
||||
|
||||
|
||||
_The cat Trady Blix. Frozen in emptiness. Immaculate whiskers rigid. Placid
|
||||
eyes of lake. Tail of warm icicle. Sponsored by a Very Powerful Pause Button._
|
||||
|
||||
|
||||
The darkness surrounding Blix can be called *negative space*. Hang on to that phrase.
|
||||
Let it suggest that the emptiness has a negative connotation. In a similar way,
|
||||
@nil@ has a slightly sour note that it whistles.
|
||||
|
||||
|
||||
Generally speaking, everything in Ruby has a positive charge to it. This spark
|
||||
flows through strings, numbers, regexps, all of it. Only two keywords wear a
|
||||
shady cloak: @nil@ and @false@ draggin us down.
|
||||
|
||||
|
||||
You can test that charge with an @if@ keyword. It looks very much like the
|
||||
@do@ blocks we saw in the last chapter, in that both end with an @end@.
|
||||
|
||||
|
||||
<pre>
|
||||
if plastic_cup
|
||||
print "Plastic cup is on the up 'n' up!"
|
||||
end
|
||||
</pre>
|
||||
|
||||
|
||||
If @plastic_cup@ contains either @nil@ or @false@, you won't see anything print
|
||||
to the screen. They're not on the @if@ guest list. So @if@ isn't going to run
|
||||
any of the code it's protecting.
|
||||
|
||||
|
||||
But @nil@ and @false@ need not walk away in shame. They may be of questionable
|
||||
character, but @unless@ runs a smaller establishment that caters to the bedraggled.
|
||||
The @unless@ keyword has a policy of only allowing those with a negative charge in.
|
||||
Who are: @nil@ and @false@.
|
||||
|
||||
|
||||
<pre>
|
||||
unless plastic_cup
|
||||
print "Plastic cup is on the down low."
|
||||
end
|
||||
</pre>
|
||||
|
||||
|
||||
You can also use @if@ and @unless@ at the end of a single line of code, if that's
|
||||
all that is being protected.
|
||||
|
||||
|
||||
<pre>
|
||||
print "Yeah, plastic cup is up again!" if plastic_cup
|
||||
print "Hardly. It's down." unless plastic_cup
|
||||
</pre>
|
||||
|
||||
|
||||
Now that you've met @false@, I'm sure you can see what's on next.
|
||||
|
||||
out: "<h3>False</h3>\n\n\t<p style=\"float:left\"><img src=\"i/blix-neg.gif\" title=\"Shape of a cat.\" alt=\"Shape of a cat.\" /></p>\n\n\t<p><em>The cat Trady Blix. Frozen in emptiness. Immaculate whiskers rigid. Placid eyes of lake. Tail of warm icicle. Sponsored by a Very Powerful Pause Button.</em></p>\n\n\t<p>The darkness surrounding Blix can be called <strong>negative space</strong>. Hang on to that phrase. Let it suggest that the emptiness has a negative connotation. In a similar way, <code>nil</code> has a slightly sour note that it whistles.</p>\n\n\t<p>Generally speaking, everything in Ruby has a positive charge to it. This spark flows through strings, numbers, regexps, all of it. Only two keywords wear a shady cloak: <code>nil</code> and <code>false</code> draggin us down.</p>\n\n\t<p>You can test that charge with an <code>if</code> keyword. It looks very much like the <code>do</code> blocks we saw in the last chapter, in that both end with an <code>end</code>.</p>\n\n\n<pre>\n if plastic_cup\n print \"Plastic cup is on the up 'n' up!\" \n end\n</pre>\n\t<p>If <code>plastic_cup</code> contains either <code>nil</code> or <code>false</code>, you won’t see anything print to the screen. They’re not on the <code>if</code> guest list. So <code>if</code> isn’t going to run any of the code it’s protecting.</p>\n\n\t<p>But <code>nil</code> and <code>false</code> need not walk away in shame. They may be of questionable character, but <code>unless</code> runs a smaller establishment that caters to the bedraggled. The <code>unless</code> keyword has a policy of only allowing those with a negative charge in. Who are: <code>nil</code> and <code>false</code>.</p>\n\n\n<pre>\n unless plastic_cup\n print \"Plastic cup is on the down low.\" \n end\n</pre>\n\t<p>You can also use <code>if</code> and <code>unless</code> at the end of a single line of code, if that’s all that is being protected.</p>\n\n\n<pre>\n print \"Yeah, plastic cup is up again!\" if plastic_cup\n print \"Hardly. It's down.\" unless plastic_cup\n</pre>\n\t<p>Now that you’ve met <code>false</code>, I’m sure you can see what’s on next.</p>"
|
||||
198
tracks/vendor/RedCloth-3.0.3/tests/table.yml
vendored
Normal file
198
tracks/vendor/RedCloth-3.0.3/tests/table.yml
vendored
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
in: |
|
||||
{background:#ddd}. |S|Target|Complete|App|Milestone|
|
||||
|!/i/g.gif!|11/18/04|11/18/04|070|XML spec complete|
|
||||
|!/i/g.gif!|11/29/04|11/29/04|011|XML spec complete (KH is on schedule)|
|
||||
|!/i/g.gif!|11/29/04|11/29/04|051|XML spec complete (KH is on schedule)|
|
||||
|!/i/g.gif!|11/29/04|11/29/04|081|XML spec complete (KH is on schedule)|
|
||||
|!/i/g.gif!|11/19/04|11/22/04|070|Preprocessor complete|
|
||||
|!/i/g.gif!|11/22/04|11/22/04|070|Dialog pass 1 builds an index file|
|
||||
|!/i/g.gif!|11/24/04|11/24/04|070|Dialog pass 2 98% complete|
|
||||
|!/i/g.gif!|11/30/04|11/30/04|070|Feature complete. Passes end-to-end smoke test.|
|
||||
|!/i/g.gif!|11/30/04|11/30/04|011|Preprocessor updates complete|
|
||||
|!/i/g.gif!|11/30/04|11/30/04|051|Preprocessor updates complete|
|
||||
|!/i/g.gif!|11/30/04|11/29/04|081|Preprocessor updates complete|
|
||||
|!/i/w.gif!|12/02/04|.|011|Dialog pass 1 and 2 complete (98+%)|
|
||||
|!/i/w.gif!|12/02/04|.|051|Dialog pass 1 and 2 complete (98+%)|
|
||||
|!/i/w.gif!|12/02/04|.|081|Dialog pass 1 and 2 complete (98+%)|
|
||||
|!/i/w.gif!|12/03/04|.|011|Feature complete|
|
||||
|!/i/w.gif!|12/03/04|.|051|Feature complete|
|
||||
|!/i/w.gif!|12/03/04|.|081|Feature complete|
|
||||
|!/i/w.gif!|12/10/04|.|011|Deployed to Napa test workstation. Passes smoke test.|
|
||||
|!/i/w.gif!|12/10/04|.|051|Deployed to Napa test workstation. Passes smoke test.|
|
||||
|!/i/w.gif!|12/10/04|.|081|Deployed to Napa test workstation. Passes smoke test.|
|
||||
|!/i/w.gif!|12/10/04|.|070|Deployed to Napa test workstation. Passes smoke test.|
|
||||
|!/i/w.gif!|12/17/04|.|011|System testing complete. Begin testing with live customer data.|
|
||||
|!/i/w.gif!|12/17/04|.|051|System testing complete. Begin testing with live customer data.|
|
||||
|!/i/w.gif!|12/17/04|.|081|System testing complete. Begin testing with live customer data.|
|
||||
|!/i/w.gif!|12/17/04|.|070|System testing complete. Begin testing with live customer data.|
|
||||
out: |-
|
||||
<table>
|
||||
<tr style="background:#ddd;">
|
||||
<td>S</td>
|
||||
<td>Target</td>
|
||||
<td>Complete</td>
|
||||
<td>App</td>
|
||||
<td>Milestone</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/g.gif" alt="" /></td>
|
||||
<td>11/18/04</td>
|
||||
<td>11/18/04</td>
|
||||
<td>070</td>
|
||||
<td>XML spec complete</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/g.gif" alt="" /></td>
|
||||
<td>11/29/04</td>
|
||||
<td>11/29/04</td>
|
||||
<td>011</td>
|
||||
<td>XML spec complete (KH is on schedule)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/g.gif" alt="" /></td>
|
||||
<td>11/29/04</td>
|
||||
<td>11/29/04</td>
|
||||
<td>051</td>
|
||||
<td>XML spec complete (KH is on schedule)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/g.gif" alt="" /></td>
|
||||
<td>11/29/04</td>
|
||||
<td>11/29/04</td>
|
||||
<td>081</td>
|
||||
<td>XML spec complete (KH is on schedule)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/g.gif" alt="" /></td>
|
||||
<td>11/19/04</td>
|
||||
<td>11/22/04</td>
|
||||
<td>070</td>
|
||||
<td>Preprocessor complete</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/g.gif" alt="" /></td>
|
||||
<td>11/22/04</td>
|
||||
<td>11/22/04</td>
|
||||
<td>070</td>
|
||||
<td>Dialog pass 1 builds an index file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/g.gif" alt="" /></td>
|
||||
<td>11/24/04</td>
|
||||
<td>11/24/04</td>
|
||||
<td>070</td>
|
||||
<td>Dialog pass 2 98% complete</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/g.gif" alt="" /></td>
|
||||
<td>11/30/04</td>
|
||||
<td>11/30/04</td>
|
||||
<td>070</td>
|
||||
<td>Feature complete. Passes end-to-end smoke test.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/g.gif" alt="" /></td>
|
||||
<td>11/30/04</td>
|
||||
<td>11/30/04</td>
|
||||
<td>011</td>
|
||||
<td>Preprocessor updates complete</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/g.gif" alt="" /></td>
|
||||
<td>11/30/04</td>
|
||||
<td>11/30/04</td>
|
||||
<td>051</td>
|
||||
<td>Preprocessor updates complete</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/g.gif" alt="" /></td>
|
||||
<td>11/30/04</td>
|
||||
<td>11/29/04</td>
|
||||
<td>081</td>
|
||||
<td>Preprocessor updates complete</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/02/04</td>
|
||||
<td>011</td>
|
||||
<td>Dialog pass 1 and 2 complete (98+%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/02/04</td>
|
||||
<td>051</td>
|
||||
<td>Dialog pass 1 and 2 complete (98+%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/02/04</td>
|
||||
<td>081</td>
|
||||
<td>Dialog pass 1 and 2 complete (98+%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/03/04</td>
|
||||
<td>011</td>
|
||||
<td>Feature complete</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/03/04</td>
|
||||
<td>051</td>
|
||||
<td>Feature complete</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/03/04</td>
|
||||
<td>081</td>
|
||||
<td>Feature complete</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/10/04</td>
|
||||
<td>011</td>
|
||||
<td>Deployed to Napa test workstation. Passes smoke test.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/10/04</td>
|
||||
<td>051</td>
|
||||
<td>Deployed to Napa test workstation. Passes smoke test.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/10/04</td>
|
||||
<td>081</td>
|
||||
<td>Deployed to Napa test workstation. Passes smoke test.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/10/04</td>
|
||||
<td>070</td>
|
||||
<td>Deployed to Napa test workstation. Passes smoke test.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/17/04</td>
|
||||
<td>011</td>
|
||||
<td>System testing complete. Begin testing with live customer data.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/17/04</td>
|
||||
<td>051</td>
|
||||
<td>System testing complete. Begin testing with live customer data.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/17/04</td>
|
||||
<td>081</td>
|
||||
<td>System testing complete. Begin testing with live customer data.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/i/w.gif" alt="" /></td>
|
||||
<td>12/17/04</td>
|
||||
<td>070</td>
|
||||
<td>System testing complete. Begin testing with live customer data.</td>
|
||||
</tr>
|
||||
</table>
|
||||
397
tracks/vendor/RedCloth-3.0.3/tests/textism.yml
vendored
Normal file
397
tracks/vendor/RedCloth-3.0.3/tests/textism.yml
vendored
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
---
|
||||
in: h1. Header 1
|
||||
out: <h1>Header 1</h1>
|
||||
---
|
||||
in: h2. Header 2
|
||||
out: <h2>Header 2</h2>
|
||||
---
|
||||
in: h3. Header 3
|
||||
out: <h3>Header 3</h3>
|
||||
---
|
||||
in: |-
|
||||
Any old text.
|
||||
|
||||
bq. A block quotation.
|
||||
|
||||
Any old text.
|
||||
|
||||
out: |-
|
||||
<p>Any old text.</p>
|
||||
|
||||
<blockquote>
|
||||
<p>A block quotation.</p>
|
||||
</blockquote>
|
||||
|
||||
<p>Any old text.</p>
|
||||
|
||||
---
|
||||
in: This is covered elsewhere[1].
|
||||
out: <p>This is covered elsewhere<sup><a href="#fn1">1</a></sup>.</p>
|
||||
---
|
||||
in: fn1. Down here, in fact.
|
||||
out: <p id="fn1"><sup>1</sup> Down here, in fact.</p>
|
||||
---
|
||||
in: |-
|
||||
# A first item
|
||||
# A second item
|
||||
# A third item
|
||||
# A fourth item
|
||||
out: |-
|
||||
<ol>
|
||||
<li>A first item</li>
|
||||
<li>A second item</li>
|
||||
<li>A third item</li>
|
||||
<li>A fourth item</li>
|
||||
</ol>
|
||||
---
|
||||
in: |-
|
||||
* A first item
|
||||
* A second item
|
||||
* A third item
|
||||
* A fourth item
|
||||
|
||||
out: |-
|
||||
<ul>
|
||||
<li>A first item</li>
|
||||
<li>A second item</li>
|
||||
<li>A third item</li>
|
||||
<li>A fourth item</li>
|
||||
</ul>
|
||||
|
||||
---
|
||||
in: _a phrase_
|
||||
out: <p><em>a phrase</em></p>
|
||||
---
|
||||
in: __a phrase__
|
||||
out: <p><i>a phrase</i></p>
|
||||
---
|
||||
in: '*a phrase*'
|
||||
out: <p><strong>a phrase</strong></p>
|
||||
---
|
||||
in: '**a phrase**'
|
||||
out: <p><b>a phrase</b></p>
|
||||
---
|
||||
in: Nabokov's ??Pnin??
|
||||
out: <p>Nabokov’s <cite>Pnin</cite></p>
|
||||
---
|
||||
in: -a phrase-
|
||||
out: <p><del>a phrase</del></p>
|
||||
---
|
||||
in: +a phrase+
|
||||
out: <p><ins>a phrase</ins></p>
|
||||
---
|
||||
in: ^a phrase^
|
||||
out: <p><sup>a phrase</sup></p>
|
||||
---
|
||||
in: ~a phrase~
|
||||
out: <p><sub>a phrase</sub></p>
|
||||
# ---
|
||||
# in: %(caps)SPAN%
|
||||
# out: <p><span class="caps">SPAN</span>
|
||||
---
|
||||
in: %{color:red}red%
|
||||
out: <p><span style="color:red;">red</span></p>
|
||||
---
|
||||
in: %[fr]rouge%
|
||||
out: <p><span lang="fr">rouge</span></p>
|
||||
---
|
||||
in: _(big)red_
|
||||
out: <p><em class="big">red</em></p>
|
||||
---
|
||||
in: p(bob). A paragraph
|
||||
out: <p class="bob">A paragraph</p>
|
||||
---
|
||||
in: p{color:#ddd}. A paragraph
|
||||
out: <p style="color:#ddd;">A paragraph</p>
|
||||
---
|
||||
in: p[fr]. A paragraph
|
||||
out: <p lang="fr">A paragraph</p>
|
||||
---
|
||||
in: h2()>. right-aligned header2, indented 1em both side
|
||||
out: <h2 style="padding-left:1em;padding-right:1em;text-align:right;">right-aligned header2, indented 1em both side</h2>
|
||||
---
|
||||
in: h3=. centered header
|
||||
out: <h3 style="text-align:center;">centered header</h3>
|
||||
---
|
||||
in: '!>/image.gif! right-aligned image'
|
||||
out: <p style="float:right"><img src="/image.gif" alt="" /> right-aligned image</p>
|
||||
---
|
||||
in: p[no]{color:red}. A Norse of a different colour.
|
||||
out: <p style="color:red;" lang="no">A Norse of a different colour.</p>
|
||||
---
|
||||
in: |-
|
||||
|This|is|a|simple|table|
|
||||
|This|is|a|simple|row|
|
||||
out: |-
|
||||
<table>
|
||||
<tr>
|
||||
<td>This</td>
|
||||
<td>is</td>
|
||||
<td>a</td>
|
||||
<td>simple</td>
|
||||
<td>table</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>This</td>
|
||||
<td>is</td>
|
||||
<td>a</td>
|
||||
<td>simple</td>
|
||||
<td>row</td>
|
||||
</tr>
|
||||
</table>
|
||||
---
|
||||
in: |-
|
||||
table{border:1px solid black}.
|
||||
|This|is|a|row|
|
||||
|This|is|a|row|
|
||||
out: |-
|
||||
<table style="border:1px solid black;">
|
||||
<tr>
|
||||
<td>This</td>
|
||||
<td>is</td>
|
||||
<td>a</td>
|
||||
<td>row</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>This</td>
|
||||
<td>is</td>
|
||||
<td>a</td>
|
||||
<td>row</td>
|
||||
</tr>
|
||||
</table>
|
||||
---
|
||||
in: '{background:#ddd}. |This|is|a|row|'
|
||||
out: |-
|
||||
<table>
|
||||
<tr style="background:#ddd;">
|
||||
<td>This</td>
|
||||
<td>is</td>
|
||||
<td>a</td>
|
||||
<td>row</td>
|
||||
</tr>
|
||||
</table>
|
||||
---
|
||||
in: |-
|
||||
|{background:#ddd}. Cell with gray background|
|
||||
|\2. Cell spanning 2 columns|
|
||||
|/3. Cell spanning 3 rows|
|
||||
|>. Right-aligned cell|
|
||||
out: |-
|
||||
<table>
|
||||
<tr>
|
||||
<td style="background:#ddd;">Cell with gray background</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">Cell spanning 2 columns</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="3">Cell spanning 3 rows</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right;">Right-aligned cell</td>
|
||||
</tr>
|
||||
</table>
|
||||
# ---
|
||||
# in: |-
|
||||
# This is a "link":bob to Bob's website.
|
||||
#
|
||||
# [bob]http://itsbob.com/index.html
|
||||
---
|
||||
in: ACLU(American Civil Liberties Union)
|
||||
out: <p><acronym title="American Civil Liberties Union">ACLU</acronym></p>
|
||||
---
|
||||
in: |-
|
||||
h2{color:green}. This is a title
|
||||
|
||||
h3. This is a subhead
|
||||
|
||||
p{color:red}. This is some text of dubious character. Isn't the use of "quotes" just lazy writing -- and theft of 'intellectual property' besides? I think the time has come to see a block quote.
|
||||
|
||||
bq[fr]. This is a block quote. I'll admit it's not the most exciting block quote ever devised.
|
||||
|
||||
Simple list:
|
||||
|
||||
#{color:blue} one
|
||||
# two
|
||||
# three
|
||||
|
||||
Multi-level list:
|
||||
|
||||
# one
|
||||
## aye
|
||||
## bee
|
||||
## see
|
||||
# two
|
||||
## x
|
||||
## y
|
||||
# three
|
||||
|
||||
Mixed list:
|
||||
|
||||
* Point one
|
||||
* Point two
|
||||
## Step 1
|
||||
## Step 2
|
||||
## Step 3
|
||||
* Point three
|
||||
** Sub point 1
|
||||
** Sub point 2
|
||||
|
||||
|
||||
Well, that went well. How about we insert an <a href="/" title="watch out">old-fashioned hypertext link</a>? Will the quote marks in the tags get messed up? No!
|
||||
|
||||
"This is a link (optional title)":http://www.textism.com
|
||||
|
||||
table{border:1px solid black}.
|
||||
|_. this|_. is|_. a|_. header|
|
||||
<{background:gray}. |\2. this is|{background:red;width:200px}. a|^<>{height:200px}. row|
|
||||
|this|<>{padding:10px}. is|^. another|(bob#bob). row|
|
||||
|
||||
An image:
|
||||
|
||||
!/common/textist.gif(optional alt text)!
|
||||
|
||||
# Librarians rule
|
||||
# Yes they do
|
||||
# But you knew that
|
||||
|
||||
Some more text of dubious character. Here is a noisome string of CAPITAL letters. Here is something we want to _emphasize_.
|
||||
That was a linebreak. And something to indicate *strength*. Of course I could use <em>my own HTML tags</em> if I <strong>felt</strong> like it.
|
||||
|
||||
h3. Coding
|
||||
|
||||
This <code>is some code, "isn't it"</code>. Watch those quote marks! Now for some preformatted text:
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$text = str_replace("<p>%::%</p>","",$text);
|
||||
$text = str_replace("%::%</p>","",$text);
|
||||
$text = str_replace("%::%","",$text);
|
||||
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
This isn't code.
|
||||
|
||||
|
||||
So you see, my friends:
|
||||
|
||||
* The time is now
|
||||
* The time is not later
|
||||
* The time is not yesterday
|
||||
* We must act
|
||||
|
||||
out: |-
|
||||
<h2 style="color:green;">This is a title</h2>
|
||||
|
||||
<h3>This is a subhead</h3>
|
||||
|
||||
<p style="color:red;">This is some text of dubious character. Isn’t the use of “quotes” just lazy writing—and theft of ‘intellectual property’ besides? I think the time has come to see a block quote.</p>
|
||||
|
||||
<blockquote>
|
||||
<p lang="fr">This is a block quote. I’ll admit it’s not the most exciting block quote ever devised.</p>
|
||||
</blockquote>
|
||||
|
||||
<p>Simple list:</p>
|
||||
<ol style="color:blue;">
|
||||
<li>one</li>
|
||||
<li>two</li>
|
||||
<li>three</li>
|
||||
</ol>
|
||||
|
||||
<p>Multi-level list:</p>
|
||||
<ol>
|
||||
<li>one
|
||||
<ol>
|
||||
<li>aye</li>
|
||||
<li>bee</li>
|
||||
<li>see</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>two
|
||||
<ol>
|
||||
<li>x</li>
|
||||
<li>y</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>three</li>
|
||||
</ol>
|
||||
|
||||
<p>Mixed list:</p>
|
||||
<ul>
|
||||
<li>Point one</li>
|
||||
<li>Point two
|
||||
<ol>
|
||||
<li>Step 1</li>
|
||||
<li>Step 2</li>
|
||||
<li>Step 3</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>Point three
|
||||
<ul>
|
||||
<li>Sub point 1</li>
|
||||
<li>Sub point 2</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<p>Well, that went well. How about we insert an <a href="/" title="watch out">old-fashioned hypertext link</a>? Will the quote marks in the tags get messed up? No!</p>
|
||||
|
||||
<p><a href="http://www.textism.com" title="optional title">This is a link</a></p>
|
||||
|
||||
<table style="border:1px solid black;">
|
||||
<tr>
|
||||
<th>this</th>
|
||||
<th>is</th>
|
||||
<th>a</th>
|
||||
<th>header</th>
|
||||
</tr>
|
||||
<tr style="background:gray;text-align:left;">
|
||||
<td colspan="2">this is</td>
|
||||
<td style="background:red;width:200px;">a</td>
|
||||
<td style="vertical-align:top;height:200px;text-align:justify;">row</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>this</td>
|
||||
<td style="padding:10px;text-align:justify;">is</td>
|
||||
<td style="vertical-align:top;">another</td>
|
||||
<td class="bob" id="bob">row</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
<p>An image:</p>
|
||||
|
||||
<p><img src="/common/textist.gif" title="optional alt text" alt="optional alt text" /></p>
|
||||
<ol>
|
||||
<li>Librarians rule</li>
|
||||
<li>Yes they do</li>
|
||||
<li>But you knew that</li>
|
||||
</ol>
|
||||
|
||||
<p>Some more text of dubious character. Here is a noisome string of <span class="caps">CAPITAL</span> letters. Here is something we want to <em>emphasize</em>.
|
||||
That was a linebreak. And something to indicate <strong>strength</strong>. Of course I could use <em>my own <span class="caps">HTML</span> tags</em> if I <strong>felt</strong> like it.</p>
|
||||
|
||||
<h3>Coding</h3>
|
||||
|
||||
<p>This <code>is some code, "isn't it"</code>. Watch those quote marks! Now for some preformatted text:</p>
|
||||
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$text = str_replace("<p>%::%</p>","",$text);
|
||||
$text = str_replace("%::%</p>","",$text);
|
||||
$text = str_replace("%::%","",$text);
|
||||
|
||||
</code>
|
||||
</pre>
|
||||
<p>This isn’t code.</p>
|
||||
|
||||
<p>So you see, my friends:</p>
|
||||
<ul>
|
||||
<li>The time is now</li>
|
||||
<li>The time is not later</li>
|
||||
<li>The time is not yesterday</li>
|
||||
<li>We must act</li>
|
||||
</ul>
|
||||
|
||||
211
tracks/vendor/rails/actionmailer/CHANGELOG
vendored
Normal file
211
tracks/vendor/rails/actionmailer/CHANGELOG
vendored
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
*1.1.5* (December 13th, 2005)
|
||||
|
||||
* Become part of Rails 1.0
|
||||
|
||||
|
||||
*1.1.4* (December 7th, 2005)
|
||||
|
||||
* Rename Version constant to VERSION. #2802 [Marcel Molina Jr.]
|
||||
|
||||
|
||||
*1.1.3* (November 7th, 2005)
|
||||
|
||||
* Allow Mailers to have custom initialize methods that set default instance variables for all mail actions #2563 [mrj@bigpond.net.au]
|
||||
|
||||
|
||||
*1.1.2* (October 26th, 2005)
|
||||
|
||||
* Upgraded to Action Pack 1.10.2
|
||||
|
||||
|
||||
*1.1.1* (October 19th, 2005)
|
||||
|
||||
* Upgraded to Action Pack 1.10.1
|
||||
|
||||
|
||||
*1.1.0* (October 16th, 2005)
|
||||
|
||||
* Update and extend documentation (rdoc)
|
||||
|
||||
* Minero Aoki made TMail available to Rails/ActionMailer under the MIT license (instead of LGPL) [RubyConf '05]
|
||||
|
||||
* Austin Ziegler made Text::Simple available to Rails/ActionMailer under a MIT-like licens [See rails ML, subject "Text::Format Licence Exception" on Oct 15, 2005]
|
||||
|
||||
* Fix vendor require paths to prevent files being required twice
|
||||
|
||||
* Don't add charset to content-type header for a part that contains subparts (for AOL compatibility) #2013 [John Long]
|
||||
|
||||
* Preserve underscores when unquoting message bodies #1930
|
||||
|
||||
* Encode multibyte characters correctly #1894
|
||||
|
||||
* Multipart messages specify a MIME-Version header automatically #2003 [John Long]
|
||||
|
||||
* Add a unified render method to ActionMailer (delegates to ActionView::Base#render)
|
||||
|
||||
* Move mailer initialization to a separate (overridable) method, so that subclasses may alter the various defaults #1727
|
||||
|
||||
* Look at content-location header (if available) to determine filename of attachments #1670
|
||||
|
||||
* ActionMailer::Base.deliver(email) had been accidentally removed, but was documented in the Rails book #1849
|
||||
|
||||
* Fix problem with sendmail delivery where headers should be delimited by \n characters instead of \r\n, which confuses some mail readers #1742 [Kent Sibilev]
|
||||
|
||||
|
||||
*1.0.1* (11 July, 2005)
|
||||
|
||||
* Bind to Action Pack 1.9.1
|
||||
|
||||
|
||||
*1.0.0* (6 July, 2005)
|
||||
|
||||
* Avoid adding nil header values #1392
|
||||
|
||||
* Better multipart support with implicit multipart/alternative and sorting of subparts [John Long]
|
||||
|
||||
* Allow for nested parts in multipart mails #1570 [Flurin Egger]
|
||||
|
||||
* Normalize line endings in outgoing mail bodies to "\n" #1536 [John Long]
|
||||
|
||||
* Allow template to be explicitly specified #1448 [tuxie@dekadance.se]
|
||||
|
||||
* Allow specific "multipart/xxx" content-type to be set on multipart messages #1412 [Flurin Egger]
|
||||
|
||||
* Unquoted @ characters in headers are now accepted in spite of RFC 822 #1206
|
||||
|
||||
* Helper support (borrowed from ActionPack)
|
||||
|
||||
* Silently ignore Errno::EINVAL errors when converting text.
|
||||
|
||||
* Don't cause an error when parsing an encoded attachment name #1340 [lon@speedymac.com]
|
||||
|
||||
* Nested multipart message parts are correctly processed in TMail::Mail#body
|
||||
|
||||
* BCC headers are removed when sending via SMTP #1402
|
||||
|
||||
* Added 'content_type' accessor, to allow content type to be set on a per-message basis. content_type defaults to "text/plain".
|
||||
|
||||
* Silently ignore Iconv::IllegalSequence errors when converting text #1341 [lon@speedymac.com]
|
||||
|
||||
* Support attachments and multipart messages.
|
||||
|
||||
* Added new accessors for the various mail properties.
|
||||
|
||||
* Fix to only perform the charset conversion if a 'from' and a 'to' charset are given (make no assumptions about what the charset was) #1276 [Jamis Buck]
|
||||
|
||||
* Fix attachments and content-type problems #1276 [Jamis Buck]
|
||||
|
||||
* Fixed the TMail#body method to look at the content-transfer-encoding header and unquote the body according to the rules it specifies #1265 [Jamis Buck]
|
||||
|
||||
* Added unquoting even if the iconv lib can't be loaded--in that case, only the charset conversion is skipped #1265 [Jamis Buck]
|
||||
|
||||
* Added automatic decoding of base64 bodies #1214 [Jamis Buck]
|
||||
|
||||
* Added that delivery errors are caught in a way so the mail is still returned whether the delivery was successful or not
|
||||
|
||||
* Fixed that email address like "Jamis Buck, M.D." <wild.medicine@example.net> would cause the quoter to generate emails resulting in "bad address" errors from the mail server #1220 [Jamis Buck]
|
||||
|
||||
|
||||
*0.9.1* (20th April, 2005)
|
||||
|
||||
* Depend on Action Pack 1.8.1
|
||||
|
||||
|
||||
*0.9.0* (19th April, 2005)
|
||||
|
||||
* Added that deliver_* will now return the email that was sent
|
||||
|
||||
* Added that quoting to UTF-8 only happens if the characters used are in that range #955 [Jamis Buck]
|
||||
|
||||
* Fixed quoting for all address headers, not just to #955 [Jamis Buck]
|
||||
|
||||
* Fixed unquoting of emails that doesn't have an explicit charset #1036 [wolfgang@stufenlos.net]
|
||||
|
||||
|
||||
*0.8.1* (27th March, 2005)
|
||||
|
||||
* Fixed that if charset was found that the end of a mime part declaration TMail would throw an error #919 [lon@speedymac.com]
|
||||
|
||||
* Fixed that TMail::Unquoter would fail to recognize quoting method if it was in lowercase #919 [lon@speedymac.com]
|
||||
|
||||
* Fixed that TMail::Encoder would fail when it attempts to parse e-mail addresses which are encoded using something other than the messages encoding method #919 [lon@speedymac.com]
|
||||
|
||||
* Added rescue for missing iconv library and throws warnings if subject/body is called on a TMail object without it instead
|
||||
|
||||
|
||||
*0.8.0* (22th March, 2005)
|
||||
|
||||
* Added framework support for processing incoming emails with an Action Mailer class. See example in README.
|
||||
|
||||
|
||||
*0.7.1* (7th March, 2005)
|
||||
|
||||
* Bind to newest Action Pack (1.5.1)
|
||||
|
||||
|
||||
*0.7.0* (24th February, 2005)
|
||||
|
||||
* Added support for charsets for both subject and body. The default charset is now UTF-8 #673 [Jamis Buck]. Examples:
|
||||
|
||||
def iso_charset(recipient)
|
||||
@recipients = recipient
|
||||
@subject = "testing iso charsets"
|
||||
@from = "system@loudthinking.com"
|
||||
@body = "Nothing to see here."
|
||||
@charset = "iso-8859-1"
|
||||
end
|
||||
|
||||
def unencoded_subject(recipient)
|
||||
@recipients = recipient
|
||||
@subject = "testing unencoded subject"
|
||||
@from = "system@loudthinking.com"
|
||||
@body = "Nothing to see here."
|
||||
@encode_subject = false
|
||||
@charset = "iso-8859-1"
|
||||
end
|
||||
|
||||
|
||||
*0.6.1* (January 18th, 2005)
|
||||
|
||||
* Fixed sending of emails to use Tmail#from not the deprecated Tmail#from_address
|
||||
|
||||
|
||||
*0.6* (January 17th, 2005)
|
||||
|
||||
* Fixed that bcc and cc should be settable through @bcc and @cc -- not just @headers["Bcc"] and @headers["Cc"] #453 [Eric Hodel]
|
||||
|
||||
* Fixed Action Mailer to be "warnings safe" so you can run with ruby -w and not get framework warnings #453 [Eric Hodel]
|
||||
|
||||
|
||||
*0.5*
|
||||
|
||||
* Added access to custom headers, like cc, bcc, and reply-to #268 [Andreas Schwarz]. Example:
|
||||
|
||||
def post_notification(recipients, post)
|
||||
@recipients = recipients
|
||||
@from = post.author.email_address_with_name
|
||||
@headers["bcc"] = SYSTEM_ADMINISTRATOR_EMAIL
|
||||
@headers["reply-to"] = "notifications@example.com"
|
||||
@subject = "[#{post.account.name} #{post.title}]"
|
||||
@body["post"] = post
|
||||
end
|
||||
|
||||
*0.4* (5)
|
||||
|
||||
* Consolidated the server configuration options into Base#server_settings= and expanded that with controls for authentication and more [Marten]
|
||||
NOTE: This is an API change that could potentially break your application if you used the old application form. Please do change!
|
||||
|
||||
* Added Base#deliveries as an accessor for an array of emails sent out through that ActionMailer class when using the :test delivery option. [Jeremy Kemper]
|
||||
|
||||
* Added Base#perform_deliveries= which can be set to false to turn off the actual delivery of the email through smtp or sendmail.
|
||||
This is especially useful for functional testing that shouldn't send off real emails, but still trigger delivery_* methods.
|
||||
|
||||
* Added option to specify delivery method with Base#delivery_method=. Default is :smtp and :sendmail is currently the only other option.
|
||||
Sendmail is assumed to be present at "/usr/sbin/sendmail" if that option is used. [Kent Sibilev]
|
||||
|
||||
* Dropped "include TMail" as it added to much baggage into the default namespace (like Version) [Chad Fowler]
|
||||
|
||||
|
||||
*0.3*
|
||||
|
||||
* First release
|
||||
21
tracks/vendor/rails/actionmailer/MIT-LICENSE
vendored
Normal file
21
tracks/vendor/rails/actionmailer/MIT-LICENSE
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
Copyright (c) 2004 David Heinemeier Hansson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
148
tracks/vendor/rails/actionmailer/README
vendored
Normal file
148
tracks/vendor/rails/actionmailer/README
vendored
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
= Action Mailer -- Easy email delivery and testing
|
||||
|
||||
Action Mailer is a framework for designing email-service layers. These layers
|
||||
are used to consolidate code for sending out forgotten passwords, welcoming
|
||||
wishes on signup, invoices for billing, and any other use case that requires
|
||||
a written notification to either a person or another system.
|
||||
|
||||
Additionally, an Action Mailer class can be used to process incoming email,
|
||||
such as allowing a weblog to accept new posts from an email (which could even
|
||||
have been sent from a phone).
|
||||
|
||||
== Sending emails
|
||||
|
||||
The framework works by setting up all the email details, except the body,
|
||||
in methods on the service layer. Subject, recipients, sender, and timestamp
|
||||
are all set up this way. An example of such a method:
|
||||
|
||||
def signed_up(recipient)
|
||||
recipients recipient
|
||||
subject "[Signed up] Welcome #{recipient}"
|
||||
from "system@loudthinking.com"
|
||||
|
||||
body(:recipient => recipient)
|
||||
end
|
||||
|
||||
The body of the email is created by using an Action View template (regular
|
||||
ERb) that has the content of the body hash parameter available as instance variables.
|
||||
So the corresponding body template for the method above could look like this:
|
||||
|
||||
Hello there,
|
||||
|
||||
Mr. <%= @recipient %>
|
||||
|
||||
And if the recipient was given as "david@loudthinking.com", the email
|
||||
generated would look like this:
|
||||
|
||||
Date: Sun, 12 Dec 2004 00:00:00 +0100
|
||||
From: system@loudthinking.com
|
||||
To: david@loudthinking.com
|
||||
Subject: [Signed up] Welcome david@loudthinking.com
|
||||
|
||||
Hello there,
|
||||
|
||||
Mr. david@loudthinking.com
|
||||
|
||||
You never actually call the instance methods like signed_up directly. Instead,
|
||||
you call class methods like deliver_* and create_* that are automatically
|
||||
created for each instance method. So if the signed_up method sat on
|
||||
ApplicationMailer, it would look like this:
|
||||
|
||||
ApplicationMailer.create_signed_up("david@loudthinking.com") # => tmail object for testing
|
||||
ApplicationMailer.deliver_signed_up("david@loudthinking.com") # sends the email
|
||||
ApplicationMailer.new.signed_up("david@loudthinking.com") # won't work!
|
||||
|
||||
== Receiving emails
|
||||
|
||||
To receive emails, you need to implement a public instance method called receive that takes a
|
||||
tmail object as its single parameter. The Action Mailer framework has a corresponding class method,
|
||||
which is also called receive, that accepts a raw, unprocessed email as a string, which it then turns
|
||||
into the tmail object and calls the receive instance method.
|
||||
|
||||
Example:
|
||||
|
||||
class Mailman < ActionMailer::Base
|
||||
def receive(email)
|
||||
page = Page.find_by_address(email.to.first)
|
||||
page.emails.create(
|
||||
:subject => email.subject, :body => email.body
|
||||
)
|
||||
|
||||
if email.has_attachments?
|
||||
for attachment in email.attachments
|
||||
page.attachments.create({
|
||||
:file => attachment, :description => email.subject
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
This Mailman can be the target for Postfix. In Rails, you would use the runner like this:
|
||||
|
||||
./script/runner 'Mailman.receive(STDIN.read)'
|
||||
|
||||
== Configuration
|
||||
|
||||
The Base class has the full list of configuration options. Here's an example:
|
||||
|
||||
ActionMailer::Base.server_settings = {
|
||||
:address=>'smtp.yourserver.com', # default: localhost
|
||||
:port=>'25', # default: 25
|
||||
:user_name=>'user',
|
||||
:password=>'pass',
|
||||
:authentication=>:plain # :plain, :login or :cram_md5
|
||||
}
|
||||
|
||||
== Dependencies
|
||||
|
||||
Action Mailer requires that the Action Pack is either available to be required immediately
|
||||
or is accessible as a GEM.
|
||||
|
||||
|
||||
== Bundled software
|
||||
|
||||
* tmail 0.10.8 by Minero Aoki released under LGPL
|
||||
Read more on http://i.loveruby.net/en/prog/tmail.html
|
||||
|
||||
* Text::Format 0.63 by Austin Ziegler released under OpenSource
|
||||
Read more on http://www.halostatue.ca/ruby/Text__Format.html
|
||||
|
||||
|
||||
== Download
|
||||
|
||||
The latest version of Action Mailer can be found at
|
||||
|
||||
* http://rubyforge.org/project/showfiles.php?group_id=361
|
||||
|
||||
Documentation can be found at
|
||||
|
||||
* http://actionmailer.rubyonrails.org
|
||||
|
||||
|
||||
== Installation
|
||||
|
||||
You can install Action Mailer with the following command.
|
||||
|
||||
% [sudo] ruby install.rb
|
||||
|
||||
from its distribution directory.
|
||||
|
||||
|
||||
== License
|
||||
|
||||
Action Mailer is released under the MIT license.
|
||||
|
||||
|
||||
== Support
|
||||
|
||||
The Action Mailer homepage is http://actionmailer.rubyonrails.org. You can find
|
||||
the Action Mailer RubyForge page at http://rubyforge.org/projects/actionmailer.
|
||||
And as Jim from Rake says:
|
||||
|
||||
Feel free to submit commits or feature requests. If you send a patch,
|
||||
remember to update the corresponding unit tests. If fact, I prefer
|
||||
new feature to be submitted in the form of new unit tests.
|
||||
|
||||
For other information, feel free to ask on the ruby-talk mailing list (which
|
||||
is mirrored to comp.lang.ruby) or contact mailto:david@loudthinking.com.
|
||||
30
tracks/vendor/rails/actionmailer/install.rb
vendored
Normal file
30
tracks/vendor/rails/actionmailer/install.rb
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
require 'rbconfig'
|
||||
require 'find'
|
||||
require 'ftools'
|
||||
|
||||
include Config
|
||||
|
||||
# this was adapted from rdoc's install.rb by way of Log4r
|
||||
|
||||
$sitedir = CONFIG["sitelibdir"]
|
||||
unless $sitedir
|
||||
version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"]
|
||||
$libdir = File.join(CONFIG["libdir"], "ruby", version)
|
||||
$sitedir = $:.find {|x| x =~ /site_ruby/ }
|
||||
if !$sitedir
|
||||
$sitedir = File.join($libdir, "site_ruby")
|
||||
elsif $sitedir !~ Regexp.quote(version)
|
||||
$sitedir = File.join($sitedir, version)
|
||||
end
|
||||
end
|
||||
|
||||
# the acual gruntwork
|
||||
Dir.chdir("lib")
|
||||
|
||||
Find.find("action_mailer", "action_mailer.rb") { |f|
|
||||
if f[-3..-1] == ".rb"
|
||||
File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true)
|
||||
else
|
||||
File::makedirs(File.join($sitedir, *f.split(/\//)))
|
||||
end
|
||||
}
|
||||
51
tracks/vendor/rails/actionmailer/lib/action_mailer.rb
vendored
Normal file
51
tracks/vendor/rails/actionmailer/lib/action_mailer.rb
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#--
|
||||
# Copyright (c) 2004 David Heinemeier Hansson
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#++
|
||||
|
||||
begin
|
||||
require 'action_controller'
|
||||
rescue LoadError
|
||||
begin
|
||||
require File.dirname(__FILE__) + '/../../actionpack/lib/action_controller'
|
||||
rescue LoadError
|
||||
require 'rubygems'
|
||||
require_gem 'actionpack', '>= 1.9.1'
|
||||
end
|
||||
end
|
||||
|
||||
$:.unshift(File.dirname(__FILE__) + "/action_mailer/vendor/")
|
||||
|
||||
require 'action_mailer/base'
|
||||
require 'action_mailer/helpers'
|
||||
require 'action_mailer/mail_helper'
|
||||
require 'action_mailer/quoting'
|
||||
require 'tmail'
|
||||
require 'net/smtp'
|
||||
|
||||
ActionMailer::Base.class_eval do
|
||||
include ActionMailer::Quoting
|
||||
include ActionMailer::Helpers
|
||||
|
||||
helper MailHelper
|
||||
end
|
||||
|
||||
silence_warnings { TMail::Encoder.const_set("MAX_LINE_LEN", 200) }
|
||||
27
tracks/vendor/rails/actionmailer/lib/action_mailer/adv_attr_accessor.rb
vendored
Normal file
27
tracks/vendor/rails/actionmailer/lib/action_mailer/adv_attr_accessor.rb
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
module ActionMailer
|
||||
module AdvAttrAccessor #:nodoc:
|
||||
def self.append_features(base)
|
||||
super
|
||||
base.extend(ClassMethods)
|
||||
end
|
||||
|
||||
module ClassMethods #:nodoc:
|
||||
def adv_attr_accessor(*names)
|
||||
names.each do |name|
|
||||
define_method("#{name}=") do |value|
|
||||
instance_variable_set("@#{name}", value)
|
||||
end
|
||||
|
||||
define_method(name) do |*parameters|
|
||||
raise ArgumentError, "expected 0 or 1 parameters" unless parameters.length <= 1
|
||||
if parameters.empty?
|
||||
instance_variable_get("@#{name}")
|
||||
else
|
||||
instance_variable_set("@#{name}", parameters.first)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
453
tracks/vendor/rails/actionmailer/lib/action_mailer/base.rb
vendored
Normal file
453
tracks/vendor/rails/actionmailer/lib/action_mailer/base.rb
vendored
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
require 'action_mailer/adv_attr_accessor'
|
||||
require 'action_mailer/part'
|
||||
require 'action_mailer/part_container'
|
||||
require 'action_mailer/utils'
|
||||
require 'tmail/net'
|
||||
|
||||
module ActionMailer
|
||||
# Usage:
|
||||
#
|
||||
# class ApplicationMailer < ActionMailer::Base
|
||||
# # Set up properties
|
||||
# # Properties can also be specified via accessor methods
|
||||
# # (i.e. self.subject = "foo") and instance variables (@subject = "foo").
|
||||
# def signup_notification(recipient)
|
||||
# recipients recipient.email_address_with_name
|
||||
# subject "New account information"
|
||||
# body { "account" => recipient }
|
||||
# from "system@example.com"
|
||||
# end
|
||||
#
|
||||
# # explicitly specify multipart messages
|
||||
# def signup_notification(recipient)
|
||||
# recipients recipient.email_address_with_name
|
||||
# subject "New account information"
|
||||
# from "system@example.com"
|
||||
#
|
||||
# part :content_type => "text/html",
|
||||
# :body => render_message("signup-as-html", :account => recipient)
|
||||
#
|
||||
# part "text/plain" do |p|
|
||||
# p.body = render_message("signup-as-plain", :account => recipient)
|
||||
# p.transfer_encoding = "base64"
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # attachments
|
||||
# def signup_notification(recipient)
|
||||
# recipients recipient.email_address_with_name
|
||||
# subject "New account information"
|
||||
# from "system@example.com"
|
||||
#
|
||||
# attachment :content_type => "image/jpeg",
|
||||
# :body => File.read("an-image.jpg")
|
||||
#
|
||||
# attachment "application/pdf" do |a|
|
||||
# a.body = generate_your_pdf_here()
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # implicitly multipart messages
|
||||
# def signup_notification(recipient)
|
||||
# recipients recipient.email_address_with_name
|
||||
# subject "New account information"
|
||||
# from "system@example.com"
|
||||
# body(:account => "recipient")
|
||||
#
|
||||
# # ActionMailer will automatically detect and use multipart templates,
|
||||
# # where each template is named after the name of the action, followed
|
||||
# # by the content type. Each such detected template will be added as
|
||||
# # a separate part to the message.
|
||||
# #
|
||||
# # for example, if the following templates existed:
|
||||
# # * signup_notification.text.plain.rhtml
|
||||
# # * signup_notification.text.html.rhtml
|
||||
# # * signup_notification.text.xml.rxml
|
||||
# # * signup_notification.text.x-yaml.rhtml
|
||||
# #
|
||||
# # Each would be rendered and added as a separate part to the message,
|
||||
# # with the corresponding content type. The same body hash is passed to
|
||||
# # each template.
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # After this, post_notification will look for "templates/application_mailer/post_notification.rhtml"
|
||||
# ApplicationMailer.template_root = "templates"
|
||||
#
|
||||
# ApplicationMailer.create_comment_notification(david, hello_world) # => a tmail object
|
||||
# ApplicationMailer.deliver_comment_notification(david, hello_world) # sends the email
|
||||
#
|
||||
# = Configuration options
|
||||
#
|
||||
# These options are specified on the class level, like <tt>ActionMailer::Base.template_root = "/my/templates"</tt>
|
||||
#
|
||||
# * <tt>template_root</tt> - template root determines the base from which template references will be made.
|
||||
#
|
||||
# * <tt>logger</tt> - the logger is used for generating information on the mailing run if available.
|
||||
# Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.
|
||||
#
|
||||
# * <tt>server_settings</tt> - Allows detailed configuration of the server:
|
||||
# * <tt>:address</tt> Allows you to use a remote mail server. Just change it from its default "localhost" setting.
|
||||
# * <tt>:port</tt> On the off chance that your mail server doesn't run on port 25, you can change it.
|
||||
# * <tt>:domain</tt> If you need to specify a HELO domain, you can do it here.
|
||||
# * <tt>:user_name</tt> If your mail server requires authentication, set the username in this setting.
|
||||
# * <tt>:password</tt> If your mail server requires authentication, set the password in this setting.
|
||||
# * <tt>:authentication</tt> If your mail server requires authentication, you need to specify the authentication type here.
|
||||
# This is a symbol and one of :plain, :login, :cram_md5
|
||||
#
|
||||
# * <tt>raise_delivery_errors</tt> - whether or not errors should be raised if the email fails to be delivered.
|
||||
#
|
||||
# * <tt>delivery_method</tt> - Defines a delivery method. Possible values are :smtp (default), :sendmail, and :test.
|
||||
# Sendmail is assumed to be present at "/usr/sbin/sendmail".
|
||||
#
|
||||
# * <tt>perform_deliveries</tt> - Determines whether deliver_* methods are actually carried out. By default they are,
|
||||
# but this can be turned off to help functional testing.
|
||||
#
|
||||
# * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with delivery_method :test. Most useful
|
||||
# for unit and functional testing.
|
||||
#
|
||||
# * <tt>default_charset</tt> - The default charset used for the body and to encode the subject. Defaults to UTF-8. You can also
|
||||
# pick a different charset from inside a method with <tt>@charset</tt>.
|
||||
# * <tt>default_content_type</tt> - The default content type used for the main part of the message. Defaults to "text/plain". You
|
||||
# can also pick a different content type from inside a method with <tt>@content_type</tt>.
|
||||
# * <tt>default_mime_version</tt> - The default mime version used for the message. Defaults to nil. You
|
||||
# can also pick a different value from inside a method with <tt>@mime_version</tt>. When multipart messages are in
|
||||
# use, <tt>@mime_version</tt> will be set to "1.0" if it is not set inside a method.
|
||||
# * <tt>default_implicit_parts_order</tt> - When a message is built implicitly (i.e. multiple parts are assembled from templates
|
||||
# which specify the content type in their filenames) this variable controls how the parts are ordered. Defaults to
|
||||
# ["text/html", "text/enriched", "text/plain"]. Items that appear first in the array have higher priority in the mail client
|
||||
# and appear last in the mime encoded message. You can also pick a different order from inside a method with
|
||||
# <tt>@implicit_parts_order</tt>.
|
||||
class Base
|
||||
include AdvAttrAccessor, PartContainer
|
||||
|
||||
private_class_method :new #:nodoc:
|
||||
|
||||
cattr_accessor :template_root
|
||||
cattr_accessor :logger
|
||||
|
||||
@@server_settings = {
|
||||
:address => "localhost",
|
||||
:port => 25,
|
||||
:domain => 'localhost.localdomain',
|
||||
:user_name => nil,
|
||||
:password => nil,
|
||||
:authentication => nil
|
||||
}
|
||||
cattr_accessor :server_settings
|
||||
|
||||
@@raise_delivery_errors = true
|
||||
cattr_accessor :raise_delivery_errors
|
||||
|
||||
@@delivery_method = :smtp
|
||||
cattr_accessor :delivery_method
|
||||
|
||||
@@perform_deliveries = true
|
||||
cattr_accessor :perform_deliveries
|
||||
|
||||
@@deliveries = []
|
||||
cattr_accessor :deliveries
|
||||
|
||||
@@default_charset = "utf-8"
|
||||
cattr_accessor :default_charset
|
||||
|
||||
@@default_content_type = "text/plain"
|
||||
cattr_accessor :default_content_type
|
||||
|
||||
@@default_mime_version = nil
|
||||
cattr_accessor :default_mime_version
|
||||
|
||||
@@default_implicit_parts_order = [ "text/html", "text/enriched", "text/plain" ]
|
||||
cattr_accessor :default_implicit_parts_order
|
||||
|
||||
# Specify the BCC addresses for the message
|
||||
adv_attr_accessor :bcc
|
||||
|
||||
# Define the body of the message. This is either a Hash (in which case it
|
||||
# specifies the variables to pass to the template when it is rendered),
|
||||
# or a string, in which case it specifies the actual text of the message.
|
||||
adv_attr_accessor :body
|
||||
|
||||
# Specify the CC addresses for the message.
|
||||
adv_attr_accessor :cc
|
||||
|
||||
# Specify the charset to use for the message. This defaults to the
|
||||
# +default_charset+ specified for ActionMailer::Base.
|
||||
adv_attr_accessor :charset
|
||||
|
||||
# Specify the content type for the message. This defaults to <tt>text/plain</tt>
|
||||
# in most cases, but can be automatically set in some situations.
|
||||
adv_attr_accessor :content_type
|
||||
|
||||
# Specify the from address for the message.
|
||||
adv_attr_accessor :from
|
||||
|
||||
# Specify additional headers to be added to the message.
|
||||
adv_attr_accessor :headers
|
||||
|
||||
# Specify the order in which parts should be sorted, based on content-type.
|
||||
# This defaults to the value for the +default_implicit_parts_order+.
|
||||
adv_attr_accessor :implicit_parts_order
|
||||
|
||||
# Override the mailer name, which defaults to an inflected version of the
|
||||
# mailer's class name. If you want to use a template in a non-standard
|
||||
# location, you can use this to specify that location.
|
||||
adv_attr_accessor :mailer_name
|
||||
|
||||
# Defaults to "1.0", but may be explicitly given if needed.
|
||||
adv_attr_accessor :mime_version
|
||||
|
||||
# The recipient addresses for the message, either as a string (for a single
|
||||
# address) or an array (for multiple addresses).
|
||||
adv_attr_accessor :recipients
|
||||
|
||||
# The date on which the message was sent. If not set (the default), the
|
||||
# header will be set by the delivery agent.
|
||||
adv_attr_accessor :sent_on
|
||||
|
||||
# Specify the subject of the message.
|
||||
adv_attr_accessor :subject
|
||||
|
||||
# Specify the template name to use for current message. This is the "base"
|
||||
# template name, without the extension or directory, and may be used to
|
||||
# have multiple mailer methods share the same template.
|
||||
adv_attr_accessor :template
|
||||
|
||||
# The mail object instance referenced by this mailer.
|
||||
attr_reader :mail
|
||||
|
||||
class << self
|
||||
def method_missing(method_symbol, *parameters)#:nodoc:
|
||||
case method_symbol.id2name
|
||||
when /^create_([_a-z]\w*)/ then new($1, *parameters).mail
|
||||
when /^deliver_([_a-z]\w*)/ then new($1, *parameters).deliver!
|
||||
when "new" then nil
|
||||
else super
|
||||
end
|
||||
end
|
||||
|
||||
# Receives a raw email, parses it into an email object, decodes it,
|
||||
# instantiates a new mailer, and passes the email object to the mailer
|
||||
# object's #receive method. If you want your mailer to be able to
|
||||
# process incoming messages, you'll need to implement a #receive
|
||||
# method that accepts the email object as a parameter:
|
||||
#
|
||||
# class MyMailer < ActionMailer::Base
|
||||
# def receive(mail)
|
||||
# ...
|
||||
# end
|
||||
# end
|
||||
def receive(raw_email)
|
||||
logger.info "Received mail:\n #{raw_email}" unless logger.nil?
|
||||
mail = TMail::Mail.parse(raw_email)
|
||||
mail.base64_decode
|
||||
new.receive(mail)
|
||||
end
|
||||
|
||||
# Deliver the given mail object directly. This can be used to deliver
|
||||
# a preconstructed mail object, like:
|
||||
#
|
||||
# email = MyMailer.create_some_mail(parameters)
|
||||
# email.set_some_obscure_header "frobnicate"
|
||||
# MyMailer.deliver(email)
|
||||
def deliver(mail)
|
||||
new.deliver!(mail)
|
||||
end
|
||||
end
|
||||
|
||||
# Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer
|
||||
# will be initialized according to the named method. If not, the mailer will
|
||||
# remain uninitialized (useful when you only need to invoke the "receive"
|
||||
# method, for instance).
|
||||
def initialize(method_name=nil, *parameters) #:nodoc:
|
||||
create!(method_name, *parameters) if method_name
|
||||
end
|
||||
|
||||
# Initialize the mailer via the given +method_name+. The body will be
|
||||
# rendered and a new TMail::Mail object created.
|
||||
def create!(method_name, *parameters) #:nodoc:
|
||||
initialize_defaults(method_name)
|
||||
send(method_name, *parameters)
|
||||
|
||||
# If an explicit, textual body has not been set, we check assumptions.
|
||||
unless String === @body
|
||||
# First, we look to see if there are any likely templates that match,
|
||||
# which include the content-type in their file name (i.e.,
|
||||
# "the_template_file.text.html.rhtml", etc.). Only do this if parts
|
||||
# have not already been specified manually.
|
||||
if @parts.empty?
|
||||
templates = Dir.glob("#{template_path}/#{@template}.*")
|
||||
templates.each do |path|
|
||||
type = (File.basename(path).split(".")[1..-2] || []).join("/")
|
||||
next if type.empty?
|
||||
@parts << Part.new(:content_type => type,
|
||||
:disposition => "inline", :charset => charset,
|
||||
:body => render_message(File.basename(path).split(".")[0..-2].join('.'), @body))
|
||||
end
|
||||
unless @parts.empty?
|
||||
@content_type = "multipart/alternative"
|
||||
@charset = nil
|
||||
@parts = sort_parts(@parts, @implicit_parts_order)
|
||||
end
|
||||
end
|
||||
|
||||
# Then, if there were such templates, we check to see if we ought to
|
||||
# also render a "normal" template (without the content type). If a
|
||||
# normal template exists (or if there were no implicit parts) we render
|
||||
# it.
|
||||
template_exists = @parts.empty?
|
||||
template_exists ||= Dir.glob("#{template_path}/#{@template}.*").any? { |i| i.split(".").length == 2 }
|
||||
@body = render_message(@template, @body) if template_exists
|
||||
|
||||
# Finally, if there are other message parts and a textual body exists,
|
||||
# we shift it onto the front of the parts and set the body to nil (so
|
||||
# that create_mail doesn't try to render it in addition to the parts).
|
||||
if !@parts.empty? && String === @body
|
||||
@parts.unshift Part.new(:charset => charset, :body => @body)
|
||||
@body = nil
|
||||
end
|
||||
end
|
||||
|
||||
# If this is a multipart e-mail add the mime_version if it is not
|
||||
# already set.
|
||||
@mime_version ||= "1.0" if !@parts.empty?
|
||||
|
||||
# build the mail object itself
|
||||
@mail = create_mail
|
||||
end
|
||||
|
||||
# Delivers a TMail::Mail object. By default, it delivers the cached mail
|
||||
# object (from the #create! method). If no cached mail object exists, and
|
||||
# no alternate has been given as the parameter, this will fail.
|
||||
def deliver!(mail = @mail)
|
||||
raise "no mail object available for delivery!" unless mail
|
||||
logger.info "Sent mail:\n #{mail.encoded}" unless logger.nil?
|
||||
|
||||
begin
|
||||
send("perform_delivery_#{delivery_method}", mail) if perform_deliveries
|
||||
rescue Object => e
|
||||
raise e if raise_delivery_errors
|
||||
end
|
||||
|
||||
return mail
|
||||
end
|
||||
|
||||
private
|
||||
# Set up the default values for the various instance variables of this
|
||||
# mailer. Subclasses may override this method to provide different
|
||||
# defaults.
|
||||
def initialize_defaults(method_name)
|
||||
@charset ||= @@default_charset.dup
|
||||
@content_type ||= @@default_content_type.dup
|
||||
@implicit_parts_order ||= @@default_implicit_parts_order.dup
|
||||
@template ||= method_name
|
||||
@mailer_name ||= Inflector.underscore(self.class.name)
|
||||
@parts ||= []
|
||||
@headers ||= {}
|
||||
@body ||= {}
|
||||
@mime_version = @@default_mime_version.dup if @@default_mime_version
|
||||
end
|
||||
|
||||
def render_message(method_name, body)
|
||||
render :file => method_name, :body => body
|
||||
end
|
||||
|
||||
def render(opts)
|
||||
body = opts.delete(:body)
|
||||
initialize_template_class(body).render(opts)
|
||||
end
|
||||
|
||||
def template_path
|
||||
"#{template_root}/#{mailer_name}"
|
||||
end
|
||||
|
||||
def initialize_template_class(assigns)
|
||||
ActionView::Base.new(template_path, assigns, self)
|
||||
end
|
||||
|
||||
def sort_parts(parts, order = [])
|
||||
order = order.collect { |s| s.downcase }
|
||||
|
||||
parts = parts.sort do |a, b|
|
||||
a_ct = a.content_type.downcase
|
||||
b_ct = b.content_type.downcase
|
||||
|
||||
a_in = order.include? a_ct
|
||||
b_in = order.include? b_ct
|
||||
|
||||
s = case
|
||||
when a_in && b_in
|
||||
order.index(a_ct) <=> order.index(b_ct)
|
||||
when a_in
|
||||
-1
|
||||
when b_in
|
||||
1
|
||||
else
|
||||
a_ct <=> b_ct
|
||||
end
|
||||
|
||||
# reverse the ordering because parts that come last are displayed
|
||||
# first in mail clients
|
||||
(s * -1)
|
||||
end
|
||||
|
||||
parts
|
||||
end
|
||||
|
||||
def create_mail
|
||||
m = TMail::Mail.new
|
||||
|
||||
m.subject, = quote_any_if_necessary(charset, subject)
|
||||
m.to, m.from = quote_any_address_if_necessary(charset, recipients, from)
|
||||
m.bcc = quote_address_if_necessary(bcc, charset) unless bcc.nil?
|
||||
m.cc = quote_address_if_necessary(cc, charset) unless cc.nil?
|
||||
|
||||
m.mime_version = mime_version unless mime_version.nil?
|
||||
m.date = sent_on.to_time rescue sent_on if sent_on
|
||||
headers.each { |k, v| m[k] = v }
|
||||
|
||||
if @parts.empty?
|
||||
m.set_content_type content_type, nil, { "charset" => charset }
|
||||
m.body = Utils.normalize_new_lines(body)
|
||||
else
|
||||
if String === body
|
||||
part = TMail::Mail.new
|
||||
part.body = Utils.normalize_new_lines(body)
|
||||
part.set_content_type content_type, nil, { "charset" => charset }
|
||||
part.set_content_disposition "inline"
|
||||
m.parts << part
|
||||
end
|
||||
|
||||
@parts.each do |p|
|
||||
part = (TMail::Mail === p ? p : p.to_mail(self))
|
||||
m.parts << part
|
||||
end
|
||||
|
||||
m.set_content_type(content_type, nil, { "charset" => charset }) if content_type =~ /multipart/
|
||||
end
|
||||
|
||||
@mail = m
|
||||
end
|
||||
|
||||
def perform_delivery_smtp(mail)
|
||||
destinations = mail.destinations
|
||||
mail.ready_to_send
|
||||
|
||||
Net::SMTP.start(server_settings[:address], server_settings[:port], server_settings[:domain],
|
||||
server_settings[:user_name], server_settings[:password], server_settings[:authentication]) do |smtp|
|
||||
smtp.sendmail(mail.encoded, mail.from, destinations)
|
||||
end
|
||||
end
|
||||
|
||||
def perform_delivery_sendmail(mail)
|
||||
IO.popen("/usr/sbin/sendmail -i -t","w+") do |sm|
|
||||
sm.print(mail.encoded.gsub(/\r/, ''))
|
||||
sm.flush
|
||||
end
|
||||
end
|
||||
|
||||
def perform_delivery_test(mail)
|
||||
deliveries << mail
|
||||
end
|
||||
end
|
||||
end
|
||||
115
tracks/vendor/rails/actionmailer/lib/action_mailer/helpers.rb
vendored
Normal file
115
tracks/vendor/rails/actionmailer/lib/action_mailer/helpers.rb
vendored
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
module ActionMailer
|
||||
module Helpers #:nodoc:
|
||||
def self.append_features(base) #:nodoc:
|
||||
super
|
||||
|
||||
# Initialize the base module to aggregate its helpers.
|
||||
base.class_inheritable_accessor :master_helper_module
|
||||
base.master_helper_module = Module.new
|
||||
|
||||
# Extend base with class methods to declare helpers.
|
||||
base.extend(ClassMethods)
|
||||
|
||||
base.class_eval do
|
||||
# Wrap inherited to create a new master helper module for subclasses.
|
||||
class << self
|
||||
alias_method :inherited_without_helper, :inherited
|
||||
alias_method :inherited, :inherited_with_helper
|
||||
end
|
||||
|
||||
# Wrap initialize_template_class to extend new template class
|
||||
# instances with the master helper module.
|
||||
alias_method :initialize_template_class_without_helper, :initialize_template_class
|
||||
alias_method :initialize_template_class, :initialize_template_class_with_helper
|
||||
end
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# Makes all the (instance) methods in the helper module available to templates rendered through this controller.
|
||||
# See ActionView::Helpers (link:classes/ActionView/Helpers.html) for more about making your own helper modules
|
||||
# available to the templates.
|
||||
def add_template_helper(helper_module) #:nodoc:
|
||||
master_helper_module.module_eval "include #{helper_module}"
|
||||
end
|
||||
|
||||
# Declare a helper:
|
||||
# helper :foo
|
||||
# requires 'foo_helper' and includes FooHelper in the template class.
|
||||
# helper FooHelper
|
||||
# includes FooHelper in the template class.
|
||||
# helper { def foo() "#{bar} is the very best" end }
|
||||
# evaluates the block in the template class, adding method #foo.
|
||||
# helper(:three, BlindHelper) { def mice() 'mice' end }
|
||||
# does all three.
|
||||
def helper(*args, &block)
|
||||
args.flatten.each do |arg|
|
||||
case arg
|
||||
when Module
|
||||
add_template_helper(arg)
|
||||
when String, Symbol
|
||||
file_name = arg.to_s.underscore + '_helper'
|
||||
class_name = file_name.camelize
|
||||
|
||||
begin
|
||||
require_dependency(file_name)
|
||||
rescue LoadError => load_error
|
||||
requiree = / -- (.*?)(\.rb)?$/.match(load_error).to_a[1]
|
||||
msg = (requiree == file_name) ? "Missing helper file helpers/#{file_name}.rb" : "Can't load file: #{requiree}"
|
||||
raise LoadError.new(msg).copy_blame!(load_error)
|
||||
end
|
||||
|
||||
add_template_helper(class_name.constantize)
|
||||
else
|
||||
raise ArgumentError, 'helper expects String, Symbol, or Module argument'
|
||||
end
|
||||
end
|
||||
|
||||
# Evaluate block in template class if given.
|
||||
master_helper_module.module_eval(&block) if block_given?
|
||||
end
|
||||
|
||||
# Declare a controller method as a helper. For example,
|
||||
# helper_method :link_to
|
||||
# def link_to(name, options) ... end
|
||||
# makes the link_to controller method available in the view.
|
||||
def helper_method(*methods)
|
||||
methods.flatten.each do |method|
|
||||
master_helper_module.module_eval <<-end_eval
|
||||
def #{method}(*args, &block)
|
||||
controller.send(%(#{method}), *args, &block)
|
||||
end
|
||||
end_eval
|
||||
end
|
||||
end
|
||||
|
||||
# Declare a controller attribute as a helper. For example,
|
||||
# helper_attr :name
|
||||
# attr_accessor :name
|
||||
# makes the name and name= controller methods available in the view.
|
||||
# The is a convenience wrapper for helper_method.
|
||||
def helper_attr(*attrs)
|
||||
attrs.flatten.each { |attr| helper_method(attr, "#{attr}=") }
|
||||
end
|
||||
|
||||
private
|
||||
def inherited_with_helper(child)
|
||||
inherited_without_helper(child)
|
||||
begin
|
||||
child.master_helper_module = Module.new
|
||||
child.master_helper_module.send :include, master_helper_module
|
||||
child.helper child.name.underscore
|
||||
rescue MissingSourceFile => e
|
||||
raise unless e.is_missing?("helpers/#{child.name.underscore}_helper")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
# Extend the template class instance with our controller's helper module.
|
||||
def initialize_template_class_with_helper(assigns)
|
||||
returning(template = initialize_template_class_without_helper(assigns)) do
|
||||
template.extend self.class.master_helper_module
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
19
tracks/vendor/rails/actionmailer/lib/action_mailer/mail_helper.rb
vendored
Normal file
19
tracks/vendor/rails/actionmailer/lib/action_mailer/mail_helper.rb
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
require 'text/format'
|
||||
|
||||
module MailHelper
|
||||
# Uses Text::Format to take the text and format it, indented two spaces for
|
||||
# each line, and wrapped at 72 columns.
|
||||
def block_format(text)
|
||||
formatted = text.split(/\n\r\n/).collect { |paragraph|
|
||||
Text::Format.new(
|
||||
:columns => 72, :first_indent => 2, :body_indent => 2, :text => paragraph
|
||||
).format
|
||||
}.join("\n")
|
||||
|
||||
# Make list points stand on their own line
|
||||
formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { |s| " #{$1} #{$2.strip}\n" }
|
||||
formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { |s| " #{$1} #{$2.strip}\n" }
|
||||
|
||||
formatted
|
||||
end
|
||||
end
|
||||
108
tracks/vendor/rails/actionmailer/lib/action_mailer/part.rb
vendored
Normal file
108
tracks/vendor/rails/actionmailer/lib/action_mailer/part.rb
vendored
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
require 'action_mailer/adv_attr_accessor'
|
||||
require 'action_mailer/part_container'
|
||||
require 'action_mailer/utils'
|
||||
|
||||
module ActionMailer
|
||||
# Represents a subpart of an email message. It shares many similar
|
||||
# attributes of ActionMailer::Base. Although you can create parts manually
|
||||
# and add them to the #parts list of the mailer, it is easier
|
||||
# to use the helper methods in ActionMailer::PartContainer.
|
||||
class Part
|
||||
include ActionMailer::AdvAttrAccessor
|
||||
include ActionMailer::PartContainer
|
||||
|
||||
# Represents the body of the part, as a string. This should not be a
|
||||
# Hash (like ActionMailer::Base), but if you want a template to be rendered
|
||||
# into the body of a subpart you can do it with the mailer's #render method
|
||||
# and assign the result here.
|
||||
adv_attr_accessor :body
|
||||
|
||||
# Specify the charset for this subpart. By default, it will be the charset
|
||||
# of the containing part or mailer.
|
||||
adv_attr_accessor :charset
|
||||
|
||||
# The content disposition of this part, typically either "inline" or
|
||||
# "attachment".
|
||||
adv_attr_accessor :content_disposition
|
||||
|
||||
# The content type of the part.
|
||||
adv_attr_accessor :content_type
|
||||
|
||||
# The filename to use for this subpart (usually for attachments).
|
||||
adv_attr_accessor :filename
|
||||
|
||||
# Accessor for specifying additional headers to include with this part.
|
||||
adv_attr_accessor :headers
|
||||
|
||||
# The transfer encoding to use for this subpart, like "base64" or
|
||||
# "quoted-printable".
|
||||
adv_attr_accessor :transfer_encoding
|
||||
|
||||
# Create a new part from the given +params+ hash. The valid params keys
|
||||
# correspond to the accessors.
|
||||
def initialize(params)
|
||||
@content_type = params[:content_type]
|
||||
@content_disposition = params[:disposition] || "inline"
|
||||
@charset = params[:charset]
|
||||
@body = params[:body]
|
||||
@filename = params[:filename]
|
||||
@transfer_encoding = params[:transfer_encoding] || "quoted-printable"
|
||||
@headers = params[:headers] || {}
|
||||
@parts = []
|
||||
end
|
||||
|
||||
# Convert the part to a mail object which can be included in the parts
|
||||
# list of another mail object.
|
||||
def to_mail(defaults)
|
||||
part = TMail::Mail.new
|
||||
|
||||
if @parts.empty?
|
||||
part.content_transfer_encoding = transfer_encoding || "quoted-printable"
|
||||
case (transfer_encoding || "").downcase
|
||||
when "base64" then
|
||||
part.body = TMail::Base64.folding_encode(body)
|
||||
when "quoted-printable"
|
||||
part.body = [Utils.normalize_new_lines(body)].pack("M*")
|
||||
else
|
||||
part.body = body
|
||||
end
|
||||
|
||||
# Always set the content_type after setting the body and or parts!
|
||||
# Also don't set filename and name when there is none (like in
|
||||
# non-attachment parts)
|
||||
if content_disposition == "attachment"
|
||||
part.set_content_type(content_type || defaults.content_type, nil,
|
||||
squish("charset" => nil, "name" => filename))
|
||||
part.set_content_disposition(content_disposition,
|
||||
squish("filename" => filename))
|
||||
else
|
||||
part.set_content_type(content_type || defaults.content_type, nil,
|
||||
"charset" => (charset || defaults.charset))
|
||||
part.set_content_disposition(content_disposition)
|
||||
end
|
||||
else
|
||||
if String === body
|
||||
part = TMail::Mail.new
|
||||
part.body = body
|
||||
part.set_content_type content_type, nil, { "charset" => charset }
|
||||
part.set_content_disposition "inline"
|
||||
m.parts << part
|
||||
end
|
||||
|
||||
@parts.each do |p|
|
||||
prt = (TMail::Mail === p ? p : p.to_mail(defaults))
|
||||
part.parts << prt
|
||||
end
|
||||
|
||||
part.set_content_type(content_type, nil, { "charset" => charset }) if content_type =~ /multipart/
|
||||
end
|
||||
|
||||
part
|
||||
end
|
||||
|
||||
private
|
||||
def squish(values={})
|
||||
values.delete_if { |k,v| v.nil? }
|
||||
end
|
||||
end
|
||||
end
|
||||
42
tracks/vendor/rails/actionmailer/lib/action_mailer/part_container.rb
vendored
Normal file
42
tracks/vendor/rails/actionmailer/lib/action_mailer/part_container.rb
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
module ActionMailer
|
||||
# Accessors and helpers that ActionMailer::Base and ActionMailer::Part have
|
||||
# in common. Using these helpers you can easily add subparts or attachments
|
||||
# to your message:
|
||||
#
|
||||
# def my_mail_message(...)
|
||||
# ...
|
||||
# part "text/plain" do |p|
|
||||
# p.body "hello, world"
|
||||
# p.transfer_encoding "base64"
|
||||
# end
|
||||
#
|
||||
# attachment "image/jpg" do |a|
|
||||
# a.body = File.read("hello.jpg")
|
||||
# a.filename = "hello.jpg"
|
||||
# end
|
||||
# end
|
||||
module PartContainer
|
||||
# The list of subparts of this container
|
||||
attr_reader :parts
|
||||
|
||||
# Add a part to a multipart message, with the given content-type. The
|
||||
# part itself is yielded to the block so that other properties (charset,
|
||||
# body, headers, etc.) can be set on it.
|
||||
def part(params)
|
||||
params = {:content_type => params} if String === params
|
||||
part = Part.new(params)
|
||||
yield part if block_given?
|
||||
@parts << part
|
||||
end
|
||||
|
||||
# Add an attachment to a multipart message. This is simply a part with the
|
||||
# content-disposition set to "attachment".
|
||||
def attachment(params, &block)
|
||||
params = { :content_type => params } if String === params
|
||||
params = { :disposition => "attachment",
|
||||
:transfer_encoding => "base64" }.merge(params)
|
||||
part(params, &block)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
59
tracks/vendor/rails/actionmailer/lib/action_mailer/quoting.rb
vendored
Normal file
59
tracks/vendor/rails/actionmailer/lib/action_mailer/quoting.rb
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
module ActionMailer
|
||||
module Quoting #:nodoc:
|
||||
# Convert the given text into quoted printable format, with an instruction
|
||||
# that the text be eventually interpreted in the given charset.
|
||||
def quoted_printable(text, charset)
|
||||
text = text.gsub( /[^a-z ]/i ) { quoted_printable_encode($&) }.
|
||||
gsub( / /, "_" )
|
||||
"=?#{charset}?Q?#{text}?="
|
||||
end
|
||||
|
||||
# Convert the given character to quoted printable format, taking into
|
||||
# account multi-byte characters (if executing with $KCODE="u", for instance)
|
||||
def quoted_printable_encode(character)
|
||||
result = ""
|
||||
character.each_byte { |b| result << "=%02x" % b }
|
||||
result
|
||||
end
|
||||
|
||||
# A quick-and-dirty regexp for determining whether a string contains any
|
||||
# characters that need escaping.
|
||||
if !defined?(CHARS_NEEDING_QUOTING)
|
||||
CHARS_NEEDING_QUOTING = /[\000-\011\013\014\016-\037\177-\377]/
|
||||
end
|
||||
|
||||
# Quote the given text if it contains any "illegal" characters
|
||||
def quote_if_necessary(text, charset)
|
||||
(text =~ CHARS_NEEDING_QUOTING) ?
|
||||
quoted_printable(text, charset) :
|
||||
text
|
||||
end
|
||||
|
||||
# Quote any of the given strings if they contain any "illegal" characters
|
||||
def quote_any_if_necessary(charset, *args)
|
||||
args.map { |v| quote_if_necessary(v, charset) }
|
||||
end
|
||||
|
||||
# Quote the given address if it needs to be. The address may be a
|
||||
# regular email address, or it can be a phrase followed by an address in
|
||||
# brackets. The phrase is the only part that will be quoted, and only if
|
||||
# it needs to be. This allows extended characters to be used in the
|
||||
# "to", "from", "cc", and "bcc" headers.
|
||||
def quote_address_if_necessary(address, charset)
|
||||
if Array === address
|
||||
address.map { |a| quote_address_if_necessary(a, charset) }
|
||||
elsif address =~ /^(\S.*)\s+(<.*>)$/
|
||||
address = $2
|
||||
phrase = quote_if_necessary($1.gsub(/^['"](.*)['"]$/, '\1'), charset)
|
||||
"\"#{phrase}\" #{address}"
|
||||
else
|
||||
address
|
||||
end
|
||||
end
|
||||
|
||||
# Quote any of the given addresses, if they need to be.
|
||||
def quote_any_address_if_necessary(charset, *args)
|
||||
args.map { |v| quote_address_if_necessary(v, charset) }
|
||||
end
|
||||
end
|
||||
end
|
||||
8
tracks/vendor/rails/actionmailer/lib/action_mailer/utils.rb
vendored
Normal file
8
tracks/vendor/rails/actionmailer/lib/action_mailer/utils.rb
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
module ActionMailer
|
||||
module Utils #:nodoc:
|
||||
def normalize_new_lines(text)
|
||||
text.to_s.gsub(/\r\n?/, "\n")
|
||||
end
|
||||
module_function :normalize_new_lines
|
||||
end
|
||||
end
|
||||
1466
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/text/format.rb
vendored
Normal file
1466
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/text/format.rb
vendored
Normal file
File diff suppressed because it is too large
Load diff
3
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail.rb
vendored
Normal file
3
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail.rb
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
require 'tmail/info'
|
||||
require 'tmail/mail'
|
||||
require 'tmail/mailbox'
|
||||
242
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/address.rb
vendored
Normal file
242
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/address.rb
vendored
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
#
|
||||
# address.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
require 'tmail/encode'
|
||||
require 'tmail/parser'
|
||||
|
||||
|
||||
module TMail
|
||||
|
||||
class Address
|
||||
|
||||
include TextUtils
|
||||
|
||||
def Address.parse( str )
|
||||
Parser.parse :ADDRESS, str
|
||||
end
|
||||
|
||||
def address_group?
|
||||
false
|
||||
end
|
||||
|
||||
def initialize( local, domain )
|
||||
if domain
|
||||
domain.each do |s|
|
||||
raise SyntaxError, 'empty word in domain' if s.empty?
|
||||
end
|
||||
end
|
||||
@local = local
|
||||
@domain = domain
|
||||
@name = nil
|
||||
@routes = []
|
||||
end
|
||||
|
||||
attr_reader :name
|
||||
|
||||
def name=( str )
|
||||
@name = str
|
||||
@name = nil if str and str.empty?
|
||||
end
|
||||
|
||||
alias phrase name
|
||||
alias phrase= name=
|
||||
|
||||
attr_reader :routes
|
||||
|
||||
def inspect
|
||||
"#<#{self.class} #{address()}>"
|
||||
end
|
||||
|
||||
def local
|
||||
return nil unless @local
|
||||
return '""' if @local.size == 1 and @local[0].empty?
|
||||
@local.map {|i| quote_atom(i) }.join('.')
|
||||
end
|
||||
|
||||
def domain
|
||||
return nil unless @domain
|
||||
join_domain(@domain)
|
||||
end
|
||||
|
||||
def spec
|
||||
s = self.local
|
||||
d = self.domain
|
||||
if s and d
|
||||
s + '@' + d
|
||||
else
|
||||
s
|
||||
end
|
||||
end
|
||||
|
||||
alias address spec
|
||||
|
||||
|
||||
def ==( other )
|
||||
other.respond_to? :spec and self.spec == other.spec
|
||||
end
|
||||
|
||||
alias eql? ==
|
||||
|
||||
def hash
|
||||
@local.hash ^ @domain.hash
|
||||
end
|
||||
|
||||
def dup
|
||||
obj = self.class.new(@local.dup, @domain.dup)
|
||||
obj.name = @name.dup if @name
|
||||
obj.routes.replace @routes
|
||||
obj
|
||||
end
|
||||
|
||||
include StrategyInterface
|
||||
|
||||
def accept( strategy, dummy1 = nil, dummy2 = nil )
|
||||
unless @local
|
||||
strategy.meta '<>' # empty return-path
|
||||
return
|
||||
end
|
||||
|
||||
spec_p = (not @name and @routes.empty?)
|
||||
if @name
|
||||
strategy.phrase @name
|
||||
strategy.space
|
||||
end
|
||||
tmp = spec_p ? '' : '<'
|
||||
unless @routes.empty?
|
||||
tmp << @routes.map {|i| '@' + i }.join(',') << ':'
|
||||
end
|
||||
tmp << self.spec
|
||||
tmp << '>' unless spec_p
|
||||
strategy.meta tmp
|
||||
strategy.lwsp ''
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class AddressGroup
|
||||
|
||||
include Enumerable
|
||||
|
||||
def address_group?
|
||||
true
|
||||
end
|
||||
|
||||
def initialize( name, addrs )
|
||||
@name = name
|
||||
@addresses = addrs
|
||||
end
|
||||
|
||||
attr_reader :name
|
||||
|
||||
def ==( other )
|
||||
other.respond_to? :to_a and @addresses == other.to_a
|
||||
end
|
||||
|
||||
alias eql? ==
|
||||
|
||||
def hash
|
||||
map {|i| i.hash }.hash
|
||||
end
|
||||
|
||||
def []( idx )
|
||||
@addresses[idx]
|
||||
end
|
||||
|
||||
def size
|
||||
@addresses.size
|
||||
end
|
||||
|
||||
def empty?
|
||||
@addresses.empty?
|
||||
end
|
||||
|
||||
def each( &block )
|
||||
@addresses.each(&block)
|
||||
end
|
||||
|
||||
def to_a
|
||||
@addresses.dup
|
||||
end
|
||||
|
||||
alias to_ary to_a
|
||||
|
||||
def include?( a )
|
||||
@addresses.include? a
|
||||
end
|
||||
|
||||
def flatten
|
||||
set = []
|
||||
@addresses.each do |a|
|
||||
if a.respond_to? :flatten
|
||||
set.concat a.flatten
|
||||
else
|
||||
set.push a
|
||||
end
|
||||
end
|
||||
set
|
||||
end
|
||||
|
||||
def each_address( &block )
|
||||
flatten.each(&block)
|
||||
end
|
||||
|
||||
def add( a )
|
||||
@addresses.push a
|
||||
end
|
||||
|
||||
alias push add
|
||||
|
||||
def delete( a )
|
||||
@addresses.delete a
|
||||
end
|
||||
|
||||
include StrategyInterface
|
||||
|
||||
def accept( strategy, dummy1 = nil, dummy2 = nil )
|
||||
strategy.phrase @name
|
||||
strategy.meta ':'
|
||||
strategy.space
|
||||
first = true
|
||||
each do |mbox|
|
||||
if first
|
||||
first = false
|
||||
else
|
||||
strategy.meta ','
|
||||
end
|
||||
strategy.space
|
||||
mbox.accept strategy
|
||||
end
|
||||
strategy.meta ';'
|
||||
strategy.lwsp ''
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end # module TMail
|
||||
34
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/attachments.rb
vendored
Normal file
34
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/attachments.rb
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
require 'stringio'
|
||||
|
||||
module TMail
|
||||
class Attachment < StringIO
|
||||
attr_accessor :original_filename, :content_type
|
||||
end
|
||||
|
||||
class Mail
|
||||
def has_attachments?
|
||||
multipart? && parts.any? { |part| part.header["content-type"].main_type != "text" }
|
||||
end
|
||||
|
||||
def attachments
|
||||
if multipart?
|
||||
parts.collect { |part|
|
||||
if part.header["content-type"].main_type != "text"
|
||||
content = part.body # unquoted automatically by TMail#body
|
||||
file_name = (part['content-location'] &&
|
||||
part['content-location'].body) ||
|
||||
part.sub_header("content-type", "name") ||
|
||||
part.sub_header("content-disposition", "filename")
|
||||
|
||||
next if file_name.blank? || content.blank?
|
||||
|
||||
attachment = Attachment.new(content)
|
||||
attachment.original_filename = file_name.strip
|
||||
attachment.content_type = part.content_type
|
||||
attachment
|
||||
end
|
||||
}.compact
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
71
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/base64.rb
vendored
Normal file
71
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/base64.rb
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#
|
||||
# base64.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
module TMail
|
||||
|
||||
module Base64
|
||||
|
||||
module_function
|
||||
|
||||
def rb_folding_encode( str, eol = "\n", limit = 60 )
|
||||
[str].pack('m')
|
||||
end
|
||||
|
||||
def rb_encode( str )
|
||||
[str].pack('m').tr( "\r\n", '' )
|
||||
end
|
||||
|
||||
def rb_decode( str, strict = false )
|
||||
str.unpack('m')
|
||||
end
|
||||
|
||||
begin
|
||||
require 'tmail/base64.so'
|
||||
alias folding_encode c_folding_encode
|
||||
alias encode c_encode
|
||||
alias decode c_decode
|
||||
class << self
|
||||
alias folding_encode c_folding_encode
|
||||
alias encode c_encode
|
||||
alias decode c_decode
|
||||
end
|
||||
rescue LoadError
|
||||
alias folding_encode rb_folding_encode
|
||||
alias encode rb_encode
|
||||
alias decode rb_decode
|
||||
class << self
|
||||
alias folding_encode rb_folding_encode
|
||||
alias encode rb_encode
|
||||
alias decode rb_decode
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
69
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/config.rb
vendored
Normal file
69
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/config.rb
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#
|
||||
# config.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
module TMail
|
||||
|
||||
class Config
|
||||
|
||||
def initialize( strict )
|
||||
@strict_parse = strict
|
||||
@strict_base64decode = strict
|
||||
end
|
||||
|
||||
def strict_parse?
|
||||
@strict_parse
|
||||
end
|
||||
|
||||
attr_writer :strict_parse
|
||||
|
||||
def strict_base64decode?
|
||||
@strict_base64decode
|
||||
end
|
||||
|
||||
attr_writer :strict_base64decode
|
||||
|
||||
def new_body_port( mail )
|
||||
StringPort.new
|
||||
end
|
||||
|
||||
alias new_preamble_port new_body_port
|
||||
alias new_part_port new_body_port
|
||||
|
||||
end
|
||||
|
||||
DEFAULT_CONFIG = Config.new(false)
|
||||
DEFAULT_STRICT_CONFIG = Config.new(true)
|
||||
|
||||
def Config.to_config( arg )
|
||||
return DEFAULT_STRICT_CONFIG if arg == true
|
||||
return DEFAULT_CONFIG if arg == false
|
||||
arg or DEFAULT_CONFIG
|
||||
end
|
||||
|
||||
end
|
||||
467
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/encode.rb
vendored
Normal file
467
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/encode.rb
vendored
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
#
|
||||
# encode.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
require 'nkf'
|
||||
require 'tmail/base64.rb'
|
||||
require 'tmail/stringio'
|
||||
require 'tmail/utils'
|
||||
|
||||
|
||||
module TMail
|
||||
|
||||
module StrategyInterface
|
||||
|
||||
def create_dest( obj )
|
||||
case obj
|
||||
when nil
|
||||
StringOutput.new
|
||||
when String
|
||||
StringOutput.new(obj)
|
||||
when IO, StringOutput
|
||||
obj
|
||||
else
|
||||
raise TypeError, 'cannot handle this type of object for dest'
|
||||
end
|
||||
end
|
||||
module_function :create_dest
|
||||
|
||||
def encoded( eol = "\r\n", charset = 'j', dest = nil )
|
||||
accept_strategy Encoder, eol, charset, dest
|
||||
end
|
||||
|
||||
def decoded( eol = "\n", charset = 'e', dest = nil )
|
||||
accept_strategy Decoder, eol, charset, dest
|
||||
end
|
||||
|
||||
alias to_s decoded
|
||||
|
||||
def accept_strategy( klass, eol, charset, dest = nil )
|
||||
dest ||= ''
|
||||
accept klass.new(create_dest(dest), charset, eol)
|
||||
dest
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
### MIME B encoding decoder
|
||||
###
|
||||
|
||||
class Decoder
|
||||
|
||||
include TextUtils
|
||||
|
||||
encoded = '=\?(?:iso-2022-jp|euc-jp|shift_jis)\?[QB]\?[a-z0-9+/=]+\?='
|
||||
ENCODED_WORDS = /#{encoded}(?:\s+#{encoded})*/i
|
||||
|
||||
OUTPUT_ENCODING = {
|
||||
'EUC' => 'e',
|
||||
'SJIS' => 's',
|
||||
}
|
||||
|
||||
def self.decode( str, encoding = nil )
|
||||
encoding ||= (OUTPUT_ENCODING[$KCODE] || 'j')
|
||||
opt = '-m' + encoding
|
||||
str.gsub(ENCODED_WORDS) {|s| NKF.nkf(opt, s) }
|
||||
end
|
||||
|
||||
def initialize( dest, encoding = nil, eol = "\n" )
|
||||
@f = StrategyInterface.create_dest(dest)
|
||||
@encoding = (/\A[ejs]/ === encoding) ? encoding[0,1] : nil
|
||||
@eol = eol
|
||||
end
|
||||
|
||||
def decode( str )
|
||||
self.class.decode(str, @encoding)
|
||||
end
|
||||
private :decode
|
||||
|
||||
def terminate
|
||||
end
|
||||
|
||||
def header_line( str )
|
||||
@f << decode(str)
|
||||
end
|
||||
|
||||
def header_name( nm )
|
||||
@f << nm << ': '
|
||||
end
|
||||
|
||||
def header_body( str )
|
||||
@f << decode(str)
|
||||
end
|
||||
|
||||
def space
|
||||
@f << ' '
|
||||
end
|
||||
|
||||
alias spc space
|
||||
|
||||
def lwsp( str )
|
||||
@f << str
|
||||
end
|
||||
|
||||
def meta( str )
|
||||
@f << str
|
||||
end
|
||||
|
||||
def text( str )
|
||||
@f << decode(str)
|
||||
end
|
||||
|
||||
def phrase( str )
|
||||
@f << quote_phrase(decode(str))
|
||||
end
|
||||
|
||||
def kv_pair( k, v )
|
||||
@f << k << '=' << v
|
||||
end
|
||||
|
||||
def puts( str = nil )
|
||||
@f << str if str
|
||||
@f << @eol
|
||||
end
|
||||
|
||||
def write( str )
|
||||
@f << str
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
### MIME B-encoding encoder
|
||||
###
|
||||
|
||||
#
|
||||
# FIXME: This class can handle only (euc-jp/shift_jis -> iso-2022-jp).
|
||||
#
|
||||
class Encoder
|
||||
|
||||
include TextUtils
|
||||
|
||||
BENCODE_DEBUG = false unless defined?(BENCODE_DEBUG)
|
||||
|
||||
def Encoder.encode( str )
|
||||
e = new()
|
||||
e.header_body str
|
||||
e.terminate
|
||||
e.dest.string
|
||||
end
|
||||
|
||||
SPACER = "\t"
|
||||
MAX_LINE_LEN = 70
|
||||
|
||||
OPTIONS = {
|
||||
'EUC' => '-Ej -m0',
|
||||
'SJIS' => '-Sj -m0',
|
||||
'UTF8' => nil, # FIXME
|
||||
'NONE' => nil
|
||||
}
|
||||
|
||||
def initialize( dest = nil, encoding = nil, eol = "\r\n", limit = nil )
|
||||
@f = StrategyInterface.create_dest(dest)
|
||||
@opt = OPTIONS[$KCODE]
|
||||
@eol = eol
|
||||
reset
|
||||
end
|
||||
|
||||
def normalize_encoding( str )
|
||||
if @opt
|
||||
then NKF.nkf(@opt, str)
|
||||
else str
|
||||
end
|
||||
end
|
||||
|
||||
def reset
|
||||
@text = ''
|
||||
@lwsp = ''
|
||||
@curlen = 0
|
||||
end
|
||||
|
||||
def terminate
|
||||
add_lwsp ''
|
||||
reset
|
||||
end
|
||||
|
||||
def dest
|
||||
@f
|
||||
end
|
||||
|
||||
def puts( str = nil )
|
||||
@f << str if str
|
||||
@f << @eol
|
||||
end
|
||||
|
||||
def write( str )
|
||||
@f << str
|
||||
end
|
||||
|
||||
#
|
||||
# add
|
||||
#
|
||||
|
||||
def header_line( line )
|
||||
scanadd line
|
||||
end
|
||||
|
||||
def header_name( name )
|
||||
add_text name.split(/-/).map {|i| i.capitalize }.join('-')
|
||||
add_text ':'
|
||||
add_lwsp ' '
|
||||
end
|
||||
|
||||
def header_body( str )
|
||||
scanadd normalize_encoding(str)
|
||||
end
|
||||
|
||||
def space
|
||||
add_lwsp ' '
|
||||
end
|
||||
|
||||
alias spc space
|
||||
|
||||
def lwsp( str )
|
||||
add_lwsp str.sub(/[\r\n]+[^\r\n]*\z/, '')
|
||||
end
|
||||
|
||||
def meta( str )
|
||||
add_text str
|
||||
end
|
||||
|
||||
def text( str )
|
||||
scanadd normalize_encoding(str)
|
||||
end
|
||||
|
||||
def phrase( str )
|
||||
str = normalize_encoding(str)
|
||||
if CONTROL_CHAR === str
|
||||
scanadd str
|
||||
else
|
||||
add_text quote_phrase(str)
|
||||
end
|
||||
end
|
||||
|
||||
# FIXME: implement line folding
|
||||
#
|
||||
def kv_pair( k, v )
|
||||
return if v.nil?
|
||||
v = normalize_encoding(v)
|
||||
if token_safe?(v)
|
||||
add_text k + '=' + v
|
||||
elsif not CONTROL_CHAR === v
|
||||
add_text k + '=' + quote_token(v)
|
||||
else
|
||||
# apply RFC2231 encoding
|
||||
kv = k + '*=' + "iso-2022-jp'ja'" + encode_value(v)
|
||||
add_text kv
|
||||
end
|
||||
end
|
||||
|
||||
def encode_value( str )
|
||||
str.gsub(TOKEN_UNSAFE) {|s| '%%%02x' % s[0] }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def scanadd( str, force = false )
|
||||
types = ''
|
||||
strs = []
|
||||
|
||||
until str.empty?
|
||||
if m = /\A[^\e\t\r\n ]+/.match(str)
|
||||
types << (force ? 'j' : 'a')
|
||||
strs.push m[0]
|
||||
|
||||
elsif m = /\A[\t\r\n ]+/.match(str)
|
||||
types << 's'
|
||||
strs.push m[0]
|
||||
|
||||
elsif m = /\A\e../.match(str)
|
||||
esc = m[0]
|
||||
str = m.post_match
|
||||
if esc != "\e(B" and m = /\A[^\e]+/.match(str)
|
||||
types << 'j'
|
||||
strs.push m[0]
|
||||
end
|
||||
|
||||
else
|
||||
raise 'TMail FATAL: encoder scan fail'
|
||||
end
|
||||
(str = m.post_match) unless m.nil?
|
||||
end
|
||||
|
||||
do_encode types, strs
|
||||
end
|
||||
|
||||
def do_encode( types, strs )
|
||||
#
|
||||
# result : (A|E)(S(A|E))*
|
||||
# E : W(SW)*
|
||||
# W : (J|A)+ but must contain J # (J|A)*J(J|A)*
|
||||
# A : <<A character string not to be encoded>>
|
||||
# J : <<A character string to be encoded>>
|
||||
# S : <<LWSP>>
|
||||
#
|
||||
# An encoding unit is `E'.
|
||||
# Input (parameter `types') is (J|A)(J|A|S)*(J|A)
|
||||
#
|
||||
if BENCODE_DEBUG
|
||||
puts
|
||||
puts '-- do_encode ------------'
|
||||
puts types.split(//).join(' ')
|
||||
p strs
|
||||
end
|
||||
|
||||
e = /[ja]*j[ja]*(?:s[ja]*j[ja]*)*/
|
||||
|
||||
while m = e.match(types)
|
||||
pre = m.pre_match
|
||||
concat_A_S pre, strs[0, pre.size] unless pre.empty?
|
||||
concat_E m[0], strs[m.begin(0) ... m.end(0)]
|
||||
types = m.post_match
|
||||
strs.slice! 0, m.end(0)
|
||||
end
|
||||
concat_A_S types, strs
|
||||
end
|
||||
|
||||
def concat_A_S( types, strs )
|
||||
i = 0
|
||||
types.each_byte do |t|
|
||||
case t
|
||||
when ?a then add_text strs[i]
|
||||
when ?s then add_lwsp strs[i]
|
||||
else
|
||||
raise "TMail FATAL: unknown flag: #{t.chr}"
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
METHOD_ID = {
|
||||
?j => :extract_J,
|
||||
?e => :extract_E,
|
||||
?a => :extract_A,
|
||||
?s => :extract_S
|
||||
}
|
||||
|
||||
def concat_E( types, strs )
|
||||
if BENCODE_DEBUG
|
||||
puts '---- concat_E'
|
||||
puts "types=#{types.split(//).join(' ')}"
|
||||
puts "strs =#{strs.inspect}"
|
||||
end
|
||||
|
||||
flush() unless @text.empty?
|
||||
|
||||
chunk = ''
|
||||
strs.each_with_index do |s,i|
|
||||
mid = METHOD_ID[types[i]]
|
||||
until s.empty?
|
||||
unless c = __send__(mid, chunk.size, s)
|
||||
add_with_encode chunk unless chunk.empty?
|
||||
flush
|
||||
chunk = ''
|
||||
fold
|
||||
c = __send__(mid, 0, s)
|
||||
raise 'TMail FATAL: extract fail' unless c
|
||||
end
|
||||
chunk << c
|
||||
end
|
||||
end
|
||||
add_with_encode chunk unless chunk.empty?
|
||||
end
|
||||
|
||||
def extract_J( chunksize, str )
|
||||
size = max_bytes(chunksize, str.size) - 6
|
||||
size = (size % 2 == 0) ? (size) : (size - 1)
|
||||
return nil if size <= 0
|
||||
"\e$B#{str.slice!(0, size)}\e(B"
|
||||
end
|
||||
|
||||
def extract_A( chunksize, str )
|
||||
size = max_bytes(chunksize, str.size)
|
||||
return nil if size <= 0
|
||||
str.slice!(0, size)
|
||||
end
|
||||
|
||||
alias extract_S extract_A
|
||||
|
||||
def max_bytes( chunksize, ssize )
|
||||
(restsize() - '=?iso-2022-jp?B??='.size) / 4 * 3 - chunksize
|
||||
end
|
||||
|
||||
#
|
||||
# free length buffer
|
||||
#
|
||||
|
||||
def add_text( str )
|
||||
@text << str
|
||||
# puts '---- text -------------------------------------'
|
||||
# puts "+ #{str.inspect}"
|
||||
# puts "txt >>>#{@text.inspect}<<<"
|
||||
end
|
||||
|
||||
def add_with_encode( str )
|
||||
@text << "=?iso-2022-jp?B?#{Base64.encode(str)}?="
|
||||
end
|
||||
|
||||
def add_lwsp( lwsp )
|
||||
# puts '---- lwsp -------------------------------------'
|
||||
# puts "+ #{lwsp.inspect}"
|
||||
fold if restsize() <= 0
|
||||
flush
|
||||
@lwsp = lwsp
|
||||
end
|
||||
|
||||
def flush
|
||||
# puts '---- flush ----'
|
||||
# puts "spc >>>#{@lwsp.inspect}<<<"
|
||||
# puts "txt >>>#{@text.inspect}<<<"
|
||||
@f << @lwsp << @text
|
||||
@curlen += (@lwsp.size + @text.size)
|
||||
@text = ''
|
||||
@lwsp = ''
|
||||
end
|
||||
|
||||
def fold
|
||||
# puts '---- fold ----'
|
||||
@f << @eol
|
||||
@curlen = 0
|
||||
@lwsp = SPACER
|
||||
end
|
||||
|
||||
def restsize
|
||||
MAX_LINE_LEN - (@curlen + @lwsp.size + @text.size)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end # module TMail
|
||||
552
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/facade.rb
vendored
Normal file
552
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/facade.rb
vendored
Normal file
|
|
@ -0,0 +1,552 @@
|
|||
#
|
||||
# facade.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
require 'tmail/utils'
|
||||
|
||||
|
||||
module TMail
|
||||
|
||||
class Mail
|
||||
|
||||
def header_string( name, default = nil )
|
||||
h = @header[name.downcase] or return default
|
||||
h.to_s
|
||||
end
|
||||
|
||||
###
|
||||
### attributes
|
||||
###
|
||||
|
||||
include TextUtils
|
||||
|
||||
def set_string_array_attr( key, strs )
|
||||
strs.flatten!
|
||||
if strs.empty?
|
||||
@header.delete key.downcase
|
||||
else
|
||||
store key, strs.join(', ')
|
||||
end
|
||||
strs
|
||||
end
|
||||
private :set_string_array_attr
|
||||
|
||||
def set_string_attr( key, str )
|
||||
if str
|
||||
store key, str
|
||||
else
|
||||
@header.delete key.downcase
|
||||
end
|
||||
str
|
||||
end
|
||||
private :set_string_attr
|
||||
|
||||
def set_addrfield( name, arg )
|
||||
if arg
|
||||
h = HeaderField.internal_new(name, @config)
|
||||
h.addrs.replace [arg].flatten
|
||||
@header[name] = h
|
||||
else
|
||||
@header.delete name
|
||||
end
|
||||
arg
|
||||
end
|
||||
private :set_addrfield
|
||||
|
||||
def addrs2specs( addrs )
|
||||
return nil unless addrs
|
||||
list = addrs.map {|addr|
|
||||
if addr.address_group?
|
||||
then addr.map {|a| a.spec }
|
||||
else addr.spec
|
||||
end
|
||||
}.flatten
|
||||
return nil if list.empty?
|
||||
list
|
||||
end
|
||||
private :addrs2specs
|
||||
|
||||
|
||||
#
|
||||
# date time
|
||||
#
|
||||
|
||||
def date( default = nil )
|
||||
if h = @header['date']
|
||||
h.date
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def date=( time )
|
||||
if time
|
||||
store 'Date', time2str(time)
|
||||
else
|
||||
@header.delete 'date'
|
||||
end
|
||||
time
|
||||
end
|
||||
|
||||
def strftime( fmt, default = nil )
|
||||
if t = date
|
||||
t.strftime(fmt)
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# destination
|
||||
#
|
||||
|
||||
def to_addrs( default = nil )
|
||||
if h = @header['to']
|
||||
h.addrs
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def cc_addrs( default = nil )
|
||||
if h = @header['cc']
|
||||
h.addrs
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def bcc_addrs( default = nil )
|
||||
if h = @header['bcc']
|
||||
h.addrs
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def to_addrs=( arg )
|
||||
set_addrfield 'to', arg
|
||||
end
|
||||
|
||||
def cc_addrs=( arg )
|
||||
set_addrfield 'cc', arg
|
||||
end
|
||||
|
||||
def bcc_addrs=( arg )
|
||||
set_addrfield 'bcc', arg
|
||||
end
|
||||
|
||||
def to( default = nil )
|
||||
addrs2specs(to_addrs(nil)) || default
|
||||
end
|
||||
|
||||
def cc( default = nil )
|
||||
addrs2specs(cc_addrs(nil)) || default
|
||||
end
|
||||
|
||||
def bcc( default = nil )
|
||||
addrs2specs(bcc_addrs(nil)) || default
|
||||
end
|
||||
|
||||
def to=( *strs )
|
||||
set_string_array_attr 'To', strs
|
||||
end
|
||||
|
||||
def cc=( *strs )
|
||||
set_string_array_attr 'Cc', strs
|
||||
end
|
||||
|
||||
def bcc=( *strs )
|
||||
set_string_array_attr 'Bcc', strs
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# originator
|
||||
#
|
||||
|
||||
def from_addrs( default = nil )
|
||||
if h = @header['from']
|
||||
h.addrs
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def from_addrs=( arg )
|
||||
set_addrfield 'from', arg
|
||||
end
|
||||
|
||||
def from( default = nil )
|
||||
addrs2specs(from_addrs(nil)) || default
|
||||
end
|
||||
|
||||
def from=( *strs )
|
||||
set_string_array_attr 'From', strs
|
||||
end
|
||||
|
||||
def friendly_from( default = nil )
|
||||
h = @header['from']
|
||||
a, = h.addrs
|
||||
return default unless a
|
||||
return a.phrase if a.phrase
|
||||
return h.comments.join(' ') unless h.comments.empty?
|
||||
a.spec
|
||||
end
|
||||
|
||||
|
||||
def reply_to_addrs( default = nil )
|
||||
if h = @header['reply-to']
|
||||
h.addrs
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def reply_to_addrs=( arg )
|
||||
set_addrfield 'reply-to', arg
|
||||
end
|
||||
|
||||
def reply_to( default = nil )
|
||||
addrs2specs(reply_to_addrs(nil)) || default
|
||||
end
|
||||
|
||||
def reply_to=( *strs )
|
||||
set_string_array_attr 'Reply-To', strs
|
||||
end
|
||||
|
||||
|
||||
def sender_addr( default = nil )
|
||||
f = @header['sender'] or return default
|
||||
f.addr or return default
|
||||
end
|
||||
|
||||
def sender_addr=( addr )
|
||||
if addr
|
||||
h = HeaderField.internal_new('sender', @config)
|
||||
h.addr = addr
|
||||
@header['sender'] = h
|
||||
else
|
||||
@header.delete 'sender'
|
||||
end
|
||||
addr
|
||||
end
|
||||
|
||||
def sender( default )
|
||||
f = @header['sender'] or return default
|
||||
a = f.addr or return default
|
||||
a.spec
|
||||
end
|
||||
|
||||
def sender=( str )
|
||||
set_string_attr 'Sender', str
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# subject
|
||||
#
|
||||
|
||||
def subject( default = nil )
|
||||
if h = @header['subject']
|
||||
h.body
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
alias quoted_subject subject
|
||||
|
||||
def subject=( str )
|
||||
set_string_attr 'Subject', str
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# identity & threading
|
||||
#
|
||||
|
||||
def message_id( default = nil )
|
||||
if h = @header['message-id']
|
||||
h.id || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def message_id=( str )
|
||||
set_string_attr 'Message-Id', str
|
||||
end
|
||||
|
||||
def in_reply_to( default = nil )
|
||||
if h = @header['in-reply-to']
|
||||
h.ids
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def in_reply_to=( *idstrs )
|
||||
set_string_array_attr 'In-Reply-To', idstrs
|
||||
end
|
||||
|
||||
def references( default = nil )
|
||||
if h = @header['references']
|
||||
h.refs
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def references=( *strs )
|
||||
set_string_array_attr 'References', strs
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# MIME headers
|
||||
#
|
||||
|
||||
def mime_version( default = nil )
|
||||
if h = @header['mime-version']
|
||||
h.version || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def mime_version=( m, opt = nil )
|
||||
if opt
|
||||
if h = @header['mime-version']
|
||||
h.major = m
|
||||
h.minor = opt
|
||||
else
|
||||
store 'Mime-Version', "#{m}.#{opt}"
|
||||
end
|
||||
else
|
||||
store 'Mime-Version', m
|
||||
end
|
||||
m
|
||||
end
|
||||
|
||||
|
||||
def content_type( default = nil )
|
||||
if h = @header['content-type']
|
||||
h.content_type || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def main_type( default = nil )
|
||||
if h = @header['content-type']
|
||||
h.main_type || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def sub_type( default = nil )
|
||||
if h = @header['content-type']
|
||||
h.sub_type || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def set_content_type( str, sub = nil, param = nil )
|
||||
if sub
|
||||
main, sub = str, sub
|
||||
else
|
||||
main, sub = str.split(%r</>, 2)
|
||||
raise ArgumentError, "sub type missing: #{str.inspect}" unless sub
|
||||
end
|
||||
if h = @header['content-type']
|
||||
h.main_type = main
|
||||
h.sub_type = sub
|
||||
h.params.clear
|
||||
else
|
||||
store 'Content-Type', "#{main}/#{sub}"
|
||||
end
|
||||
@header['content-type'].params.replace param if param
|
||||
|
||||
str
|
||||
end
|
||||
|
||||
alias content_type= set_content_type
|
||||
|
||||
def type_param( name, default = nil )
|
||||
if h = @header['content-type']
|
||||
h[name] || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def charset( default = nil )
|
||||
if h = @header['content-type']
|
||||
h['charset'] or default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def charset=( str )
|
||||
if str
|
||||
if h = @header[ 'content-type' ]
|
||||
h['charset'] = str
|
||||
else
|
||||
store 'Content-Type', "text/plain; charset=#{str}"
|
||||
end
|
||||
end
|
||||
str
|
||||
end
|
||||
|
||||
|
||||
def transfer_encoding( default = nil )
|
||||
if h = @header['content-transfer-encoding']
|
||||
h.encoding || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def transfer_encoding=( str )
|
||||
set_string_attr 'Content-Transfer-Encoding', str
|
||||
end
|
||||
|
||||
alias encoding transfer_encoding
|
||||
alias encoding= transfer_encoding=
|
||||
alias content_transfer_encoding transfer_encoding
|
||||
alias content_transfer_encoding= transfer_encoding=
|
||||
|
||||
|
||||
def disposition( default = nil )
|
||||
if h = @header['content-disposition']
|
||||
h.disposition || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
alias content_disposition disposition
|
||||
|
||||
def set_disposition( str, params = nil )
|
||||
if h = @header['content-disposition']
|
||||
h.disposition = str
|
||||
h.params.clear
|
||||
else
|
||||
store('Content-Disposition', str)
|
||||
h = @header['content-disposition']
|
||||
end
|
||||
h.params.replace params if params
|
||||
end
|
||||
|
||||
alias disposition= set_disposition
|
||||
alias set_content_disposition set_disposition
|
||||
alias content_disposition= set_disposition
|
||||
|
||||
def disposition_param( name, default = nil )
|
||||
if h = @header['content-disposition']
|
||||
h[name] || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
###
|
||||
### utils
|
||||
###
|
||||
|
||||
def create_reply
|
||||
mail = TMail::Mail.parse('')
|
||||
mail.subject = 'Re: ' + subject('').sub(/\A(?:\[[^\]]+\])?(?:\s*Re:)*\s*/i, '')
|
||||
mail.to_addrs = reply_addresses([])
|
||||
mail.in_reply_to = [message_id(nil)].compact
|
||||
mail.references = references([]) + [message_id(nil)].compact
|
||||
mail.mime_version = '1.0'
|
||||
mail
|
||||
end
|
||||
|
||||
|
||||
def base64_encode
|
||||
store 'Content-Transfer-Encoding', 'Base64'
|
||||
self.body = Base64.folding_encode(self.body)
|
||||
end
|
||||
|
||||
def base64_decode
|
||||
if /base64/i === self.transfer_encoding('')
|
||||
store 'Content-Transfer-Encoding', '8bit'
|
||||
self.body = Base64.decode(self.body, @config.strict_base64decode?)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def destinations( default = nil )
|
||||
ret = []
|
||||
%w( to cc bcc ).each do |nm|
|
||||
if h = @header[nm]
|
||||
h.addrs.each {|i| ret.push i.address }
|
||||
end
|
||||
end
|
||||
ret.empty? ? default : ret
|
||||
end
|
||||
|
||||
def each_destination( &block )
|
||||
destinations([]).each do |i|
|
||||
if Address === i
|
||||
yield i
|
||||
else
|
||||
i.each(&block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
alias each_dest each_destination
|
||||
|
||||
|
||||
def reply_addresses( default = nil )
|
||||
reply_to_addrs(nil) or from_addrs(nil) or default
|
||||
end
|
||||
|
||||
def error_reply_addresses( default = nil )
|
||||
if s = sender(nil)
|
||||
[s]
|
||||
else
|
||||
from_addrs(default)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def multipart?
|
||||
main_type('').downcase == 'multipart'
|
||||
end
|
||||
|
||||
end # class Mail
|
||||
|
||||
end # module TMail
|
||||
914
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/header.rb
vendored
Normal file
914
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/header.rb
vendored
Normal file
|
|
@ -0,0 +1,914 @@
|
|||
#
|
||||
# header.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
require 'tmail/encode'
|
||||
require 'tmail/address'
|
||||
require 'tmail/parser'
|
||||
require 'tmail/config'
|
||||
require 'tmail/utils'
|
||||
|
||||
|
||||
module TMail
|
||||
|
||||
class HeaderField
|
||||
|
||||
include TextUtils
|
||||
|
||||
class << self
|
||||
|
||||
alias newobj new
|
||||
|
||||
def new( name, body, conf = DEFAULT_CONFIG )
|
||||
klass = FNAME_TO_CLASS[name.downcase] || UnstructuredHeader
|
||||
klass.newobj body, conf
|
||||
end
|
||||
|
||||
def new_from_port( port, name, conf = DEFAULT_CONFIG )
|
||||
re = Regep.new('\A(' + Regexp.quote(name) + '):', 'i')
|
||||
str = nil
|
||||
port.ropen {|f|
|
||||
f.each do |line|
|
||||
if m = re.match(line) then str = m.post_match.strip
|
||||
elsif str and /\A[\t ]/ === line then str << ' ' << line.strip
|
||||
elsif /\A-*\s*\z/ === line then break
|
||||
elsif str then break
|
||||
end
|
||||
end
|
||||
}
|
||||
new(name, str, Config.to_config(conf))
|
||||
end
|
||||
|
||||
def internal_new( name, conf )
|
||||
FNAME_TO_CLASS[name].newobj('', conf, true)
|
||||
end
|
||||
|
||||
end # class << self
|
||||
|
||||
def initialize( body, conf, intern = false )
|
||||
@body = body
|
||||
@config = conf
|
||||
|
||||
@illegal = false
|
||||
@parsed = false
|
||||
if intern
|
||||
@parsed = true
|
||||
parse_init
|
||||
end
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{self.class} #{@body.inspect}>"
|
||||
end
|
||||
|
||||
def illegal?
|
||||
@illegal
|
||||
end
|
||||
|
||||
def empty?
|
||||
ensure_parsed
|
||||
return true if @illegal
|
||||
isempty?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_parsed
|
||||
return if @parsed
|
||||
@parsed = true
|
||||
parse
|
||||
end
|
||||
|
||||
# defabstract parse
|
||||
# end
|
||||
|
||||
def clear_parse_status
|
||||
@parsed = false
|
||||
@illegal = false
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
def body
|
||||
ensure_parsed
|
||||
v = Decoder.new(s = '')
|
||||
do_accept v
|
||||
v.terminate
|
||||
s
|
||||
end
|
||||
|
||||
def body=( str )
|
||||
@body = str
|
||||
clear_parse_status
|
||||
end
|
||||
|
||||
include StrategyInterface
|
||||
|
||||
def accept( strategy, dummy1 = nil, dummy2 = nil )
|
||||
ensure_parsed
|
||||
do_accept strategy
|
||||
strategy.terminate
|
||||
end
|
||||
|
||||
# abstract do_accept
|
||||
|
||||
end
|
||||
|
||||
|
||||
class UnstructuredHeader < HeaderField
|
||||
|
||||
def body
|
||||
ensure_parsed
|
||||
@body
|
||||
end
|
||||
|
||||
def body=( arg )
|
||||
ensure_parsed
|
||||
@body = arg
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parse_init
|
||||
end
|
||||
|
||||
def parse
|
||||
@body = Decoder.decode(@body.gsub(/\n|\r\n|\r/, ''))
|
||||
end
|
||||
|
||||
def isempty?
|
||||
not @body
|
||||
end
|
||||
|
||||
def do_accept( strategy )
|
||||
strategy.text @body
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class StructuredHeader < HeaderField
|
||||
|
||||
def comments
|
||||
ensure_parsed
|
||||
@comments
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parse
|
||||
save = nil
|
||||
|
||||
begin
|
||||
parse_init
|
||||
do_parse
|
||||
rescue SyntaxError
|
||||
if not save and mime_encoded? @body
|
||||
save = @body
|
||||
@body = Decoder.decode(save)
|
||||
retry
|
||||
elsif save
|
||||
@body = save
|
||||
end
|
||||
|
||||
@illegal = true
|
||||
raise if @config.strict_parse?
|
||||
end
|
||||
end
|
||||
|
||||
def parse_init
|
||||
@comments = []
|
||||
init
|
||||
end
|
||||
|
||||
def do_parse
|
||||
obj = Parser.parse(self.class::PARSE_TYPE, @body, @comments)
|
||||
set obj if obj
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class DateTimeHeader < StructuredHeader
|
||||
|
||||
PARSE_TYPE = :DATETIME
|
||||
|
||||
def date
|
||||
ensure_parsed
|
||||
@date
|
||||
end
|
||||
|
||||
def date=( arg )
|
||||
ensure_parsed
|
||||
@date = arg
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@date = nil
|
||||
end
|
||||
|
||||
def set( t )
|
||||
@date = t
|
||||
end
|
||||
|
||||
def isempty?
|
||||
not @date
|
||||
end
|
||||
|
||||
def do_accept( strategy )
|
||||
strategy.meta time2str(@date)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class AddressHeader < StructuredHeader
|
||||
|
||||
PARSE_TYPE = :MADDRESS
|
||||
|
||||
def addrs
|
||||
ensure_parsed
|
||||
@addrs
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@addrs = []
|
||||
end
|
||||
|
||||
def set( a )
|
||||
@addrs = a
|
||||
end
|
||||
|
||||
def isempty?
|
||||
@addrs.empty?
|
||||
end
|
||||
|
||||
def do_accept( strategy )
|
||||
first = true
|
||||
@addrs.each do |a|
|
||||
if first
|
||||
first = false
|
||||
else
|
||||
strategy.meta ','
|
||||
strategy.space
|
||||
end
|
||||
a.accept strategy
|
||||
end
|
||||
|
||||
@comments.each do |c|
|
||||
strategy.space
|
||||
strategy.meta '('
|
||||
strategy.text c
|
||||
strategy.meta ')'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class ReturnPathHeader < AddressHeader
|
||||
|
||||
PARSE_TYPE = :RETPATH
|
||||
|
||||
def addr
|
||||
addrs()[0]
|
||||
end
|
||||
|
||||
def spec
|
||||
a = addr() or return nil
|
||||
a.spec
|
||||
end
|
||||
|
||||
def routes
|
||||
a = addr() or return nil
|
||||
a.routes
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def do_accept( strategy )
|
||||
a = addr()
|
||||
|
||||
strategy.meta '<'
|
||||
unless a.routes.empty?
|
||||
strategy.meta a.routes.map {|i| '@' + i }.join(',')
|
||||
strategy.meta ':'
|
||||
end
|
||||
spec = a.spec
|
||||
strategy.meta spec if spec
|
||||
strategy.meta '>'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class SingleAddressHeader < AddressHeader
|
||||
|
||||
def addr
|
||||
addrs()[0]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def do_accept( strategy )
|
||||
a = addr()
|
||||
a.accept strategy
|
||||
@comments.each do |c|
|
||||
strategy.space
|
||||
strategy.meta '('
|
||||
strategy.text c
|
||||
strategy.meta ')'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class MessageIdHeader < StructuredHeader
|
||||
|
||||
def id
|
||||
ensure_parsed
|
||||
@id
|
||||
end
|
||||
|
||||
def id=( arg )
|
||||
ensure_parsed
|
||||
@id = arg
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@id = nil
|
||||
end
|
||||
|
||||
def isempty?
|
||||
not @id
|
||||
end
|
||||
|
||||
def do_parse
|
||||
@id = @body.slice(MESSAGE_ID) or
|
||||
raise SyntaxError, "wrong Message-ID format: #{@body}"
|
||||
end
|
||||
|
||||
def do_accept( strategy )
|
||||
strategy.meta @id
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class ReferencesHeader < StructuredHeader
|
||||
|
||||
def refs
|
||||
ensure_parsed
|
||||
@refs
|
||||
end
|
||||
|
||||
def each_id
|
||||
self.refs.each do |i|
|
||||
yield i if MESSAGE_ID === i
|
||||
end
|
||||
end
|
||||
|
||||
def ids
|
||||
ensure_parsed
|
||||
@ids
|
||||
end
|
||||
|
||||
def each_phrase
|
||||
self.refs.each do |i|
|
||||
yield i unless MESSAGE_ID === i
|
||||
end
|
||||
end
|
||||
|
||||
def phrases
|
||||
ret = []
|
||||
each_phrase {|i| ret.push i }
|
||||
ret
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@refs = []
|
||||
@ids = []
|
||||
end
|
||||
|
||||
def isempty?
|
||||
@ids.empty?
|
||||
end
|
||||
|
||||
def do_parse
|
||||
str = @body
|
||||
while m = MESSAGE_ID.match(str)
|
||||
pre = m.pre_match.strip
|
||||
@refs.push pre unless pre.empty?
|
||||
@refs.push s = m[0]
|
||||
@ids.push s
|
||||
str = m.post_match
|
||||
end
|
||||
str = str.strip
|
||||
@refs.push str unless str.empty?
|
||||
end
|
||||
|
||||
def do_accept( strategy )
|
||||
first = true
|
||||
@ids.each do |i|
|
||||
if first
|
||||
first = false
|
||||
else
|
||||
strategy.space
|
||||
end
|
||||
strategy.meta i
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class ReceivedHeader < StructuredHeader
|
||||
|
||||
PARSE_TYPE = :RECEIVED
|
||||
|
||||
def from
|
||||
ensure_parsed
|
||||
@from
|
||||
end
|
||||
|
||||
def from=( arg )
|
||||
ensure_parsed
|
||||
@from = arg
|
||||
end
|
||||
|
||||
def by
|
||||
ensure_parsed
|
||||
@by
|
||||
end
|
||||
|
||||
def by=( arg )
|
||||
ensure_parsed
|
||||
@by = arg
|
||||
end
|
||||
|
||||
def via
|
||||
ensure_parsed
|
||||
@via
|
||||
end
|
||||
|
||||
def via=( arg )
|
||||
ensure_parsed
|
||||
@via = arg
|
||||
end
|
||||
|
||||
def with
|
||||
ensure_parsed
|
||||
@with
|
||||
end
|
||||
|
||||
def id
|
||||
ensure_parsed
|
||||
@id
|
||||
end
|
||||
|
||||
def id=( arg )
|
||||
ensure_parsed
|
||||
@id = arg
|
||||
end
|
||||
|
||||
def _for
|
||||
ensure_parsed
|
||||
@_for
|
||||
end
|
||||
|
||||
def _for=( arg )
|
||||
ensure_parsed
|
||||
@_for = arg
|
||||
end
|
||||
|
||||
def date
|
||||
ensure_parsed
|
||||
@date
|
||||
end
|
||||
|
||||
def date=( arg )
|
||||
ensure_parsed
|
||||
@date = arg
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@from = @by = @via = @with = @id = @_for = nil
|
||||
@with = []
|
||||
@date = nil
|
||||
end
|
||||
|
||||
def set( args )
|
||||
@from, @by, @via, @with, @id, @_for, @date = *args
|
||||
end
|
||||
|
||||
def isempty?
|
||||
@with.empty? and not (@from or @by or @via or @id or @_for or @date)
|
||||
end
|
||||
|
||||
def do_accept( strategy )
|
||||
list = []
|
||||
list.push 'from ' + @from if @from
|
||||
list.push 'by ' + @by if @by
|
||||
list.push 'via ' + @via if @via
|
||||
@with.each do |i|
|
||||
list.push 'with ' + i
|
||||
end
|
||||
list.push 'id ' + @id if @id
|
||||
list.push 'for <' + @_for + '>' if @_for
|
||||
|
||||
first = true
|
||||
list.each do |i|
|
||||
strategy.space unless first
|
||||
strategy.meta i
|
||||
first = false
|
||||
end
|
||||
if @date
|
||||
strategy.meta ';'
|
||||
strategy.space
|
||||
strategy.meta time2str(@date)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class KeywordsHeader < StructuredHeader
|
||||
|
||||
PARSE_TYPE = :KEYWORDS
|
||||
|
||||
def keys
|
||||
ensure_parsed
|
||||
@keys
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@keys = []
|
||||
end
|
||||
|
||||
def set( a )
|
||||
@keys = a
|
||||
end
|
||||
|
||||
def isempty?
|
||||
@keys.empty?
|
||||
end
|
||||
|
||||
def do_accept( strategy )
|
||||
first = true
|
||||
@keys.each do |i|
|
||||
if first
|
||||
first = false
|
||||
else
|
||||
strategy.meta ','
|
||||
end
|
||||
strategy.meta i
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class EncryptedHeader < StructuredHeader
|
||||
|
||||
PARSE_TYPE = :ENCRYPTED
|
||||
|
||||
def encrypter
|
||||
ensure_parsed
|
||||
@encrypter
|
||||
end
|
||||
|
||||
def encrypter=( arg )
|
||||
ensure_parsed
|
||||
@encrypter = arg
|
||||
end
|
||||
|
||||
def keyword
|
||||
ensure_parsed
|
||||
@keyword
|
||||
end
|
||||
|
||||
def keyword=( arg )
|
||||
ensure_parsed
|
||||
@keyword = arg
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@encrypter = nil
|
||||
@keyword = nil
|
||||
end
|
||||
|
||||
def set( args )
|
||||
@encrypter, @keyword = args
|
||||
end
|
||||
|
||||
def isempty?
|
||||
not (@encrypter or @keyword)
|
||||
end
|
||||
|
||||
def do_accept( strategy )
|
||||
if @key
|
||||
strategy.meta @encrypter + ','
|
||||
strategy.space
|
||||
strategy.meta @keyword
|
||||
else
|
||||
strategy.meta @encrypter
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class MimeVersionHeader < StructuredHeader
|
||||
|
||||
PARSE_TYPE = :MIMEVERSION
|
||||
|
||||
def major
|
||||
ensure_parsed
|
||||
@major
|
||||
end
|
||||
|
||||
def major=( arg )
|
||||
ensure_parsed
|
||||
@major = arg
|
||||
end
|
||||
|
||||
def minor
|
||||
ensure_parsed
|
||||
@minor
|
||||
end
|
||||
|
||||
def minor=( arg )
|
||||
ensure_parsed
|
||||
@minor = arg
|
||||
end
|
||||
|
||||
def version
|
||||
sprintf('%d.%d', major, minor)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@major = nil
|
||||
@minor = nil
|
||||
end
|
||||
|
||||
def set( args )
|
||||
@major, @minor = *args
|
||||
end
|
||||
|
||||
def isempty?
|
||||
not (@major or @minor)
|
||||
end
|
||||
|
||||
def do_accept( strategy )
|
||||
strategy.meta sprintf('%d.%d', @major, @minor)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class ContentTypeHeader < StructuredHeader
|
||||
|
||||
PARSE_TYPE = :CTYPE
|
||||
|
||||
def main_type
|
||||
ensure_parsed
|
||||
@main
|
||||
end
|
||||
|
||||
def main_type=( arg )
|
||||
ensure_parsed
|
||||
@main = arg.downcase
|
||||
end
|
||||
|
||||
def sub_type
|
||||
ensure_parsed
|
||||
@sub
|
||||
end
|
||||
|
||||
def sub_type=( arg )
|
||||
ensure_parsed
|
||||
@sub = arg.downcase
|
||||
end
|
||||
|
||||
def content_type
|
||||
ensure_parsed
|
||||
@sub ? sprintf('%s/%s', @main, @sub) : @main
|
||||
end
|
||||
|
||||
def params
|
||||
ensure_parsed
|
||||
@params
|
||||
end
|
||||
|
||||
def []( key )
|
||||
ensure_parsed
|
||||
@params and @params[key]
|
||||
end
|
||||
|
||||
def []=( key, val )
|
||||
ensure_parsed
|
||||
(@params ||= {})[key] = val
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@main = @sub = @params = nil
|
||||
end
|
||||
|
||||
def set( args )
|
||||
@main, @sub, @params = *args
|
||||
end
|
||||
|
||||
def isempty?
|
||||
not (@main or @sub)
|
||||
end
|
||||
|
||||
def do_accept( strategy )
|
||||
if @sub
|
||||
strategy.meta sprintf('%s/%s', @main, @sub)
|
||||
else
|
||||
strategy.meta @main
|
||||
end
|
||||
@params.each do |k,v|
|
||||
if v
|
||||
strategy.meta ';'
|
||||
strategy.space
|
||||
strategy.kv_pair k, v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class ContentTransferEncodingHeader < StructuredHeader
|
||||
|
||||
PARSE_TYPE = :CENCODING
|
||||
|
||||
def encoding
|
||||
ensure_parsed
|
||||
@encoding
|
||||
end
|
||||
|
||||
def encoding=( arg )
|
||||
ensure_parsed
|
||||
@encoding = arg
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@encoding = nil
|
||||
end
|
||||
|
||||
def set( s )
|
||||
@encoding = s
|
||||
end
|
||||
|
||||
def isempty?
|
||||
not @encoding
|
||||
end
|
||||
|
||||
def do_accept( strategy )
|
||||
strategy.meta @encoding.capitalize
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class ContentDispositionHeader < StructuredHeader
|
||||
|
||||
PARSE_TYPE = :CDISPOSITION
|
||||
|
||||
def disposition
|
||||
ensure_parsed
|
||||
@disposition
|
||||
end
|
||||
|
||||
def disposition=( str )
|
||||
ensure_parsed
|
||||
@disposition = str.downcase
|
||||
end
|
||||
|
||||
def params
|
||||
ensure_parsed
|
||||
@params
|
||||
end
|
||||
|
||||
def []( key )
|
||||
ensure_parsed
|
||||
@params and @params[key]
|
||||
end
|
||||
|
||||
def []=( key, val )
|
||||
ensure_parsed
|
||||
(@params ||= {})[key] = val
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@disposition = @params = nil
|
||||
end
|
||||
|
||||
def set( args )
|
||||
@disposition, @params = *args
|
||||
end
|
||||
|
||||
def isempty?
|
||||
not @disposition and (not @params or @params.empty?)
|
||||
end
|
||||
|
||||
def do_accept( strategy )
|
||||
strategy.meta @disposition
|
||||
@params.each do |k,v|
|
||||
strategy.meta ';'
|
||||
strategy.space
|
||||
strategy.kv_pair k, v
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class HeaderField # redefine
|
||||
|
||||
FNAME_TO_CLASS = {
|
||||
'date' => DateTimeHeader,
|
||||
'resent-date' => DateTimeHeader,
|
||||
'to' => AddressHeader,
|
||||
'cc' => AddressHeader,
|
||||
'bcc' => AddressHeader,
|
||||
'from' => AddressHeader,
|
||||
'reply-to' => AddressHeader,
|
||||
'resent-to' => AddressHeader,
|
||||
'resent-cc' => AddressHeader,
|
||||
'resent-bcc' => AddressHeader,
|
||||
'resent-from' => AddressHeader,
|
||||
'resent-reply-to' => AddressHeader,
|
||||
'sender' => SingleAddressHeader,
|
||||
'resent-sender' => SingleAddressHeader,
|
||||
'return-path' => ReturnPathHeader,
|
||||
'message-id' => MessageIdHeader,
|
||||
'resent-message-id' => MessageIdHeader,
|
||||
'in-reply-to' => ReferencesHeader,
|
||||
'received' => ReceivedHeader,
|
||||
'references' => ReferencesHeader,
|
||||
'keywords' => KeywordsHeader,
|
||||
'encrypted' => EncryptedHeader,
|
||||
'mime-version' => MimeVersionHeader,
|
||||
'content-type' => ContentTypeHeader,
|
||||
'content-transfer-encoding' => ContentTransferEncodingHeader,
|
||||
'content-disposition' => ContentDispositionHeader,
|
||||
'content-id' => MessageIdHeader,
|
||||
'subject' => UnstructuredHeader,
|
||||
'comments' => UnstructuredHeader,
|
||||
'content-description' => UnstructuredHeader
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
end # module TMail
|
||||
35
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/info.rb
vendored
Normal file
35
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/info.rb
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#
|
||||
# info.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
module TMail
|
||||
|
||||
Version = '0.10.7'
|
||||
Copyright = 'Copyright (c) 1998-2002 Minero Aoki'
|
||||
|
||||
end
|
||||
1
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/loader.rb
vendored
Normal file
1
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/loader.rb
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
require 'tmail/mailbox'
|
||||
447
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/mail.rb
vendored
Normal file
447
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/mail.rb
vendored
Normal file
|
|
@ -0,0 +1,447 @@
|
|||
#
|
||||
# mail.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
require 'tmail/facade'
|
||||
require 'tmail/encode'
|
||||
require 'tmail/header'
|
||||
require 'tmail/port'
|
||||
require 'tmail/config'
|
||||
require 'tmail/utils'
|
||||
require 'tmail/attachments'
|
||||
require 'tmail/quoting'
|
||||
require 'socket'
|
||||
|
||||
|
||||
module TMail
|
||||
|
||||
class Mail
|
||||
|
||||
class << self
|
||||
def load( fname )
|
||||
new(FilePort.new(fname))
|
||||
end
|
||||
|
||||
alias load_from load
|
||||
alias loadfrom load
|
||||
|
||||
def parse( str )
|
||||
new(StringPort.new(str))
|
||||
end
|
||||
end
|
||||
|
||||
def initialize( port = nil, conf = DEFAULT_CONFIG )
|
||||
@port = port || StringPort.new
|
||||
@config = Config.to_config(conf)
|
||||
|
||||
@header = {}
|
||||
@body_port = nil
|
||||
@body_parsed = false
|
||||
@epilogue = ''
|
||||
@parts = []
|
||||
|
||||
@port.ropen {|f|
|
||||
parse_header f
|
||||
parse_body f unless @port.reproducible?
|
||||
}
|
||||
end
|
||||
|
||||
attr_reader :port
|
||||
|
||||
def inspect
|
||||
"\#<#{self.class} port=#{@port.inspect} bodyport=#{@body_port.inspect}>"
|
||||
end
|
||||
|
||||
#
|
||||
# to_s interfaces
|
||||
#
|
||||
|
||||
public
|
||||
|
||||
include StrategyInterface
|
||||
|
||||
def write_back( eol = "\n", charset = 'e' )
|
||||
parse_body
|
||||
@port.wopen {|stream| encoded eol, charset, stream }
|
||||
end
|
||||
|
||||
def accept( strategy )
|
||||
with_multipart_encoding(strategy) {
|
||||
ordered_each do |name, field|
|
||||
next if field.empty?
|
||||
strategy.header_name canonical(name)
|
||||
field.accept strategy
|
||||
strategy.puts
|
||||
end
|
||||
strategy.puts
|
||||
body_port().ropen {|r|
|
||||
strategy.write r.read
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def canonical( name )
|
||||
name.split(/-/).map {|s| s.capitalize }.join('-')
|
||||
end
|
||||
|
||||
def with_multipart_encoding( strategy )
|
||||
if parts().empty? # DO NOT USE @parts
|
||||
yield
|
||||
|
||||
else
|
||||
bound = ::TMail.new_boundary
|
||||
if @header.key? 'content-type'
|
||||
@header['content-type'].params['boundary'] = bound
|
||||
else
|
||||
store 'Content-Type', %<multipart/mixed; boundary="#{bound}">
|
||||
end
|
||||
|
||||
yield
|
||||
|
||||
parts().each do |tm|
|
||||
strategy.puts
|
||||
strategy.puts '--' + bound
|
||||
tm.accept strategy
|
||||
end
|
||||
strategy.puts
|
||||
strategy.puts '--' + bound + '--'
|
||||
strategy.write epilogue()
|
||||
end
|
||||
end
|
||||
|
||||
###
|
||||
### header
|
||||
###
|
||||
|
||||
public
|
||||
|
||||
ALLOW_MULTIPLE = {
|
||||
'received' => true,
|
||||
'resent-date' => true,
|
||||
'resent-from' => true,
|
||||
'resent-sender' => true,
|
||||
'resent-to' => true,
|
||||
'resent-cc' => true,
|
||||
'resent-bcc' => true,
|
||||
'resent-message-id' => true,
|
||||
'comments' => true,
|
||||
'keywords' => true
|
||||
}
|
||||
USE_ARRAY = ALLOW_MULTIPLE
|
||||
|
||||
def header
|
||||
@header.dup
|
||||
end
|
||||
|
||||
def []( key )
|
||||
@header[key.downcase]
|
||||
end
|
||||
|
||||
def sub_header(key, param)
|
||||
(hdr = self[key]) ? hdr[param] : nil
|
||||
end
|
||||
|
||||
alias fetch []
|
||||
|
||||
def []=( key, val )
|
||||
dkey = key.downcase
|
||||
|
||||
if val.nil?
|
||||
@header.delete dkey
|
||||
return nil
|
||||
end
|
||||
|
||||
case val
|
||||
when String
|
||||
header = new_hf(key, val)
|
||||
when HeaderField
|
||||
;
|
||||
when Array
|
||||
ALLOW_MULTIPLE.include? dkey or
|
||||
raise ArgumentError, "#{key}: Header must not be multiple"
|
||||
@header[dkey] = val
|
||||
return val
|
||||
else
|
||||
header = new_hf(key, val.to_s)
|
||||
end
|
||||
if ALLOW_MULTIPLE.include? dkey
|
||||
(@header[dkey] ||= []).push header
|
||||
else
|
||||
@header[dkey] = header
|
||||
end
|
||||
|
||||
val
|
||||
end
|
||||
|
||||
alias store []=
|
||||
|
||||
def each_header
|
||||
@header.each do |key, val|
|
||||
[val].flatten.each {|v| yield key, v }
|
||||
end
|
||||
end
|
||||
|
||||
alias each_pair each_header
|
||||
|
||||
def each_header_name( &block )
|
||||
@header.each_key(&block)
|
||||
end
|
||||
|
||||
alias each_key each_header_name
|
||||
|
||||
def each_field( &block )
|
||||
@header.values.flatten.each(&block)
|
||||
end
|
||||
|
||||
alias each_value each_field
|
||||
|
||||
FIELD_ORDER = %w(
|
||||
return-path received
|
||||
resent-date resent-from resent-sender resent-to
|
||||
resent-cc resent-bcc resent-message-id
|
||||
date from sender reply-to to cc bcc
|
||||
message-id in-reply-to references
|
||||
subject comments keywords
|
||||
mime-version content-type content-transfer-encoding
|
||||
content-disposition content-description
|
||||
)
|
||||
|
||||
def ordered_each
|
||||
list = @header.keys
|
||||
FIELD_ORDER.each do |name|
|
||||
if list.delete(name)
|
||||
[@header[name]].flatten.each {|v| yield name, v }
|
||||
end
|
||||
end
|
||||
list.each do |name|
|
||||
[@header[name]].flatten.each {|v| yield name, v }
|
||||
end
|
||||
end
|
||||
|
||||
def clear
|
||||
@header.clear
|
||||
end
|
||||
|
||||
def delete( key )
|
||||
@header.delete key.downcase
|
||||
end
|
||||
|
||||
def delete_if
|
||||
@header.delete_if do |key,val|
|
||||
if Array === val
|
||||
val.delete_if {|v| yield key, v }
|
||||
val.empty?
|
||||
else
|
||||
yield key, val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def keys
|
||||
@header.keys
|
||||
end
|
||||
|
||||
def key?( key )
|
||||
@header.key? key.downcase
|
||||
end
|
||||
|
||||
def values_at( *args )
|
||||
args.map {|k| @header[k.downcase] }.flatten
|
||||
end
|
||||
|
||||
alias indexes values_at
|
||||
alias indices values_at
|
||||
|
||||
private
|
||||
|
||||
def parse_header( f )
|
||||
name = field = nil
|
||||
unixfrom = nil
|
||||
|
||||
while line = f.gets
|
||||
case line
|
||||
when /\A[ \t]/ # continue from prev line
|
||||
raise SyntaxError, 'mail is began by space' unless field
|
||||
field << ' ' << line.strip
|
||||
|
||||
when /\A([^\: \t]+):\s*/ # new header line
|
||||
add_hf name, field if field
|
||||
name = $1
|
||||
field = $' #.strip
|
||||
|
||||
when /\A\-*\s*\z/ # end of header
|
||||
add_hf name, field if field
|
||||
name = field = nil
|
||||
break
|
||||
|
||||
when /\AFrom (\S+)/
|
||||
unixfrom = $1
|
||||
|
||||
when /^charset=.*/
|
||||
|
||||
else
|
||||
raise SyntaxError, "wrong mail header: '#{line.inspect}'"
|
||||
end
|
||||
end
|
||||
add_hf name, field if name
|
||||
|
||||
if unixfrom
|
||||
add_hf 'Return-Path', "<#{unixfrom}>" unless @header['return-path']
|
||||
end
|
||||
end
|
||||
|
||||
def add_hf( name, field )
|
||||
key = name.downcase
|
||||
field = new_hf(name, field)
|
||||
|
||||
if ALLOW_MULTIPLE.include? key
|
||||
(@header[key] ||= []).push field
|
||||
else
|
||||
@header[key] = field
|
||||
end
|
||||
end
|
||||
|
||||
def new_hf( name, field )
|
||||
HeaderField.new(name, field, @config)
|
||||
end
|
||||
|
||||
###
|
||||
### body
|
||||
###
|
||||
|
||||
public
|
||||
|
||||
def body_port
|
||||
parse_body
|
||||
@body_port
|
||||
end
|
||||
|
||||
def each( &block )
|
||||
body_port().ropen {|f| f.each(&block) }
|
||||
end
|
||||
|
||||
def quoted_body
|
||||
parse_body
|
||||
@body_port.ropen {|f|
|
||||
return f.read
|
||||
}
|
||||
end
|
||||
|
||||
def body=( str )
|
||||
parse_body
|
||||
@body_port.wopen {|f| f.write str }
|
||||
str
|
||||
end
|
||||
|
||||
alias preamble body
|
||||
alias preamble= body=
|
||||
|
||||
def epilogue
|
||||
parse_body
|
||||
@epilogue.dup
|
||||
end
|
||||
|
||||
def epilogue=( str )
|
||||
parse_body
|
||||
@epilogue = str
|
||||
str
|
||||
end
|
||||
|
||||
def parts
|
||||
parse_body
|
||||
@parts
|
||||
end
|
||||
|
||||
def each_part( &block )
|
||||
parts().each(&block)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parse_body( f = nil )
|
||||
return if @body_parsed
|
||||
if f
|
||||
parse_body_0 f
|
||||
else
|
||||
@port.ropen {|f|
|
||||
skip_header f
|
||||
parse_body_0 f
|
||||
}
|
||||
end
|
||||
@body_parsed = true
|
||||
end
|
||||
|
||||
def skip_header( f )
|
||||
while line = f.gets
|
||||
return if /\A[\r\n]*\z/ === line
|
||||
end
|
||||
end
|
||||
|
||||
def parse_body_0( f )
|
||||
if multipart?
|
||||
read_multipart f
|
||||
else
|
||||
@body_port = @config.new_body_port(self)
|
||||
@body_port.wopen {|w|
|
||||
w.write f.read
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def read_multipart( src )
|
||||
bound = @header['content-type'].params['boundary']
|
||||
is_sep = /\A--#{Regexp.quote bound}(?:--)?[ \t]*(?:\n|\r\n|\r)/
|
||||
lastbound = "--#{bound}--"
|
||||
|
||||
ports = [ @config.new_preamble_port(self) ]
|
||||
begin
|
||||
f = ports.last.wopen
|
||||
while line = src.gets
|
||||
if is_sep === line
|
||||
f.close
|
||||
break if line.strip == lastbound
|
||||
ports.push @config.new_part_port(self)
|
||||
f = ports.last.wopen
|
||||
else
|
||||
f << line
|
||||
end
|
||||
end
|
||||
@epilogue = (src.read || '')
|
||||
ensure
|
||||
f.close if f and not f.closed?
|
||||
end
|
||||
|
||||
@body_port = ports.shift
|
||||
@parts = ports.map {|p| self.class.new(p, @config) }
|
||||
end
|
||||
|
||||
end # class Mail
|
||||
|
||||
end # module TMail
|
||||
433
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/mailbox.rb
vendored
Normal file
433
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/mailbox.rb
vendored
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
#
|
||||
# mailbox.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
require 'tmail/port'
|
||||
require 'socket'
|
||||
require 'mutex_m'
|
||||
|
||||
|
||||
unless [].respond_to?(:sort_by)
|
||||
module Enumerable#:nodoc:
|
||||
def sort_by
|
||||
map {|i| [yield(i), i] }.sort {|a,b| a.first <=> b.first }.map {|i| i[1] }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module TMail
|
||||
|
||||
class MhMailbox
|
||||
|
||||
PORT_CLASS = MhPort
|
||||
|
||||
def initialize( dir )
|
||||
edir = File.expand_path(dir)
|
||||
raise ArgumentError, "not directory: #{dir}"\
|
||||
unless FileTest.directory? edir
|
||||
@dirname = edir
|
||||
@last_file = nil
|
||||
@last_atime = nil
|
||||
end
|
||||
|
||||
def directory
|
||||
@dirname
|
||||
end
|
||||
|
||||
alias dirname directory
|
||||
|
||||
attr_accessor :last_atime
|
||||
|
||||
def inspect
|
||||
"#<#{self.class} #{@dirname}>"
|
||||
end
|
||||
|
||||
def close
|
||||
end
|
||||
|
||||
def new_port
|
||||
PORT_CLASS.new(next_file_name())
|
||||
end
|
||||
|
||||
def each_port
|
||||
mail_files().each do |path|
|
||||
yield PORT_CLASS.new(path)
|
||||
end
|
||||
@last_atime = Time.now
|
||||
end
|
||||
|
||||
alias each each_port
|
||||
|
||||
def reverse_each_port
|
||||
mail_files().reverse_each do |path|
|
||||
yield PORT_CLASS.new(path)
|
||||
end
|
||||
@last_atime = Time.now
|
||||
end
|
||||
|
||||
alias reverse_each reverse_each_port
|
||||
|
||||
# old #each_mail returns Port
|
||||
#def each_mail
|
||||
# each_port do |port|
|
||||
# yield Mail.new(port)
|
||||
# end
|
||||
#end
|
||||
|
||||
def each_new_port( mtime = nil, &block )
|
||||
mtime ||= @last_atime
|
||||
return each_port(&block) unless mtime
|
||||
return unless File.mtime(@dirname) >= mtime
|
||||
|
||||
mail_files().each do |path|
|
||||
yield PORT_CLASS.new(path) if File.mtime(path) > mtime
|
||||
end
|
||||
@last_atime = Time.now
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def mail_files
|
||||
Dir.entries(@dirname)\
|
||||
.select {|s| /\A\d+\z/ === s }\
|
||||
.map {|s| s.to_i }\
|
||||
.sort\
|
||||
.map {|i| "#{@dirname}/#{i}" }\
|
||||
.select {|path| FileTest.file? path }
|
||||
end
|
||||
|
||||
def next_file_name
|
||||
unless n = @last_file
|
||||
n = 0
|
||||
Dir.entries(@dirname)\
|
||||
.select {|s| /\A\d+\z/ === s }\
|
||||
.map {|s| s.to_i }.sort\
|
||||
.each do |i|
|
||||
next unless FileTest.file? "#{@dirname}/#{i}"
|
||||
n = i
|
||||
end
|
||||
end
|
||||
begin
|
||||
n += 1
|
||||
end while FileTest.exist? "#{@dirname}/#{n}"
|
||||
@last_file = n
|
||||
|
||||
"#{@dirname}/#{n}"
|
||||
end
|
||||
|
||||
end # MhMailbox
|
||||
|
||||
MhLoader = MhMailbox
|
||||
|
||||
|
||||
class UNIXMbox
|
||||
|
||||
def UNIXMbox.lock( fname )
|
||||
begin
|
||||
f = File.open(fname)
|
||||
f.flock File::LOCK_EX
|
||||
yield f
|
||||
ensure
|
||||
f.flock File::LOCK_UN
|
||||
f.close if f and not f.closed?
|
||||
end
|
||||
end
|
||||
|
||||
class << self
|
||||
alias newobj new
|
||||
end
|
||||
|
||||
def UNIXMbox.new( fname, tmpdir = nil, readonly = false )
|
||||
tmpdir = ENV['TEMP'] || ENV['TMP'] || '/tmp'
|
||||
newobj(fname, "#{tmpdir}/ruby_tmail_#{$$}_#{rand()}", readonly, false)
|
||||
end
|
||||
|
||||
def UNIXMbox.static_new( fname, dir, readonly = false )
|
||||
newobj(fname, dir, readonly, true)
|
||||
end
|
||||
|
||||
def initialize( fname, mhdir, readonly, static )
|
||||
@filename = fname
|
||||
@readonly = readonly
|
||||
@closed = false
|
||||
|
||||
Dir.mkdir mhdir
|
||||
@real = MhMailbox.new(mhdir)
|
||||
@finalizer = UNIXMbox.mkfinal(@real, @filename, !@readonly, !static)
|
||||
ObjectSpace.define_finalizer self, @finalizer
|
||||
end
|
||||
|
||||
def UNIXMbox.mkfinal( mh, mboxfile, writeback_p, cleanup_p )
|
||||
lambda {
|
||||
if writeback_p
|
||||
lock(mboxfile) {|f|
|
||||
mh.each_port do |port|
|
||||
f.puts create_from_line(port)
|
||||
port.ropen {|r|
|
||||
f.puts r.read
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
if cleanup_p
|
||||
Dir.foreach(mh.dirname) do |fname|
|
||||
next if /\A\.\.?\z/ === fname
|
||||
File.unlink "#{mh.dirname}/#{fname}"
|
||||
end
|
||||
Dir.rmdir mh.dirname
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
# make _From line
|
||||
def UNIXMbox.create_from_line( port )
|
||||
sprintf 'From %s %s',
|
||||
fromaddr(), TextUtils.time2str(File.mtime(port.filename))
|
||||
end
|
||||
|
||||
def UNIXMbox.fromaddr
|
||||
h = HeaderField.new_from_port(port, 'Return-Path') ||
|
||||
HeaderField.new_from_port(port, 'From') or return 'nobody'
|
||||
a = h.addrs[0] or return 'nobody'
|
||||
a.spec
|
||||
end
|
||||
private_class_method :fromaddr
|
||||
|
||||
def close
|
||||
return if @closed
|
||||
|
||||
ObjectSpace.undefine_finalizer self
|
||||
@finalizer.call
|
||||
@finalizer = nil
|
||||
@real = nil
|
||||
@closed = true
|
||||
@updated = nil
|
||||
end
|
||||
|
||||
def each_port( &block )
|
||||
close_check
|
||||
update
|
||||
@real.each_port(&block)
|
||||
end
|
||||
|
||||
alias each each_port
|
||||
|
||||
def reverse_each_port( &block )
|
||||
close_check
|
||||
update
|
||||
@real.reverse_each_port(&block)
|
||||
end
|
||||
|
||||
alias reverse_each reverse_each_port
|
||||
|
||||
# old #each_mail returns Port
|
||||
#def each_mail( &block )
|
||||
# each_port do |port|
|
||||
# yield Mail.new(port)
|
||||
# end
|
||||
#end
|
||||
|
||||
def each_new_port( mtime = nil )
|
||||
close_check
|
||||
update
|
||||
@real.each_new_port(mtime) {|p| yield p }
|
||||
end
|
||||
|
||||
def new_port
|
||||
close_check
|
||||
@real.new_port
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def close_check
|
||||
@closed and raise ArgumentError, 'accessing already closed mbox'
|
||||
end
|
||||
|
||||
def update
|
||||
return if FileTest.zero?(@filename)
|
||||
return if @updated and File.mtime(@filename) < @updated
|
||||
w = nil
|
||||
port = nil
|
||||
time = nil
|
||||
UNIXMbox.lock(@filename) {|f|
|
||||
begin
|
||||
f.each do |line|
|
||||
if /\AFrom / === line
|
||||
w.close if w
|
||||
File.utime time, time, port.filename if time
|
||||
|
||||
port = @real.new_port
|
||||
w = port.wopen
|
||||
time = fromline2time(line)
|
||||
else
|
||||
w.print line if w
|
||||
end
|
||||
end
|
||||
ensure
|
||||
if w and not w.closed?
|
||||
w.close
|
||||
File.utime time, time, port.filename if time
|
||||
end
|
||||
end
|
||||
f.truncate(0) unless @readonly
|
||||
@updated = Time.now
|
||||
}
|
||||
end
|
||||
|
||||
def fromline2time( line )
|
||||
m = /\AFrom \S+ \w+ (\w+) (\d+) (\d+):(\d+):(\d+) (\d+)/.match(line) \
|
||||
or return nil
|
||||
Time.local(m[6].to_i, m[1], m[2].to_i, m[3].to_i, m[4].to_i, m[5].to_i)
|
||||
end
|
||||
|
||||
end # UNIXMbox
|
||||
|
||||
MboxLoader = UNIXMbox
|
||||
|
||||
|
||||
class Maildir
|
||||
|
||||
extend Mutex_m
|
||||
|
||||
PORT_CLASS = MaildirPort
|
||||
|
||||
@seq = 0
|
||||
def Maildir.unique_number
|
||||
synchronize {
|
||||
@seq += 1
|
||||
return @seq
|
||||
}
|
||||
end
|
||||
|
||||
def initialize( dir = nil )
|
||||
@dirname = dir || ENV['MAILDIR']
|
||||
raise ArgumentError, "not directory: #{@dirname}"\
|
||||
unless FileTest.directory? @dirname
|
||||
@new = "#{@dirname}/new"
|
||||
@tmp = "#{@dirname}/tmp"
|
||||
@cur = "#{@dirname}/cur"
|
||||
end
|
||||
|
||||
def directory
|
||||
@dirname
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{self.class} #{@dirname}>"
|
||||
end
|
||||
|
||||
def close
|
||||
end
|
||||
|
||||
def each_port
|
||||
mail_files(@cur).each do |path|
|
||||
yield PORT_CLASS.new(path)
|
||||
end
|
||||
end
|
||||
|
||||
alias each each_port
|
||||
|
||||
def reverse_each_port
|
||||
mail_files(@cur).reverse_each do |path|
|
||||
yield PORT_CLASS.new(path)
|
||||
end
|
||||
end
|
||||
|
||||
alias reverse_each reverse_each_port
|
||||
|
||||
def new_port
|
||||
fname = nil
|
||||
tmpfname = nil
|
||||
newfname = nil
|
||||
|
||||
begin
|
||||
fname = "#{Time.now.to_i}.#{$$}_#{Maildir.unique_number}.#{Socket.gethostname}"
|
||||
|
||||
tmpfname = "#{@tmp}/#{fname}"
|
||||
newfname = "#{@new}/#{fname}"
|
||||
end while FileTest.exist? tmpfname
|
||||
|
||||
if block_given?
|
||||
File.open(tmpfname, 'w') {|f| yield f }
|
||||
File.rename tmpfname, newfname
|
||||
PORT_CLASS.new(newfname)
|
||||
else
|
||||
File.open(tmpfname, 'w') {|f| f.write "\n\n" }
|
||||
PORT_CLASS.new(tmpfname)
|
||||
end
|
||||
end
|
||||
|
||||
def each_new_port
|
||||
mail_files(@new).each do |path|
|
||||
dest = @cur + '/' + File.basename(path)
|
||||
File.rename path, dest
|
||||
yield PORT_CLASS.new(dest)
|
||||
end
|
||||
|
||||
check_tmp
|
||||
end
|
||||
|
||||
TOO_OLD = 60 * 60 * 36 # 36 hour
|
||||
|
||||
def check_tmp
|
||||
old = Time.now.to_i - TOO_OLD
|
||||
|
||||
each_filename(@tmp) do |full, fname|
|
||||
if FileTest.file? full and
|
||||
File.stat(full).mtime.to_i < old
|
||||
File.unlink full
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def mail_files( dir )
|
||||
Dir.entries(dir)\
|
||||
.select {|s| s[0] != ?. }\
|
||||
.sort_by {|s| s.slice(/\A\d+/).to_i }\
|
||||
.map {|s| "#{dir}/#{s}" }\
|
||||
.select {|path| FileTest.file? path }
|
||||
end
|
||||
|
||||
def each_filename( dir )
|
||||
Dir.foreach(dir) do |fname|
|
||||
path = "#{dir}/#{fname}"
|
||||
if fname[0] != ?. and FileTest.file? path
|
||||
yield path, fname
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end # Maildir
|
||||
|
||||
MaildirLoader = Maildir
|
||||
|
||||
end # module TMail
|
||||
1
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/mbox.rb
vendored
Normal file
1
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/mbox.rb
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
require 'tmail/mailbox'
|
||||
280
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/net.rb
vendored
Normal file
280
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/net.rb
vendored
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
#
|
||||
# net.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
require 'nkf'
|
||||
|
||||
|
||||
module TMail
|
||||
|
||||
class Mail
|
||||
|
||||
def send_to( smtp )
|
||||
do_send_to(smtp) do
|
||||
ready_to_send
|
||||
end
|
||||
end
|
||||
|
||||
def send_text_to( smtp )
|
||||
do_send_to(smtp) do
|
||||
ready_to_send
|
||||
mime_encode
|
||||
end
|
||||
end
|
||||
|
||||
def do_send_to( smtp )
|
||||
from = from_address or raise ArgumentError, 'no from address'
|
||||
(dests = destinations).empty? and raise ArgumentError, 'no receipient'
|
||||
yield
|
||||
send_to_0 smtp, from, dests
|
||||
end
|
||||
private :do_send_to
|
||||
|
||||
def send_to_0( smtp, from, to )
|
||||
smtp.ready(from, to) do |f|
|
||||
encoded "\r\n", 'j', f, ''
|
||||
end
|
||||
end
|
||||
|
||||
def ready_to_send
|
||||
delete_no_send_fields
|
||||
add_message_id
|
||||
add_date
|
||||
end
|
||||
|
||||
NOSEND_FIELDS = %w(
|
||||
received
|
||||
bcc
|
||||
)
|
||||
|
||||
def delete_no_send_fields
|
||||
NOSEND_FIELDS.each do |nm|
|
||||
delete nm
|
||||
end
|
||||
delete_if {|n,v| v.empty? }
|
||||
end
|
||||
|
||||
def add_message_id( fqdn = nil )
|
||||
self.message_id = ::TMail::new_message_id(fqdn)
|
||||
end
|
||||
|
||||
def add_date
|
||||
self.date = Time.now
|
||||
end
|
||||
|
||||
def mime_encode
|
||||
if parts.empty?
|
||||
mime_encode_singlepart
|
||||
else
|
||||
mime_encode_multipart true
|
||||
end
|
||||
end
|
||||
|
||||
def mime_encode_singlepart
|
||||
self.mime_version = '1.0'
|
||||
b = body
|
||||
if NKF.guess(b) != NKF::BINARY
|
||||
mime_encode_text b
|
||||
else
|
||||
mime_encode_binary b
|
||||
end
|
||||
end
|
||||
|
||||
def mime_encode_text( body )
|
||||
self.body = NKF.nkf('-j -m0', body)
|
||||
self.set_content_type 'text', 'plain', {'charset' => 'iso-2022-jp'}
|
||||
self.encoding = '7bit'
|
||||
end
|
||||
|
||||
def mime_encode_binary( body )
|
||||
self.body = [body].pack('m')
|
||||
self.set_content_type 'application', 'octet-stream'
|
||||
self.encoding = 'Base64'
|
||||
end
|
||||
|
||||
def mime_encode_multipart( top = true )
|
||||
self.mime_version = '1.0' if top
|
||||
self.set_content_type 'multipart', 'mixed'
|
||||
e = encoding(nil)
|
||||
if e and not /\A(?:7bit|8bit|binary)\z/i === e
|
||||
raise ArgumentError,
|
||||
'using C.T.Encoding with multipart mail is not permitted'
|
||||
end
|
||||
end
|
||||
|
||||
def create_empty_mail
|
||||
self.class.new(StringPort.new(''), @config)
|
||||
end
|
||||
|
||||
def create_reply
|
||||
setup_reply create_empty_mail()
|
||||
end
|
||||
|
||||
def setup_reply( m )
|
||||
if tmp = reply_addresses(nil)
|
||||
m.to_addrs = tmp
|
||||
end
|
||||
|
||||
mid = message_id(nil)
|
||||
tmp = references(nil) || []
|
||||
tmp.push mid if mid
|
||||
m.in_reply_to = [mid] if mid
|
||||
m.references = tmp unless tmp.empty?
|
||||
m.subject = 'Re: ' + subject('').sub(/\A(?:\s*re:)+/i, '')
|
||||
|
||||
m
|
||||
end
|
||||
|
||||
def create_forward
|
||||
setup_forward create_empty_mail()
|
||||
end
|
||||
|
||||
def setup_forward( mail )
|
||||
m = Mail.new(StringPort.new(''))
|
||||
m.body = decoded
|
||||
m.set_content_type 'message', 'rfc822'
|
||||
m.encoding = encoding('7bit')
|
||||
mail.parts.push m
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class DeleteFields
|
||||
|
||||
NOSEND_FIELDS = %w(
|
||||
received
|
||||
bcc
|
||||
)
|
||||
|
||||
def initialize( nosend = nil, delempty = true )
|
||||
@no_send_fields = nosend || NOSEND_FIELDS.dup
|
||||
@delete_empty_fields = delempty
|
||||
end
|
||||
|
||||
attr :no_send_fields
|
||||
attr :delete_empty_fields, true
|
||||
|
||||
def exec( mail )
|
||||
@no_send_fields.each do |nm|
|
||||
delete nm
|
||||
end
|
||||
delete_if {|n,v| v.empty? } if @delete_empty_fields
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class AddMessageId
|
||||
|
||||
def initialize( fqdn = nil )
|
||||
@fqdn = fqdn
|
||||
end
|
||||
|
||||
attr :fqdn, true
|
||||
|
||||
def exec( mail )
|
||||
mail.message_id = ::TMail::new_msgid(@fqdn)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class AddDate
|
||||
|
||||
def exec( mail )
|
||||
mail.date = Time.now
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class MimeEncodeAuto
|
||||
|
||||
def initialize( s = nil, m = nil )
|
||||
@singlepart_composer = s || MimeEncodeSingle.new
|
||||
@multipart_composer = m || MimeEncodeMulti.new
|
||||
end
|
||||
|
||||
attr :singlepart_composer
|
||||
attr :multipart_composer
|
||||
|
||||
def exec( mail )
|
||||
if mail._builtin_multipart?
|
||||
then @multipart_composer
|
||||
else @singlepart_composer end.exec mail
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class MimeEncodeSingle
|
||||
|
||||
def exec( mail )
|
||||
mail.mime_version = '1.0'
|
||||
b = mail.body
|
||||
if NKF.guess(b) != NKF::BINARY
|
||||
on_text b
|
||||
else
|
||||
on_binary b
|
||||
end
|
||||
end
|
||||
|
||||
def on_text( body )
|
||||
mail.body = NKF.nkf('-j -m0', body)
|
||||
mail.set_content_type 'text', 'plain', {'charset' => 'iso-2022-jp'}
|
||||
mail.encoding = '7bit'
|
||||
end
|
||||
|
||||
def on_binary( body )
|
||||
mail.body = [body].pack('m')
|
||||
mail.set_content_type 'application', 'octet-stream'
|
||||
mail.encoding = 'Base64'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class MimeEncodeMulti
|
||||
|
||||
def exec( mail, top = true )
|
||||
mail.mime_version = '1.0' if top
|
||||
mail.set_content_type 'multipart', 'mixed'
|
||||
e = encoding(nil)
|
||||
if e and not /\A(?:7bit|8bit|binary)\z/i === e
|
||||
raise ArgumentError,
|
||||
'using C.T.Encoding with multipart mail is not permitted'
|
||||
end
|
||||
mail.parts.each do |m|
|
||||
exec m, false if m._builtin_multipart?
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end # module TMail
|
||||
135
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/obsolete.rb
vendored
Normal file
135
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/obsolete.rb
vendored
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
#
|
||||
# obsolete.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
module TMail
|
||||
|
||||
# mail.rb
|
||||
class Mail
|
||||
alias include? key?
|
||||
alias has_key? key?
|
||||
|
||||
def values
|
||||
ret = []
|
||||
each_field {|v| ret.push v }
|
||||
ret
|
||||
end
|
||||
|
||||
def value?( val )
|
||||
HeaderField === val or return false
|
||||
|
||||
[ @header[val.name.downcase] ].flatten.include? val
|
||||
end
|
||||
|
||||
alias has_value? value?
|
||||
end
|
||||
|
||||
|
||||
# facade.rb
|
||||
class Mail
|
||||
def from_addr( default = nil )
|
||||
addr, = from_addrs(nil)
|
||||
addr || default
|
||||
end
|
||||
|
||||
def from_address( default = nil )
|
||||
if a = from_addr(nil)
|
||||
a.spec
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
alias from_address= from_addrs=
|
||||
|
||||
def from_phrase( default = nil )
|
||||
if a = from_addr(nil)
|
||||
a.phrase
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
alias msgid message_id
|
||||
alias msgid= message_id=
|
||||
|
||||
alias each_dest each_destination
|
||||
end
|
||||
|
||||
|
||||
# address.rb
|
||||
class Address
|
||||
alias route routes
|
||||
alias addr spec
|
||||
|
||||
def spec=( str )
|
||||
@local, @domain = str.split(/@/,2).map {|s| s.split(/\./) }
|
||||
end
|
||||
|
||||
alias addr= spec=
|
||||
alias address= spec=
|
||||
end
|
||||
|
||||
|
||||
# mbox.rb
|
||||
class MhMailbox
|
||||
alias new_mail new_port
|
||||
alias each_mail each_port
|
||||
alias each_newmail each_new_port
|
||||
end
|
||||
class UNIXMbox
|
||||
alias new_mail new_port
|
||||
alias each_mail each_port
|
||||
alias each_newmail each_new_port
|
||||
end
|
||||
class Maildir
|
||||
alias new_mail new_port
|
||||
alias each_mail each_port
|
||||
alias each_newmail each_new_port
|
||||
end
|
||||
|
||||
|
||||
# utils.rb
|
||||
extend TextUtils
|
||||
|
||||
class << self
|
||||
alias msgid? message_id?
|
||||
alias boundary new_boundary
|
||||
alias msgid new_message_id
|
||||
alias new_msgid new_message_id
|
||||
end
|
||||
|
||||
def Mail.boundary
|
||||
::TMail.new_boundary
|
||||
end
|
||||
|
||||
def Mail.msgid
|
||||
::TMail.new_message_id
|
||||
end
|
||||
|
||||
end # module TMail
|
||||
1522
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/parser.rb
vendored
Normal file
1522
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/parser.rb
vendored
Normal file
File diff suppressed because it is too large
Load diff
377
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/port.rb
vendored
Normal file
377
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/port.rb
vendored
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
#
|
||||
# port.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
require 'tmail/stringio'
|
||||
|
||||
|
||||
module TMail
|
||||
|
||||
class Port
|
||||
def reproducible?
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
### FilePort
|
||||
###
|
||||
|
||||
class FilePort < Port
|
||||
|
||||
def initialize( fname )
|
||||
@filename = File.expand_path(fname)
|
||||
super()
|
||||
end
|
||||
|
||||
attr_reader :filename
|
||||
|
||||
alias ident filename
|
||||
|
||||
def ==( other )
|
||||
other.respond_to?(:filename) and @filename == other.filename
|
||||
end
|
||||
|
||||
alias eql? ==
|
||||
|
||||
def hash
|
||||
@filename.hash
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{self.class}:#{@filename}>"
|
||||
end
|
||||
|
||||
def reproducible?
|
||||
true
|
||||
end
|
||||
|
||||
def size
|
||||
File.size @filename
|
||||
end
|
||||
|
||||
|
||||
def ropen( &block )
|
||||
File.open(@filename, &block)
|
||||
end
|
||||
|
||||
def wopen( &block )
|
||||
File.open(@filename, 'w', &block)
|
||||
end
|
||||
|
||||
def aopen( &block )
|
||||
File.open(@filename, 'a', &block)
|
||||
end
|
||||
|
||||
|
||||
def read_all
|
||||
ropen {|f|
|
||||
return f.read
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def remove
|
||||
File.unlink @filename
|
||||
end
|
||||
|
||||
def move_to( port )
|
||||
begin
|
||||
File.link @filename, port.filename
|
||||
rescue Errno::EXDEV
|
||||
copy_to port
|
||||
end
|
||||
File.unlink @filename
|
||||
end
|
||||
|
||||
alias mv move_to
|
||||
|
||||
def copy_to( port )
|
||||
if FilePort === port
|
||||
copy_file @filename, port.filename
|
||||
else
|
||||
File.open(@filename) {|r|
|
||||
port.wopen {|w|
|
||||
while s = r.sysread(4096)
|
||||
w.write << s
|
||||
end
|
||||
} }
|
||||
end
|
||||
end
|
||||
|
||||
alias cp copy_to
|
||||
|
||||
private
|
||||
|
||||
# from fileutils.rb
|
||||
def copy_file( src, dest )
|
||||
st = r = w = nil
|
||||
|
||||
File.open(src, 'rb') {|r|
|
||||
File.open(dest, 'wb') {|w|
|
||||
st = r.stat
|
||||
begin
|
||||
while true
|
||||
w.write r.sysread(st.blksize)
|
||||
end
|
||||
rescue EOFError
|
||||
end
|
||||
} }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
module MailFlags
|
||||
|
||||
def seen=( b )
|
||||
set_status 'S', b
|
||||
end
|
||||
|
||||
def seen?
|
||||
get_status 'S'
|
||||
end
|
||||
|
||||
def replied=( b )
|
||||
set_status 'R', b
|
||||
end
|
||||
|
||||
def replied?
|
||||
get_status 'R'
|
||||
end
|
||||
|
||||
def flagged=( b )
|
||||
set_status 'F', b
|
||||
end
|
||||
|
||||
def flagged?
|
||||
get_status 'F'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def procinfostr( str, tag, true_p )
|
||||
a = str.upcase.split(//)
|
||||
a.push true_p ? tag : nil
|
||||
a.delete tag unless true_p
|
||||
a.compact.sort.join('').squeeze
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class MhPort < FilePort
|
||||
|
||||
include MailFlags
|
||||
|
||||
private
|
||||
|
||||
def set_status( tag, flag )
|
||||
begin
|
||||
tmpfile = @filename + '.tmailtmp.' + $$.to_s
|
||||
File.open(tmpfile, 'w') {|f|
|
||||
write_status f, tag, flag
|
||||
}
|
||||
File.unlink @filename
|
||||
File.link tmpfile, @filename
|
||||
ensure
|
||||
File.unlink tmpfile
|
||||
end
|
||||
end
|
||||
|
||||
def write_status( f, tag, flag )
|
||||
stat = ''
|
||||
File.open(@filename) {|r|
|
||||
while line = r.gets
|
||||
if line.strip.empty?
|
||||
break
|
||||
elsif m = /\AX-TMail-Status:/i.match(line)
|
||||
stat = m.post_match.strip
|
||||
else
|
||||
f.print line
|
||||
end
|
||||
end
|
||||
|
||||
s = procinfostr(stat, tag, flag)
|
||||
f.puts 'X-TMail-Status: ' + s unless s.empty?
|
||||
f.puts
|
||||
|
||||
while s = r.read(2048)
|
||||
f.write s
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def get_status( tag )
|
||||
File.foreach(@filename) {|line|
|
||||
return false if line.strip.empty?
|
||||
if m = /\AX-TMail-Status:/i.match(line)
|
||||
return m.post_match.strip.include?(tag[0])
|
||||
end
|
||||
}
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class MaildirPort < FilePort
|
||||
|
||||
def move_to_new
|
||||
new = replace_dir(@filename, 'new')
|
||||
File.rename @filename, new
|
||||
@filename = new
|
||||
end
|
||||
|
||||
def move_to_cur
|
||||
new = replace_dir(@filename, 'cur')
|
||||
File.rename @filename, new
|
||||
@filename = new
|
||||
end
|
||||
|
||||
def replace_dir( path, dir )
|
||||
"#{File.dirname File.dirname(path)}/#{dir}/#{File.basename path}"
|
||||
end
|
||||
private :replace_dir
|
||||
|
||||
|
||||
include MailFlags
|
||||
|
||||
private
|
||||
|
||||
MAIL_FILE = /\A(\d+\.[\d_]+\.[^:]+)(?:\:(\d),(\w+)?)?\z/
|
||||
|
||||
def set_status( tag, flag )
|
||||
if m = MAIL_FILE.match(File.basename(@filename))
|
||||
s, uniq, type, info, = m.to_a
|
||||
return if type and type != '2' # do not change anything
|
||||
newname = File.dirname(@filename) + '/' +
|
||||
uniq + ':2,' + procinfostr(info.to_s, tag, flag)
|
||||
else
|
||||
newname = @filename + ':2,' + tag
|
||||
end
|
||||
|
||||
File.link @filename, newname
|
||||
File.unlink @filename
|
||||
@filename = newname
|
||||
end
|
||||
|
||||
def get_status( tag )
|
||||
m = MAIL_FILE.match(File.basename(@filename)) or return false
|
||||
m[2] == '2' and m[3].to_s.include?(tag[0])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
### StringPort
|
||||
###
|
||||
|
||||
class StringPort < Port
|
||||
|
||||
def initialize( str = '' )
|
||||
@buffer = str
|
||||
super()
|
||||
end
|
||||
|
||||
def string
|
||||
@buffer
|
||||
end
|
||||
|
||||
def to_s
|
||||
@buffer.dup
|
||||
end
|
||||
|
||||
alias read_all to_s
|
||||
|
||||
def size
|
||||
@buffer.size
|
||||
end
|
||||
|
||||
def ==( other )
|
||||
StringPort === other and @buffer.equal? other.string
|
||||
end
|
||||
|
||||
alias eql? ==
|
||||
|
||||
def hash
|
||||
@buffer.object_id.hash
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{self.class}:id=#{sprintf '0x%x', @buffer.object_id}>"
|
||||
end
|
||||
|
||||
def reproducible?
|
||||
true
|
||||
end
|
||||
|
||||
def ropen( &block )
|
||||
@buffer or raise Errno::ENOENT, "#{inspect} is already removed"
|
||||
StringInput.open(@buffer, &block)
|
||||
end
|
||||
|
||||
def wopen( &block )
|
||||
@buffer = ''
|
||||
StringOutput.new(@buffer, &block)
|
||||
end
|
||||
|
||||
def aopen( &block )
|
||||
@buffer ||= ''
|
||||
StringOutput.new(@buffer, &block)
|
||||
end
|
||||
|
||||
def remove
|
||||
@buffer = nil
|
||||
end
|
||||
|
||||
alias rm remove
|
||||
|
||||
def copy_to( port )
|
||||
port.wopen {|f|
|
||||
f.write @buffer
|
||||
}
|
||||
end
|
||||
|
||||
alias cp copy_to
|
||||
|
||||
def move_to( port )
|
||||
if StringPort === port
|
||||
str = @buffer
|
||||
port.instance_eval { @buffer = str }
|
||||
else
|
||||
copy_to port
|
||||
end
|
||||
remove
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end # module TMail
|
||||
125
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/quoting.rb
vendored
Normal file
125
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/quoting.rb
vendored
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
module TMail
|
||||
class Mail
|
||||
def subject(to_charset = 'utf-8')
|
||||
Unquoter.unquote_and_convert_to(quoted_subject, to_charset)
|
||||
end
|
||||
|
||||
def unquoted_body(to_charset = 'utf-8')
|
||||
from_charset = sub_header("content-type", "charset")
|
||||
case (content_transfer_encoding || "7bit").downcase
|
||||
when "quoted-printable"
|
||||
Unquoter.unquote_quoted_printable_and_convert_to(quoted_body,
|
||||
to_charset, from_charset, true)
|
||||
when "base64"
|
||||
Unquoter.unquote_base64_and_convert_to(quoted_body, to_charset,
|
||||
from_charset)
|
||||
when "7bit", "8bit"
|
||||
Unquoter.convert_to(quoted_body, to_charset, from_charset)
|
||||
when "binary"
|
||||
quoted_body
|
||||
else
|
||||
quoted_body
|
||||
end
|
||||
end
|
||||
|
||||
def body(to_charset = 'utf-8', &block)
|
||||
attachment_presenter = block || Proc.new { |file_name| "Attachment: #{file_name}\n" }
|
||||
|
||||
if multipart?
|
||||
parts.collect { |part|
|
||||
header = part["content-type"]
|
||||
|
||||
if part.multipart?
|
||||
part.body(to_charset, &attachment_presenter)
|
||||
elsif header.nil?
|
||||
""
|
||||
elsif header.main_type == "text"
|
||||
part.unquoted_body(to_charset)
|
||||
else
|
||||
attachment_presenter.call(header["name"] || "(unnamed)")
|
||||
end
|
||||
}.join
|
||||
else
|
||||
unquoted_body(to_charset)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Unquoter
|
||||
class << self
|
||||
def unquote_and_convert_to(text, to_charset, from_charset = "iso-8859-1", preserve_underscores=false)
|
||||
return "" if text.nil?
|
||||
if text =~ /^=\?(.*?)\?(.)\?(.*)\?=$/
|
||||
from_charset = $1
|
||||
quoting_method = $2
|
||||
text = $3
|
||||
case quoting_method.upcase
|
||||
when "Q" then
|
||||
unquote_quoted_printable_and_convert_to(text, to_charset, from_charset, preserve_underscores)
|
||||
when "B" then
|
||||
unquote_base64_and_convert_to(text, to_charset, from_charset)
|
||||
else
|
||||
raise "unknown quoting method #{quoting_method.inspect}"
|
||||
end
|
||||
else
|
||||
convert_to(text, to_charset, from_charset)
|
||||
end
|
||||
end
|
||||
|
||||
def unquote_quoted_printable_and_convert_to(text, to, from, preserve_underscores=false)
|
||||
text = text.gsub(/_/, " ") unless preserve_underscores
|
||||
convert_to(text.unpack("M*").first, to, from)
|
||||
end
|
||||
|
||||
def unquote_base64_and_convert_to(text, to, from)
|
||||
convert_to(Base64.decode(text).first, to, from)
|
||||
end
|
||||
|
||||
begin
|
||||
require 'iconv'
|
||||
def convert_to(text, to, from)
|
||||
return text unless to && from
|
||||
text ? Iconv.iconv(to, from, text).first : ""
|
||||
rescue Iconv::IllegalSequence, Errno::EINVAL
|
||||
# the 'from' parameter specifies a charset other than what the text
|
||||
# actually is...not much we can do in this case but just return the
|
||||
# unconverted text.
|
||||
#
|
||||
# Ditto if either parameter represents an unknown charset, like
|
||||
# X-UNKNOWN.
|
||||
text
|
||||
end
|
||||
rescue LoadError
|
||||
# Not providing quoting support
|
||||
def convert_to(text, to, from)
|
||||
warn "Action Mailer: iconv not loaded; ignoring conversion from #{from} to #{to} (#{__FILE__}:#{__LINE__})"
|
||||
text
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if __FILE__ == $0
|
||||
require 'test/unit'
|
||||
|
||||
class TC_Unquoter < Test::Unit::TestCase
|
||||
def test_unquote_quoted_printable
|
||||
a ="=?ISO-8859-1?Q?[166417]_Bekr=E6ftelse_fra_Rejsefeber?="
|
||||
b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8')
|
||||
assert_equal "[166417] Bekr\303\246ftelse fra Rejsefeber", b
|
||||
end
|
||||
|
||||
def test_unquote_base64
|
||||
a ="=?ISO-8859-1?B?WzE2NjQxN10gQmVrcuZmdGVsc2UgZnJhIFJlanNlZmViZXI=?="
|
||||
b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8')
|
||||
assert_equal "[166417] Bekr\303\246ftelse fra Rejsefeber", b
|
||||
end
|
||||
|
||||
def test_unquote_without_charset
|
||||
a ="[166417]_Bekr=E6ftelse_fra_Rejsefeber"
|
||||
b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8')
|
||||
assert_equal "[166417]_Bekr=E6ftelse_fra_Rejsefeber", b
|
||||
end
|
||||
end
|
||||
end
|
||||
41
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/scanner.rb
vendored
Normal file
41
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/scanner.rb
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#
|
||||
# scanner.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
require 'tmail/utils'
|
||||
|
||||
module TMail
|
||||
require 'tmail/scanner_r.rb'
|
||||
begin
|
||||
raise LoadError, 'Turn off Ruby extention by user choice' if ENV['NORUBYEXT']
|
||||
require 'tmail/scanner_c.so'
|
||||
Scanner = Scanner_C
|
||||
rescue LoadError
|
||||
Scanner = Scanner_R
|
||||
end
|
||||
end
|
||||
263
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/scanner_r.rb
vendored
Normal file
263
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/scanner_r.rb
vendored
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
#
|
||||
# scanner_r.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
require 'tmail/config'
|
||||
|
||||
|
||||
module TMail
|
||||
|
||||
class Scanner_R
|
||||
|
||||
Version = '0.10.7'
|
||||
Version.freeze
|
||||
|
||||
MIME_HEADERS = {
|
||||
:CTYPE => true,
|
||||
:CENCODING => true,
|
||||
:CDISPOSITION => true
|
||||
}
|
||||
|
||||
alnum = 'a-zA-Z0-9'
|
||||
atomsyms = %q[ _#!$%&`'*+-{|}~^@/=? ].strip
|
||||
tokensyms = %q[ _#!$%&`'*+-{|}~^@. ].strip
|
||||
|
||||
atomchars = alnum + Regexp.quote(atomsyms)
|
||||
tokenchars = alnum + Regexp.quote(tokensyms)
|
||||
iso2022str = '\e(?!\(B)..(?:[^\e]+|\e(?!\(B)..)*\e\(B'
|
||||
|
||||
eucstr = '(?:[\xa1-\xfe][\xa1-\xfe])+'
|
||||
sjisstr = '(?:[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc])+'
|
||||
utf8str = '(?:[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf][\x80-\xbf])+'
|
||||
|
||||
quoted_with_iso2022 = /\A(?:[^\\\e"]+|#{iso2022str})+/n
|
||||
domlit_with_iso2022 = /\A(?:[^\\\e\]]+|#{iso2022str})+/n
|
||||
comment_with_iso2022 = /\A(?:[^\\\e()]+|#{iso2022str})+/n
|
||||
|
||||
quoted_without_iso2022 = /\A[^\\"]+/n
|
||||
domlit_without_iso2022 = /\A[^\\\]]+/n
|
||||
comment_without_iso2022 = /\A[^\\()]+/n
|
||||
|
||||
PATTERN_TABLE = {}
|
||||
PATTERN_TABLE['EUC'] =
|
||||
[
|
||||
/\A(?:[#{atomchars}]+|#{iso2022str}|#{eucstr})+/n,
|
||||
/\A(?:[#{tokenchars}]+|#{iso2022str}|#{eucstr})+/n,
|
||||
quoted_with_iso2022,
|
||||
domlit_with_iso2022,
|
||||
comment_with_iso2022
|
||||
]
|
||||
PATTERN_TABLE['SJIS'] =
|
||||
[
|
||||
/\A(?:[#{atomchars}]+|#{iso2022str}|#{sjisstr})+/n,
|
||||
/\A(?:[#{tokenchars}]+|#{iso2022str}|#{sjisstr})+/n,
|
||||
quoted_with_iso2022,
|
||||
domlit_with_iso2022,
|
||||
comment_with_iso2022
|
||||
]
|
||||
PATTERN_TABLE['UTF8'] =
|
||||
[
|
||||
/\A(?:[#{atomchars}]+|#{utf8str})+/n,
|
||||
/\A(?:[#{tokenchars}]+|#{utf8str})+/n,
|
||||
quoted_without_iso2022,
|
||||
domlit_without_iso2022,
|
||||
comment_without_iso2022
|
||||
]
|
||||
PATTERN_TABLE['NONE'] =
|
||||
[
|
||||
/\A[#{atomchars}]+/n,
|
||||
/\A[#{tokenchars}]+/n,
|
||||
quoted_without_iso2022,
|
||||
domlit_without_iso2022,
|
||||
comment_without_iso2022
|
||||
]
|
||||
|
||||
|
||||
def initialize( str, scantype, comments )
|
||||
init_scanner str
|
||||
@comments = comments || []
|
||||
@debug = false
|
||||
|
||||
# fix scanner mode
|
||||
@received = (scantype == :RECEIVED)
|
||||
@is_mime_header = MIME_HEADERS[scantype]
|
||||
|
||||
atom, token, @quoted_re, @domlit_re, @comment_re = PATTERN_TABLE[$KCODE]
|
||||
@word_re = (MIME_HEADERS[scantype] ? token : atom)
|
||||
end
|
||||
|
||||
attr_accessor :debug
|
||||
|
||||
def scan( &block )
|
||||
if @debug
|
||||
scan_main do |arr|
|
||||
s, v = arr
|
||||
printf "%7d %-10s %s\n",
|
||||
rest_size(),
|
||||
s.respond_to?(:id2name) ? s.id2name : s.inspect,
|
||||
v.inspect
|
||||
yield arr
|
||||
end
|
||||
else
|
||||
scan_main(&block)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
RECV_TOKEN = {
|
||||
'from' => :FROM,
|
||||
'by' => :BY,
|
||||
'via' => :VIA,
|
||||
'with' => :WITH,
|
||||
'id' => :ID,
|
||||
'for' => :FOR
|
||||
}
|
||||
|
||||
def scan_main
|
||||
until eof?
|
||||
if skip(/\A[\n\r\t ]+/n) # LWSP
|
||||
break if eof?
|
||||
end
|
||||
|
||||
if s = readstr(@word_re)
|
||||
if @is_mime_header
|
||||
yield :TOKEN, s
|
||||
else
|
||||
# atom
|
||||
if /\A\d+\z/ === s
|
||||
yield :DIGIT, s
|
||||
elsif @received
|
||||
yield RECV_TOKEN[s.downcase] || :ATOM, s
|
||||
else
|
||||
yield :ATOM, s
|
||||
end
|
||||
end
|
||||
|
||||
elsif skip(/\A"/)
|
||||
yield :QUOTED, scan_quoted_word()
|
||||
|
||||
elsif skip(/\A\[/)
|
||||
yield :DOMLIT, scan_domain_literal()
|
||||
|
||||
elsif skip(/\A\(/)
|
||||
@comments.push scan_comment()
|
||||
|
||||
else
|
||||
c = readchar()
|
||||
yield c, c
|
||||
end
|
||||
end
|
||||
|
||||
yield false, '$'
|
||||
end
|
||||
|
||||
def scan_quoted_word
|
||||
scan_qstr(@quoted_re, /\A"/, 'quoted-word')
|
||||
end
|
||||
|
||||
def scan_domain_literal
|
||||
'[' + scan_qstr(@domlit_re, /\A\]/, 'domain-literal') + ']'
|
||||
end
|
||||
|
||||
def scan_qstr( pattern, terminal, type )
|
||||
result = ''
|
||||
until eof?
|
||||
if s = readstr(pattern) then result << s
|
||||
elsif skip(terminal) then return result
|
||||
elsif skip(/\A\\/) then result << readchar()
|
||||
else
|
||||
raise "TMail FATAL: not match in #{type}"
|
||||
end
|
||||
end
|
||||
scan_error! "found unterminated #{type}"
|
||||
end
|
||||
|
||||
def scan_comment
|
||||
result = ''
|
||||
nest = 1
|
||||
content = @comment_re
|
||||
|
||||
until eof?
|
||||
if s = readstr(content) then result << s
|
||||
elsif skip(/\A\)/) then nest -= 1
|
||||
return result if nest == 0
|
||||
result << ')'
|
||||
elsif skip(/\A\(/) then nest += 1
|
||||
result << '('
|
||||
elsif skip(/\A\\/) then result << readchar()
|
||||
else
|
||||
raise 'TMail FATAL: not match in comment'
|
||||
end
|
||||
end
|
||||
scan_error! 'found unterminated comment'
|
||||
end
|
||||
|
||||
# string scanner
|
||||
|
||||
def init_scanner( str )
|
||||
@src = str
|
||||
end
|
||||
|
||||
def eof?
|
||||
@src.empty?
|
||||
end
|
||||
|
||||
def rest_size
|
||||
@src.size
|
||||
end
|
||||
|
||||
def readstr( re )
|
||||
if m = re.match(@src)
|
||||
@src = m.post_match
|
||||
m[0]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def readchar
|
||||
readstr(/\A./)
|
||||
end
|
||||
|
||||
def skip( re )
|
||||
if m = re.match(@src)
|
||||
@src = m.post_match
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def scan_error!( msg )
|
||||
raise SyntaxError, msg
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end # module TMail
|
||||
277
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/stringio.rb
vendored
Normal file
277
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/stringio.rb
vendored
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
#
|
||||
# stringio.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
class StringInput#:nodoc:
|
||||
|
||||
include Enumerable
|
||||
|
||||
class << self
|
||||
|
||||
def new( str )
|
||||
if block_given?
|
||||
begin
|
||||
f = super
|
||||
yield f
|
||||
ensure
|
||||
f.close if f
|
||||
end
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
alias open new
|
||||
|
||||
end
|
||||
|
||||
def initialize( str )
|
||||
@src = str
|
||||
@pos = 0
|
||||
@closed = false
|
||||
@lineno = 0
|
||||
end
|
||||
|
||||
attr_reader :lineno
|
||||
|
||||
def string
|
||||
@src
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{self.class}:#{@closed ? 'closed' : 'open'},src=#{@src[0,30].inspect}>"
|
||||
end
|
||||
|
||||
def close
|
||||
stream_check!
|
||||
@pos = nil
|
||||
@closed = true
|
||||
end
|
||||
|
||||
def closed?
|
||||
@closed
|
||||
end
|
||||
|
||||
def pos
|
||||
stream_check!
|
||||
[@pos, @src.size].min
|
||||
end
|
||||
|
||||
alias tell pos
|
||||
|
||||
def seek( offset, whence = IO::SEEK_SET )
|
||||
stream_check!
|
||||
case whence
|
||||
when IO::SEEK_SET
|
||||
@pos = offset
|
||||
when IO::SEEK_CUR
|
||||
@pos += offset
|
||||
when IO::SEEK_END
|
||||
@pos = @src.size - offset
|
||||
else
|
||||
raise ArgumentError, "unknown seek flag: #{whence}"
|
||||
end
|
||||
@pos = 0 if @pos < 0
|
||||
@pos = [@pos, @src.size + 1].min
|
||||
offset
|
||||
end
|
||||
|
||||
def rewind
|
||||
stream_check!
|
||||
@pos = 0
|
||||
end
|
||||
|
||||
def eof?
|
||||
stream_check!
|
||||
@pos > @src.size
|
||||
end
|
||||
|
||||
def each( &block )
|
||||
stream_check!
|
||||
begin
|
||||
@src.each(&block)
|
||||
ensure
|
||||
@pos = 0
|
||||
end
|
||||
end
|
||||
|
||||
def gets
|
||||
stream_check!
|
||||
if idx = @src.index(?\n, @pos)
|
||||
idx += 1 # "\n".size
|
||||
line = @src[ @pos ... idx ]
|
||||
@pos = idx
|
||||
@pos += 1 if @pos == @src.size
|
||||
else
|
||||
line = @src[ @pos .. -1 ]
|
||||
@pos = @src.size + 1
|
||||
end
|
||||
@lineno += 1
|
||||
|
||||
line
|
||||
end
|
||||
|
||||
def getc
|
||||
stream_check!
|
||||
ch = @src[@pos]
|
||||
@pos += 1
|
||||
@pos += 1 if @pos == @src.size
|
||||
ch
|
||||
end
|
||||
|
||||
def read( len = nil )
|
||||
stream_check!
|
||||
return read_all unless len
|
||||
str = @src[@pos, len]
|
||||
@pos += len
|
||||
@pos += 1 if @pos == @src.size
|
||||
str
|
||||
end
|
||||
|
||||
alias sysread read
|
||||
|
||||
def read_all
|
||||
stream_check!
|
||||
return nil if eof?
|
||||
rest = @src[@pos ... @src.size]
|
||||
@pos = @src.size + 1
|
||||
rest
|
||||
end
|
||||
|
||||
def stream_check!
|
||||
@closed and raise IOError, 'closed stream'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class StringOutput#:nodoc:
|
||||
|
||||
class << self
|
||||
|
||||
def new( str = '' )
|
||||
if block_given?
|
||||
begin
|
||||
f = super
|
||||
yield f
|
||||
ensure
|
||||
f.close if f
|
||||
end
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
alias open new
|
||||
|
||||
end
|
||||
|
||||
def initialize( str = '' )
|
||||
@dest = str
|
||||
@closed = false
|
||||
end
|
||||
|
||||
def close
|
||||
@closed = true
|
||||
end
|
||||
|
||||
def closed?
|
||||
@closed
|
||||
end
|
||||
|
||||
def string
|
||||
@dest
|
||||
end
|
||||
|
||||
alias value string
|
||||
alias to_str string
|
||||
|
||||
def size
|
||||
@dest.size
|
||||
end
|
||||
|
||||
alias pos size
|
||||
|
||||
def inspect
|
||||
"#<#{self.class}:#{@dest ? 'open' : 'closed'},#{id}>"
|
||||
end
|
||||
|
||||
def print( *args )
|
||||
stream_check!
|
||||
raise ArgumentError, 'wrong # of argument (0 for >1)' if args.empty?
|
||||
args.each do |s|
|
||||
raise ArgumentError, 'nil not allowed' if s.nil?
|
||||
@dest << s.to_s
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def puts( *args )
|
||||
stream_check!
|
||||
args.each do |str|
|
||||
@dest << (s = str.to_s)
|
||||
@dest << "\n" unless s[-1] == ?\n
|
||||
end
|
||||
@dest << "\n" if args.empty?
|
||||
nil
|
||||
end
|
||||
|
||||
def putc( ch )
|
||||
stream_check!
|
||||
@dest << ch.chr
|
||||
nil
|
||||
end
|
||||
|
||||
def printf( *args )
|
||||
stream_check!
|
||||
@dest << sprintf(*args)
|
||||
nil
|
||||
end
|
||||
|
||||
def write( str )
|
||||
stream_check!
|
||||
s = str.to_s
|
||||
@dest << s
|
||||
s.size
|
||||
end
|
||||
|
||||
alias syswrite write
|
||||
|
||||
def <<( str )
|
||||
stream_check!
|
||||
@dest << str.to_s
|
||||
self
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def stream_check!
|
||||
@closed and raise IOError, 'closed stream'
|
||||
end
|
||||
|
||||
end
|
||||
1
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/tmail.rb
vendored
Normal file
1
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/tmail.rb
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
require 'tmail'
|
||||
238
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/utils.rb
vendored
Normal file
238
tracks/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/utils.rb
vendored
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
#
|
||||
# utils.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
||||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
module TMail
|
||||
|
||||
class SyntaxError < StandardError; end
|
||||
|
||||
|
||||
def TMail.new_boundary
|
||||
'mimepart_' + random_tag
|
||||
end
|
||||
|
||||
def TMail.new_message_id( fqdn = nil )
|
||||
fqdn ||= ::Socket.gethostname
|
||||
"<#{random_tag()}@#{fqdn}.tmail>"
|
||||
end
|
||||
|
||||
def TMail.random_tag
|
||||
@uniq += 1
|
||||
t = Time.now
|
||||
sprintf('%x%x_%x%x%d%x',
|
||||
t.to_i, t.tv_usec,
|
||||
$$, Thread.current.object_id, @uniq, rand(255))
|
||||
end
|
||||
private_class_method :random_tag
|
||||
|
||||
@uniq = 0
|
||||
|
||||
|
||||
module TextUtils
|
||||
|
||||
aspecial = '()<>[]:;.\\,"'
|
||||
tspecial = '()<>[];:\\,"/?='
|
||||
lwsp = " \t\r\n"
|
||||
control = '\x00-\x1f\x7f-\xff'
|
||||
|
||||
ATOM_UNSAFE = /[#{Regexp.quote aspecial}#{control}#{lwsp}]/n
|
||||
PHRASE_UNSAFE = /[#{Regexp.quote aspecial}#{control}]/n
|
||||
TOKEN_UNSAFE = /[#{Regexp.quote tspecial}#{control}#{lwsp}]/n
|
||||
CONTROL_CHAR = /[#{control}]/n
|
||||
|
||||
def atom_safe?( str )
|
||||
not ATOM_UNSAFE === str
|
||||
end
|
||||
|
||||
def quote_atom( str )
|
||||
(ATOM_UNSAFE === str) ? dquote(str) : str
|
||||
end
|
||||
|
||||
def quote_phrase( str )
|
||||
(PHRASE_UNSAFE === str) ? dquote(str) : str
|
||||
end
|
||||
|
||||
def token_safe?( str )
|
||||
not TOKEN_UNSAFE === str
|
||||
end
|
||||
|
||||
def quote_token( str )
|
||||
(TOKEN_UNSAFE === str) ? dquote(str) : str
|
||||
end
|
||||
|
||||
def dquote( str )
|
||||
'"' + str.gsub(/["\\]/n) {|s| '\\' + s } + '"'
|
||||
end
|
||||
private :dquote
|
||||
|
||||
|
||||
def join_domain( arr )
|
||||
arr.map {|i|
|
||||
if /\A\[.*\]\z/ === i
|
||||
i
|
||||
else
|
||||
quote_atom(i)
|
||||
end
|
||||
}.join('.')
|
||||
end
|
||||
|
||||
|
||||
ZONESTR_TABLE = {
|
||||
'jst' => 9 * 60,
|
||||
'eet' => 2 * 60,
|
||||
'bst' => 1 * 60,
|
||||
'met' => 1 * 60,
|
||||
'gmt' => 0,
|
||||
'utc' => 0,
|
||||
'ut' => 0,
|
||||
'nst' => -(3 * 60 + 30),
|
||||
'ast' => -4 * 60,
|
||||
'edt' => -4 * 60,
|
||||
'est' => -5 * 60,
|
||||
'cdt' => -5 * 60,
|
||||
'cst' => -6 * 60,
|
||||
'mdt' => -6 * 60,
|
||||
'mst' => -7 * 60,
|
||||
'pdt' => -7 * 60,
|
||||
'pst' => -8 * 60,
|
||||
'a' => -1 * 60,
|
||||
'b' => -2 * 60,
|
||||
'c' => -3 * 60,
|
||||
'd' => -4 * 60,
|
||||
'e' => -5 * 60,
|
||||
'f' => -6 * 60,
|
||||
'g' => -7 * 60,
|
||||
'h' => -8 * 60,
|
||||
'i' => -9 * 60,
|
||||
# j not use
|
||||
'k' => -10 * 60,
|
||||
'l' => -11 * 60,
|
||||
'm' => -12 * 60,
|
||||
'n' => 1 * 60,
|
||||
'o' => 2 * 60,
|
||||
'p' => 3 * 60,
|
||||
'q' => 4 * 60,
|
||||
'r' => 5 * 60,
|
||||
's' => 6 * 60,
|
||||
't' => 7 * 60,
|
||||
'u' => 8 * 60,
|
||||
'v' => 9 * 60,
|
||||
'w' => 10 * 60,
|
||||
'x' => 11 * 60,
|
||||
'y' => 12 * 60,
|
||||
'z' => 0 * 60
|
||||
}
|
||||
|
||||
def timezone_string_to_unixtime( str )
|
||||
if m = /([\+\-])(\d\d?)(\d\d)/.match(str)
|
||||
sec = (m[2].to_i * 60 + m[3].to_i) * 60
|
||||
m[1] == '-' ? -sec : sec
|
||||
else
|
||||
min = ZONESTR_TABLE[str.downcase] or
|
||||
raise SyntaxError, "wrong timezone format '#{str}'"
|
||||
min * 60
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
WDAY = %w( Sun Mon Tue Wed Thu Fri Sat TMailBUG )
|
||||
MONTH = %w( TMailBUG Jan Feb Mar Apr May Jun
|
||||
Jul Aug Sep Oct Nov Dec TMailBUG )
|
||||
|
||||
def time2str( tm )
|
||||
# [ruby-list:7928]
|
||||
gmt = Time.at(tm.to_i)
|
||||
gmt.gmtime
|
||||
offset = tm.to_i - Time.local(*gmt.to_a[0,6].reverse).to_i
|
||||
|
||||
# DO NOT USE strftime: setlocale() breaks it
|
||||
sprintf '%s, %s %s %d %02d:%02d:%02d %+.2d%.2d',
|
||||
WDAY[tm.wday], tm.mday, MONTH[tm.month],
|
||||
tm.year, tm.hour, tm.min, tm.sec,
|
||||
*(offset / 60).divmod(60)
|
||||
end
|
||||
|
||||
|
||||
MESSAGE_ID = /<[^\@>]+\@[^>\@]+>/
|
||||
|
||||
def message_id?( str )
|
||||
MESSAGE_ID === str
|
||||
end
|
||||
|
||||
|
||||
MIME_ENCODED = /=\?[^\s?=]+\?[QB]\?[^\s?=]+\?=/i
|
||||
|
||||
def mime_encoded?( str )
|
||||
MIME_ENCODED === str
|
||||
end
|
||||
|
||||
|
||||
def decode_params( hash )
|
||||
new = Hash.new
|
||||
encoded = nil
|
||||
hash.each do |key, value|
|
||||
if m = /\*(?:(\d+)\*)?\z/.match(key)
|
||||
((encoded ||= {})[m.pre_match] ||= [])[(m[1] || 0).to_i] = value
|
||||
else
|
||||
new[key] = to_kcode(value)
|
||||
end
|
||||
end
|
||||
if encoded
|
||||
encoded.each do |key, strings|
|
||||
new[key] = decode_RFC2231(strings.join(''))
|
||||
end
|
||||
end
|
||||
|
||||
new
|
||||
end
|
||||
|
||||
NKF_FLAGS = {
|
||||
'EUC' => '-e -m',
|
||||
'SJIS' => '-s -m'
|
||||
}
|
||||
|
||||
def to_kcode( str )
|
||||
flag = NKF_FLAGS[$KCODE] or return str
|
||||
NKF.nkf(flag, str)
|
||||
end
|
||||
|
||||
RFC2231_ENCODED = /\A(?:iso-2022-jp|euc-jp|shift_jis|us-ascii)?'[a-z]*'/in
|
||||
|
||||
def decode_RFC2231( str )
|
||||
m = RFC2231_ENCODED.match(str) or return str
|
||||
begin
|
||||
NKF.nkf(NKF_FLAGS[$KCODE],
|
||||
m.post_match.gsub(/%[\da-f]{2}/in) {|s| s[1,2].hex.chr })
|
||||
rescue
|
||||
m.post_match.gsub(/%[\da-f]{2}/in, "")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
9
tracks/vendor/rails/actionmailer/lib/action_mailer/version.rb
vendored
Normal file
9
tracks/vendor/rails/actionmailer/lib/action_mailer/version.rb
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
module ActionMailer
|
||||
module VERSION #:nodoc:
|
||||
MAJOR = 1
|
||||
MINOR = 1
|
||||
TINY = 5
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||
end
|
||||
end
|
||||
198
tracks/vendor/rails/actionmailer/rakefile
vendored
Normal file
198
tracks/vendor/rails/actionmailer/rakefile
vendored
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
require 'rubygems'
|
||||
require 'rake'
|
||||
require 'rake/testtask'
|
||||
require 'rake/rdoctask'
|
||||
require 'rake/packagetask'
|
||||
require 'rake/gempackagetask'
|
||||
require 'rake/contrib/rubyforgepublisher'
|
||||
require File.join(File.dirname(__FILE__), 'lib', 'action_mailer', 'version')
|
||||
|
||||
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
|
||||
PKG_NAME = 'actionmailer'
|
||||
PKG_VERSION = ActionMailer::VERSION::STRING + PKG_BUILD
|
||||
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
||||
|
||||
RELEASE_NAME = "REL #{PKG_VERSION}"
|
||||
|
||||
RUBY_FORGE_PROJECT = "actionmailer"
|
||||
RUBY_FORGE_USER = "webster132"
|
||||
|
||||
desc "Default Task"
|
||||
task :default => [ :test ]
|
||||
|
||||
# Run the unit tests
|
||||
Rake::TestTask.new { |t|
|
||||
t.libs << "test"
|
||||
t.pattern = 'test/*_test.rb'
|
||||
t.verbose = true
|
||||
}
|
||||
|
||||
|
||||
# Genereate the RDoc documentation
|
||||
Rake::RDocTask.new { |rdoc|
|
||||
rdoc.rdoc_dir = 'doc'
|
||||
rdoc.title = "Action Mailer -- Easy email delivery and testing"
|
||||
rdoc.options << '--line-numbers --inline-source --main README --accessor adv_attr_accessor=M'
|
||||
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
||||
rdoc.rdoc_files.include('README', 'CHANGELOG')
|
||||
rdoc.rdoc_files.include('lib/action_mailer.rb')
|
||||
rdoc.rdoc_files.include('lib/action_mailer/*.rb')
|
||||
}
|
||||
|
||||
|
||||
# Create compressed packages
|
||||
spec = Gem::Specification.new do |s|
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.name = PKG_NAME
|
||||
s.summary = "Service layer for easy email delivery and testing."
|
||||
s.description = %q{Makes it trivial to test and deliver emails sent from a single service layer.}
|
||||
s.version = PKG_VERSION
|
||||
|
||||
s.author = "David Heinemeier Hansson"
|
||||
s.email = "david@loudthinking.com"
|
||||
s.rubyforge_project = "actionmailer"
|
||||
s.homepage = "http://www.rubyonrails.org"
|
||||
|
||||
s.add_dependency('actionpack', '= 1.11.2' + PKG_BUILD)
|
||||
|
||||
s.has_rdoc = true
|
||||
s.requirements << 'none'
|
||||
s.require_path = 'lib'
|
||||
s.autorequire = 'action_mailer'
|
||||
|
||||
s.files = [ "rakefile", "install.rb", "README", "CHANGELOG", "MIT-LICENSE" ]
|
||||
s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
||||
s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
||||
end
|
||||
|
||||
Rake::GemPackageTask.new(spec) do |p|
|
||||
p.gem_spec = spec
|
||||
p.need_tar = true
|
||||
p.need_zip = true
|
||||
end
|
||||
|
||||
|
||||
desc "Publish the API documentation"
|
||||
task :pgem => [:package] do
|
||||
Rake::SshFilePublisher.new("davidhh@wrath.rubyonrails.org", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
|
||||
end
|
||||
|
||||
desc "Publish the API documentation"
|
||||
task :pdoc => [:rdoc] do
|
||||
Rake::SshDirPublisher.new("davidhh@wrath.rubyonrails.org", "public_html/am", "doc").upload
|
||||
end
|
||||
|
||||
desc "Publish the release files to RubyForge."
|
||||
task :release => [:package] do
|
||||
files = ["gem", "tgz", "zip"].map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
|
||||
|
||||
if RUBY_FORGE_PROJECT then
|
||||
require 'net/http'
|
||||
require 'open-uri'
|
||||
|
||||
project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
|
||||
project_data = open(project_uri) { |data| data.read }
|
||||
group_id = project_data[/[?&]group_id=(\d+)/, 1]
|
||||
raise "Couldn't get group id" unless group_id
|
||||
|
||||
# This echos password to shell which is a bit sucky
|
||||
if ENV["RUBY_FORGE_PASSWORD"]
|
||||
password = ENV["RUBY_FORGE_PASSWORD"]
|
||||
else
|
||||
print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
|
||||
password = STDIN.gets.chomp
|
||||
end
|
||||
|
||||
login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
|
||||
data = [
|
||||
"login=1",
|
||||
"form_loginname=#{RUBY_FORGE_USER}",
|
||||
"form_pw=#{password}"
|
||||
].join("&")
|
||||
http.post("/account/login.php", data)
|
||||
end
|
||||
|
||||
cookie = login_response["set-cookie"]
|
||||
raise "Login failed" unless cookie
|
||||
headers = { "Cookie" => cookie }
|
||||
|
||||
release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
|
||||
release_data = open(release_uri, headers) { |data| data.read }
|
||||
package_id = release_data[/[?&]package_id=(\d+)/, 1]
|
||||
raise "Couldn't get package id" unless package_id
|
||||
|
||||
first_file = true
|
||||
release_id = ""
|
||||
|
||||
files.each do |filename|
|
||||
basename = File.basename(filename)
|
||||
file_ext = File.extname(filename)
|
||||
file_data = File.open(filename, "rb") { |file| file.read }
|
||||
|
||||
puts "Releasing #{basename}..."
|
||||
|
||||
release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
|
||||
release_date = Time.now.strftime("%Y-%m-%d %H:%M")
|
||||
type_map = {
|
||||
".zip" => "3000",
|
||||
".tgz" => "3110",
|
||||
".gz" => "3110",
|
||||
".gem" => "1400"
|
||||
}; type_map.default = "9999"
|
||||
type = type_map[file_ext]
|
||||
boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
|
||||
|
||||
query_hash = if first_file then
|
||||
{
|
||||
"group_id" => group_id,
|
||||
"package_id" => package_id,
|
||||
"release_name" => RELEASE_NAME,
|
||||
"release_date" => release_date,
|
||||
"type_id" => type,
|
||||
"processor_id" => "8000", # Any
|
||||
"release_notes" => "",
|
||||
"release_changes" => "",
|
||||
"preformatted" => "1",
|
||||
"submit" => "1"
|
||||
}
|
||||
else
|
||||
{
|
||||
"group_id" => group_id,
|
||||
"release_id" => release_id,
|
||||
"package_id" => package_id,
|
||||
"step2" => "1",
|
||||
"type_id" => type,
|
||||
"processor_id" => "8000", # Any
|
||||
"submit" => "Add This File"
|
||||
}
|
||||
end
|
||||
|
||||
query = "?" + query_hash.map do |(name, value)|
|
||||
[name, URI.encode(value)].join("=")
|
||||
end.join("&")
|
||||
|
||||
data = [
|
||||
"--" + boundary,
|
||||
"Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
|
||||
"Content-Type: application/octet-stream",
|
||||
"Content-Transfer-Encoding: binary",
|
||||
"", file_data, ""
|
||||
].join("\x0D\x0A")
|
||||
|
||||
release_headers = headers.merge(
|
||||
"Content-Type" => "multipart/form-data; boundary=#{boundary}"
|
||||
)
|
||||
|
||||
target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
|
||||
http.post(target + query, data, release_headers)
|
||||
end
|
||||
|
||||
if first_file then
|
||||
release_id = release_response.body[/release_id=(\d+)/, 1]
|
||||
raise("Couldn't get release id") unless release_id
|
||||
end
|
||||
|
||||
first_file = false
|
||||
end
|
||||
end
|
||||
end
|
||||
1
tracks/vendor/rails/actionmailer/test/fixtures/helper_mailer/use_helper.rhtml
vendored
Normal file
1
tracks/vendor/rails/actionmailer/test/fixtures/helper_mailer/use_helper.rhtml
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
Hello, <%= person_name %>. Thanks for registering!
|
||||
1
tracks/vendor/rails/actionmailer/test/fixtures/helper_mailer/use_helper_method.rhtml
vendored
Normal file
1
tracks/vendor/rails/actionmailer/test/fixtures/helper_mailer/use_helper_method.rhtml
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
This message brought to you by <%= name_of_the_mailer_class %>.
|
||||
5
tracks/vendor/rails/actionmailer/test/fixtures/helper_mailer/use_mail_helper.rhtml
vendored
Normal file
5
tracks/vendor/rails/actionmailer/test/fixtures/helper_mailer/use_mail_helper.rhtml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
From "Romeo and Juliet":
|
||||
|
||||
<%= block_format @text %>
|
||||
|
||||
Good ol' Shakespeare.
|
||||
1
tracks/vendor/rails/actionmailer/test/fixtures/helper_mailer/use_test_helper.rhtml
vendored
Normal file
1
tracks/vendor/rails/actionmailer/test/fixtures/helper_mailer/use_test_helper.rhtml
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
So, <%= test_format(@text) %>
|
||||
5
tracks/vendor/rails/actionmailer/test/fixtures/helpers/test_helper.rb
vendored
Normal file
5
tracks/vendor/rails/actionmailer/test/fixtures/helpers/test_helper.rb
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
module TestHelper
|
||||
def test_format(text)
|
||||
"<em><strong><small>#{text}</small></strong></em>"
|
||||
end
|
||||
end
|
||||
14
tracks/vendor/rails/actionmailer/test/fixtures/raw_email
vendored
Normal file
14
tracks/vendor/rails/actionmailer/test/fixtures/raw_email
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
From jamis_buck@byu.edu Mon May 2 16:07:05 2005
|
||||
Mime-Version: 1.0 (Apple Message framework v622)
|
||||
Content-Transfer-Encoding: base64
|
||||
Message-Id: <d3b8cf8e49f04480850c28713a1f473e@37signals.com>
|
||||
Content-Type: text/plain;
|
||||
charset=EUC-KR;
|
||||
format=flowed
|
||||
To: willard15georgina@jamis.backpackit.com
|
||||
From: Jamis Buck <jamis@37signals.com>
|
||||
Subject: =?EUC-KR?Q?NOTE:_=C7=D1=B1=B9=B8=BB=B7=CE_=C7=CF=B4=C2_=B0=CD?=
|
||||
Date: Mon, 2 May 2005 16:07:05 -0600
|
||||
|
||||
tOu6zrrQwMcguLbC+bChwfa3ziwgv+y4rrTCIMfPs6q01MC7ILnPvcC0z7TZLg0KDQrBpiDAzLin
|
||||
wLogSmFtaXPA1LTPtNku
|
||||
20
tracks/vendor/rails/actionmailer/test/fixtures/raw_email10
vendored
Normal file
20
tracks/vendor/rails/actionmailer/test/fixtures/raw_email10
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
Return-Path: <xxx@xxxx.xxx>
|
||||
Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id C1B953B4CB6 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:05 -0500
|
||||
Received: from SMS-GTYxxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id ca for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:04 -0500
|
||||
Received: from xxx.xxxx.xxx by SMS-GTYxxx.xxxx.xxx with ESMTP id j4AKR3r23323 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:03 -0500
|
||||
Date: Tue, 10 May 2005 15:27:03 -0500
|
||||
From: xxx@xxxx.xxx
|
||||
Sender: xxx@xxxx.xxx
|
||||
To: xxxxxxxxxxx@xxxx.xxxx.xxx
|
||||
Message-Id: <xxx@xxxx.xxx>
|
||||
X-Original-To: xxxxxxxxxxx@xxxx.xxxx.xxx
|
||||
Delivered-To: xxx@xxxx.xxx
|
||||
Importance: normal
|
||||
Content-Type: text/plain; charset=X-UNKNOWN
|
||||
|
||||
Test test. Hi. Waving. m
|
||||
|
||||
----------------------------------------------------------------
|
||||
Sent via Bell Mobility's Text Messaging service.
|
||||
Envoyé par le service de messagerie texte de Bell Mobilité.
|
||||
----------------------------------------------------------------
|
||||
34
tracks/vendor/rails/actionmailer/test/fixtures/raw_email11
vendored
Normal file
34
tracks/vendor/rails/actionmailer/test/fixtures/raw_email11
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
From xxx@xxxx.com Wed Apr 27 14:15:31 2005
|
||||
Mime-Version: 1.0 (Apple Message framework v619.2)
|
||||
To: xxxxx@xxxxx <matmail>
|
||||
Message-Id: <416eaebec6d333ec6939eaf8a7d80724@xxxxx>
|
||||
Content-Type: multipart/alternative;
|
||||
boundary=Apple-Mail-5-1037861608
|
||||
From: xxxxx@xxxxx <xxxxx@xxxxx>
|
||||
Subject: worse when you use them.
|
||||
Date: Wed, 27 Apr 2005 14:15:31 -0700
|
||||
|
||||
|
||||
|
||||
|
||||
--Apple-Mail-5-1037861608
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Type: text/plain;
|
||||
charset=US-ASCII;
|
||||
format=flowed
|
||||
|
||||
|
||||
XXXXX Xxxxx
|
||||
|
||||
--Apple-Mail-5-1037861608
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Type: text/enriched;
|
||||
charset=US-ASCII
|
||||
|
||||
|
||||
|
||||
<bold>XXXXX Xxxxx</bold>
|
||||
|
||||
|
||||
--Apple-Mail-5-1037861608--
|
||||
|
||||
32
tracks/vendor/rails/actionmailer/test/fixtures/raw_email12
vendored
Normal file
32
tracks/vendor/rails/actionmailer/test/fixtures/raw_email12
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
Mime-Version: 1.0 (Apple Message framework v730)
|
||||
Content-Type: multipart/mixed; boundary=Apple-Mail-13-196941151
|
||||
Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
|
||||
From: foo@example.com
|
||||
Subject: testing
|
||||
Date: Mon, 6 Jun 2005 22:21:22 +0200
|
||||
To: blah@example.com
|
||||
|
||||
|
||||
--Apple-Mail-13-196941151
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Type: text/plain;
|
||||
charset=ISO-8859-1;
|
||||
delsp=yes;
|
||||
format=flowed
|
||||
|
||||
This is the first part.
|
||||
|
||||
--Apple-Mail-13-196941151
|
||||
Content-Type: image/jpeg
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Location: Photo25.jpg
|
||||
Content-ID: <qbFGyPQAS8>
|
||||
Content-Disposition: inline
|
||||
|
||||
jamisSqGSIb3DQEHAqCAMIjamisxCzAJBgUrDgMCGgUAMIAGCSqGSjamisEHAQAAoIIFSjCCBUYw
|
||||
ggQujamisQICBD++ukQwDQYJKojamisNAQEFBQAwMTELMAkGA1UEBhMCRjamisAKBgNVBAoTA1RE
|
||||
QzEUMBIGjamisxMLVERDIE9DRVMgQ0jamisNMDQwMjI5MTE1OTAxWhcNMDYwMjamisIyOTAxWjCB
|
||||
gDELMAkGA1UEjamisEsxKTAnBgNVBAoTIEjamisuIG9yZ2FuaXNhdG9yaXNrIHRpbjamisRuaW5=
|
||||
|
||||
--Apple-Mail-13-196941151--
|
||||
|
||||
114
tracks/vendor/rails/actionmailer/test/fixtures/raw_email2
vendored
Normal file
114
tracks/vendor/rails/actionmailer/test/fixtures/raw_email2
vendored
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
From xxxxxxxxx.xxxxxxx@gmail.com Sun May 8 19:07:09 2005
|
||||
Return-Path: <xxxxxxxxx.xxxxxxx@gmail.com>
|
||||
X-Original-To: xxxxx@xxxxx.xxxxxxxxx.com
|
||||
Delivered-To: xxxxx@xxxxx.xxxxxxxxx.com
|
||||
Received: from localhost (localhost [127.0.0.1])
|
||||
by xxxxx.xxxxxxxxx.com (Postfix) with ESMTP id 06C9DA98D
|
||||
for <xxxxx@xxxxx.xxxxxxxxx.com>; Sun, 8 May 2005 19:09:13 +0000 (GMT)
|
||||
Received: from xxxxx.xxxxxxxxx.com ([127.0.0.1])
|
||||
by localhost (xxxxx.xxxxxxxxx.com [127.0.0.1]) (amavisd-new, port 10024)
|
||||
with LMTP id 88783-08 for <xxxxx@xxxxx.xxxxxxxxx.com>;
|
||||
Sun, 8 May 2005 19:09:12 +0000 (GMT)
|
||||
Received: from xxxxxxx.xxxxxxxxx.com (xxxxxxx.xxxxxxxxx.com [69.36.39.150])
|
||||
by xxxxx.xxxxxxxxx.com (Postfix) with ESMTP id 10D8BA960
|
||||
for <xxxxx@xxxxxxxxx.org>; Sun, 8 May 2005 19:09:12 +0000 (GMT)
|
||||
Received: from zproxy.gmail.com (zproxy.gmail.com [64.233.162.199])
|
||||
by xxxxxxx.xxxxxxxxx.com (Postfix) with ESMTP id 9EBC4148EAB
|
||||
for <xxxxx@xxxxxxxxx.com>; Sun, 8 May 2005 14:09:11 -0500 (CDT)
|
||||
Received: by zproxy.gmail.com with SMTP id 13so1233405nzp
|
||||
for <xxxxx@xxxxxxxxx.com>; Sun, 08 May 2005 12:09:11 -0700 (PDT)
|
||||
DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;
|
||||
s=beta; d=gmail.com;
|
||||
h=received:message-id:date:from:reply-to:to:subject:in-reply-to:mime-version:content-type:references;
|
||||
b=cid1mzGEFa3gtRa06oSrrEYfKca2CTKu9sLMkWxjbvCsWMtp9RGEILjUz0L5RySdH5iO661LyNUoHRFQIa57bylAbXM3g2DTEIIKmuASDG3x3rIQ4sHAKpNxP7Pul+mgTaOKBv+spcH7af++QEJ36gHFXD2O/kx9RePs3JNf/K8=
|
||||
Received: by 10.36.10.16 with SMTP id 16mr1012493nzj;
|
||||
Sun, 08 May 2005 12:09:11 -0700 (PDT)
|
||||
Received: by 10.36.5.10 with HTTP; Sun, 8 May 2005 12:09:11 -0700 (PDT)
|
||||
Message-ID: <e85734b90505081209eaaa17b@mail.gmail.com>
|
||||
Date: Sun, 8 May 2005 14:09:11 -0500
|
||||
From: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
|
||||
Reply-To: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
|
||||
To: xxxxx xxxx <xxxxx@xxxxxxxxx.com>
|
||||
Subject: Fwd: Signed email causes file attachments
|
||||
In-Reply-To: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="----=_Part_5028_7368284.1115579351471"
|
||||
References: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
|
||||
|
||||
------=_Part_5028_7368284.1115579351471
|
||||
Content-Type: text/plain; charset=ISO-8859-1
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Disposition: inline
|
||||
|
||||
We should not include these files or vcards as attachments.
|
||||
|
||||
---------- Forwarded message ----------
|
||||
From: xxxxx xxxxxx <xxxxxxxx@xxx.com>
|
||||
Date: May 8, 2005 1:17 PM
|
||||
Subject: Signed email causes file attachments
|
||||
To: xxxxxxx@xxxxxxxxxx.com
|
||||
|
||||
|
||||
Hi,
|
||||
|
||||
Just started to use my xxxxxxxx account (to set-up a GTD system,
|
||||
natch) and noticed that when I send content via email the signature/
|
||||
certificate from my email account gets added as a file (e.g.
|
||||
"smime.p7s").
|
||||
|
||||
Obviously I can uncheck the signature option in the Mail compose
|
||||
window but how often will I remember to do that?
|
||||
|
||||
Is there any way these kind of files could be ignored, e.g. via some
|
||||
sort of exclusions list?
|
||||
|
||||
------=_Part_5028_7368284.1115579351471
|
||||
Content-Type: application/pkcs7-signature; name=smime.p7s
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: attachment; filename="smime.p7s"
|
||||
|
||||
MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIGFDCCAs0w
|
||||
ggI2oAMCAQICAw5c+TANBgkqhkiG9w0BAQQFADBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
|
||||
d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVt
|
||||
YWlsIElzc3VpbmcgQ0EwHhcNMDUwMzI5MDkzOTEwWhcNMDYwMzI5MDkzOTEwWjBCMR8wHQYDVQQD
|
||||
ExZUaGF3dGUgRnJlZW1haWwgTWVtYmVyMR8wHQYJKoZIhvcNAQkBFhBzbWhhdW5jaEBtYWMuY29t
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn90dPsYS3LjfMY211OSYrDQLzwNYPlAL
|
||||
7+/0XA+kdy8/rRnyEHFGwhNCDmg0B6pxC7z3xxJD/8GfCd+IYUUNUQV5m9MkxfP9pTVXZVIYLaBw
|
||||
o8xS3A0a1LXealcmlEbJibmKkEaoXci3MhryLgpaa+Kk/sH02SNatDO1vS28bPsibZpcc6deFrla
|
||||
hSYnL+PW54mDTGHIcCN2fbx/Y6qspzqmtKaXrv75NBtuy9cB6KzU4j2xXbTkAwz3pRSghJJaAwdp
|
||||
+yIivAD3vr0kJE3p+Ez34HMh33EXEpFoWcN+MCEQZD9WnmFViMrvfvMXLGVFQfAAcC060eGFSRJ1
|
||||
ZQ9UVQIDAQABoy0wKzAbBgNVHREEFDASgRBzbWhhdW5jaEBtYWMuY29tMAwGA1UdEwEB/wQCMAAw
|
||||
DQYJKoZIhvcNAQEEBQADgYEAQMrg1n2pXVWteP7BBj+Pk3UfYtbuHb42uHcLJjfjnRlH7AxnSwrd
|
||||
L3HED205w3Cq8T7tzVxIjRRLO/ljq0GedSCFBky7eYo1PrXhztGHCTSBhsiWdiyLWxKlOxGAwJc/
|
||||
lMMnwqLOdrQcoF/YgbjeaUFOQbUh94w9VDNpWZYCZwcwggM/MIICqKADAgECAgENMA0GCSqGSIb3
|
||||
DQEBBQUAMIHRMQswCQYDVQQGEwJaQTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlD
|
||||
YXBlIFRvd24xGjAYBgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0
|
||||
aW9uIFNlcnZpY2VzIERpdmlzaW9uMSQwIgYDVQQDExtUaGF3dGUgUGVyc29uYWwgRnJlZW1haWwg
|
||||
Q0ExKzApBgkqhkiG9w0BCQEWHHBlcnNvbmFsLWZyZWVtYWlsQHRoYXd0ZS5jb20wHhcNMDMwNzE3
|
||||
MDAwMDAwWhcNMTMwNzE2MjM1OTU5WjBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENv
|
||||
bnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVtYWlsIElz
|
||||
c3VpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMSmPFVzVftOucqZWh5owHUEcJ3f
|
||||
6f+jHuy9zfVb8hp2vX8MOmHyv1HOAdTlUAow1wJjWiyJFXCO3cnwK4Vaqj9xVsuvPAsH5/EfkTYk
|
||||
KhPPK9Xzgnc9A74r/rsYPge/QIACZNenprufZdHFKlSFD0gEf6e20TxhBEAeZBlyYLf7AgMBAAGj
|
||||
gZQwgZEwEgYDVR0TAQH/BAgwBgEB/wIBADBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsLnRo
|
||||
YXd0ZS5jb20vVGhhd3RlUGVyc29uYWxGcmVlbWFpbENBLmNybDALBgNVHQ8EBAMCAQYwKQYDVR0R
|
||||
BCIwIKQeMBwxGjAYBgNVBAMTEVByaXZhdGVMYWJlbDItMTM4MA0GCSqGSIb3DQEBBQUAA4GBAEiM
|
||||
0VCD6gsuzA2jZqxnD3+vrL7CF6FDlpSdf0whuPg2H6otnzYvwPQcUCCTcDz9reFhYsPZOhl+hLGZ
|
||||
GwDFGguCdJ4lUJRix9sncVcljd2pnDmOjCBPZV+V2vf3h9bGCE6u9uo05RAaWzVNd+NWIXiC3CEZ
|
||||
Nd4ksdMdRv9dX2VPMYIC5zCCAuMCAQEwaTBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3Rl
|
||||
IENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVtYWls
|
||||
IElzc3VpbmcgQ0ECAw5c+TAJBgUrDgMCGgUAoIIBUzAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcB
|
||||
MBwGCSqGSIb3DQEJBTEPFw0wNTA1MDgxODE3NDZaMCMGCSqGSIb3DQEJBDEWBBQSkG9j6+hB0pKp
|
||||
fV9tCi/iP59sNTB4BgkrBgEEAYI3EAQxazBpMGIxCzAJBgNVBAYTAlpBMSUwIwYDVQQKExxUaGF3
|
||||
dGUgQ29uc3VsdGluZyAoUHR5KSBMdGQuMSwwKgYDVQQDEyNUaGF3dGUgUGVyc29uYWwgRnJlZW1h
|
||||
aWwgSXNzdWluZyBDQQIDDlz5MHoGCyqGSIb3DQEJEAILMWugaTBiMQswCQYDVQQGEwJaQTElMCMG
|
||||
A1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNv
|
||||
bmFsIEZyZWVtYWlsIElzc3VpbmcgQ0ECAw5c+TANBgkqhkiG9w0BAQEFAASCAQAm1GeF7dWfMvrW
|
||||
8yMPjkhE+R8D1DsiCoWSCp+5gAQm7lcK7V3KrZh5howfpI3TmCZUbbaMxOH+7aKRKpFemxoBY5Q8
|
||||
rnCkbpg/++/+MI01T69hF/rgMmrGcrv2fIYy8EaARLG0xUVFSZHSP+NQSYz0TTmh4cAESHMzY3JA
|
||||
nHOoUkuPyl8RXrimY1zn0lceMXlweZRouiPGuPNl1hQKw8P+GhOC5oLlM71UtStnrlk3P9gqX5v7
|
||||
Tj7Hx057oVfY8FMevjxGwU3EK5TczHezHbWWgTyum9l2ZQbUQsDJxSniD3BM46C1VcbDLPaotAZ0
|
||||
fTYLZizQfm5hcWEbfYVzkSzLAAAAAAAA
|
||||
------=_Part_5028_7368284.1115579351471--
|
||||
|
||||
70
tracks/vendor/rails/actionmailer/test/fixtures/raw_email3
vendored
Normal file
70
tracks/vendor/rails/actionmailer/test/fixtures/raw_email3
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
From xxxx@xxxx.com Tue May 10 11:28:07 2005
|
||||
Return-Path: <xxxx@xxxx.com>
|
||||
X-Original-To: xxxx@xxxx.com
|
||||
Delivered-To: xxxx@xxxx.com
|
||||
Received: from localhost (localhost [127.0.0.1])
|
||||
by xxx.xxxxx.com (Postfix) with ESMTP id 50FD3A96F
|
||||
for <xxxx@xxxx.com>; Tue, 10 May 2005 17:26:50 +0000 (GMT)
|
||||
Received: from xxx.xxxxx.com ([127.0.0.1])
|
||||
by localhost (xxx.xxxxx.com [127.0.0.1]) (amavisd-new, port 10024)
|
||||
with LMTP id 70060-03 for <xxxx@xxxx.com>;
|
||||
Tue, 10 May 2005 17:26:49 +0000 (GMT)
|
||||
Received: from xxx.xxxxx.com (xxx.xxxxx.com [69.36.39.150])
|
||||
by xxx.xxxxx.com (Postfix) with ESMTP id 8B957A94B
|
||||
for <xxxx@xxxx.com>; Tue, 10 May 2005 17:26:48 +0000 (GMT)
|
||||
Received: from xxx.xxxxx.com (xxx.xxxxx.com [64.233.184.203])
|
||||
by xxx.xxxxx.com (Postfix) with ESMTP id 9972514824C
|
||||
for <xxxx@xxxx.com>; Tue, 10 May 2005 12:26:40 -0500 (CDT)
|
||||
Received: by xxx.xxxxx.com with SMTP id 68so1694448wri
|
||||
for <xxxx@xxxx.com>; Tue, 10 May 2005 10:26:40 -0700 (PDT)
|
||||
DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;
|
||||
s=beta; d=xxxxx.com;
|
||||
h=received:message-id:date:from:reply-to:to:subject:mime-version:content-type;
|
||||
b=g8ZO5ttS6GPEMAz9WxrRk9+9IXBUfQIYsZLL6T88+ECbsXqGIgfGtzJJFn6o9CE3/HMrrIGkN5AisxVFTGXWxWci5YA/7PTVWwPOhJff5BRYQDVNgRKqMl/SMttNrrRElsGJjnD1UyQ/5kQmcBxq2PuZI5Zc47u6CILcuoBcM+A=
|
||||
Received: by 10.54.96.19 with SMTP id t19mr621017wrb;
|
||||
Tue, 10 May 2005 10:26:39 -0700 (PDT)
|
||||
Received: by 10.54.110.5 with HTTP; Tue, 10 May 2005 10:26:39 -0700 (PDT)
|
||||
Message-ID: <xxxx@xxxx.com>
|
||||
Date: Tue, 10 May 2005 11:26:39 -0600
|
||||
From: Test Tester <xxxx@xxxx.com>
|
||||
Reply-To: Test Tester <xxxx@xxxx.com>
|
||||
To: xxxx@xxxx.com, xxxx@xxxx.com
|
||||
Subject: Another PDF
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="----=_Part_2192_32400445.1115745999735"
|
||||
X-Virus-Scanned: amavisd-new at textdrive.com
|
||||
|
||||
------=_Part_2192_32400445.1115745999735
|
||||
Content-Type: text/plain; charset=ISO-8859-1
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Disposition: inline
|
||||
|
||||
Just attaching another PDF, here, to see what the message looks like,
|
||||
and to see if I can figure out what is going wrong here.
|
||||
|
||||
------=_Part_2192_32400445.1115745999735
|
||||
Content-Type: application/pdf; name="broken.pdf"
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: attachment; filename="broken.pdf"
|
||||
|
||||
JVBERi0xLjQNCiXk9tzfDQoxIDAgb2JqDQo8PCAvTGVuZ3RoIDIgMCBSDQogICAvRmlsdGVyIC9G
|
||||
bGF0ZURlY29kZQ0KPj4NCnN0cmVhbQ0KeJy9Wt2KJbkNvm/od6jrhZxYln9hWEh2p+8HBvICySaE
|
||||
ycLuTV4/1ifJ9qnq09NpSBimu76yLUuy/qzqcPz7+em3Ixx/CDc6CsXxs3b5+fvfjr/8cPz6/BRu
|
||||
rbfAx/n3739/fuJylJ5u5fjX81OuDr4deK4Bz3z/aDP+8fz0yw8g0Ofq7ktr1Mn+u28rvhy/jVeD
|
||||
QSa+9YNKHP/pxjvDNfVAx/m3MFz54FhvTbaseaxiDoN2LeMVMw+yA7RbHSCDzxZuaYB2E1Yay7QU
|
||||
x89vz0+tyFDKMlAHK5yqLmnjF+c4RjEiQIUeKwblXMe+AsZjN1J5yGQL5DHpDHksurM81rF6PKab
|
||||
gK6zAarIDzIiUY23rJsN9iorAE816aIu6lsgAdQFsuhhkHOUFgVjp2GjMqSewITXNQ27jrMeamkg
|
||||
1rPI3iLWG2CIaSBB+V1245YVRICGbbpYKHc2USFDl6M09acQVQYhlwIrkBNLISvXhGlF1wi5FHCw
|
||||
wxZkoGNJlVeJCEsqKA+3YAV5AMb6KkeaqEJQmFKKQU8T1pRi2ihE1Y4CDrqoYFFXYjJJOatsyzuI
|
||||
8SIlykuxKTMibWK8H1PgEvqYgs4GmQSrEjJAalgGirIhik+p4ZQN9E3ETFPAHE1b8pp1l/0Rc1gl
|
||||
fQs0ABWvyoZZzU8VnPXwVVcO9BEsyjEJaO6eBoZRyKGlrKoYoOygA8BGIzgwN3RQ15ouigG5idZQ
|
||||
fx2U4Db2CqiLO0WHAZoylGiCAqhniNQjFjQPSkmjwfNTgQ6M1Ih+eWo36wFmjIxDJZiGUBiWsAyR
|
||||
xX3EekGOizkGI96Ol9zVZTAivikURhRsHh2E3JhWMpSTZCnnonrLhMCodgrNcgo4uyJUJc6qnVss
|
||||
nrGd1Ptr0YwisCOYyIbUwVjV4xBUNLbguSO2YHujonAMJkMdSI7bIw91Akq2AUlMUWGFTMAOamjU
|
||||
OvZQCxIkY2pCpMFo/IwLdVLHs6nddwTRrgoVbvLU9eB0G4EMndV0TNoxHbt3JBWwK6hhv3iHfDtF
|
||||
yokB302IpEBTnWICde4uYc/1khDbSIkQopO6lcqamGBu1OSE3N5IPSsZX00CkSHRiiyx6HQIShsS
|
||||
HSVNswdVsaOUSAWq9aYhDtGDaoG5a3lBGkYt/lFlBFt1UqrYnzVtUpUQnLiZeouKgf1KhRBViRRk
|
||||
ExepJCzTwEmFDalIRbLEGtw0gfpESOpIAF/NnpPzcVCG86s0g2DuSyd41uhNGbEgaSrWEXORErbw
|
||||
------=_Part_2192_32400445.1115745999735--
|
||||
|
||||
59
tracks/vendor/rails/actionmailer/test/fixtures/raw_email4
vendored
Normal file
59
tracks/vendor/rails/actionmailer/test/fixtures/raw_email4
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
Return-Path: <xxx@xxxx.xxx>
|
||||
Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id 6AAEE3B4D23 for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:23 -0500
|
||||
Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id j48HUC213279 for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:13 -0500
|
||||
Received: from conversion-xxx.xxxx.xxx.net by xxx.xxxx.xxx id <0IG600901LQ64I@xxx.xxxx.xxx> for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:12 -0500
|
||||
Received: from agw1 by xxx.xxxx.xxx with ESMTP id <0IG600JFYLYCAxxx@xxxx.xxx> for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:12 -0500
|
||||
Date: Sun, 8 May 2005 12:30:08 -0500
|
||||
From: xxx@xxxx.xxx
|
||||
To: xxx@xxxx.xxx
|
||||
Message-Id: <7864245.1115573412626.JavaMxxx@xxxx.xxx>
|
||||
Subject: Filth
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary=mimepart_427e4cb4ca329_133ae40413c81ef
|
||||
X-Mms-Priority: 1
|
||||
X-Mms-Transaction-Id: 3198421808-0
|
||||
X-Mms-Message-Type: 0
|
||||
X-Mms-Sender-Visibility: 1
|
||||
X-Mms-Read-Reply: 1
|
||||
X-Original-To: xxx@xxxx.xxx
|
||||
X-Mms-Message-Class: 0
|
||||
X-Mms-Delivery-Report: 0
|
||||
X-Mms-Mms-Version: 16
|
||||
Delivered-To: xxx@xxxx.xxx
|
||||
X-Nokia-Ag-Version: 2.0
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
|
||||
--mimepart_427e4cb4ca329_133ae40413c81ef
|
||||
Content-Type: multipart/mixed; boundary=mimepart_427e4cb4cbd97_133ae40413c8217
|
||||
|
||||
|
||||
|
||||
--mimepart_427e4cb4cbd97_133ae40413c8217
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Disposition: inline
|
||||
Content-Location: text.txt
|
||||
|
||||
Some text
|
||||
|
||||
--mimepart_427e4cb4cbd97_133ae40413c8217--
|
||||
|
||||
--mimepart_427e4cb4ca329_133ae40413c81ef
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
|
||||
--
|
||||
This Orange Multi Media Message was sent wirefree from an Orange
|
||||
MMS phone. If you would like to reply, please text or phone the
|
||||
sender directly by using the phone number listed in the sender's
|
||||
address. To learn more about Orange's Multi Media Messaging
|
||||
Service, find us on the Web at xxx.xxxx.xxx.uk/mms
|
||||
|
||||
|
||||
--mimepart_427e4cb4ca329_133ae40413c81ef
|
||||
|
||||
|
||||
--mimepart_427e4cb4ca329_133ae40413c81ef-
|
||||
|
||||
19
tracks/vendor/rails/actionmailer/test/fixtures/raw_email5
vendored
Normal file
19
tracks/vendor/rails/actionmailer/test/fixtures/raw_email5
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
Return-Path: <xxx@xxxx.xxx>
|
||||
Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id C1B953B4CB6 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:05 -0500
|
||||
Received: from SMS-GTYxxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id ca for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:04 -0500
|
||||
Received: from xxx.xxxx.xxx by SMS-GTYxxx.xxxx.xxx with ESMTP id j4AKR3r23323 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:03 -0500
|
||||
Date: Tue, 10 May 2005 15:27:03 -0500
|
||||
From: xxx@xxxx.xxx
|
||||
Sender: xxx@xxxx.xxx
|
||||
To: xxxxxxxxxxx@xxxx.xxxx.xxx
|
||||
Message-Id: <xxx@xxxx.xxx>
|
||||
X-Original-To: xxxxxxxxxxx@xxxx.xxxx.xxx
|
||||
Delivered-To: xxx@xxxx.xxx
|
||||
Importance: normal
|
||||
|
||||
Test test. Hi. Waving. m
|
||||
|
||||
----------------------------------------------------------------
|
||||
Sent via Bell Mobility's Text Messaging service.
|
||||
Envoyé par le service de messagerie texte de Bell Mobilité.
|
||||
----------------------------------------------------------------
|
||||
20
tracks/vendor/rails/actionmailer/test/fixtures/raw_email6
vendored
Normal file
20
tracks/vendor/rails/actionmailer/test/fixtures/raw_email6
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
Return-Path: <xxx@xxxx.xxx>
|
||||
Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id C1B953B4CB6 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:05 -0500
|
||||
Received: from SMS-GTYxxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id ca for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:04 -0500
|
||||
Received: from xxx.xxxx.xxx by SMS-GTYxxx.xxxx.xxx with ESMTP id j4AKR3r23323 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:03 -0500
|
||||
Date: Tue, 10 May 2005 15:27:03 -0500
|
||||
From: xxx@xxxx.xxx
|
||||
Sender: xxx@xxxx.xxx
|
||||
To: xxxxxxxxxxx@xxxx.xxxx.xxx
|
||||
Message-Id: <xxx@xxxx.xxx>
|
||||
X-Original-To: xxxxxxxxxxx@xxxx.xxxx.xxx
|
||||
Delivered-To: xxx@xxxx.xxx
|
||||
Importance: normal
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
|
||||
Test test. Hi. Waving. m
|
||||
|
||||
----------------------------------------------------------------
|
||||
Sent via Bell Mobility's Text Messaging service.
|
||||
Envoyé par le service de messagerie texte de Bell Mobilité.
|
||||
----------------------------------------------------------------
|
||||
56
tracks/vendor/rails/actionmailer/test/fixtures/raw_email7
vendored
Normal file
56
tracks/vendor/rails/actionmailer/test/fixtures/raw_email7
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
Mime-Version: 1.0 (Apple Message framework v730)
|
||||
Content-Type: multipart/mixed; boundary=Apple-Mail-13-196941151
|
||||
Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
|
||||
From: foo@example.com
|
||||
Subject: testing
|
||||
Date: Mon, 6 Jun 2005 22:21:22 +0200
|
||||
To: blah@example.com
|
||||
|
||||
|
||||
--Apple-Mail-13-196941151
|
||||
Content-Type: multipart/mixed;
|
||||
boundary=Apple-Mail-12-196940926
|
||||
|
||||
|
||||
--Apple-Mail-12-196940926
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Type: text/plain;
|
||||
charset=ISO-8859-1;
|
||||
delsp=yes;
|
||||
format=flowed
|
||||
|
||||
This is the first part.
|
||||
|
||||
--Apple-Mail-12-196940926
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Type: application/pdf;
|
||||
x-unix-mode=0666;
|
||||
name="test.pdf"
|
||||
Content-Disposition: inline;
|
||||
filename=test.pdf
|
||||
|
||||
YmxhaCBibGFoIGJsYWg=
|
||||
|
||||
--Apple-Mail-12-196940926
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Type: text/plain;
|
||||
charset=US-ASCII;
|
||||
format=flowed
|
||||
|
||||
|
||||
|
||||
--Apple-Mail-12-196940926--
|
||||
|
||||
--Apple-Mail-13-196941151
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Type: application/pkcs7-signature;
|
||||
name=smime.p7s
|
||||
Content-Disposition: attachment;
|
||||
filename=smime.p7s
|
||||
|
||||
jamisSqGSIb3DQEHAqCAMIjamisxCzAJBgUrDgMCGgUAMIAGCSqGSjamisEHAQAAoIIFSjCCBUYw
|
||||
ggQujamisQICBD++ukQwDQYJKojamisNAQEFBQAwMTELMAkGA1UEBhMCRjamisAKBgNVBAoTA1RE
|
||||
QzEUMBIGjamisxMLVERDIE9DRVMgQ0jamisNMDQwMjI5MTE1OTAxWhcNMDYwMjamisIyOTAxWjCB
|
||||
gDELMAkGA1UEjamisEsxKTAnBgNVBAoTIEjamisuIG9yZ2FuaXNhdG9yaXNrIHRpbjamisRuaW5=
|
||||
|
||||
--Apple-Mail-13-196941151--
|
||||
47
tracks/vendor/rails/actionmailer/test/fixtures/raw_email8
vendored
Normal file
47
tracks/vendor/rails/actionmailer/test/fixtures/raw_email8
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
From xxxxxxxxx.xxxxxxx@gmail.com Sun May 8 19:07:09 2005
|
||||
Return-Path: <xxxxxxxxx.xxxxxxx@gmail.com>
|
||||
Message-ID: <e85734b90505081209eaaa17b@mail.gmail.com>
|
||||
Date: Sun, 8 May 2005 14:09:11 -0500
|
||||
From: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
|
||||
Reply-To: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
|
||||
To: xxxxx xxxx <xxxxx@xxxxxxxxx.com>
|
||||
Subject: Fwd: Signed email causes file attachments
|
||||
In-Reply-To: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="----=_Part_5028_7368284.1115579351471"
|
||||
References: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
|
||||
|
||||
------=_Part_5028_7368284.1115579351471
|
||||
Content-Type: text/plain; charset=ISO-8859-1
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Disposition: inline
|
||||
|
||||
We should not include these files or vcards as attachments.
|
||||
|
||||
---------- Forwarded message ----------
|
||||
From: xxxxx xxxxxx <xxxxxxxx@xxx.com>
|
||||
Date: May 8, 2005 1:17 PM
|
||||
Subject: Signed email causes file attachments
|
||||
To: xxxxxxx@xxxxxxxxxx.com
|
||||
|
||||
|
||||
Hi,
|
||||
|
||||
Test attachments oddly encoded with japanese charset.
|
||||
|
||||
|
||||
------=_Part_5028_7368284.1115579351471
|
||||
Content-Type: application/octet-stream; name*=iso-2022-jp'ja'01%20Quien%20Te%20Dij%8aat.%20Pitbull.mp3
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: attachment
|
||||
|
||||
MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIGFDCCAs0w
|
||||
ggI2oAMCAQICAw5c+TANBgkqhkiG9w0BAQQFADBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
|
||||
d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVt
|
||||
YWlsIElzc3VpbmcgQ0EwHhcNMDUwMzI5MDkzOTEwWhcNMDYwMzI5MDkzOTEwWjBCMR8wHQYDVQQD
|
||||
ExZUaGF3dGUgRnJlZW1haWwgTWVtYmVyMR8wHQYJKoZIhvcNAQkBFhBzbWhhdW5jaEBtYWMuY29t
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn90dPsYS3LjfMY211OSYrDQLzwNYPlAL
|
||||
7+/0XA+kdy8/rRnyEHFGwhNCDmg0B6pxC7z3xxJD/8GfCd+IYUUNUQV5m9MkxfP9pTVXZVIYLaBw
|
||||
------=_Part_5028_7368284.1115579351471--
|
||||
|
||||
28
tracks/vendor/rails/actionmailer/test/fixtures/raw_email9
vendored
Normal file
28
tracks/vendor/rails/actionmailer/test/fixtures/raw_email9
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
Received: from xxx.xxx.xxx ([xxx.xxx.xxx.xxx] verified)
|
||||
by xxx.com (CommuniGate Pro SMTP 4.2.8)
|
||||
with SMTP id 2532598 for xxx@xxx.com; Wed, 23 Feb 2005 17:51:49 -0500
|
||||
Received-SPF: softfail
|
||||
receiver=xxx.com; client-ip=xxx.xxx.xxx.xxx; envelope-from=xxx@xxx.xxx
|
||||
quite Delivered-To: xxx@xxx.xxx
|
||||
Received: by xxx.xxx.xxx (Wostfix, from userid xxx)
|
||||
id 0F87F333; Wed, 23 Feb 2005 16:16:17 -0600
|
||||
Date: Wed, 23 Feb 2005 18:20:17 -0400
|
||||
From: "xxx xxx" <xxx@xxx.xxx>
|
||||
Message-ID: <4D6AA7EB.6490534@xxx.xxx>
|
||||
To: xxx@xxx.com
|
||||
Subject: Stop adware/spyware once and for all.
|
||||
X-Scanned-By: MIMEDefang 2.11 (www dot roaringpenguin dot com slash mimedefang)
|
||||
|
||||
You are infected with:
|
||||
Ad Ware and Spy Ware
|
||||
|
||||
Get your free scan and removal download now,
|
||||
before it gets any worse.
|
||||
|
||||
http://xxx.xxx.info?aid=3D13&?stat=3D4327kdzt
|
||||
|
||||
|
||||
|
||||
|
||||
no more? (you will still be infected)
|
||||
http://xxx.xxx.info/discon/?xxx@xxx.com
|
||||
3
tracks/vendor/rails/actionmailer/test/fixtures/templates/signed_up.rhtml
vendored
Normal file
3
tracks/vendor/rails/actionmailer/test/fixtures/templates/signed_up.rhtml
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Hello there,
|
||||
|
||||
Mr. <%= @recipient %>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<html>
|
||||
<body>
|
||||
HTML formatted message to <strong><%= @recipient %></strong>.
|
||||
</body>
|
||||
</html>
|
||||
<html>
|
||||
<body>
|
||||
HTML formatted message to <strong><%= @recipient %></strong>.
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
Plain text to <%= @recipient %>.
|
||||
Plain text to <%= @recipient %>.
|
||||
|
|
@ -0,0 +1 @@
|
|||
yaml to: <%= @recipient %>
|
||||
3
tracks/vendor/rails/actionmailer/test/fixtures/test_mailer/signed_up.rhtml
vendored
Normal file
3
tracks/vendor/rails/actionmailer/test/fixtures/test_mailer/signed_up.rhtml
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Hello there,
|
||||
|
||||
Mr. <%= @recipient %>
|
||||
97
tracks/vendor/rails/actionmailer/test/mail_helper_test.rb
vendored
Normal file
97
tracks/vendor/rails/actionmailer/test/mail_helper_test.rb
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
||||
$:.unshift File.dirname(__FILE__) + "/fixtures/helpers"
|
||||
|
||||
require 'test/unit'
|
||||
require 'action_mailer'
|
||||
|
||||
module MailerHelper
|
||||
def person_name
|
||||
"Mr. Joe Person"
|
||||
end
|
||||
end
|
||||
|
||||
class HelperMailer < ActionMailer::Base
|
||||
helper MailerHelper
|
||||
helper :test
|
||||
|
||||
def use_helper(recipient)
|
||||
recipients recipient
|
||||
subject "using helpers"
|
||||
from "tester@example.com"
|
||||
end
|
||||
|
||||
def use_test_helper(recipient)
|
||||
recipients recipient
|
||||
subject "using helpers"
|
||||
from "tester@example.com"
|
||||
self.body = { :text => "emphasize me!" }
|
||||
end
|
||||
|
||||
def use_mail_helper(recipient)
|
||||
recipients recipient
|
||||
subject "using mailing helpers"
|
||||
from "tester@example.com"
|
||||
self.body = { :text =>
|
||||
"But soft! What light through yonder window breaks? It is the east, " +
|
||||
"and Juliet is the sun. Arise, fair sun, and kill the envious moon, " +
|
||||
"which is sick and pale with grief that thou, her maid, art far more " +
|
||||
"fair than she. Be not her maid, for she is envious! Her vestal " +
|
||||
"livery is but sick and green, and none but fools do wear it. Cast " +
|
||||
"it off!"
|
||||
}
|
||||
end
|
||||
|
||||
def use_helper_method(recipient)
|
||||
recipients recipient
|
||||
subject "using helpers"
|
||||
from "tester@example.com"
|
||||
self.body = { :text => "emphasize me!" }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def name_of_the_mailer_class
|
||||
self.class.name
|
||||
end
|
||||
helper_method :name_of_the_mailer_class
|
||||
end
|
||||
|
||||
HelperMailer.template_root = File.dirname(__FILE__) + "/fixtures"
|
||||
|
||||
class MailerHelperTest < Test::Unit::TestCase
|
||||
def new_mail( charset="utf-8" )
|
||||
mail = TMail::Mail.new
|
||||
mail.set_content_type "text", "plain", { "charset" => charset } if charset
|
||||
mail
|
||||
end
|
||||
|
||||
def setup
|
||||
ActionMailer::Base.delivery_method = :test
|
||||
ActionMailer::Base.perform_deliveries = true
|
||||
ActionMailer::Base.deliveries = []
|
||||
|
||||
@recipient = 'test@localhost'
|
||||
end
|
||||
|
||||
def test_use_helper
|
||||
mail = HelperMailer.create_use_helper(@recipient)
|
||||
assert_match %r{Mr. Joe Person}, mail.encoded
|
||||
end
|
||||
|
||||
def test_use_test_helper
|
||||
mail = HelperMailer.create_use_test_helper(@recipient)
|
||||
assert_match %r{<em><strong><small>emphasize me!}, mail.encoded
|
||||
end
|
||||
|
||||
def test_use_helper_method
|
||||
mail = HelperMailer.create_use_helper_method(@recipient)
|
||||
assert_match %r{HelperMailer}, mail.encoded
|
||||
end
|
||||
|
||||
def test_use_mail_helper
|
||||
mail = HelperMailer.create_use_mail_helper(@recipient)
|
||||
assert_match %r{ But soft!}, mail.encoded
|
||||
assert_match %r{east, and\n Juliet}, mail.encoded
|
||||
end
|
||||
end
|
||||
|
||||
48
tracks/vendor/rails/actionmailer/test/mail_render_test.rb
vendored
Normal file
48
tracks/vendor/rails/actionmailer/test/mail_render_test.rb
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
||||
|
||||
require 'test/unit'
|
||||
require 'action_mailer'
|
||||
|
||||
class RenderMailer < ActionMailer::Base
|
||||
def inline_template(recipient)
|
||||
recipients recipient
|
||||
subject "using helpers"
|
||||
from "tester@example.com"
|
||||
body render(:inline => "Hello, <%= @world %>", :body => { :world => "Earth" })
|
||||
end
|
||||
|
||||
def file_template(recipient)
|
||||
recipients recipient
|
||||
subject "using helpers"
|
||||
from "tester@example.com"
|
||||
body render(:file => "signed_up", :body => { :recipient => recipient })
|
||||
end
|
||||
|
||||
def initialize_defaults(method_name)
|
||||
super
|
||||
mailer_name "test_mailer"
|
||||
end
|
||||
end
|
||||
|
||||
RenderMailer.template_root = File.dirname(__FILE__) + "/fixtures"
|
||||
|
||||
class RenderHelperTest < Test::Unit::TestCase
|
||||
def setup
|
||||
ActionMailer::Base.delivery_method = :test
|
||||
ActionMailer::Base.perform_deliveries = true
|
||||
ActionMailer::Base.deliveries = []
|
||||
|
||||
@recipient = 'test@localhost'
|
||||
end
|
||||
|
||||
def test_inline_template
|
||||
mail = RenderMailer.create_inline_template(@recipient)
|
||||
assert_equal "Hello, Earth", mail.body.strip
|
||||
end
|
||||
|
||||
def test_file_template
|
||||
mail = RenderMailer.create_file_template(@recipient)
|
||||
assert_equal "Hello there, \n\nMr. test@localhost", mail.body.strip
|
||||
end
|
||||
end
|
||||
|
||||
749
tracks/vendor/rails/actionmailer/test/mail_service_test.rb
vendored
Normal file
749
tracks/vendor/rails/actionmailer/test/mail_service_test.rb
vendored
Normal file
|
|
@ -0,0 +1,749 @@
|
|||
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
||||
|
||||
require 'test/unit'
|
||||
require 'action_mailer'
|
||||
|
||||
class MockSMTP
|
||||
def self.deliveries
|
||||
@@deliveries
|
||||
end
|
||||
|
||||
def initialize
|
||||
@@deliveries = []
|
||||
end
|
||||
|
||||
def sendmail(mail, from, to)
|
||||
@@deliveries << [mail, from, to]
|
||||
end
|
||||
end
|
||||
|
||||
class Net::SMTP
|
||||
def self.start(*args)
|
||||
yield MockSMTP.new
|
||||
end
|
||||
end
|
||||
|
||||
class TestMailer < ActionMailer::Base
|
||||
|
||||
def signed_up(recipient)
|
||||
@recipients = recipient
|
||||
@subject = "[Signed up] Welcome #{recipient}"
|
||||
@from = "system@loudthinking.com"
|
||||
@sent_on = Time.local(2004, 12, 12)
|
||||
@body["recipient"] = recipient
|
||||
end
|
||||
|
||||
def cancelled_account(recipient)
|
||||
self.recipients = recipient
|
||||
self.subject = "[Cancelled] Goodbye #{recipient}"
|
||||
self.from = "system@loudthinking.com"
|
||||
self.sent_on = Time.local(2004, 12, 12)
|
||||
self.body = "Goodbye, Mr. #{recipient}"
|
||||
end
|
||||
|
||||
def cc_bcc(recipient)
|
||||
recipients recipient
|
||||
subject "testing bcc/cc"
|
||||
from "system@loudthinking.com"
|
||||
sent_on Time.local(2004, 12, 12)
|
||||
cc "nobody@loudthinking.com"
|
||||
bcc "root@loudthinking.com"
|
||||
body "Nothing to see here."
|
||||
end
|
||||
|
||||
def iso_charset(recipient)
|
||||
@recipients = recipient
|
||||
@subject = "testing isø charsets"
|
||||
@from = "system@loudthinking.com"
|
||||
@sent_on = Time.local 2004, 12, 12
|
||||
@cc = "nobody@loudthinking.com"
|
||||
@bcc = "root@loudthinking.com"
|
||||
@body = "Nothing to see here."
|
||||
@charset = "iso-8859-1"
|
||||
end
|
||||
|
||||
def unencoded_subject(recipient)
|
||||
@recipients = recipient
|
||||
@subject = "testing unencoded subject"
|
||||
@from = "system@loudthinking.com"
|
||||
@sent_on = Time.local 2004, 12, 12
|
||||
@cc = "nobody@loudthinking.com"
|
||||
@bcc = "root@loudthinking.com"
|
||||
@body = "Nothing to see here."
|
||||
end
|
||||
|
||||
def extended_headers(recipient)
|
||||
@recipients = recipient
|
||||
@subject = "testing extended headers"
|
||||
@from = "Grytøyr <stian1@example.net>"
|
||||
@sent_on = Time.local 2004, 12, 12
|
||||
@cc = "Grytøyr <stian2@example.net>"
|
||||
@bcc = "Grytøyr <stian3@example.net>"
|
||||
@body = "Nothing to see here."
|
||||
@charset = "iso-8859-1"
|
||||
end
|
||||
|
||||
def utf8_body(recipient)
|
||||
@recipients = recipient
|
||||
@subject = "testing utf-8 body"
|
||||
@from = "Foo áëô îü <extended@example.net>"
|
||||
@sent_on = Time.local 2004, 12, 12
|
||||
@cc = "Foo áëô îü <extended@example.net>"
|
||||
@bcc = "Foo áëô îü <extended@example.net>"
|
||||
@body = "åœö blah"
|
||||
@charset = "utf-8"
|
||||
end
|
||||
|
||||
def multipart_with_mime_version(recipient)
|
||||
recipients recipient
|
||||
subject "multipart with mime_version"
|
||||
from "test@example.com"
|
||||
sent_on Time.local(2004, 12, 12)
|
||||
mime_version "1.1"
|
||||
content_type "multipart/alternative"
|
||||
|
||||
part "text/plain" do |p|
|
||||
p.body = "blah"
|
||||
end
|
||||
|
||||
part "text/html" do |p|
|
||||
p.body = "<b>blah</b>"
|
||||
end
|
||||
end
|
||||
|
||||
def multipart_with_utf8_subject(recipient)
|
||||
recipients recipient
|
||||
subject "Foo áëô îü"
|
||||
from "test@example.com"
|
||||
charset "utf-8"
|
||||
|
||||
part "text/plain" do |p|
|
||||
p.body = "blah"
|
||||
end
|
||||
|
||||
part "text/html" do |p|
|
||||
p.body = "<b>blah</b>"
|
||||
end
|
||||
end
|
||||
|
||||
def explicitly_multipart_example(recipient, ct=nil)
|
||||
recipients recipient
|
||||
subject "multipart example"
|
||||
from "test@example.com"
|
||||
sent_on Time.local(2004, 12, 12)
|
||||
body "plain text default"
|
||||
content_type ct if ct
|
||||
|
||||
part "text/html" do |p|
|
||||
p.charset = "iso-8859-1"
|
||||
p.body = "blah"
|
||||
end
|
||||
|
||||
attachment :content_type => "image/jpeg", :filename => "foo.jpg",
|
||||
:body => "123456789"
|
||||
end
|
||||
|
||||
def implicitly_multipart_example(recipient, cs = nil, order = nil)
|
||||
@recipients = recipient
|
||||
@subject = "multipart example"
|
||||
@from = "test@example.com"
|
||||
@sent_on = Time.local 2004, 12, 12
|
||||
@body = { "recipient" => recipient }
|
||||
@charset = cs if cs
|
||||
@implicit_parts_order = order if order
|
||||
end
|
||||
|
||||
def html_mail(recipient)
|
||||
recipients recipient
|
||||
subject "html mail"
|
||||
from "test@example.com"
|
||||
body "<em>Emphasize</em> <strong>this</strong>"
|
||||
content_type "text/html"
|
||||
end
|
||||
|
||||
def html_mail_with_underscores(recipient)
|
||||
subject "html mail with underscores"
|
||||
body %{<a href="http://google.com" target="_blank">_Google</a>}
|
||||
end
|
||||
|
||||
def custom_template(recipient)
|
||||
recipients recipient
|
||||
subject "[Signed up] Welcome #{recipient}"
|
||||
from "system@loudthinking.com"
|
||||
sent_on Time.local(2004, 12, 12)
|
||||
template "signed_up"
|
||||
|
||||
body["recipient"] = recipient
|
||||
end
|
||||
|
||||
def various_newlines(recipient)
|
||||
recipients recipient
|
||||
subject "various newlines"
|
||||
from "test@example.com"
|
||||
body "line #1\nline #2\rline #3\r\nline #4\r\r" +
|
||||
"line #5\n\nline#6\r\n\r\nline #7"
|
||||
end
|
||||
|
||||
def various_newlines_multipart(recipient)
|
||||
recipients recipient
|
||||
subject "various newlines multipart"
|
||||
from "test@example.com"
|
||||
content_type "multipart/alternative"
|
||||
part :content_type => "text/plain", :body => "line #1\nline #2\rline #3\r\nline #4\r\r"
|
||||
part :content_type => "text/html", :body => "<p>line #1</p>\n<p>line #2</p>\r<p>line #3</p>\r\n<p>line #4</p>\r\r"
|
||||
end
|
||||
|
||||
def nested_multipart(recipient)
|
||||
recipients recipient
|
||||
subject "nested multipart"
|
||||
from "test@example.com"
|
||||
content_type "multipart/mixed"
|
||||
part :content_type => "multipart/alternative", :content_disposition => "inline" do |p|
|
||||
p.part :content_type => "text/plain", :body => "test text\nline #2"
|
||||
p.part :content_type => "text/html", :body => "<b>test</b> HTML<br/>\nline #2"
|
||||
end
|
||||
attachment :content_type => "application/octet-stream",:filename => "test.txt", :body => "test abcdefghijklmnopqstuvwxyz"
|
||||
end
|
||||
|
||||
def unnamed_attachment(recipient)
|
||||
recipients recipient
|
||||
subject "nested multipart"
|
||||
from "test@example.com"
|
||||
content_type "multipart/mixed"
|
||||
part :content_type => "text/plain", :body => "hullo"
|
||||
attachment :content_type => "application/octet-stream", :body => "test abcdefghijklmnopqstuvwxyz"
|
||||
end
|
||||
|
||||
def headers_with_nonalpha_chars(recipient)
|
||||
recipients recipient
|
||||
subject "nonalpha chars"
|
||||
from "One: Two <test@example.com>"
|
||||
cc "Three: Four <test@example.com>"
|
||||
bcc "Five: Six <test@example.com>"
|
||||
body "testing"
|
||||
end
|
||||
|
||||
class <<self
|
||||
attr_accessor :received_body
|
||||
end
|
||||
|
||||
def receive(mail)
|
||||
self.class.received_body = mail.body
|
||||
end
|
||||
end
|
||||
|
||||
TestMailer.template_root = File.dirname(__FILE__) + "/fixtures"
|
||||
|
||||
class ActionMailerTest < Test::Unit::TestCase
|
||||
include ActionMailer::Quoting
|
||||
|
||||
def encode( text, charset="utf-8" )
|
||||
quoted_printable( text, charset )
|
||||
end
|
||||
|
||||
def new_mail( charset="utf-8" )
|
||||
mail = TMail::Mail.new
|
||||
if charset
|
||||
mail.set_content_type "text", "plain", { "charset" => charset }
|
||||
end
|
||||
mail
|
||||
end
|
||||
|
||||
def setup
|
||||
ActionMailer::Base.delivery_method = :test
|
||||
ActionMailer::Base.perform_deliveries = true
|
||||
ActionMailer::Base.deliveries = []
|
||||
|
||||
@recipient = 'test@localhost'
|
||||
end
|
||||
|
||||
def test_nested_parts
|
||||
created = nil
|
||||
assert_nothing_raised { created = TestMailer.create_nested_multipart(@recipient)}
|
||||
assert_equal 2,created.parts.size
|
||||
assert_equal 2,created.parts.first.parts.size
|
||||
|
||||
assert_equal "multipart/mixed", created.content_type
|
||||
assert_equal "multipart/alternative", created.parts.first.content_type
|
||||
assert_equal "text/plain", created.parts.first.parts.first.content_type
|
||||
assert_equal "text/html", created.parts.first.parts[1].content_type
|
||||
assert_equal "application/octet-stream", created.parts[1].content_type
|
||||
end
|
||||
|
||||
def test_signed_up
|
||||
expected = new_mail
|
||||
expected.to = @recipient
|
||||
expected.subject = "[Signed up] Welcome #{@recipient}"
|
||||
expected.body = "Hello there, \n\nMr. #{@recipient}"
|
||||
expected.from = "system@loudthinking.com"
|
||||
expected.date = Time.local(2004, 12, 12)
|
||||
expected.mime_version = nil
|
||||
|
||||
created = nil
|
||||
assert_nothing_raised { created = TestMailer.create_signed_up(@recipient) }
|
||||
assert_not_nil created
|
||||
assert_equal expected.encoded, created.encoded
|
||||
|
||||
assert_nothing_raised { TestMailer.deliver_signed_up(@recipient) }
|
||||
assert_not_nil ActionMailer::Base.deliveries.first
|
||||
assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
|
||||
end
|
||||
|
||||
def test_custom_template
|
||||
expected = new_mail
|
||||
expected.to = @recipient
|
||||
expected.subject = "[Signed up] Welcome #{@recipient}"
|
||||
expected.body = "Hello there, \n\nMr. #{@recipient}"
|
||||
expected.from = "system@loudthinking.com"
|
||||
expected.date = Time.local(2004, 12, 12)
|
||||
|
||||
created = nil
|
||||
assert_nothing_raised { created = TestMailer.create_custom_template(@recipient) }
|
||||
assert_not_nil created
|
||||
assert_equal expected.encoded, created.encoded
|
||||
end
|
||||
|
||||
def test_cancelled_account
|
||||
expected = new_mail
|
||||
expected.to = @recipient
|
||||
expected.subject = "[Cancelled] Goodbye #{@recipient}"
|
||||
expected.body = "Goodbye, Mr. #{@recipient}"
|
||||
expected.from = "system@loudthinking.com"
|
||||
expected.date = Time.local(2004, 12, 12)
|
||||
|
||||
created = nil
|
||||
assert_nothing_raised { created = TestMailer.create_cancelled_account(@recipient) }
|
||||
assert_not_nil created
|
||||
assert_equal expected.encoded, created.encoded
|
||||
|
||||
assert_nothing_raised { TestMailer.deliver_cancelled_account(@recipient) }
|
||||
assert_not_nil ActionMailer::Base.deliveries.first
|
||||
assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
|
||||
end
|
||||
|
||||
def test_cc_bcc
|
||||
expected = new_mail
|
||||
expected.to = @recipient
|
||||
expected.subject = "testing bcc/cc"
|
||||
expected.body = "Nothing to see here."
|
||||
expected.from = "system@loudthinking.com"
|
||||
expected.cc = "nobody@loudthinking.com"
|
||||
expected.bcc = "root@loudthinking.com"
|
||||
expected.date = Time.local 2004, 12, 12
|
||||
|
||||
created = nil
|
||||
assert_nothing_raised do
|
||||
created = TestMailer.create_cc_bcc @recipient
|
||||
end
|
||||
assert_not_nil created
|
||||
assert_equal expected.encoded, created.encoded
|
||||
|
||||
assert_nothing_raised do
|
||||
TestMailer.deliver_cc_bcc @recipient
|
||||
end
|
||||
|
||||
assert_not_nil ActionMailer::Base.deliveries.first
|
||||
assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
|
||||
end
|
||||
|
||||
def test_iso_charset
|
||||
expected = new_mail( "iso-8859-1" )
|
||||
expected.to = @recipient
|
||||
expected.subject = encode "testing isø charsets", "iso-8859-1"
|
||||
expected.body = "Nothing to see here."
|
||||
expected.from = "system@loudthinking.com"
|
||||
expected.cc = "nobody@loudthinking.com"
|
||||
expected.bcc = "root@loudthinking.com"
|
||||
expected.date = Time.local 2004, 12, 12
|
||||
|
||||
created = nil
|
||||
assert_nothing_raised do
|
||||
created = TestMailer.create_iso_charset @recipient
|
||||
end
|
||||
assert_not_nil created
|
||||
assert_equal expected.encoded, created.encoded
|
||||
|
||||
assert_nothing_raised do
|
||||
TestMailer.deliver_iso_charset @recipient
|
||||
end
|
||||
|
||||
assert_not_nil ActionMailer::Base.deliveries.first
|
||||
assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
|
||||
end
|
||||
|
||||
def test_unencoded_subject
|
||||
expected = new_mail
|
||||
expected.to = @recipient
|
||||
expected.subject = "testing unencoded subject"
|
||||
expected.body = "Nothing to see here."
|
||||
expected.from = "system@loudthinking.com"
|
||||
expected.cc = "nobody@loudthinking.com"
|
||||
expected.bcc = "root@loudthinking.com"
|
||||
expected.date = Time.local 2004, 12, 12
|
||||
|
||||
created = nil
|
||||
assert_nothing_raised do
|
||||
created = TestMailer.create_unencoded_subject @recipient
|
||||
end
|
||||
assert_not_nil created
|
||||
assert_equal expected.encoded, created.encoded
|
||||
|
||||
assert_nothing_raised do
|
||||
TestMailer.deliver_unencoded_subject @recipient
|
||||
end
|
||||
|
||||
assert_not_nil ActionMailer::Base.deliveries.first
|
||||
assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
|
||||
end
|
||||
|
||||
def test_instances_are_nil
|
||||
assert_nil ActionMailer::Base.new
|
||||
assert_nil TestMailer.new
|
||||
end
|
||||
|
||||
def test_deliveries_array
|
||||
assert_not_nil ActionMailer::Base.deliveries
|
||||
assert_equal 0, ActionMailer::Base.deliveries.size
|
||||
TestMailer.deliver_signed_up(@recipient)
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
assert_not_nil ActionMailer::Base.deliveries.first
|
||||
end
|
||||
|
||||
def test_perform_deliveries_flag
|
||||
ActionMailer::Base.perform_deliveries = false
|
||||
TestMailer.deliver_signed_up(@recipient)
|
||||
assert_equal 0, ActionMailer::Base.deliveries.size
|
||||
ActionMailer::Base.perform_deliveries = true
|
||||
TestMailer.deliver_signed_up(@recipient)
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_unquote_quoted_printable_subject
|
||||
msg = <<EOF
|
||||
From: me@example.com
|
||||
Subject: =?utf-8?Q?testing_testing_=D6=A4?=
|
||||
Content-Type: text/plain; charset=iso-8859-1
|
||||
|
||||
The body
|
||||
EOF
|
||||
mail = TMail::Mail.parse(msg)
|
||||
assert_equal "testing testing \326\244", mail.subject
|
||||
assert_equal "=?utf-8?Q?testing_testing_=D6=A4?=", mail.quoted_subject
|
||||
end
|
||||
|
||||
def test_unquote_7bit_subject
|
||||
msg = <<EOF
|
||||
From: me@example.com
|
||||
Subject: this == working?
|
||||
Content-Type: text/plain; charset=iso-8859-1
|
||||
|
||||
The body
|
||||
EOF
|
||||
mail = TMail::Mail.parse(msg)
|
||||
assert_equal "this == working?", mail.subject
|
||||
assert_equal "this == working?", mail.quoted_subject
|
||||
end
|
||||
|
||||
def test_unquote_7bit_body
|
||||
msg = <<EOF
|
||||
From: me@example.com
|
||||
Subject: subject
|
||||
Content-Type: text/plain; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
The=3Dbody
|
||||
EOF
|
||||
mail = TMail::Mail.parse(msg)
|
||||
assert_equal "The=3Dbody", mail.body.strip
|
||||
assert_equal "The=3Dbody", mail.quoted_body.strip
|
||||
end
|
||||
|
||||
def test_unquote_quoted_printable_body
|
||||
msg = <<EOF
|
||||
From: me@example.com
|
||||
Subject: subject
|
||||
Content-Type: text/plain; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
The=3Dbody
|
||||
EOF
|
||||
mail = TMail::Mail.parse(msg)
|
||||
assert_equal "The=body", mail.body.strip
|
||||
assert_equal "The=3Dbody", mail.quoted_body.strip
|
||||
end
|
||||
|
||||
def test_unquote_base64_body
|
||||
msg = <<EOF
|
||||
From: me@example.com
|
||||
Subject: subject
|
||||
Content-Type: text/plain; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
VGhlIGJvZHk=
|
||||
EOF
|
||||
mail = TMail::Mail.parse(msg)
|
||||
assert_equal "The body", mail.body.strip
|
||||
assert_equal "VGhlIGJvZHk=", mail.quoted_body.strip
|
||||
end
|
||||
|
||||
def test_extended_headers
|
||||
@recipient = "Grytøyr <test@localhost>"
|
||||
|
||||
expected = new_mail "iso-8859-1"
|
||||
expected.to = quote_address_if_necessary @recipient, "iso-8859-1"
|
||||
expected.subject = "testing extended headers"
|
||||
expected.body = "Nothing to see here."
|
||||
expected.from = quote_address_if_necessary "Grytøyr <stian1@example.net>", "iso-8859-1"
|
||||
expected.cc = quote_address_if_necessary "Grytøyr <stian2@example.net>", "iso-8859-1"
|
||||
expected.bcc = quote_address_if_necessary "Grytøyr <stian3@example.net>", "iso-8859-1"
|
||||
expected.date = Time.local 2004, 12, 12
|
||||
|
||||
created = nil
|
||||
assert_nothing_raised do
|
||||
created = TestMailer.create_extended_headers @recipient
|
||||
end
|
||||
|
||||
assert_not_nil created
|
||||
assert_equal expected.encoded, created.encoded
|
||||
|
||||
assert_nothing_raised do
|
||||
TestMailer.deliver_extended_headers @recipient
|
||||
end
|
||||
|
||||
assert_not_nil ActionMailer::Base.deliveries.first
|
||||
assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
|
||||
end
|
||||
|
||||
def test_utf8_body_is_not_quoted
|
||||
@recipient = "Foo áëô îü <extended@example.net>"
|
||||
expected = new_mail "utf-8"
|
||||
expected.to = quote_address_if_necessary @recipient, "utf-8"
|
||||
expected.subject = "testing utf-8 body"
|
||||
expected.body = "åœö blah"
|
||||
expected.from = quote_address_if_necessary @recipient, "utf-8"
|
||||
expected.cc = quote_address_if_necessary @recipient, "utf-8"
|
||||
expected.bcc = quote_address_if_necessary @recipient, "utf-8"
|
||||
expected.date = Time.local 2004, 12, 12
|
||||
|
||||
created = TestMailer.create_utf8_body @recipient
|
||||
assert_match(/åœö blah/, created.encoded)
|
||||
end
|
||||
|
||||
def test_multiple_utf8_recipients
|
||||
@recipient = ["\"Foo áëô îü\" <extended@example.net>", "\"Example Recipient\" <me@example.com>"]
|
||||
expected = new_mail "utf-8"
|
||||
expected.to = quote_address_if_necessary @recipient, "utf-8"
|
||||
expected.subject = "testing utf-8 body"
|
||||
expected.body = "åœö blah"
|
||||
expected.from = quote_address_if_necessary @recipient.first, "utf-8"
|
||||
expected.cc = quote_address_if_necessary @recipient, "utf-8"
|
||||
expected.bcc = quote_address_if_necessary @recipient, "utf-8"
|
||||
expected.date = Time.local 2004, 12, 12
|
||||
|
||||
created = TestMailer.create_utf8_body @recipient
|
||||
assert_match(/\nFrom: =\?utf-8\?Q\?Foo_.*?\?= <extended@example.net>\r/, created.encoded)
|
||||
assert_match(/\nTo: =\?utf-8\?Q\?Foo_.*?\?= <extended@example.net>, Example Recipient <me/, created.encoded)
|
||||
end
|
||||
|
||||
def test_receive_decodes_base64_encoded_mail
|
||||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email")
|
||||
TestMailer.receive(fixture)
|
||||
assert_match(/Jamis/, TestMailer.received_body)
|
||||
end
|
||||
|
||||
def test_receive_attachments
|
||||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email2")
|
||||
mail = TMail::Mail.parse(fixture)
|
||||
attachment = mail.attachments.last
|
||||
assert_equal "smime.p7s", attachment.original_filename
|
||||
assert_equal "application/pkcs7-signature", attachment.content_type
|
||||
end
|
||||
|
||||
def test_decode_attachment_without_charset
|
||||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email3")
|
||||
mail = TMail::Mail.parse(fixture)
|
||||
attachment = mail.attachments.last
|
||||
assert_equal 1026, attachment.read.length
|
||||
end
|
||||
|
||||
def test_attachment_using_content_location
|
||||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email12")
|
||||
mail = TMail::Mail.parse(fixture)
|
||||
assert_equal 1, mail.attachments.length
|
||||
assert_equal "Photo25.jpg", mail.attachments.first.original_filename
|
||||
end
|
||||
|
||||
def test_decode_part_without_content_type
|
||||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email4")
|
||||
mail = TMail::Mail.parse(fixture)
|
||||
assert_nothing_raised { mail.body }
|
||||
end
|
||||
|
||||
def test_decode_message_without_content_type
|
||||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email5")
|
||||
mail = TMail::Mail.parse(fixture)
|
||||
assert_nothing_raised { mail.body }
|
||||
end
|
||||
|
||||
def test_decode_message_with_incorrect_charset
|
||||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email6")
|
||||
mail = TMail::Mail.parse(fixture)
|
||||
assert_nothing_raised { mail.body }
|
||||
end
|
||||
|
||||
def test_multipart_with_mime_version
|
||||
mail = TestMailer.create_multipart_with_mime_version(@recipient)
|
||||
assert_equal "1.1", mail.mime_version
|
||||
end
|
||||
|
||||
def test_multipart_with_utf8_subject
|
||||
mail = TestMailer.create_multipart_with_utf8_subject(@recipient)
|
||||
assert_match(/\nSubject: =\?utf-8\?Q\?Foo_.*?\?=/, mail.encoded)
|
||||
end
|
||||
|
||||
def test_explicitly_multipart_messages
|
||||
mail = TestMailer.create_explicitly_multipart_example(@recipient)
|
||||
assert_equal 3, mail.parts.length
|
||||
assert_nil mail.content_type
|
||||
assert_equal "text/plain", mail.parts[0].content_type
|
||||
|
||||
assert_equal "text/html", mail.parts[1].content_type
|
||||
assert_equal "iso-8859-1", mail.parts[1].sub_header("content-type", "charset")
|
||||
assert_equal "inline", mail.parts[1].content_disposition
|
||||
|
||||
assert_equal "image/jpeg", mail.parts[2].content_type
|
||||
assert_equal "attachment", mail.parts[2].content_disposition
|
||||
assert_equal "foo.jpg", mail.parts[2].sub_header("content-disposition", "filename")
|
||||
assert_equal "foo.jpg", mail.parts[2].sub_header("content-type", "name")
|
||||
assert_nil mail.parts[2].sub_header("content-type", "charset")
|
||||
end
|
||||
|
||||
def test_explicitly_multipart_with_content_type
|
||||
mail = TestMailer.create_explicitly_multipart_example(@recipient, "multipart/alternative")
|
||||
assert_equal 3, mail.parts.length
|
||||
assert_equal "multipart/alternative", mail.content_type
|
||||
end
|
||||
|
||||
def test_explicitly_multipart_with_invalid_content_type
|
||||
mail = TestMailer.create_explicitly_multipart_example(@recipient, "text/xml")
|
||||
assert_equal 3, mail.parts.length
|
||||
assert_nil mail.content_type
|
||||
end
|
||||
|
||||
def test_implicitly_multipart_messages
|
||||
mail = TestMailer.create_implicitly_multipart_example(@recipient)
|
||||
assert_equal 3, mail.parts.length
|
||||
assert_equal "1.0", mail.mime_version
|
||||
assert_equal "multipart/alternative", mail.content_type
|
||||
assert_equal "text/yaml", mail.parts[0].content_type
|
||||
assert_equal "utf-8", mail.parts[0].sub_header("content-type", "charset")
|
||||
assert_equal "text/plain", mail.parts[1].content_type
|
||||
assert_equal "utf-8", mail.parts[1].sub_header("content-type", "charset")
|
||||
assert_equal "text/html", mail.parts[2].content_type
|
||||
assert_equal "utf-8", mail.parts[2].sub_header("content-type", "charset")
|
||||
end
|
||||
|
||||
def test_implicitly_multipart_messages_with_custom_order
|
||||
mail = TestMailer.create_implicitly_multipart_example(@recipient, nil, ["text/yaml", "text/plain"])
|
||||
assert_equal 3, mail.parts.length
|
||||
assert_equal "text/html", mail.parts[0].content_type
|
||||
assert_equal "text/plain", mail.parts[1].content_type
|
||||
assert_equal "text/yaml", mail.parts[2].content_type
|
||||
end
|
||||
|
||||
def test_implicitly_multipart_messages_with_charset
|
||||
mail = TestMailer.create_implicitly_multipart_example(@recipient, 'iso-8859-1')
|
||||
|
||||
assert_equal "multipart/alternative", mail.header['content-type'].body
|
||||
|
||||
assert_equal 'iso-8859-1', mail.parts[0].sub_header("content-type", "charset")
|
||||
assert_equal 'iso-8859-1', mail.parts[1].sub_header("content-type", "charset")
|
||||
assert_equal 'iso-8859-1', mail.parts[2].sub_header("content-type", "charset")
|
||||
end
|
||||
|
||||
def test_html_mail
|
||||
mail = TestMailer.create_html_mail(@recipient)
|
||||
assert_equal "text/html", mail.content_type
|
||||
end
|
||||
|
||||
def test_html_mail_with_underscores
|
||||
mail = TestMailer.create_html_mail_with_underscores(@recipient)
|
||||
assert_equal %{<a href="http://google.com" target="_blank">_Google</a>}, mail.body
|
||||
end
|
||||
|
||||
def test_various_newlines
|
||||
mail = TestMailer.create_various_newlines(@recipient)
|
||||
assert_equal("line #1\nline #2\nline #3\nline #4\n\n" +
|
||||
"line #5\n\nline#6\n\nline #7", mail.body)
|
||||
end
|
||||
|
||||
def test_various_newlines_multipart
|
||||
mail = TestMailer.create_various_newlines_multipart(@recipient)
|
||||
assert_equal "line #1\nline #2\nline #3\nline #4\n\n", mail.parts[0].body
|
||||
assert_equal "<p>line #1</p>\n<p>line #2</p>\n<p>line #3</p>\n<p>line #4</p>\n\n", mail.parts[1].body
|
||||
end
|
||||
|
||||
def test_headers_removed_on_smtp_delivery
|
||||
ActionMailer::Base.delivery_method = :smtp
|
||||
TestMailer.deliver_cc_bcc(@recipient)
|
||||
assert MockSMTP.deliveries[0][2].include?("root@loudthinking.com")
|
||||
assert MockSMTP.deliveries[0][2].include?("nobody@loudthinking.com")
|
||||
assert MockSMTP.deliveries[0][2].include?(@recipient)
|
||||
assert_match %r{^Cc: nobody@loudthinking.com}, MockSMTP.deliveries[0][0]
|
||||
assert_match %r{^To: #{@recipient}}, MockSMTP.deliveries[0][0]
|
||||
assert_no_match %r{^Bcc: root@loudthinking.com}, MockSMTP.deliveries[0][0]
|
||||
end
|
||||
|
||||
def test_recursive_multipart_processing
|
||||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email7")
|
||||
mail = TMail::Mail.parse(fixture)
|
||||
assert_equal "This is the first part.\n\nAttachment: test.pdf\n\n\nAttachment: smime.p7s\n", mail.body
|
||||
end
|
||||
|
||||
def test_decode_encoded_attachment_filename
|
||||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email8")
|
||||
mail = TMail::Mail.parse(fixture)
|
||||
attachment = mail.attachments.last
|
||||
assert_equal "01QuienTeDijat.Pitbull.mp3", attachment.original_filename
|
||||
end
|
||||
|
||||
def test_wrong_mail_header
|
||||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email9")
|
||||
assert_raise(TMail::SyntaxError) { TMail::Mail.parse(fixture) }
|
||||
end
|
||||
|
||||
def test_decode_message_with_unknown_charset
|
||||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email10")
|
||||
mail = TMail::Mail.parse(fixture)
|
||||
assert_nothing_raised { mail.body }
|
||||
end
|
||||
|
||||
def test_decode_message_with_unquoted_atchar_in_header
|
||||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email11")
|
||||
mail = TMail::Mail.parse(fixture)
|
||||
assert_not_nil mail.from
|
||||
end
|
||||
|
||||
def test_empty_header_values_omitted
|
||||
result = TestMailer.create_unnamed_attachment(@recipient).encoded
|
||||
assert_match %r{Content-Type: application/octet-stream[^;]}, result
|
||||
assert_match %r{Content-Disposition: attachment[^;]}, result
|
||||
end
|
||||
|
||||
def test_headers_with_nonalpha_chars
|
||||
mail = TestMailer.create_headers_with_nonalpha_chars(@recipient)
|
||||
assert !mail.from_addrs.empty?
|
||||
assert !mail.cc_addrs.empty?
|
||||
assert !mail.bcc_addrs.empty?
|
||||
assert_match(/:/, mail.from_addrs.to_s)
|
||||
assert_match(/:/, mail.cc_addrs.to_s)
|
||||
assert_match(/:/, mail.bcc_addrs.to_s)
|
||||
end
|
||||
|
||||
def test_deliver_with_mail_object
|
||||
mail = TestMailer::create_headers_with_nonalpha_chars(@recipient)
|
||||
assert_nothing_raised { TestMailer.deliver(mail) }
|
||||
assert_equal 1, TestMailer.deliveries.length
|
||||
end
|
||||
end
|
||||
|
||||
48
tracks/vendor/rails/actionmailer/test/quoting_test.rb
vendored
Normal file
48
tracks/vendor/rails/actionmailer/test/quoting_test.rb
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
||||
$:.unshift(File.dirname(__FILE__) + "/../lib/action_mailer/vendor")
|
||||
|
||||
require 'test/unit'
|
||||
require 'tmail'
|
||||
require 'tempfile'
|
||||
|
||||
class QuotingTest < Test::Unit::TestCase
|
||||
def test_quote_multibyte_chars
|
||||
original = "\303\246 \303\270 and \303\245"
|
||||
|
||||
result = execute_in_sandbox(<<-CODE)
|
||||
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
||||
$KCODE = 'u'
|
||||
require 'jcode'
|
||||
require 'action_mailer/quoting'
|
||||
include ActionMailer::Quoting
|
||||
quoted_printable(#{original.inspect}, "UTF-8")
|
||||
CODE
|
||||
|
||||
unquoted = TMail::Unquoter.unquote_and_convert_to(result, nil)
|
||||
assert_equal unquoted, original
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# This whole thing *could* be much simpler, but I don't think Tempfile,
|
||||
# popen and others exist on all platforms (like Windows).
|
||||
def execute_in_sandbox(code)
|
||||
test_name = "#{File.dirname(__FILE__)}/am-quoting-test.#{$$}.rb"
|
||||
res_name = "#{File.dirname(__FILE__)}/am-quoting-test.#{$$}.out"
|
||||
|
||||
File.open(test_name, "w+") do |file|
|
||||
file.write(<<-CODE)
|
||||
block = Proc.new do
|
||||
#{code}
|
||||
end
|
||||
puts block.call
|
||||
CODE
|
||||
end
|
||||
|
||||
system("ruby #{test_name} > #{res_name}") or raise "could not run test in sandbox"
|
||||
File.read(res_name)
|
||||
ensure
|
||||
File.delete(test_name) rescue nil
|
||||
File.delete(res_name) rescue nil
|
||||
end
|
||||
end
|
||||
17
tracks/vendor/rails/actionmailer/test/tmail_test.rb
vendored
Normal file
17
tracks/vendor/rails/actionmailer/test/tmail_test.rb
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
||||
$:.unshift File.dirname(__FILE__) + "/fixtures/helpers"
|
||||
|
||||
require 'test/unit'
|
||||
require 'action_mailer'
|
||||
|
||||
class TMailMailTest < Test::Unit::TestCase
|
||||
def test_body
|
||||
m = TMail::Mail.new
|
||||
expected = 'something_with_underscores'
|
||||
m.encoding = 'quoted-printable'
|
||||
quoted_body = [expected].pack('*M')
|
||||
m.body = quoted_body
|
||||
assert_equal "something_with_underscores=\n", m.quoted_body
|
||||
assert_equal expected, m.body
|
||||
end
|
||||
end
|
||||
2120
tracks/vendor/rails/actionpack/CHANGELOG
vendored
Normal file
2120
tracks/vendor/rails/actionpack/CHANGELOG
vendored
Normal file
File diff suppressed because it is too large
Load diff
21
tracks/vendor/rails/actionpack/MIT-LICENSE
vendored
Normal file
21
tracks/vendor/rails/actionpack/MIT-LICENSE
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
Copyright (c) 2004 David Heinemeier Hansson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
471
tracks/vendor/rails/actionpack/README
vendored
Normal file
471
tracks/vendor/rails/actionpack/README
vendored
Normal file
|
|
@ -0,0 +1,471 @@
|
|||
= Action Pack -- On rails from request to response
|
||||
|
||||
Action Pack splits the response to a web request into a controller part
|
||||
(performing the logic) and a view part (rendering a template). This two-step
|
||||
approach is known as an action, which will normally create, read, update, or
|
||||
delete (CRUD for short) some sort of model part (often backed by a database)
|
||||
before choosing either to render a template or redirecting to another action.
|
||||
|
||||
Action Pack implements these actions as public methods on Action Controllers
|
||||
and uses Action Views to implement the template rendering. Action Controllers
|
||||
are then responsible for handling all the actions relating to a certain part
|
||||
of an application. This grouping usually consists of actions for lists and for
|
||||
CRUDs revolving around a single (or a few) model objects. So ContactController
|
||||
would be responsible for listing contacts, creating, deleting, and updating
|
||||
contacts. A WeblogController could be responsible for both posts and comments.
|
||||
|
||||
Action View templates are written using embedded Ruby in tags mingled in with
|
||||
the HTML. To avoid cluttering the templates with code, a bunch of helper
|
||||
classes provide common behavior for forms, dates, and strings. And it's easy
|
||||
to add specific helpers to keep the separation as the application evolves.
|
||||
|
||||
Note: Some of the features, such as scaffolding and form building, are tied to
|
||||
ActiveRecord[http://activerecord.rubyonrails.org] (an object-relational
|
||||
mapping package), but that doesn't mean that Action Pack depends on Active
|
||||
Record. Action Pack is an independent package that can be used with any sort
|
||||
of backend (Instiki[http://www.instiki.org], which is based on an older version
|
||||
of Action Pack, used Madeleine for example). Read more about the role Action
|
||||
Pack can play when used together with Active Record on
|
||||
http://www.rubyonrails.org.
|
||||
|
||||
A short rundown of the major features:
|
||||
|
||||
* Actions grouped in controller as methods instead of separate command objects
|
||||
and can therefore share helper methods.
|
||||
|
||||
BlogController < ActionController::Base
|
||||
def display
|
||||
@customer = find_customer
|
||||
end
|
||||
|
||||
def update
|
||||
@customer = find_customer
|
||||
@customer.attributes = params[:customer]
|
||||
@customer.save ?
|
||||
redirect_to(:action => "display") :
|
||||
render(:action => "edit")
|
||||
end
|
||||
|
||||
private
|
||||
def find_customer() Customer.find(params[:id]) end
|
||||
end
|
||||
|
||||
{Learn more}[link:classes/ActionController/Base.html]
|
||||
|
||||
|
||||
* Embedded Ruby for templates (no new "easy" template language)
|
||||
|
||||
<% for post in @posts %>
|
||||
Title: <%= post.title %>
|
||||
<% end %>
|
||||
|
||||
All post titles: <%= @post.collect{ |p| p.title }.join ", " %>
|
||||
|
||||
<% unless @person.is_client? %>
|
||||
Not for clients to see...
|
||||
<% end %>
|
||||
|
||||
{Learn more}[link:classes/ActionView.html]
|
||||
|
||||
|
||||
* Builder-based templates (great for XML content, like RSS)
|
||||
|
||||
xml.rss("version" => "2.0") do
|
||||
xml.channel do
|
||||
xml.title(@feed_title)
|
||||
xml.link(@url)
|
||||
xml.description "Basecamp: Recent items"
|
||||
xml.language "en-us"
|
||||
xml.ttl "40"
|
||||
|
||||
for item in @recent_items
|
||||
xml.item do
|
||||
xml.title(item_title(item))
|
||||
xml.description(item_description(item))
|
||||
xml.pubDate(item_pubDate(item))
|
||||
xml.guid(@recent_items.url(item))
|
||||
xml.link(@recent_items.url(item))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
{Learn more}[link:classes/ActionView/Base.html]
|
||||
|
||||
|
||||
* Filters for pre and post processing of the response (as methods, procs, and classes)
|
||||
|
||||
class WeblogController < ActionController::Base
|
||||
before_filter :authenticate, :cache, :audit
|
||||
after_filter { |c| c.response.body = GZip::compress(c.response.body) }
|
||||
after_filter LocalizeFilter
|
||||
|
||||
def list
|
||||
# Before this action is run, the user will be authenticated, the cache
|
||||
# will be examined to see if a valid copy of the results already
|
||||
# exists, and the action will be logged for auditing.
|
||||
|
||||
# After this action has run, the output will first be localized then
|
||||
# compressed to minimize bandwidth usage
|
||||
end
|
||||
|
||||
private
|
||||
def authenticate
|
||||
# Implement the filter with full access to both request and response
|
||||
end
|
||||
end
|
||||
|
||||
{Learn more}[link:classes/ActionController/Filters/ClassMethods.html]
|
||||
|
||||
|
||||
* Helpers for forms, dates, action links, and text
|
||||
|
||||
<%= text_field "post", "title", "size" => 30 %>
|
||||
<%= html_date_select(Date.today) %>
|
||||
<%= link_to "New post", :controller => "post", :action => "new" %>
|
||||
<%= truncate(post.title, 25) %>
|
||||
|
||||
{Learn more}[link:classes/ActionView/Helpers.html]
|
||||
|
||||
|
||||
* Layout sharing for template reuse (think simple version of Struts
|
||||
Tiles[http://jakarta.apache.org/struts/userGuide/dev_tiles.html])
|
||||
|
||||
class WeblogController < ActionController::Base
|
||||
layout "weblog_layout"
|
||||
|
||||
def hello_world
|
||||
end
|
||||
end
|
||||
|
||||
Layout file (called weblog_layout):
|
||||
<html><body><%= @content_for_layout %></body></html>
|
||||
|
||||
Template for hello_world action:
|
||||
<h1>Hello world</h1>
|
||||
|
||||
Result of running hello_world action:
|
||||
<html><body><h1>Hello world</h1></body></html>
|
||||
|
||||
{Learn more}[link:classes/ActionController/Layout/ClassMethods.html]
|
||||
|
||||
|
||||
* Routing makes pretty urls incredibly easy
|
||||
|
||||
map.connect 'clients/:client_name/:project_name/:controller/:action'
|
||||
|
||||
Accessing /clients/37signals/basecamp/project/dash calls ProjectController#dash with
|
||||
{ "client_name" => "37signals", "project_name" => "basecamp" } in @params["params"]
|
||||
|
||||
From that URL, you can rewrite the redirect in a number of ways:
|
||||
|
||||
redirect_to(:action => "edit") =>
|
||||
/clients/37signals/basecamp/project/dash
|
||||
|
||||
redirect_to(:client_name => "nextangle", :project_name => "rails") =>
|
||||
/clients/nextangle/rails/project/dash
|
||||
|
||||
{Learn more}[link:classes/ActionController/Base.html]
|
||||
|
||||
|
||||
* Javascript and Ajax integration.
|
||||
|
||||
link_to_function "Greeting", "alert('Hello world!')"
|
||||
link_to_remote "Delete this post", :update => "posts",
|
||||
:url => { :action => "destroy", :id => post.id }
|
||||
|
||||
{Learn more}[link:classes/ActionView/Helpers/JavaScriptHelper.html]
|
||||
|
||||
|
||||
* Pagination for navigating lists of results.
|
||||
|
||||
# controller
|
||||
def list
|
||||
@pages, @people =
|
||||
paginate :people, :order => 'last_name, first_name'
|
||||
end
|
||||
|
||||
# view
|
||||
<%= link_to "Previous page", { :page => @pages.current.previous } if @pages.current.previous %>
|
||||
<%= link_to "Next page", { :page => @pages.current.next } if @pages.current.next %>
|
||||
|
||||
{Learn more}[link:classes/ActionController/Pagination.html]
|
||||
|
||||
|
||||
* Easy testing of both controller and template result through TestRequest/Response
|
||||
|
||||
class LoginControllerTest < Test::Unit::TestCase
|
||||
def setup
|
||||
@controller = LoginController.new
|
||||
@request = ActionController::TestRequest.new
|
||||
@response = ActionController::TestResponse.new
|
||||
end
|
||||
|
||||
def test_failing_authenticate
|
||||
process :authenticate, :user_name => "nop", :password => ""
|
||||
assert flash.has_key?(:alert)
|
||||
assert_redirected_to :action => "index"
|
||||
end
|
||||
end
|
||||
|
||||
{Learn more}[link:classes/ActionController/TestRequest.html]
|
||||
|
||||
|
||||
* Automated benchmarking and integrated logging
|
||||
|
||||
Processing WeblogController#index (for 127.0.0.1 at Fri May 28 00:41:55)
|
||||
Parameters: {"action"=>"index", "controller"=>"weblog"}
|
||||
Rendering weblog/index (200 OK)
|
||||
Completed in 0.029281 (34 reqs/sec)
|
||||
|
||||
If Active Record is used as the model, you'll have the database debugging
|
||||
as well:
|
||||
|
||||
Processing WeblogController#create (for 127.0.0.1 at Sat Jun 19 14:04:23)
|
||||
Params: {"controller"=>"weblog", "action"=>"create",
|
||||
"post"=>{"title"=>"this is good"} }
|
||||
SQL (0.000627) INSERT INTO posts (title) VALUES('this is good')
|
||||
Redirected to http://test/weblog/display/5
|
||||
Completed in 0.221764 (4 reqs/sec) | DB: 0.059920 (27%)
|
||||
|
||||
You specify a logger through a class method, such as:
|
||||
|
||||
ActionController::Base.logger = Logger.new("Application Log")
|
||||
ActionController::Base.logger = Log4r::Logger.new("Application Log")
|
||||
|
||||
|
||||
* Caching at three levels of granularity (page, action, fragment)
|
||||
|
||||
class WeblogController < ActionController::Base
|
||||
caches_page :show
|
||||
caches_action :account
|
||||
|
||||
def show
|
||||
# the output of the method will be cached as
|
||||
# ActionController::Base.page_cache_directory + "/weblog/show/n.html"
|
||||
# and the web server will pick it up without even hitting Rails
|
||||
end
|
||||
|
||||
def account
|
||||
# the output of the method will be cached in the fragment store
|
||||
# but Rails is hit to retrieve it, so filters are run
|
||||
end
|
||||
|
||||
def update
|
||||
List.update(params[:list][:id], params[:list])
|
||||
expire_page :action => "show", :id => params[:list][:id]
|
||||
expire_action :action => "account"
|
||||
redirect_to :action => "show", :id => params[:list][:id]
|
||||
end
|
||||
end
|
||||
|
||||
{Learn more}[link:classes/ActionController/Caching.html]
|
||||
|
||||
|
||||
* Component requests from one controller to another
|
||||
|
||||
class WeblogController < ActionController::Base
|
||||
# Performs a method and then lets hello_world output its render
|
||||
def delegate_action
|
||||
do_other_stuff_before_hello_world
|
||||
render_component :controller => "greeter", :action => "hello_world"
|
||||
end
|
||||
end
|
||||
|
||||
class GreeterController < ActionController::Base
|
||||
def hello_world
|
||||
render_text "Hello World!"
|
||||
end
|
||||
end
|
||||
|
||||
The same can be done in a view to do a partial rendering:
|
||||
|
||||
Let's see a greeting:
|
||||
<%= render_component :controller => "greeter", :action => "hello_world" %>
|
||||
|
||||
{Learn more}[link:classes/ActionController/Components.html]
|
||||
|
||||
|
||||
* Powerful debugging mechanism for local requests
|
||||
|
||||
All exceptions raised on actions performed on the request of a local user
|
||||
will be presented with a tailored debugging screen that includes exception
|
||||
message, stack trace, request parameters, session contents, and the
|
||||
half-finished response.
|
||||
|
||||
{Learn more}[link:classes/ActionController/Rescue.html]
|
||||
|
||||
|
||||
* Scaffolding for Action Record model objects
|
||||
|
||||
require 'account' # must be an Active Record class
|
||||
class AccountController < ActionController::Base
|
||||
scaffold :account
|
||||
end
|
||||
|
||||
The AccountController now has the full CRUD range of actions and default
|
||||
templates: list, show, destroy, new, create, edit, update
|
||||
|
||||
{Learn more}link:classes/ActionController/Scaffolding/ClassMethods.html
|
||||
|
||||
|
||||
* Form building for Active Record model objects
|
||||
|
||||
The post object has a title (varchar), content (text), and
|
||||
written_on (date)
|
||||
|
||||
<%= form "post" %>
|
||||
|
||||
...will generate something like (the selects will have more options, of
|
||||
course):
|
||||
|
||||
<form action="create" method="POST">
|
||||
<p>
|
||||
<b>Title:</b><br/>
|
||||
<input type="text" name="post[title]" value="<%= @post.title %>" />
|
||||
</p>
|
||||
<p>
|
||||
<b>Content:</b><br/>
|
||||
<textarea name="post[content]"><%= @post.title %></textarea>
|
||||
</p>
|
||||
<p>
|
||||
<b>Written on:</b><br/>
|
||||
<select name='post[written_on(3i)]'><option>18</option></select>
|
||||
<select name='post[written_on(2i)]'><option value='7'>July</option></select>
|
||||
<select name='post[written_on(1i)]'><option>2004</option></select>
|
||||
</p>
|
||||
|
||||
<input type="submit" value="Create">
|
||||
</form>
|
||||
|
||||
This form generates a @params["post"] array that can be used directly in a save action:
|
||||
|
||||
class WeblogController < ActionController::Base
|
||||
def save
|
||||
post = Post.create(params[:post])
|
||||
redirect_to :action => "display", :id => post.id
|
||||
end
|
||||
end
|
||||
|
||||
{Learn more}[link:classes/ActionView/Helpers/ActiveRecordHelper.html]
|
||||
|
||||
|
||||
* Runs on top of WEBrick, CGI, FCGI, and mod_ruby
|
||||
|
||||
|
||||
== Simple example
|
||||
|
||||
This example will implement a simple weblog system using inline templates and
|
||||
an Active Record model. So let's build that WeblogController with just a few
|
||||
methods:
|
||||
|
||||
require 'action_controller'
|
||||
require 'post'
|
||||
|
||||
class WeblogController < ActionController::Base
|
||||
layout "weblog/layout"
|
||||
|
||||
def index
|
||||
@posts = Post.find_all
|
||||
end
|
||||
|
||||
def display
|
||||
@post = Post.find(:params[:id])
|
||||
end
|
||||
|
||||
def new
|
||||
@post = Post.new
|
||||
end
|
||||
|
||||
def create
|
||||
@post = Post.create(params[:post])
|
||||
redirect_to :action => "display", :id => @post.id
|
||||
end
|
||||
end
|
||||
|
||||
WeblogController::Base.template_root = File.dirname(__FILE__)
|
||||
WeblogController.process_cgi if $0 == __FILE__
|
||||
|
||||
The last two lines are responsible for telling ActionController where the
|
||||
template files are located and actually running the controller on a new
|
||||
request from the web-server (like to be Apache).
|
||||
|
||||
And the templates look like this:
|
||||
|
||||
weblog/layout.rhtml:
|
||||
<html><body>
|
||||
<%= @content_for_layout %>
|
||||
</body></html>
|
||||
|
||||
weblog/index.rhtml:
|
||||
<% for post in @posts %>
|
||||
<p><%= link_to(post.title, :action => "display", :id => post.id %></p>
|
||||
<% end %>
|
||||
|
||||
weblog/display.rhtml:
|
||||
<p>
|
||||
<b><%= post.title %></b><br/>
|
||||
<b><%= post.content %></b>
|
||||
</p>
|
||||
|
||||
weblog/new.rhtml:
|
||||
<%= form "post" %>
|
||||
|
||||
This simple setup will list all the posts in the system on the index page,
|
||||
which is called by accessing /weblog/. It uses the form builder for the Active
|
||||
Record model to make the new screen, which in turn hands everything over to
|
||||
the create action (that's the default target for the form builder when given a
|
||||
new model). After creating the post, it'll redirect to the display page using
|
||||
an URL such as /weblog/display/5 (where 5 is the id of the post).
|
||||
|
||||
|
||||
== Examples
|
||||
|
||||
Action Pack ships with three examples that all demonstrate an increasingly
|
||||
detailed view of the possibilities. First is blog_controller that is just a
|
||||
single file for the whole MVC (but still split into separate parts). Second is
|
||||
the debate_controller that uses separate template files and multiple screens.
|
||||
Third is the address_book_controller that uses the layout feature to separate
|
||||
template casing from content.
|
||||
|
||||
Please note that you might need to change the "shebang" line to
|
||||
#!/usr/local/env ruby, if your Ruby is not placed in /usr/local/bin/ruby
|
||||
|
||||
|
||||
== Download
|
||||
|
||||
The latest version of Action Pack can be found at
|
||||
|
||||
* http://rubyforge.org/project/showfiles.php?group_id=249
|
||||
|
||||
Documentation can be found at
|
||||
|
||||
* http://ap.rubyonrails.com
|
||||
|
||||
|
||||
== Installation
|
||||
|
||||
You can install Action Pack with the following command.
|
||||
|
||||
% [sudo] ruby install.rb
|
||||
|
||||
from its distribution directory.
|
||||
|
||||
|
||||
== License
|
||||
|
||||
Action Pack is released under the MIT license.
|
||||
|
||||
|
||||
== Support
|
||||
|
||||
The Action Pack homepage is http://www.rubyonrails.com. You can find
|
||||
the Action Pack RubyForge page at http://rubyforge.org/projects/actionpack.
|
||||
And as Jim from Rake says:
|
||||
|
||||
Feel free to submit commits or feature requests. If you send a patch,
|
||||
remember to update the corresponding unit tests. If fact, I prefer
|
||||
new feature to be submitted in the form of new unit tests.
|
||||
|
||||
For other information, feel free to ask on the ruby-talk mailing list (which
|
||||
is mirrored to comp.lang.ruby) or contact mailto:david@loudthinking.com.
|
||||
25
tracks/vendor/rails/actionpack/RUNNING_UNIT_TESTS
vendored
Normal file
25
tracks/vendor/rails/actionpack/RUNNING_UNIT_TESTS
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
== Running with Rake
|
||||
|
||||
The easiest way to run the unit tests is through Rake. The default task runs
|
||||
the entire test suite for all classes. For more information, checkout the
|
||||
full array of rake tasks with "rake -T"
|
||||
|
||||
Rake can be found at http://rake.rubyforge.org
|
||||
|
||||
== Running by hand
|
||||
|
||||
If you only want to run a single test suite, or don't want to bother with Rake,
|
||||
you can do so with something like:
|
||||
|
||||
ruby controller/base_tests.rb
|
||||
|
||||
== Dependency on ActiveRecord and database setup
|
||||
|
||||
Test cases in test/controller/active_record_assertions.rb depend on having
|
||||
activerecord installed and configured in a particular way. See comment in the
|
||||
test file itself for details. If ActiveRecord is not in
|
||||
actionpack/../activerecord directory, these tests are skipped. If activerecord
|
||||
is installed, but not configured as expected, the tests will fail.
|
||||
|
||||
Other tests are runnable from a fresh copy of actionpack without any configuration.
|
||||
|
||||
24
tracks/vendor/rails/actionpack/examples/.htaccess
vendored
Normal file
24
tracks/vendor/rails/actionpack/examples/.htaccess
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<IfModule mod_ruby.c>
|
||||
RubyRequire apache/ruby-run
|
||||
RubySafeLevel 0
|
||||
|
||||
<Files *.rbx>
|
||||
SetHandler ruby-object
|
||||
RubyHandler Apache::RubyRun.instance
|
||||
</Files>
|
||||
</IfModule>
|
||||
|
||||
|
||||
RewriteEngine On
|
||||
RewriteRule ^fcgi/([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([0-9]+)$ /$1_controller.fcgi?action=$2&id=$3 [QSA]
|
||||
RewriteRule ^fcgi/([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)$ /$1_controller.fcgi?action=$2 [QSA]
|
||||
RewriteRule ^fcgi/([-_a-zA-Z0-9]+)/$ /$1_controller.fcgi?action=index [QSA]
|
||||
|
||||
RewriteRule ^modruby/([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([0-9]+)$ /$1_controller.rbx?action=$2&id=$3 [QSA]
|
||||
RewriteRule ^modruby/([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)$ /$1_controller.rbx?action=$2 [QSA]
|
||||
RewriteRule ^modruby/([-_a-zA-Z0-9]+)/$ /$1_controller.rbx?action=index [QSA]
|
||||
|
||||
RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([0-9]+)$ /$1_controller.cgi?action=$2&id=$3 [QSA]
|
||||
RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)$ /$1_controller.cgi?action=$2 [QSA]
|
||||
RewriteRule ^([-_a-zA-Z0-9]+)/$ /$1_controller.cgi?action=index [QSA]
|
||||
|
||||
33
tracks/vendor/rails/actionpack/examples/address_book/index.rhtml
vendored
Normal file
33
tracks/vendor/rails/actionpack/examples/address_book/index.rhtml
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<h1>Address Book</h1>
|
||||
|
||||
<% if @people.empty? %>
|
||||
<p>No people in the address book yet</p>
|
||||
<% else %>
|
||||
<table>
|
||||
<tr><th>Name</th><th>Email Address</th><th>Phone Number</th></tr>
|
||||
<% for person in @people %>
|
||||
<tr><td><%= person.name %></td><td><%= person.email_address %></td><td><%= person.phone_number %></td></tr>
|
||||
<% end %>
|
||||
</table>
|
||||
<% end %>
|
||||
|
||||
<form action="create_person">
|
||||
<p>
|
||||
Name:<br />
|
||||
<input type="text" name="person[name]">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Email address:<br />
|
||||
<input type="text" name="person[email_address]">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Phone number:<br />
|
||||
<input type="text" name="person[phone_number]">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="submit" value="Create Person">
|
||||
</p>
|
||||
</form>
|
||||
8
tracks/vendor/rails/actionpack/examples/address_book/layout.rhtml
vendored
Normal file
8
tracks/vendor/rails/actionpack/examples/address_book/layout.rhtml
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head>
|
||||
<title><%= @title || "Untitled" %></title>
|
||||
</head>
|
||||
<body>
|
||||
<%= @content_for_layout %>
|
||||
</body>
|
||||
</html>
|
||||
9
tracks/vendor/rails/actionpack/examples/address_book_controller.cgi
vendored
Normal file
9
tracks/vendor/rails/actionpack/examples/address_book_controller.cgi
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#!/usr/local/bin/ruby
|
||||
|
||||
require "address_book_controller"
|
||||
|
||||
begin
|
||||
AddressBookController.process_cgi(CGI.new)
|
||||
rescue => e
|
||||
CGI.new.out { "#{e.class}: #{e.message}" }
|
||||
end
|
||||
6
tracks/vendor/rails/actionpack/examples/address_book_controller.fcgi
vendored
Normal file
6
tracks/vendor/rails/actionpack/examples/address_book_controller.fcgi
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/local/bin/ruby
|
||||
|
||||
require "address_book_controller"
|
||||
require "fcgi"
|
||||
|
||||
FCGI.each_cgi { |cgi| AddressBookController.process_cgi(cgi) }
|
||||
52
tracks/vendor/rails/actionpack/examples/address_book_controller.rb
vendored
Normal file
52
tracks/vendor/rails/actionpack/examples/address_book_controller.rb
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
$:.unshift(File.dirname(__FILE__) + "/../lib")
|
||||
|
||||
require "action_controller"
|
||||
require "action_controller/test_process"
|
||||
|
||||
Person = Struct.new("Person", :id, :name, :email_address, :phone_number)
|
||||
|
||||
class AddressBookService
|
||||
attr_reader :people
|
||||
|
||||
def initialize() @people = [] end
|
||||
def create_person(data) people.unshift(Person.new(next_person_id, data["name"], data["email_address"], data["phone_number"])) end
|
||||
def find_person(topic_id) people.select { |person| person.id == person.to_i }.first end
|
||||
def next_person_id() people.first.id + 1 end
|
||||
end
|
||||
|
||||
class AddressBookController < ActionController::Base
|
||||
layout "address_book/layout"
|
||||
|
||||
before_filter :initialize_session_storage
|
||||
|
||||
# Could also have used a proc
|
||||
# before_filter proc { |c| c.instance_variable_set("@address_book", c.session["address_book"] ||= AddressBookService.new) }
|
||||
|
||||
def index
|
||||
@title = "Address Book"
|
||||
@people = @address_book.people
|
||||
end
|
||||
|
||||
def person
|
||||
@person = @address_book.find_person(@params["id"])
|
||||
end
|
||||
|
||||
def create_person
|
||||
@address_book.create_person(@params["person"])
|
||||
redirect_to :action => "index"
|
||||
end
|
||||
|
||||
private
|
||||
def initialize_session_storage
|
||||
@address_book = @session["address_book"] ||= AddressBookService.new
|
||||
end
|
||||
end
|
||||
|
||||
ActionController::Base.template_root = File.dirname(__FILE__)
|
||||
# ActionController::Base.logger = Logger.new("debug.log") # Remove first comment to turn on logging in current dir
|
||||
|
||||
begin
|
||||
AddressBookController.process_cgi(CGI.new) if $0 == __FILE__
|
||||
rescue => e
|
||||
CGI.new.out { "#{e.class}: #{e.message}" }
|
||||
end
|
||||
4
tracks/vendor/rails/actionpack/examples/address_book_controller.rbx
vendored
Normal file
4
tracks/vendor/rails/actionpack/examples/address_book_controller.rbx
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/local/bin/ruby
|
||||
|
||||
require "address_book_controller"
|
||||
AddressBookController.process_cgi(CGI.new)
|
||||
52
tracks/vendor/rails/actionpack/examples/benchmark.rb
vendored
Normal file
52
tracks/vendor/rails/actionpack/examples/benchmark.rb
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
$:.unshift(File.dirname(__FILE__) + "/../lib")
|
||||
|
||||
require "action_controller"
|
||||
require 'action_controller/test_process'
|
||||
|
||||
Person = Struct.new("Person", :name, :address, :age)
|
||||
|
||||
class BenchmarkController < ActionController::Base
|
||||
def message
|
||||
render_text "hello world"
|
||||
end
|
||||
|
||||
def list
|
||||
@people = [ Person.new("David"), Person.new("Mary") ]
|
||||
render_template "hello: <% for person in @people %>Name: <%= person.name %><% end %>"
|
||||
end
|
||||
|
||||
def form_helper
|
||||
@person = Person.new "david", "hyacintvej", 24
|
||||
render_template(
|
||||
"<% person = Person.new 'Mary', 'hyacintvej', 22 %> " +
|
||||
"change the name <%= text_field 'person', 'name' %> and <%= text_field 'person', 'address' %> and <%= text_field 'person', 'age' %>"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
#ActionController::Base.template_root = File.dirname(__FILE__)
|
||||
|
||||
require "benchmark"
|
||||
|
||||
RUNS = ARGV[0] ? ARGV[0].to_i : 50
|
||||
|
||||
require "profile" if ARGV[1]
|
||||
|
||||
runtime = Benchmark.measure {
|
||||
RUNS.times { BenchmarkController.process_test(ActionController::TestRequest.new({ "action" => "list" })) }
|
||||
}
|
||||
|
||||
puts "List: #{RUNS / runtime.real}"
|
||||
|
||||
|
||||
runtime = Benchmark.measure {
|
||||
RUNS.times { BenchmarkController.process_test(ActionController::TestRequest.new({ "action" => "message" })) }
|
||||
}
|
||||
|
||||
puts "Message: #{RUNS / runtime.real}"
|
||||
|
||||
runtime = Benchmark.measure {
|
||||
RUNS.times { BenchmarkController.process_test(ActionController::TestRequest.new({ "action" => "form_helper" })) }
|
||||
}
|
||||
|
||||
puts "Form helper: #{RUNS / runtime.real}"
|
||||
89
tracks/vendor/rails/actionpack/examples/benchmark_with_ar.fcgi
vendored
Normal file
89
tracks/vendor/rails/actionpack/examples/benchmark_with_ar.fcgi
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#!/usr/local/bin/ruby
|
||||
|
||||
begin
|
||||
|
||||
$:.unshift(File.dirname(__FILE__) + "/../lib")
|
||||
$:.unshift(File.dirname(__FILE__) + "/../../../edge/activerecord/lib")
|
||||
|
||||
require 'fcgi'
|
||||
require 'action_controller'
|
||||
require 'action_controller/test_process'
|
||||
|
||||
require 'active_record'
|
||||
|
||||
class Post < ActiveRecord::Base; end
|
||||
|
||||
ActiveRecord::Base.establish_connection(:adapter => "mysql", :database => "basecamp")
|
||||
|
||||
SESSION_OPTIONS = { "database_manager" => CGI::Session::MemoryStore }
|
||||
|
||||
class TestController < ActionController::Base
|
||||
def index
|
||||
render_template <<-EOT
|
||||
<% for post in Post.find_all(nil,nil,100) %>
|
||||
<%= post.title %>
|
||||
<% end %>
|
||||
EOT
|
||||
end
|
||||
|
||||
def show_one
|
||||
render_template <<-EOT
|
||||
<%= Post.find_first.title %>
|
||||
EOT
|
||||
end
|
||||
|
||||
def text
|
||||
render_text "hello world"
|
||||
end
|
||||
|
||||
def erb_text
|
||||
render_template "hello <%= 'world' %>"
|
||||
end
|
||||
|
||||
def erb_loop
|
||||
render_template <<-EOT
|
||||
<% for post in 1..100 %>
|
||||
<%= post %>
|
||||
<% end %>
|
||||
EOT
|
||||
end
|
||||
|
||||
def rescue_action(e) puts e.message + e.backtrace.join("\n") end
|
||||
end
|
||||
|
||||
if ARGV.empty? && ENV["REQUEST_URI"]
|
||||
FCGI.each_cgi do |cgi|
|
||||
TestController.process(ActionController::CgiRequest.new(cgi, SESSION_OPTIONS), ActionController::CgiResponse.new(cgi)).out
|
||||
end
|
||||
else
|
||||
if ARGV.empty?
|
||||
cgi = CGI.new
|
||||
end
|
||||
|
||||
require 'benchmark'
|
||||
require 'profile' if ARGV[2] == "profile"
|
||||
|
||||
RUNS = ARGV[1] ? ARGV[1].to_i : 50
|
||||
|
||||
runtime = Benchmark::measure {
|
||||
RUNS.times {
|
||||
if ARGV.empty?
|
||||
TestController.process(ActionController::CgiRequest.new(cgi, SESSION_OPTIONS), ActionController::CgiResponse.new(cgi))
|
||||
else
|
||||
response = TestController.process_test(
|
||||
ActionController::TestRequest.new({"action" => ARGV[0]})
|
||||
)
|
||||
puts(response.body) if ARGV[2] == "show"
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
puts "Runs: #{RUNS}"
|
||||
puts "Avg. runtime: #{runtime.real / RUNS}"
|
||||
puts "Requests/second: #{RUNS / runtime.real}"
|
||||
end
|
||||
|
||||
rescue Exception => e
|
||||
# CGI.new.out { "<pre>" + e.message + e.backtrace.join("\n") + "</pre>" }
|
||||
$stderr << e.message + e.backtrace.join("\n")
|
||||
end
|
||||
53
tracks/vendor/rails/actionpack/examples/blog_controller.cgi
vendored
Normal file
53
tracks/vendor/rails/actionpack/examples/blog_controller.cgi
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#!/usr/local/bin/ruby
|
||||
|
||||
$:.unshift(File.dirname(__FILE__) + "/../lib")
|
||||
|
||||
require "action_controller"
|
||||
|
||||
Post = Struct.new("Post", :title, :body)
|
||||
|
||||
class BlogController < ActionController::Base
|
||||
before_filter :initialize_session_storage
|
||||
|
||||
def index
|
||||
@posts = @session["posts"]
|
||||
|
||||
render_template <<-"EOF"
|
||||
<html><body>
|
||||
<%= @flash["alert"] %>
|
||||
<h1>Posts</h1>
|
||||
<% @posts.each do |post| %>
|
||||
<p><b><%= post.title %></b><br /><%= post.body %></p>
|
||||
<% end %>
|
||||
|
||||
<h1>Create post</h1>
|
||||
<form action="create">
|
||||
Title: <input type="text" name="post[title]"><br>
|
||||
Body: <textarea name="post[body]"></textarea><br>
|
||||
<input type="submit" value="save">
|
||||
</form>
|
||||
|
||||
</body></html>
|
||||
EOF
|
||||
end
|
||||
|
||||
def create
|
||||
@session["posts"].unshift(Post.new(@params["post"]["title"], @params["post"]["body"]))
|
||||
flash["alert"] = "New post added!"
|
||||
redirect_to :action => "index"
|
||||
end
|
||||
|
||||
private
|
||||
def initialize_session_storage
|
||||
@session["posts"] = [] if @session["posts"].nil?
|
||||
end
|
||||
end
|
||||
|
||||
ActionController::Base.template_root = File.dirname(__FILE__)
|
||||
# ActionController::Base.logger = Logger.new("debug.log") # Remove first comment to turn on logging in current dir
|
||||
|
||||
begin
|
||||
BlogController.process_cgi(CGI.new) if $0 == __FILE__
|
||||
rescue => e
|
||||
CGI.new.out { "#{e.class}: #{e.message}" }
|
||||
end
|
||||
14
tracks/vendor/rails/actionpack/examples/debate/index.rhtml
vendored
Normal file
14
tracks/vendor/rails/actionpack/examples/debate/index.rhtml
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<html>
|
||||
<body>
|
||||
<h1>Topics</h1>
|
||||
|
||||
<%= link_to "New topic", :action => "new_topic" %>
|
||||
|
||||
<ul>
|
||||
<% for topic in @topics %>
|
||||
<li><%= link_to "#{topic.title} (#{topic.replies.length} replies)", :action => "topic", :path_params => { "id" => topic.id } %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
22
tracks/vendor/rails/actionpack/examples/debate/new_topic.rhtml
vendored
Normal file
22
tracks/vendor/rails/actionpack/examples/debate/new_topic.rhtml
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<html>
|
||||
<body>
|
||||
<h1>New topic</h1>
|
||||
|
||||
<form action="<%= url_for(:action => "create_topic") %>" method="post">
|
||||
<p>
|
||||
Title:<br>
|
||||
<input type="text" name="topic[title]">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Body:<br>
|
||||
<textarea name="topic[body]" style="width: 200px; height: 200px"></textarea>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="submit" value="Create topic">
|
||||
</p>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
32
tracks/vendor/rails/actionpack/examples/debate/topic.rhtml
vendored
Normal file
32
tracks/vendor/rails/actionpack/examples/debate/topic.rhtml
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<html>
|
||||
<body>
|
||||
<h1><%= @topic.title %></h1>
|
||||
|
||||
<p><%= @topic.body %></p>
|
||||
|
||||
<%= link_to "Back to topics", :action => "index" %>
|
||||
|
||||
<% unless @topic.replies.empty? %>
|
||||
<h2>Replies</h2>
|
||||
<ol>
|
||||
<% for reply in @topic.replies %>
|
||||
<li><%= reply.body %></li>
|
||||
<% end %>
|
||||
</ol>
|
||||
<% end %>
|
||||
|
||||
<h2>Reply to this topic</h2>
|
||||
|
||||
<form action="<%= url_for(:action => "create_reply") %>" method="post">
|
||||
<input type="hidden" name="reply[topic_id]" value="<%= @topic.id %>">
|
||||
<p>
|
||||
<textarea name="reply[body]" style="width: 200px; height: 200px"></textarea>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="submit" value="Create reply">
|
||||
</p>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
57
tracks/vendor/rails/actionpack/examples/debate_controller.cgi
vendored
Normal file
57
tracks/vendor/rails/actionpack/examples/debate_controller.cgi
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/local/bin/ruby
|
||||
|
||||
$:.unshift(File.dirname(__FILE__) + "/../lib")
|
||||
|
||||
require "action_controller"
|
||||
|
||||
Topic = Struct.new("Topic", :id, :title, :body, :replies)
|
||||
Reply = Struct.new("Reply", :body)
|
||||
|
||||
class DebateService
|
||||
attr_reader :topics
|
||||
|
||||
def initialize() @topics = [] end
|
||||
def create_topic(data) topics.unshift(Topic.new(next_topic_id, data["title"], data["body"], [])) end
|
||||
def create_reply(data) find_topic(data["topic_id"]).replies << Reply.new(data["body"]) end
|
||||
def find_topic(topic_id) topics.select { |topic| topic.id == topic_id.to_i }.first end
|
||||
def next_topic_id() topics.first.id + 1 end
|
||||
end
|
||||
|
||||
class DebateController < ActionController::Base
|
||||
before_filter :initialize_session_storage
|
||||
|
||||
def index
|
||||
@topics = @debate.topics
|
||||
end
|
||||
|
||||
def topic
|
||||
@topic = @debate.find_topic(@params["id"])
|
||||
end
|
||||
|
||||
# def new_topic() end <-- This is not needed as the template doesn't require any assigns
|
||||
|
||||
def create_topic
|
||||
@debate.create_topic(@params["topic"])
|
||||
redirect_to :action => "index"
|
||||
end
|
||||
|
||||
def create_reply
|
||||
@debate.create_reply(@params["reply"])
|
||||
redirect_to :action => "topic", :path_params => { "id" => @params["reply"]["topic_id"] }
|
||||
end
|
||||
|
||||
private
|
||||
def initialize_session_storage
|
||||
@session["debate"] = DebateService.new if @session["debate"].nil?
|
||||
@debate = @session["debate"]
|
||||
end
|
||||
end
|
||||
|
||||
ActionController::Base.template_root = File.dirname(__FILE__)
|
||||
# ActionController::Base.logger = Logger.new("debug.log") # Remove first comment to turn on logging in current dir
|
||||
|
||||
begin
|
||||
DebateController.process_cgi(CGI.new) if $0 == __FILE__
|
||||
rescue => e
|
||||
CGI.new.out { "#{e.class}: #{e.message}" }
|
||||
end
|
||||
30
tracks/vendor/rails/actionpack/install.rb
vendored
Normal file
30
tracks/vendor/rails/actionpack/install.rb
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
require 'rbconfig'
|
||||
require 'find'
|
||||
require 'ftools'
|
||||
|
||||
include Config
|
||||
|
||||
# this was adapted from rdoc's install.rb by ways of Log4r
|
||||
|
||||
$sitedir = CONFIG["sitelibdir"]
|
||||
unless $sitedir
|
||||
version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"]
|
||||
$libdir = File.join(CONFIG["libdir"], "ruby", version)
|
||||
$sitedir = $:.find {|x| x =~ /site_ruby/ }
|
||||
if !$sitedir
|
||||
$sitedir = File.join($libdir, "site_ruby")
|
||||
elsif $sitedir !~ Regexp.quote(version)
|
||||
$sitedir = File.join($sitedir, version)
|
||||
end
|
||||
end
|
||||
|
||||
# the acual gruntwork
|
||||
Dir.chdir("lib")
|
||||
|
||||
Find.find("action_controller", "action_controller.rb", "action_view", "action_view.rb") { |f|
|
||||
if f[-3..-1] == ".rb"
|
||||
File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true)
|
||||
else
|
||||
File::makedirs(File.join($sitedir, *f.split(/\//)))
|
||||
end
|
||||
}
|
||||
79
tracks/vendor/rails/actionpack/lib/action_controller.rb
vendored
Normal file
79
tracks/vendor/rails/actionpack/lib/action_controller.rb
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#--
|
||||
# Copyright (c) 2004 David Heinemeier Hansson
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#++
|
||||
|
||||
$:.unshift(File.dirname(__FILE__)) unless
|
||||
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
||||
|
||||
unless defined?(ActiveSupport)
|
||||
begin
|
||||
$:.unshift(File.dirname(__FILE__) + "/../../activesupport/lib")
|
||||
require 'active_support'
|
||||
rescue LoadError
|
||||
require 'rubygems'
|
||||
require_gem 'activesupport'
|
||||
end
|
||||
end
|
||||
|
||||
require 'action_controller/base'
|
||||
require 'action_controller/deprecated_redirects'
|
||||
require 'action_controller/rescue'
|
||||
require 'action_controller/benchmarking'
|
||||
require 'action_controller/filters'
|
||||
require 'action_controller/layout'
|
||||
require 'action_controller/flash'
|
||||
require 'action_controller/dependencies'
|
||||
require 'action_controller/pagination'
|
||||
require 'action_controller/scaffolding'
|
||||
require 'action_controller/helpers'
|
||||
require 'action_controller/cookies'
|
||||
require 'action_controller/cgi_process'
|
||||
require 'action_controller/caching'
|
||||
require 'action_controller/components'
|
||||
require 'action_controller/verification'
|
||||
require 'action_controller/streaming'
|
||||
require 'action_controller/session_management'
|
||||
require 'action_controller/macros/auto_complete'
|
||||
require 'action_controller/macros/in_place_editing'
|
||||
|
||||
require 'action_view'
|
||||
ActionController::Base.template_class = ActionView::Base
|
||||
|
||||
ActionController::Base.class_eval do
|
||||
include ActionController::Filters
|
||||
include ActionController::Layout
|
||||
include ActionController::Flash
|
||||
include ActionController::Benchmarking
|
||||
include ActionController::Rescue
|
||||
include ActionController::Dependencies
|
||||
include ActionController::Pagination
|
||||
include ActionController::Scaffolding
|
||||
include ActionController::Helpers
|
||||
include ActionController::Cookies
|
||||
include ActionController::Caching
|
||||
include ActionController::Components
|
||||
include ActionController::Verification
|
||||
include ActionController::Streaming
|
||||
include ActionController::SessionManagement
|
||||
include ActionController::Macros::AutoComplete
|
||||
include ActionController::Macros::InPlaceEditing
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue