ucf 0.1.0 → 0.5.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/Changes.rdoc +11 -0
- data/ReadMe.rdoc +3 -2
- data/lib/ucf.rb +6 -0
- data/lib/ucf/container.rb +54 -57
- data/lib/ucf/entries/directory.rb +71 -0
- data/lib/ucf/entries/entry.rb +134 -0
- data/lib/ucf/entries/file.rb +101 -0
- data/lib/ucf/entries/managed.rb +183 -0
- data/lib/ucf/entries/reserved.rb +88 -0
- data/lib/ucf/exceptions.rb +3 -1
- data/lib/ucf/meta-inf.rb +52 -0
- data/test/tc_managed_entries.rb +206 -0
- data/test/tc_reserved_names.rb +126 -78
- data/test/ts_ucf.rb +1 -0
- data/ucf.gemspec +9 -2
- data/version.yml +1 -1
- metadata +9 -2
@@ -0,0 +1,101 @@
|
|
1
|
+
# Copyright (c) 2013 The University of Manchester, UK.
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# * Neither the names of The University of Manchester nor the names of its
|
16
|
+
# contributors may be used to endorse or promote products derived from this
|
17
|
+
# software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
#
|
31
|
+
# Author: Robert Haines
|
32
|
+
|
33
|
+
#
|
34
|
+
module UCF
|
35
|
+
|
36
|
+
# A ManagedFile is used to reserve a filename in a Container namespace.
|
37
|
+
class ManagedFile < ManagedEntry
|
38
|
+
|
39
|
+
# :call-seq:
|
40
|
+
# new(name, required = false, validation_proc = nil) -> ManagedFile
|
41
|
+
#
|
42
|
+
# Create a new ManagedFile with the supplied name and whether it is
|
43
|
+
# required to exist or not.
|
44
|
+
#
|
45
|
+
# If supplied <tt>validation_proc</tt> should be a Proc that takes a
|
46
|
+
# single parameter and returns +true+ or +false+ depending on whether the
|
47
|
+
# contents of the file were validated or not.
|
48
|
+
#
|
49
|
+
# For more complex content validation subclasses may override the validate
|
50
|
+
# method.
|
51
|
+
#
|
52
|
+
# The following example creates a ManagedFile that is not required to be
|
53
|
+
# present in the container, but if it is, its contents must be the single
|
54
|
+
# word "Boo!".
|
55
|
+
#
|
56
|
+
# valid = Proc.new { |contents| contents == "Boo!" }
|
57
|
+
# ManagedFile.new("Surprize.txt", false, valid)
|
58
|
+
def initialize(name, required = false, validation_proc = nil)
|
59
|
+
super(name, required)
|
60
|
+
|
61
|
+
@validation_proc = validation_proc.is_a?(Proc) ? validation_proc : nil
|
62
|
+
end
|
63
|
+
|
64
|
+
# :call-seq:
|
65
|
+
# verify!
|
66
|
+
#
|
67
|
+
# Verify this ManagedFile for correctness. The contents are validated if
|
68
|
+
# required.
|
69
|
+
#
|
70
|
+
# A MalformedUCFError is raised if it does not pass verification.
|
71
|
+
def verify!
|
72
|
+
super
|
73
|
+
unless (exists? ? validate : true)
|
74
|
+
raise MalformedUCFError.new("The contents of file '#{full_name}' do "\
|
75
|
+
"not pass validation.")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
protected
|
80
|
+
|
81
|
+
# :call-seq:
|
82
|
+
# validate -> boolean
|
83
|
+
#
|
84
|
+
# Validate the contents of this ManagedFile. By default this methods uses
|
85
|
+
# the validation Proc supplied on object initialization if there is one.
|
86
|
+
# If not it simply returns true (no validation was required).
|
87
|
+
#
|
88
|
+
# For complex validations of content subclasses can override this method.
|
89
|
+
def validate
|
90
|
+
@validation_proc.nil? ? true : @validation_proc.call(contents)
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
# Grab the contents of this ManagedFile
|
96
|
+
def contents
|
97
|
+
container.read(full_name)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# Copyright (c) 2013 The University of Manchester, UK.
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# * Neither the names of The University of Manchester nor the names of its
|
16
|
+
# contributors may be used to endorse or promote products derived from this
|
17
|
+
# software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
#
|
31
|
+
# Author: Robert Haines
|
32
|
+
|
33
|
+
require 'zip/zip_entry'
|
34
|
+
|
35
|
+
module UCF
|
36
|
+
|
37
|
+
# This module provides support for managed file and directory entries.
|
38
|
+
#
|
39
|
+
# <b>Note!</b> If you mix this module in you *must* call
|
40
|
+
# +initialize_managed_entries+ in your constructor to ensure that the
|
41
|
+
# internal lists of managed entries are correctly assigned.
|
42
|
+
module ManagedEntries
|
43
|
+
|
44
|
+
# :call-seq:
|
45
|
+
# managed_directories -> Array
|
46
|
+
#
|
47
|
+
# Return the list of managed directories.
|
48
|
+
def managed_directories
|
49
|
+
@directories.values
|
50
|
+
end
|
51
|
+
|
52
|
+
# :call-seq:
|
53
|
+
# managed_directory_names -> Array
|
54
|
+
#
|
55
|
+
# Return the list of managed directory names.
|
56
|
+
def managed_directory_names
|
57
|
+
expand_names(@directories.keys)
|
58
|
+
end
|
59
|
+
|
60
|
+
# :call-seq:
|
61
|
+
# managed_directory?(entry) -> boolean
|
62
|
+
#
|
63
|
+
# Is the supplied entry/name a managed directory?
|
64
|
+
def managed_directory?(entry)
|
65
|
+
managed_entry?(entry, managed_directory_names)
|
66
|
+
end
|
67
|
+
|
68
|
+
# :call-seq:
|
69
|
+
# managed_entries -> Array
|
70
|
+
#
|
71
|
+
# Return the list of managed files and directories.
|
72
|
+
def managed_entries
|
73
|
+
managed_files + managed_directories
|
74
|
+
end
|
75
|
+
|
76
|
+
# :call-seq:
|
77
|
+
# managed_entry_names -> Array
|
78
|
+
#
|
79
|
+
# Return the list of managed file and directory names.
|
80
|
+
def managed_entry_names
|
81
|
+
managed_file_names + managed_directory_names
|
82
|
+
end
|
83
|
+
|
84
|
+
# :call-seq:
|
85
|
+
# managed_entry?(entry) -> boolean
|
86
|
+
#
|
87
|
+
# Is the supplied entry/name a managed entry?
|
88
|
+
def managed_entry?(entry, list = managed_entry_names)
|
89
|
+
name = entry.kind_of?(::Zip::ZipEntry) ? entry.name : entry
|
90
|
+
name.chop! if name.end_with? "/"
|
91
|
+
list.map { |n| n.downcase }.include? name.downcase
|
92
|
+
end
|
93
|
+
|
94
|
+
# :call-seq:
|
95
|
+
# managed_file?(entry) -> boolean
|
96
|
+
#
|
97
|
+
# Is the supplied entry/name a managed file?
|
98
|
+
def managed_file?(entry)
|
99
|
+
managed_entry?(entry, managed_file_names)
|
100
|
+
end
|
101
|
+
|
102
|
+
# :call-seq:
|
103
|
+
# managed_files -> Array
|
104
|
+
#
|
105
|
+
# Return the list of managed files.
|
106
|
+
def managed_files
|
107
|
+
@files.values + managed_directories.map { |d| d.managed_files }.flatten
|
108
|
+
end
|
109
|
+
|
110
|
+
# :call-seq:
|
111
|
+
# managed_file_names -> Array
|
112
|
+
#
|
113
|
+
# Return the list of managed file names.
|
114
|
+
def managed_file_names
|
115
|
+
expand_names(@files.keys) +
|
116
|
+
managed_directories.map { |d| d.managed_file_names }.flatten
|
117
|
+
end
|
118
|
+
|
119
|
+
# :call-seq:
|
120
|
+
# verify_managed_entries!
|
121
|
+
#
|
122
|
+
# All managed files and directories are checked to make sure that they
|
123
|
+
# exist, if required.
|
124
|
+
def verify_managed_entries!
|
125
|
+
@directories.each_value do |dir|
|
126
|
+
dir.verify!
|
127
|
+
end
|
128
|
+
|
129
|
+
@files.each_value do |file|
|
130
|
+
file.verify!
|
131
|
+
end
|
132
|
+
|
133
|
+
true
|
134
|
+
end
|
135
|
+
|
136
|
+
protected
|
137
|
+
|
138
|
+
# :call-seq:
|
139
|
+
# initialize_managed_entries
|
140
|
+
# initialize_managed_entries(entry)
|
141
|
+
# initialize_managed_entries(entries)
|
142
|
+
#
|
143
|
+
# Initialize the managed entries and register any that are supplied. A
|
144
|
+
# single ManagedFile or ManagedDirectory or a list of them can be
|
145
|
+
# provided.
|
146
|
+
def initialize_managed_entries(entries = [])
|
147
|
+
list = [*entries]
|
148
|
+
@directories ||= {}
|
149
|
+
@files ||= {}
|
150
|
+
|
151
|
+
list.each { |item| register_managed_entry(item) }
|
152
|
+
end
|
153
|
+
|
154
|
+
# :call-seq:
|
155
|
+
# register_managed_entry(entry)
|
156
|
+
#
|
157
|
+
# Register a ManagedFile or ManagedDirectory.
|
158
|
+
#
|
159
|
+
# A ManagedFile is used to reserve the name of a file in the container
|
160
|
+
# namespace and can describe how to verify the contents of it if required.
|
161
|
+
#
|
162
|
+
# A ManagedDirectory is used to both reserve the name of a directory in
|
163
|
+
# the container namespace and act as an interface to the (possibly)
|
164
|
+
# managed files within it.
|
165
|
+
def register_managed_entry(entry)
|
166
|
+
unless entry.is_a?(ManagedDirectory) || entry.is_a?(ManagedFile)
|
167
|
+
raise ArgumentError.new("The supplied entry must be of type "\
|
168
|
+
"ManagedDirectory or ManagedFile or a subclass of either.")
|
169
|
+
end
|
170
|
+
|
171
|
+
entry.parent = self
|
172
|
+
@directories[entry.name] = entry if entry.is_a? ManagedDirectory
|
173
|
+
@files[entry.name] = entry if entry.is_a? ManagedFile
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def expand_names(names)
|
179
|
+
names.map { |n| self.is_a?(Container) ? n : "#{name}/#{n}" }
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# Copyright (c) 2013 The University of Manchester, UK.
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# * Neither the names of The University of Manchester nor the names of its
|
16
|
+
# contributors may be used to endorse or promote products derived from this
|
17
|
+
# software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
#
|
31
|
+
# Author: Robert Haines
|
32
|
+
|
33
|
+
require 'zip/zip_entry'
|
34
|
+
|
35
|
+
module UCF
|
36
|
+
|
37
|
+
# This module provides support for reserved names.
|
38
|
+
module ReservedNames
|
39
|
+
|
40
|
+
# :call-seq:
|
41
|
+
# reserved_names -> Array
|
42
|
+
#
|
43
|
+
# Return a list of reserved file and directory names for this UCF
|
44
|
+
# document.
|
45
|
+
#
|
46
|
+
# Reserved files and directories must be accessed directly by methods
|
47
|
+
# within Container (or subclasses of Container). This is because they are
|
48
|
+
# fundamental to the format and might need to exhibit certain properties
|
49
|
+
# (such as no compression) that must be preserved. The "mimetype" file is
|
50
|
+
# an example of such a reserved entry.
|
51
|
+
#
|
52
|
+
# To add a reserved name to a subclass of Container simply add it to the
|
53
|
+
# list in the constructor (you must call the super constructor first!):
|
54
|
+
#
|
55
|
+
# class MyContainer < UCF::Container
|
56
|
+
# def initialize(filename)
|
57
|
+
# super(filename)
|
58
|
+
#
|
59
|
+
# register_reserved_name("my_reserved_name")
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
def reserved_names
|
63
|
+
@reserved_names ||= []
|
64
|
+
end
|
65
|
+
|
66
|
+
# :call-seq:
|
67
|
+
# reserved_entry?(entry) -> boolean
|
68
|
+
#
|
69
|
+
# Is the given entry in the reserved list of names? A String or a
|
70
|
+
# Zip::ZipEntry object can be passed in here.
|
71
|
+
def reserved_entry?(entry)
|
72
|
+
name = entry.kind_of?(::Zip::ZipEntry) ? entry.name : entry
|
73
|
+
name.chop! if name.end_with? "/"
|
74
|
+
reserved_names.map { |n| n.downcase }.include? name.downcase
|
75
|
+
end
|
76
|
+
|
77
|
+
protected
|
78
|
+
|
79
|
+
# :call-seq:
|
80
|
+
# register_reserved_name(name)
|
81
|
+
#
|
82
|
+
# Add a reserved name to the list.
|
83
|
+
def register_reserved_name(name)
|
84
|
+
@reserved_names ||= []
|
85
|
+
@reserved_names << name unless @reserved_names.include? name
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/ucf/exceptions.rb
CHANGED
@@ -30,6 +30,7 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
+
#
|
33
34
|
module UCF
|
34
35
|
|
35
36
|
# The base class of all other exceptions raised by this library.
|
@@ -53,7 +54,8 @@ module UCF
|
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
56
|
-
# This exception is raised when a clash occurs with a reserved
|
57
|
+
# This exception is raised when a clash occurs with a reserved or managed
|
58
|
+
# name.
|
57
59
|
class ReservedNameClashError < UCFError
|
58
60
|
|
59
61
|
# :call-seq:
|
data/lib/ucf/meta-inf.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Copyright (c) 2013 The University of Manchester, UK.
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# * Neither the names of The University of Manchester nor the names of its
|
16
|
+
# contributors may be used to endorse or promote products derived from this
|
17
|
+
# software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
#
|
31
|
+
# Author: Robert Haines
|
32
|
+
|
33
|
+
#
|
34
|
+
module UCF
|
35
|
+
|
36
|
+
# This is a subclass of ManagedDirectory to represent the META-INF directory
|
37
|
+
# in a basic UCF Document.
|
38
|
+
class MetaInf < ManagedDirectory
|
39
|
+
|
40
|
+
# :call-seq:
|
41
|
+
# new -> MetaInf
|
42
|
+
#
|
43
|
+
# Create a standard META-INF ManagedDirectory.
|
44
|
+
def initialize
|
45
|
+
super("META-INF", false,
|
46
|
+
[ManagedFile.new("container.xml"), ManagedFile.new("manifest.xml"),
|
47
|
+
ManagedFile.new("metadata.xml"), ManagedFile.new("signatures.xml"),
|
48
|
+
ManagedFile.new("encryption.xml"), ManagedFile.new("rights.xml")])
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
# Copyright (c) 2013 The University of Manchester, UK.
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# * Neither the names of The University of Manchester nor the names of its
|
16
|
+
# contributors may be used to endorse or promote products derived from this
|
17
|
+
# software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
#
|
31
|
+
# Author: Robert Haines
|
32
|
+
|
33
|
+
require 'tmpdir'
|
34
|
+
require 'ucf'
|
35
|
+
|
36
|
+
# Classes to test managed entries.
|
37
|
+
class ManagedUCF < UCF::Container
|
38
|
+
|
39
|
+
private_class_method :new
|
40
|
+
|
41
|
+
def initialize(filename)
|
42
|
+
super(filename)
|
43
|
+
register_managed_entry(UCF::ManagedDirectory.new("src", true))
|
44
|
+
register_managed_entry(UCF::ManagedDirectory.new("test"))
|
45
|
+
register_managed_entry(UCF::ManagedDirectory.new("lib"))
|
46
|
+
register_managed_entry(UCF::ManagedFile.new("index.html", true))
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class ExampleUCF < UCF::Container
|
52
|
+
|
53
|
+
private_class_method :new
|
54
|
+
|
55
|
+
def initialize(filename)
|
56
|
+
super(filename)
|
57
|
+
register_managed_entry(UCF::ManagedDirectory.new("dir", true))
|
58
|
+
register_managed_entry(UCF::ManagedFile.new("greeting.txt", true))
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
class ExampleUCF2 < UCF::Container
|
64
|
+
|
65
|
+
private_class_method :new
|
66
|
+
|
67
|
+
def initialize(filename)
|
68
|
+
super(filename)
|
69
|
+
|
70
|
+
valid = Proc.new { |contents| contents.match(/[Hh]ello/) }
|
71
|
+
register_managed_entry(UCF::ManagedFile.new("greeting.txt", true, valid))
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
class TestManagedEntries < Test::Unit::TestCase
|
77
|
+
|
78
|
+
# Check that the example UCF document does not validate as a ManagedUCF.
|
79
|
+
def test_fail_verification
|
80
|
+
refute(ManagedUCF.verify($ucf_example))
|
81
|
+
|
82
|
+
assert_raises(UCF::MalformedUCFError) do
|
83
|
+
ManagedUCF.verify!($ucf_example)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Check that the example UCF document does validate as an ExampleUCF.
|
88
|
+
def test_pass_verification
|
89
|
+
assert(ExampleUCF.verify($ucf_example))
|
90
|
+
|
91
|
+
assert_nothing_raised(UCF::MalformedUCFError) do
|
92
|
+
ExampleUCF.verify!($ucf_example)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Check that the example UCF document does validate as an ExampleUCF2.
|
97
|
+
def test_pass_verification_2
|
98
|
+
assert(ExampleUCF2.verify($ucf_example))
|
99
|
+
|
100
|
+
assert_nothing_raised(UCF::MalformedUCFError) do
|
101
|
+
ExampleUCF2.verify!($ucf_example)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Check that a standard Container can be created
|
106
|
+
def test_create_standard_container
|
107
|
+
Dir.mktmpdir do |dir|
|
108
|
+
filename = File.join(dir, "test.ucf")
|
109
|
+
|
110
|
+
assert_nothing_raised do
|
111
|
+
UCF::Container.create(filename) do |c|
|
112
|
+
c.mkdir("META-INF")
|
113
|
+
assert(c.file.exists?("META-INF"))
|
114
|
+
|
115
|
+
c.file.open("META-INF/container.xml", "w") do |f|
|
116
|
+
f.puts "<?xml version=\"1.0\"?>"
|
117
|
+
end
|
118
|
+
assert(c.file.exists?("META-INF/container.xml"))
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
assert_nothing_raised(UCF::MalformedUCFError) do
|
123
|
+
UCF::Container.verify!(filename)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Check that a ManagedUCF does not verify immediately after creation.
|
129
|
+
def test_create_bad_subclassed_container
|
130
|
+
Dir.mktmpdir do |dir|
|
131
|
+
filename = File.join(dir, "test.ucf")
|
132
|
+
|
133
|
+
assert_nothing_raised do
|
134
|
+
ManagedUCF.create(filename) do |c|
|
135
|
+
assert_raises(UCF::MalformedUCFError) do
|
136
|
+
c.verify!
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
refute(ManagedUCF.verify(filename))
|
142
|
+
assert_raises(UCF::MalformedUCFError) do
|
143
|
+
ManagedUCF.verify!(filename)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Check that a ManagedUCF does verify when required objects are added.
|
149
|
+
def test_create_subclassed_container
|
150
|
+
Dir.mktmpdir do |dir|
|
151
|
+
filename = File.join(dir, "test.ucf")
|
152
|
+
|
153
|
+
assert_nothing_raised do
|
154
|
+
ManagedUCF.create(filename) do |c|
|
155
|
+
c.dir.mkdir("src")
|
156
|
+
c.file.open("index.html", "w") do |f|
|
157
|
+
f.puts "<html />"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
assert(ManagedUCF.verify(filename))
|
163
|
+
assert_nothing_raised(UCF::MalformedUCFError) do
|
164
|
+
ManagedUCF.verify!(filename)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Check that a ExampleUCF2 will only verify when required objects are added
|
170
|
+
# with the correct contents.
|
171
|
+
def test_create_subclassed_container_with_content_verification
|
172
|
+
Dir.mktmpdir do |dir|
|
173
|
+
filename = File.join(dir, "test.ucf")
|
174
|
+
|
175
|
+
assert_nothing_raised do
|
176
|
+
ExampleUCF2.create(filename) do |c|
|
177
|
+
assert_raises(UCF::MalformedUCFError) do
|
178
|
+
c.verify!
|
179
|
+
end
|
180
|
+
|
181
|
+
c.file.open("greeting.txt", "w") do |f|
|
182
|
+
f.puts "Goodbye!"
|
183
|
+
end
|
184
|
+
|
185
|
+
assert_raises(UCF::MalformedUCFError) do
|
186
|
+
c.verify!
|
187
|
+
end
|
188
|
+
|
189
|
+
c.file.open("greeting.txt", "w") do |f|
|
190
|
+
f.puts "Hello, Y'All!"
|
191
|
+
end
|
192
|
+
|
193
|
+
assert_nothing_raised(UCF::MalformedUCFError) do
|
194
|
+
c.verify!
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
assert(ExampleUCF2.verify(filename))
|
200
|
+
assert_nothing_raised(UCF::MalformedUCFError) do
|
201
|
+
ExampleUCF2.verify!(filename)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|