ucf 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,22 @@
1
1
  = Changes log for the UCF Ruby Gem
2
2
 
3
+ == Version 0.0.2
4
+
5
+ * Update the main ReadMe file.
6
+ * Add support for multiple reserved names and fix checks.
7
+ * Ensure UCF document is closed after verifying it.
8
+ * Expose the "each" method for enumerating UCF entries.
9
+ * Expose the "size" method to count UCF entries.
10
+ * Add an example program to list UCF contents.
11
+ * Add a method to directly iterate over UCF entries.
12
+
13
+ == Version 0.0.1
14
+
15
+ * Very basic UCF facilities complete (plus examples).
16
+ * Two ways of verifying UCF files.
17
+ * API documentation added.
18
+ * Add tests.
19
+
3
20
  == About this Changes file
4
21
 
5
22
  This file is, at least in part, generated by the following command:
data/Rakefile CHANGED
@@ -48,7 +48,7 @@ Jeweler::Tasks.new do |s|
48
48
  s.version = UCF::Version::STRING
49
49
  s.authors = ["Robert Haines"]
50
50
  s.email = ["support@mygrid.org.uk"]
51
- s.homepage = "http://www.taverna.org.uk/"
51
+ s.homepage = "http://mygrid.github.io/ruby-ucf/"
52
52
  s.platform = Gem::Platform::RUBY
53
53
  s.summary = "Universal Container Format (UCF) Ruby Library"
54
54
  s.description = "A Ruby library for working with Universal Container "\
@@ -2,28 +2,34 @@
2
2
 
3
3
  Authors:: Robert Haines
4
4
  Contact:: mailto:support@mygrid.org.uk
5
- URL:: http://www.taverna.org.uk/
5
+ Homepage:: http://mygrid.github.io/ruby-ucf
6
+ Source code:: https://github.com/myGrid/ruby-ucf
6
7
  Licence:: BSD (See Licence file or http://www.opensource.org/licenses/bsd-license.php)
7
8
  Copyright:: (c) 2013 The University of Manchester, UK
8
9
 
9
10
 
10
11
  == Synopsis
11
12
 
12
- This is a Ruby library for working with UCF files.
13
+ This is a Ruby library for working with UCF documents. See
14
+ {the specification}[https://learn.adobe.com/wiki/display/PDFNAV/Universal+Container+Format]
15
+ for more details.
13
16
 
14
- See https://learn.adobe.com/wiki/display/PDFNAV/Universal+Container+Format
17
+ <b>This library is a work in progress!</b> Until we release version 1.0.0 you
18
+ can expect the API to change in incompatible ways, although we will try to
19
+ keep this to an absolute minimum. Once version 1.0.0 is released we will be
20
+ following the principles of {Semantic Versioning}[http://semver.org/] for our
21
+ version numbering scheme.
15
22
 
16
- This library is a work in progress!
17
-
18
- Examples are provided in the examples directory.
23
+ There are some examples of how to use the library provided in the examples
24
+ directory. See the contents of the tests directory for even more.
19
25
 
20
26
  == What this library can not do yet
21
27
 
22
- The basic requirements of a UCF file are all implemented but there are a
28
+ The basic requirements of a UCF document are all implemented but there are a
23
29
  number of optional features that are not yet provided.
24
30
 
25
- * In memory operation. Presently all operations are performed on files that
26
- are resident on disk.
31
+ * In memory operation. Presently all operations are performed on documents
32
+ that are resident on disk.
27
33
  * META-INF directory support. Everything within the META-INF directory is
28
34
  optional but will supported in a near future version.
29
35
  * Changing the mimetype. It is not certain that this is a sensible operation
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (c) 2013 The University of Manchester, UK.
3
+ #
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # * Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # * Neither the names of The University of Manchester nor the names of its
17
+ # contributors may be used to endorse or promote products derived from this
18
+ # software without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ # POSSIBILITY OF SUCH DAMAGE.
31
+ #
32
+ # Author: Robert Haines
33
+
34
+ require 'rubygems'
35
+ require 'ucf'
36
+
37
+ def usage
38
+ puts "ucfinfo ucf-file"
39
+ exit 1
40
+ end
41
+
42
+ usage unless ARGV.length == 1
43
+
44
+ ucffile = ARGV[0]
45
+
46
+ begin
47
+ ucf = UCF::Container.open(ucffile)
48
+ rescue UCF::MalformedUCFError, Zip::ZipError => err
49
+ puts err.to_s
50
+ exit 1
51
+ end
52
+
53
+ puts "Archive: #{ucf.to_s}"
54
+ puts "UCF file size: #{File.size(ucffile)} bytes, number of entries: #{ucf.size}"
55
+
56
+ total_size = 0
57
+ total_comp = 0
58
+
59
+ ucf.each do |entry|
60
+ total_size += entry.size
61
+ total_comp += entry.compressed_size
62
+ comp = entry.compression_method == 0 ? "stor" : "defN"
63
+ size = entry.size.to_s.rjust(8)
64
+ puts "#{size} #{comp} #{entry.time} #{entry.name}"
65
+ end
66
+
67
+ ratio = ((total_size - total_comp) / total_size.to_f) * 100
68
+ puts "%d files, %d bytes uncompressed, %d bytes compressed: %.1f%%" %
69
+ [ucf.size, total_size, total_comp, ratio]
@@ -47,9 +47,9 @@ module UCF
47
47
  class Container
48
48
 
49
49
  extend Forwardable
50
- def_delegators :@zipfile, :add, :close, :comment, :commit, :dir, :extract,
51
- :file, :find_entry, :get_entry, :get_input_stream, :get_output_stream,
52
- :glob, :mkdir, :name, :read
50
+ def_delegators :@zipfile, :add, :close, :comment, :commit, :dir, :each,
51
+ :extract, :file, :find_entry, :get_entry, :get_input_stream,
52
+ :get_output_stream, :glob, :mkdir, :name, :read, :size
53
53
 
54
54
  private_class_method :new
55
55
 
@@ -59,7 +59,12 @@ module UCF
59
59
 
60
60
  # :stopdoc:
61
61
  DEFAULT_MIMETYPE = "application/epub+zip"
62
+
63
+ # Reserved root file names. File names in UCF documents are
64
+ # case-insensitive so downcase where required in the reserved list.
62
65
  MIMETYPE_FILE = "mimetype"
66
+ META_INF_DIR = "META-INF"
67
+ RESERVED_ROOT_NAMES = [MIMETYPE_FILE, META_INF_DIR.downcase]
63
68
 
64
69
  ERR_MT_NONE = "Not a UCF file. 'mimetype' file is missing."
65
70
  ERR_MT_BAD_OFF = "Not a UCF file. 'mimetype' file is not at offset 0."
@@ -86,6 +91,27 @@ module UCF
86
91
  Container.open(filename, &block)
87
92
  end
88
93
 
94
+ # :call-seq:
95
+ # Container.each_entry -> Enumerator
96
+ # Container.each_entry {|entry| ...}
97
+ #
98
+ # Iterate over the entries in the UCF document. The entry objects returned
99
+ # by this method are Zip::ZipEntry objects. Please see the rubyzip
100
+ # documentation for details.
101
+ def Container.each_entry(filename, &block)
102
+ c = new(filename)
103
+
104
+ if block_given?
105
+ begin
106
+ c.each(&block)
107
+ ensure
108
+ c.close
109
+ end
110
+ end
111
+
112
+ c.each
113
+ end
114
+
89
115
  # :call-seq:
90
116
  # Container.open(filename) -> container
91
117
  # Container.open(filename) {|container| ...}
@@ -129,28 +155,29 @@ module UCF
129
155
  # This method raises exceptions when errors are found or if there is
130
156
  # something fundamental wrong with the file itself (e.g. not found).
131
157
  def Container.verify!(filename)
132
- new(filename)
158
+ new(filename).close
133
159
  nil
134
160
  end
135
161
 
136
162
  # :call-seq:
137
163
  # remove(entry)
138
164
  #
139
- # Removes the specified entry. If asked to remove the special mimetype
140
- # header file this method will do nothing.
165
+ # Removes the specified entry. If asked to remove any reserved files such
166
+ # as the special mimetype header file this method will do nothing.
141
167
  def remove(entry)
142
- return if mimetype_entry?(entry)
168
+ return if reserved_entry?(entry)
143
169
  @zipfile.remove(entry)
144
170
  end
145
171
 
146
172
  # :call-seq:
147
173
  # rename(entry, new_name, &continueOnExistsProc)
148
174
  #
149
- # Renames the specified entry. If asked to rename the special mimetype
150
- # header file this method will do nothing. See the rubyzip documentation
151
- # for details of the +continue_on_exists_proc+ parameter.
175
+ # Renames the specified entry. If asked to rename any reserved files such
176
+ # as the special mimetype header file this method will do nothing. See the
177
+ # rubyzip documentation for details of the +continue_on_exists_proc+
178
+ # parameter.
152
179
  def rename(entry, new_name, &continue_on_exists_proc)
153
- return if mimetype_entry?(entry)
180
+ return if reserved_entry?(entry)
154
181
  @zipfile.rename(entry, new_name, continue_on_exists_proc)
155
182
  end
156
183
 
@@ -158,10 +185,10 @@ module UCF
158
185
  # replace(entry, src_path)
159
186
  #
160
187
  # Replaces the specified entry with the contents of +src_path+ (from the
161
- # file system). If asked to replace the special mimetype header file this
162
- # method will do nothing.
188
+ # file system). If asked to replace any reserved files such as the special
189
+ # mimetype header file this method will do nothing.
163
190
  def replace(entry, src_path)
164
- return if mimetype_entry?(entry)
191
+ return if reserved_entry?(entry)
165
192
  @zipfile.replace(entry, src_path)
166
193
  end
167
194
 
@@ -193,9 +220,11 @@ module UCF
193
220
  @zipfile.read(MIMETYPE_FILE)
194
221
  end
195
222
 
196
- def mimetype_entry?(entry)
197
- name = entry.kind_of?(ZipEntry) ? entry.name : entry
198
- name == MIMETYPE_FILE
223
+ # Remember that file names in UCF documents are case-insensitive so
224
+ # compare downcased versions.
225
+ def reserved_entry?(entry)
226
+ name = entry.kind_of?(::Zip::ZipEntry) ? entry.name : entry
227
+ RESERVED_ROOT_NAMES.include? name.downcase
199
228
  end
200
229
 
201
230
  public
@@ -245,6 +274,16 @@ module UCF
245
274
  #
246
275
  # See the rubyzip documentation for details.
247
276
 
277
+ ##
278
+ # :method: each
279
+ # :call-seq:
280
+ # each -> Enumerator
281
+ # each {|entry| ...}
282
+ #
283
+ # Iterate over the entries in the UCF document. The entry objects returned
284
+ # by this method are Zip::ZipEntry objects. Please see the rubyzip
285
+ # documentation for details.
286
+
248
287
  ##
249
288
  # :method: extract
250
289
  # :call-seq:
@@ -340,5 +379,12 @@ module UCF
340
379
  #
341
380
  # Returns a string containing the contents of the specified entry.
342
381
 
382
+ ##
383
+ # :method: size
384
+ # :call-seq:
385
+ # size -> int
386
+ #
387
+ # Returns the number of entries in the UCF document.
388
+
343
389
  end
344
390
  end
@@ -0,0 +1,80 @@
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 'ucf'
34
+
35
+ class TestReservedNames < Test::Unit::TestCase
36
+
37
+ # Check that nothing happens when trying to delete the mimetype file.
38
+ def test_delete_mimetype
39
+ UCF::Container.open($ucf_example) do |ucf|
40
+ assert(ucf.file.exists?("mimetype"))
41
+ assert_nil(ucf.remove("mimetype"))
42
+ assert(ucf.file.exists?("mimetype"))
43
+ end
44
+ end
45
+
46
+ # Check that nothing happens when trying to rename the mimetype file.
47
+ def test_rename_mimetype
48
+ UCF::Container.open($ucf_example) do |ucf|
49
+ assert(ucf.file.exists?("mimetype"))
50
+ assert_nil(ucf.rename("mimetype", "something-else"))
51
+ assert(ucf.file.exists?("mimetype"))
52
+ assert(!ucf.file.exists?("something-else"))
53
+ end
54
+ end
55
+
56
+ # Check that nothing happens when trying to replace the contents of the
57
+ # mimetype file.
58
+ def test_replace_mimetype
59
+ UCF::Container.open($ucf_example) do |ucf|
60
+ assert(ucf.file.exists?("mimetype"))
61
+ assert_nil(ucf.replace("mimetype", $zip_empty))
62
+ assert_equal("application/epub+zip", ucf.file.read("mimetype"))
63
+ end
64
+ end
65
+
66
+ # Check that nothing happens when trying to delete the META-INF directory.
67
+ def test_delete_metainf
68
+ UCF::Container.open($ucf_example) do |ucf|
69
+ assert_nil(ucf.remove("META-INF"))
70
+ end
71
+ end
72
+
73
+ # Check that nothing happens when trying to rename the META-INF directory.
74
+ def test_rename_metainf
75
+ UCF::Container.open($ucf_example) do |ucf|
76
+ assert_nil(ucf.rename("META-INF", "something-else"))
77
+ end
78
+ end
79
+
80
+ end
@@ -42,3 +42,4 @@ $ucf_example = "test/data/example.ucf"
42
42
  # Run test cases.
43
43
  require 'tc_create'
44
44
  require 'tc_read'
45
+ require 'tc_reserved_names'
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "ucf"
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Robert Haines"]
12
- s.date = "2013-05-24"
12
+ s.date = "2013-05-29"
13
13
  s.description = "A Ruby library for working with Universal Container Format files. See https://learn.adobe.com/wiki/display/PDFNAV/Universal+Container+Format for the specification."
14
14
  s.email = ["support@mygrid.org.uk"]
15
15
  s.extra_rdoc_files = [
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
23
23
  "Rakefile",
24
24
  "ReadMe.rdoc",
25
25
  "examples/create_ucf.rb",
26
+ "examples/ucfinfo",
26
27
  "examples/verify_ucf.rb",
27
28
  "lib/ucf.rb",
28
29
  "lib/ucf/container.rb",
@@ -33,11 +34,12 @@ Gem::Specification.new do |s|
33
34
  "test/data/null.file",
34
35
  "test/tc_create.rb",
35
36
  "test/tc_read.rb",
37
+ "test/tc_reserved_names.rb",
36
38
  "test/ts_ucf.rb",
37
39
  "ucf.gemspec",
38
40
  "version.yml"
39
41
  ]
40
- s.homepage = "http://www.taverna.org.uk/"
42
+ s.homepage = "http://mygrid.github.io/ruby-ucf/"
41
43
  s.rdoc_options = ["-N", "--tab-width=2", "--main=ReadMe.rdoc"]
42
44
  s.require_paths = ["lib"]
43
45
  s.rubygems_version = "1.8.21"
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 0
4
- :patch: 1
4
+ :patch: 2
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ucf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-24 00:00:00.000000000 Z
12
+ date: 2013-05-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -91,6 +91,7 @@ files:
91
91
  - Rakefile
92
92
  - ReadMe.rdoc
93
93
  - examples/create_ucf.rb
94
+ - examples/ucfinfo
94
95
  - examples/verify_ucf.rb
95
96
  - lib/ucf.rb
96
97
  - lib/ucf/container.rb
@@ -101,10 +102,11 @@ files:
101
102
  - test/data/null.file
102
103
  - test/tc_create.rb
103
104
  - test/tc_read.rb
105
+ - test/tc_reserved_names.rb
104
106
  - test/ts_ucf.rb
105
107
  - ucf.gemspec
106
108
  - version.yml
107
- homepage: http://www.taverna.org.uk/
109
+ homepage: http://mygrid.github.io/ruby-ucf/
108
110
  licenses: []
109
111
  post_install_message:
110
112
  rdoc_options: