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.
- data/CHANGELOG +1 -0
- data/LICENSE +19 -0
- data/Manifest +45 -0
- data/README +12 -0
- data/ape.gemspec +57 -0
- data/bin/ape_server +28 -0
- data/lib/ape.rb +982 -0
- data/lib/ape/atomURI.rb +73 -0
- data/lib/ape/auth/google_login_credentials.rb +96 -0
- data/lib/ape/auth/wsse_credentials.rb +25 -0
- data/lib/ape/authent.rb +42 -0
- data/lib/ape/categories.rb +95 -0
- data/lib/ape/collection.rb +51 -0
- data/lib/ape/crumbs.rb +39 -0
- data/lib/ape/entry.rb +151 -0
- data/lib/ape/escaper.rb +29 -0
- data/lib/ape/feed.rb +117 -0
- data/lib/ape/handler.rb +34 -0
- data/lib/ape/html.rb +17 -0
- data/lib/ape/invoker.rb +54 -0
- data/lib/ape/invokers/deleter.rb +31 -0
- data/lib/ape/invokers/getter.rb +80 -0
- data/lib/ape/invokers/poster.rb +57 -0
- data/lib/ape/invokers/putter.rb +46 -0
- data/lib/ape/layout/ape.css +56 -0
- data/lib/ape/layout/ape_logo.png +0 -0
- data/lib/ape/layout/index.html +54 -0
- data/lib/ape/layout/info.png +0 -0
- data/lib/ape/names.rb +24 -0
- data/lib/ape/print_writer.rb +21 -0
- data/lib/ape/samples.rb +180 -0
- data/lib/ape/samples/atom_schema.txt +338 -0
- data/lib/ape/samples/basic_entry.eruby +16 -0
- data/lib/ape/samples/categories_schema.txt +69 -0
- data/lib/ape/samples/mini_entry.eruby +8 -0
- data/lib/ape/samples/service_schema.txt +187 -0
- data/lib/ape/samples/unclean_xhtml_entry.eruby +21 -0
- data/lib/ape/server.rb +32 -0
- data/lib/ape/service.rb +12 -0
- data/lib/ape/validator.rb +65 -0
- data/lib/ape/version.rb +9 -0
- data/scripts/go.rb +29 -0
- data/test/test_helper.rb +17 -0
- data/test/unit/authent_test.rb +35 -0
- data/test/unit/invoker_test.rb +25 -0
- data/test/unit/samples_test.rb +36 -0
- 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 <APE> 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,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>
|
data/lib/ape/server.rb
ADDED
@@ -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
|
data/lib/ape/service.rb
ADDED
@@ -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
|
+
|
data/lib/ape/version.rb
ADDED
data/scripts/go.rb
ADDED
@@ -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
|
+
|