ape 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. data/CHANGELOG +1 -0
  2. data/LICENSE +19 -0
  3. data/Manifest +45 -0
  4. data/README +12 -0
  5. data/ape.gemspec +57 -0
  6. data/bin/ape_server +28 -0
  7. data/lib/ape.rb +982 -0
  8. data/lib/ape/atomURI.rb +73 -0
  9. data/lib/ape/auth/google_login_credentials.rb +96 -0
  10. data/lib/ape/auth/wsse_credentials.rb +25 -0
  11. data/lib/ape/authent.rb +42 -0
  12. data/lib/ape/categories.rb +95 -0
  13. data/lib/ape/collection.rb +51 -0
  14. data/lib/ape/crumbs.rb +39 -0
  15. data/lib/ape/entry.rb +151 -0
  16. data/lib/ape/escaper.rb +29 -0
  17. data/lib/ape/feed.rb +117 -0
  18. data/lib/ape/handler.rb +34 -0
  19. data/lib/ape/html.rb +17 -0
  20. data/lib/ape/invoker.rb +54 -0
  21. data/lib/ape/invokers/deleter.rb +31 -0
  22. data/lib/ape/invokers/getter.rb +80 -0
  23. data/lib/ape/invokers/poster.rb +57 -0
  24. data/lib/ape/invokers/putter.rb +46 -0
  25. data/lib/ape/layout/ape.css +56 -0
  26. data/lib/ape/layout/ape_logo.png +0 -0
  27. data/lib/ape/layout/index.html +54 -0
  28. data/lib/ape/layout/info.png +0 -0
  29. data/lib/ape/names.rb +24 -0
  30. data/lib/ape/print_writer.rb +21 -0
  31. data/lib/ape/samples.rb +180 -0
  32. data/lib/ape/samples/atom_schema.txt +338 -0
  33. data/lib/ape/samples/basic_entry.eruby +16 -0
  34. data/lib/ape/samples/categories_schema.txt +69 -0
  35. data/lib/ape/samples/mini_entry.eruby +8 -0
  36. data/lib/ape/samples/service_schema.txt +187 -0
  37. data/lib/ape/samples/unclean_xhtml_entry.eruby +21 -0
  38. data/lib/ape/server.rb +32 -0
  39. data/lib/ape/service.rb +12 -0
  40. data/lib/ape/validator.rb +65 -0
  41. data/lib/ape/version.rb +9 -0
  42. data/scripts/go.rb +29 -0
  43. data/test/test_helper.rb +17 -0
  44. data/test/unit/authent_test.rb +35 -0
  45. data/test/unit/invoker_test.rb +25 -0
  46. data/test/unit/samples_test.rb +36 -0
  47. metadata +111 -0
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0" ?>
2
+ <entry xmlns="http://www.w3.org/2005/Atom">
3
+ <id><%= id %></id>
4
+ <title><%= title %></title>
5
+ <author><name>The Atom Protocol Exerciser</name></author>
6
+ <updated><%= now %></updated>
7
+ <link href='http://www.tbray.org/ape'/>
8
+ <summary type='html'><%= summary %></summary>
9
+ <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
10
+ <p>A test post from the &lt;APE&gt; at #{updated}</p>
11
+ <p>If you see this in an entry, it's probably a left-over from an
12
+ unsuccessful Ape run; feel free to delete it.</p>
13
+ </div>
14
+ </content>
15
+ <dc:subject xmlns:dc='<%=subject%>'>Simians</dc:subject>
16
+ </entry>
@@ -0,0 +1,69 @@
1
+ # -*- rnc -*-
2
+ # RELAX NG Compact Syntax Grammar for the Atom Protocol
3
+
4
+ namespace app = "http://www.w3.org/2007/app"
5
+ namespace atom = "http://www.w3.org/2005/Atom"
6
+ namespace xsd = "http://www.w3.org/2001/XMLSchema"
7
+ namespace local = ""
8
+
9
+ start = appCategories
10
+
11
+ atomCommonAttributes =
12
+ attribute xml:base { atomURI }?,
13
+ attribute xml:lang { atomLanguageTag }?,
14
+ undefinedAttribute*
15
+
16
+ undefinedAttribute =
17
+ attribute * - (xml:base | xml:lang | local:*) { text }
18
+
19
+ atomURI = text
20
+
21
+ atomLanguageTag = xsd:string {
22
+ pattern = "[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*"
23
+ }
24
+
25
+
26
+ atomCategory =
27
+ element atom:category {
28
+ atomCommonAttributes,
29
+ attribute term { text },
30
+ attribute scheme { atomURI }?,
31
+ attribute label { text }?,
32
+ undefinedContent
33
+ }
34
+
35
+ appInlineCategories =
36
+ element app:categories {
37
+ attribute fixed { "yes" | "no" }?,
38
+ attribute scheme { atomURI }?,
39
+ (atomCategory*)
40
+ }
41
+
42
+ appOutOfLineCategories =
43
+ element app:categories {
44
+ attribute href { atomURI },
45
+ (empty)
46
+ }
47
+
48
+ appCategories = appInlineCategories | appOutOfLineCategories
49
+
50
+
51
+ # Extensibility
52
+
53
+ undefinedContent = (text|anyForeignElement)*
54
+
55
+ anyElement =
56
+ element * {
57
+ (attribute * { text }
58
+ | text
59
+ | anyElement)*
60
+ }
61
+
62
+ anyForeignElement =
63
+ element * - atom:* {
64
+ (attribute * { text }
65
+ | text
66
+ | anyElement)*
67
+ }
68
+
69
+ # EOF
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" ?>
2
+ <entry xmlns="http://www.w3.org/2005/Atom">
3
+ <title>Entry Mini-1</title>
4
+ <author><name>EM</name></author>
5
+ <id><%= id %></id>
6
+ <updated><%= now %></updated>
7
+ <content>Content of Mini-1</content>
8
+ </entry>
@@ -0,0 +1,187 @@
1
+ # -*- rnc -*-
2
+ # RELAX NG Compact Syntax Grammar for the Atom Protocol
3
+
4
+ namespace app = "http://www.w3.org/2007/app"
5
+ namespace atom = "http://www.w3.org/2005/Atom"
6
+ namespace xsd = "http://www.w3.org/2001/XMLSchema"
7
+ namespace xhtml = "http://www.w3.org/1999/xhtml"
8
+ namespace local = ""
9
+
10
+ start = appService
11
+
12
+ # common:attrs
13
+
14
+ atomURI = text
15
+
16
+ appCommonAttributes =
17
+ attribute xml:base { atomURI }?,
18
+ attribute xml:lang { atomLanguageTag }?,
19
+ attribute xml:space {"default"|"preserved"}?,
20
+ undefinedAttribute*
21
+
22
+
23
+ atomCommonAttributes = appCommonAttributes
24
+
25
+ undefinedAttribute =
26
+ attribute * - (xml:base | xml:space | xml:lang | local:*) { text }
27
+
28
+ atomLanguageTag = xsd:string {
29
+ pattern = "([A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*)?"
30
+ }
31
+
32
+ atomDateConstruct =
33
+ appCommonAttributes,
34
+ xsd:dateTime
35
+
36
+ # app:service
37
+
38
+ appService =
39
+ element app:service {
40
+ appCommonAttributes,
41
+ ( appWorkspace+
42
+ & extensionElement* )
43
+ }
44
+
45
+ # app:workspace
46
+
47
+ appWorkspace =
48
+ element app:workspace {
49
+ appCommonAttributes,
50
+ ( atomTitle
51
+ & appCollection*
52
+ & extensionSansTitleElement* )
53
+ }
54
+
55
+ atomTitle = element atom:title { atomTextConstruct }
56
+
57
+ # app:collection
58
+
59
+ appCollection =
60
+ element app:collection {
61
+ appCommonAttributes,
62
+ attribute href { atomURI },
63
+ ( atomTitle
64
+ & appAccept*
65
+ & appCategories*
66
+ & extensionSansTitleElement* )
67
+ }
68
+
69
+ # app:categories
70
+
71
+ atomCategory =
72
+ element atom:category {
73
+ atomCommonAttributes,
74
+ attribute term { text },
75
+ attribute scheme { atomURI }?,
76
+ attribute label { text }?,
77
+ undefinedContent
78
+ }
79
+
80
+ appInlineCategories =
81
+ element app:categories {
82
+ attribute fixed { "yes" | "no" }?,
83
+ attribute scheme { atomURI }?,
84
+ (atomCategory*,
85
+ undefinedContent)
86
+ }
87
+
88
+ appOutOfLineCategories =
89
+ element app:categories {
90
+ attribute href { atomURI },
91
+ undefinedContent
92
+ }
93
+
94
+ appCategories = appInlineCategories | appOutOfLineCategories
95
+
96
+
97
+ # app:accept
98
+
99
+ appAccept =
100
+ element app:accept {
101
+ appCommonAttributes,
102
+ ( text? )
103
+ }
104
+
105
+ # Simple Extension
106
+
107
+ simpleSansTitleExtensionElement =
108
+ element * - (app:*|atom:title) {
109
+ text
110
+ }
111
+
112
+ simpleExtensionElement =
113
+ element * - (app:*) {
114
+ text
115
+ }
116
+
117
+
118
+ # Structured Extension
119
+
120
+ structuredSansTitleExtensionElement =
121
+ element * - (app:*|atom:title) {
122
+ (attribute * { text }+,
123
+ (text|anyElement)*)
124
+ | (attribute * { text }*,
125
+ (text?, anyElement+, (text|anyElement)*))
126
+ }
127
+
128
+ structuredExtensionElement =
129
+ element * - (app:*) {
130
+ (attribute * { text }+,
131
+ (text|anyElement)*)
132
+ | (attribute * { text }*,
133
+ (text?, anyElement+, (text|anyElement)*))
134
+ }
135
+
136
+ # Other Extensibility
137
+
138
+ extensionSansTitleElement =
139
+ simpleSansTitleExtensionElement|structuredSansTitleExtensionElement
140
+
141
+
142
+ extensionElement =
143
+ simpleExtensionElement | structuredExtensionElement
144
+
145
+ undefinedContent = (text|anyForeignElement)*
146
+
147
+ # Extensions
148
+
149
+ anyElement =
150
+ element * {
151
+ (attribute * { text }
152
+ | text
153
+ | anyElement)*
154
+ }
155
+
156
+ anyForeignElement =
157
+ element * - app:* {
158
+ (attribute * { text }
159
+ | text
160
+ | anyElement)*
161
+ }
162
+
163
+ atomPlainTextConstruct =
164
+ atomCommonAttributes,
165
+ attribute type { "text" | "html" }?,
166
+ text
167
+
168
+ atomXHTMLTextConstruct =
169
+ atomCommonAttributes,
170
+ attribute type { "xhtml" },
171
+ xhtmlDiv
172
+
173
+ atomTextConstruct = atomPlainTextConstruct | atomXHTMLTextConstruct
174
+
175
+ anyXHTML = element xhtml:* {
176
+ (attribute * { text }
177
+ | text
178
+ | anyXHTML)*
179
+ }
180
+
181
+ xhtmlDiv = element xhtml:div {
182
+ (attribute * { text }
183
+ | text
184
+ | anyXHTML)*
185
+ }
186
+
187
+ # EOF
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" ?>
2
+ <entry xmlns="http://www.w3.org/2005/Atom">
3
+ <title>Unclean!</title>
4
+ <author><name>The Atom Protocol Exerciser</name></author>
5
+ <id><%= id %></id>
6
+ <updated><%= now %></updated>
7
+ <summary type='xhtml'>
8
+ <div xmlns='http://www.w3.org/1999/xhtml'>
9
+ <p>hey</p>
10
+ <script src='http://www.example.com/xxx' />
11
+ <script>alert('XXX')</script>
12
+ <p id='x1' background="javascript:alert('XSS')">Hey</p>
13
+ </div>
14
+ </summary>
15
+ <content type='xhtml'>
16
+ <div xmlns='http://www.w3.org/1999/xhtml'>
17
+ <p id='x2' style='...whatever...'>OK</p><object>No No No</object>
18
+ <a href='/no-problemo'>aah</a><a href='javascript:evil'>ouch</a>
19
+ </div>
20
+ </content>
21
+ </entry>
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'mongrel'
3
+ require 'ape/handler'
4
+ require 'ape/samples'
5
+
6
+ module Ape
7
+ class Server
8
+ def self.run(options)
9
+ Samples.home = options[:home]
10
+
11
+ mongrel = Mongrel::Configurator.new(:host => options[:host], :port => options[:port]) do
12
+ log "=> Booting mongrel"
13
+ begin
14
+ log "=> The ape starting on http://#{options[:host]}:#{options[:port]}"
15
+ listener do
16
+ redirect '/', '/ape/index.html'
17
+ uri '/ape', :handler => Mongrel::DirHandler.new(File.dirname(__FILE__) + '/layout', true)
18
+ uri '/atompub/go', :handler => Handler.new
19
+ end
20
+ rescue Errno::EADDRINUSE
21
+ log "ERROR: Address (#{options[:host]}:#{options[:port]}) is already in use"
22
+ exit 1
23
+ end
24
+ trap("INT") { stop }
25
+ trap("TERM") { stop }
26
+ log "=> Ctrl-C to shutdown"
27
+ run
28
+ end
29
+ mongrel.join
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,12 @@
1
+ # Copyright © 2006 Sun Microsystems, Inc. All rights reserved
2
+ # Use is subject to license terms - see file "LICENSE"
3
+ require 'rexml/xpath'
4
+
5
+ module Ape
6
+ class Service
7
+ def Service.collections(service, uri)
8
+ nodes = REXML::XPath.match(service, '//app:collection', Names::XmlNamespaces)
9
+ nodes.collect { |n| Collection.new(n, uri) }
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,65 @@
1
+ # Copyright © 2006 Sun Microsystems, Inc. All rights reserved
2
+ # Use is subject to license terms - see file "LICENSE"
3
+
4
+ if RUBY_PLATFORM =~ /java/
5
+ require 'java'
6
+ CompactSchemaReader = com.thaiopensource.validate.rng.CompactSchemaReader
7
+ ValidationDriver = com.thaiopensource.validate.ValidationDriver
8
+ StringReader = java.io.StringReader
9
+ StringWriter = java.io.StringWriter
10
+ InputSource = org.xml.sax.InputSource
11
+ ErrorHandlerImpl = com.thaiopensource.xml.sax.ErrorHandlerImpl
12
+ PropertyMapBuilder = com.thaiopensource.util.PropertyMapBuilder
13
+ ValidateProperty = com.thaiopensource.validate.ValidateProperty
14
+ end
15
+
16
+ module Ape
17
+ class Validator
18
+
19
+ attr_reader :error
20
+
21
+ def Validator.validate(schema, text, name, ape)
22
+ # Can do this in JRuby, not native Ruby (sigh)
23
+ if RUBY_PLATFORM =~ /java/
24
+ rnc_validate(schema, text, name, ape)
25
+ else
26
+ true
27
+ end
28
+ end
29
+
30
+ def Validator.rnc_validate(schema, text, name, ape)
31
+ schemaError = StringWriter.new
32
+ schemaEH = ErrorHandlerImpl.new(schemaError)
33
+ properties = PropertyMapBuilder.new
34
+ properties.put(ValidateProperty::ERROR_HANDLER, schemaEH)
35
+ error = nil
36
+ driver = ValidationDriver.new(properties.toPropertyMap, CompactSchemaReader.getInstance)
37
+ if driver.loadSchema(InputSource.new(StringReader.new(schema)))
38
+ begin
39
+ if !driver.validate(InputSource.new(StringReader.new(text)))
40
+ error = schemaError.toString
41
+ end
42
+ rescue org.xml.sax.SAXParseException
43
+ error = $!.to_s.sub(/\n.*$/, '')
44
+ end
45
+ else
46
+ error = schemaError.toString
47
+ end
48
+
49
+ if !error
50
+ ape.good "#{name} passed schema validation."
51
+ true
52
+ else
53
+ # this kind of sucks, but I spent a looong time lost in a maze of twisty
54
+ # little passages without being able to figure out how to
55
+ # tell jing what name I'd like to call the InputSource
56
+ ape.error "#{name} failed schema validation:\n" + error.gsub('(unknown file):', 'Line ')
57
+ false
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end
64
+
65
+
@@ -0,0 +1,9 @@
1
+ module Ape
2
+ module VERSION
3
+ MAJOR = 1
4
+ MINOR = 0
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,29 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'cgi'
3
+ require 'html'
4
+ require 'ape'
5
+
6
+ debug = ENV['APE_DEBUG'] || false
7
+
8
+ cgi = debug ? CGI.new('html4') : CGI.new
9
+
10
+ if !cgi['uri'] || (cgi['uri'] == '')
11
+ HTML.error "URI argument is required"
12
+ end
13
+
14
+ uri = cgi['uri']
15
+ user = cgi['username']
16
+ pass = cgi['password']
17
+
18
+ ape = Ape::Ape.new({:crumbs => true, :output => 'html', :debug => debug})
19
+
20
+ if user == ''
21
+ ape.check(uri)
22
+ else
23
+ ape.check(uri, user, pass)
24
+ end
25
+ ape.report
26
+
27
+
28
+
29
+