ape 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+