axlsx 1.1.7 → 1.1.8

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 (130) hide show
  1. data/README.md +41 -5
  2. data/Rakefile +3 -2
  3. data/examples/chart_colors.rb +18 -3
  4. data/examples/example.rb +100 -46
  5. data/examples/extractive.pdf +0 -0
  6. data/lib/axlsx.rb +7 -6
  7. data/lib/axlsx/content_type/content_type.rb +2 -0
  8. data/lib/axlsx/content_type/default.rb +21 -12
  9. data/lib/axlsx/content_type/override.rb +22 -11
  10. data/lib/axlsx/doc_props/app.rb +36 -32
  11. data/lib/axlsx/doc_props/core.rb +9 -5
  12. data/lib/axlsx/drawing/ax_data_source.rb +7 -6
  13. data/lib/axlsx/drawing/axis.rb +48 -27
  14. data/lib/axlsx/drawing/bar_3D_chart.rb +47 -37
  15. data/lib/axlsx/drawing/bar_series.rb +1 -0
  16. data/lib/axlsx/drawing/cat_axis.rb +42 -38
  17. data/lib/axlsx/drawing/chart.rb +34 -27
  18. data/lib/axlsx/drawing/drawing.rb +5 -4
  19. data/lib/axlsx/drawing/line_3D_chart.rb +1 -1
  20. data/lib/axlsx/drawing/num_data_source.rb +1 -1
  21. data/lib/axlsx/drawing/pie_3D_chart.rb +7 -7
  22. data/lib/axlsx/drawing/two_cell_anchor.rb +3 -8
  23. data/lib/axlsx/drawing/view_3D.rb +41 -31
  24. data/lib/axlsx/drawing/vml_drawing.rb +1 -1
  25. data/lib/axlsx/package.rb +11 -11
  26. data/lib/axlsx/rels/relationship.rb +3 -3
  27. data/lib/axlsx/stylesheet/styles.rb +1 -1
  28. data/lib/axlsx/util/constants.rb +4 -0
  29. data/lib/axlsx/util/simple_typed_list.rb +2 -2
  30. data/lib/axlsx/util/validators.rb +2 -2
  31. data/lib/axlsx/version.rb +1 -1
  32. data/lib/axlsx/workbook/workbook.rb +1 -2
  33. data/lib/axlsx/workbook/worksheet/cell.rb +1 -1
  34. data/lib/axlsx/workbook/worksheet/data_bar.rb +1 -1
  35. data/lib/axlsx/workbook/worksheet/page_setup.rb +9 -0
  36. data/lib/axlsx/workbook/worksheet/protected_range.rb +46 -0
  37. data/lib/axlsx/workbook/worksheet/worksheet.rb +180 -56
  38. data/test/content_type/tc_content_type.rb +1 -6
  39. data/test/doc_props/tc_core.rb +1 -1
  40. data/test/drawing/tc_axis.rb +8 -0
  41. data/test/drawing/tc_bar_3D_chart.rb +12 -12
  42. data/test/drawing/tc_bar_series.rb +0 -1
  43. data/test/drawing/tc_chart.rb +1 -5
  44. data/test/drawing/tc_pie_3D_chart.rb +3 -7
  45. data/test/drawing/tc_view_3D.rb +18 -18
  46. data/test/tc_package.rb +2 -0
  47. data/test/workbook/worksheet/tc_page_setup.rb +20 -3
  48. data/test/workbook/worksheet/tc_protected_range.rb +18 -0
  49. data/test/workbook/worksheet/tc_selection.rb +1 -1
  50. data/test/workbook/worksheet/tc_worksheet.rb +39 -18
  51. metadata +54 -103
  52. data/examples/axis-titles.xlsx +0 -0
  53. data/examples/basic_charts.xlsx +0 -0
  54. data/examples/chart_colors.xlsx +0 -0
  55. data/examples/charts.xlsx +0 -0
  56. data/examples/conditional_formatting/getting_barred.xlsx +0 -0
  57. data/examples/doc/_index.html +0 -84
  58. data/examples/doc/class_list.html +0 -47
  59. data/examples/doc/css/common.css +0 -1
  60. data/examples/doc/css/full_list.css +0 -55
  61. data/examples/doc/css/style.css +0 -322
  62. data/examples/doc/file_list.html +0 -46
  63. data/examples/doc/frames.html +0 -13
  64. data/examples/doc/index.html +0 -84
  65. data/examples/doc/js/app.js +0 -205
  66. data/examples/doc/js/full_list.js +0 -173
  67. data/examples/doc/js/jquery.js +0 -16
  68. data/examples/doc/method_list.html +0 -46
  69. data/examples/doc/top-level-namespace.html +0 -95
  70. data/examples/example.xlsx +0 -0
  71. data/examples/example_streamed.xlsx +0 -0
  72. data/examples/examples_saved.xlsx +0 -0
  73. data/examples/extractive.xlsx +0 -0
  74. data/examples/fish.xlsx +0 -0
  75. data/examples/no-use_autowidth.xlsx +0 -0
  76. data/examples/pareto.rb +0 -28
  77. data/examples/pareto.xlsx +0 -0
  78. data/examples/pie_chart_excel.xlsx +0 -0
  79. data/examples/pie_chart_saved.xlsx +0 -0
  80. data/examples/shared_strings_example.xlsx +0 -0
  81. data/examples/sheet_protection.xlsx +0 -0
  82. data/examples/sheet_view.xlsx +0 -0
  83. data/examples/two_cell_anchor_image.xlsx +0 -0
  84. data/examples/~$example.xlsx +0 -0
  85. data/lib/axlsx/drawing/ax_data_source.rb~ +0 -55
  86. data/lib/axlsx/drawing/data_source.rb~ +0 -51
  87. data/lib/axlsx/drawing/hlink_click.rb~ +0 -0
  88. data/lib/axlsx/drawing/hyperlink.rb~ +0 -64
  89. data/lib/axlsx/drawing/num_data.rb~ +0 -51
  90. data/lib/axlsx/drawing/num_data_source.rb~ +0 -54
  91. data/lib/axlsx/drawing/num_val.rb~ +0 -40
  92. data/lib/axlsx/drawing/picture_locking.rb~ +0 -36
  93. data/lib/axlsx/drawing/ref.rb~ +0 -41
  94. data/lib/axlsx/drawing/str_data.rb~ +0 -58
  95. data/lib/axlsx/drawing/str_val.rb~ +0 -35
  96. data/lib/axlsx/drawing/vml_drawing.rb~ +0 -6
  97. data/lib/axlsx/drawing/vml_shape.rb~ +0 -61
  98. data/lib/axlsx/util/cbf.rb +0 -333
  99. data/lib/axlsx/util/cfb.rb~ +0 -201
  100. data/lib/axlsx/util/font_tables.rb~ +0 -0
  101. data/lib/axlsx/util/ms_off_crypto.rb +0 -189
  102. data/lib/axlsx/util/ms_off_crypto.rb~ +0 -3
  103. data/lib/axlsx/util/ms_offcrypto.rb~ +0 -0
  104. data/lib/axlsx/util/parser.rb~ +0 -6
  105. data/lib/axlsx/util/storage.rb~ +0 -0
  106. data/lib/axlsx/workbook/shared_strings_table.rb~ +0 -69
  107. data/lib/axlsx/workbook/worksheet/cfvo.rb~ +0 -0
  108. data/lib/axlsx/workbook/worksheet/col.rb~ +0 -0
  109. data/lib/axlsx/workbook/worksheet/color_scale.rb~ +0 -46
  110. data/lib/axlsx/workbook/worksheet/comment.rb~ +0 -91
  111. data/lib/axlsx/workbook/worksheet/comments.rb~ +0 -86
  112. data/lib/axlsx/workbook/worksheet/data_bar.rb~ +0 -0
  113. data/lib/axlsx/workbook/worksheet/icon_set.rb~ +0 -95
  114. data/lib/axlsx/workbook/worksheet/shared_strings_table.rb~ +0 -0
  115. data/lib/axlsx/workbook/worksheet/table.rb~ +0 -97
  116. data/lib/schema/dc.xsd~ +0 -118
  117. data/lib/schema/dcterms.xsd~ +0 -331
  118. data/lib/schema/opc-coreProperties.xsd~ +0 -50
  119. data/test/drawing/tc_data_source.rb~ +0 -30
  120. data/test/drawing/tc_num_data.rb~ +0 -35
  121. data/test/drawing/tc_num_val.rb~ +0 -29
  122. data/test/drawing/tc_str_data.rb~ +0 -30
  123. data/test/drawing/tc_str_val.rb~ +0 -26
  124. data/test/drawing/tc_vml_drawing.rb~ +0 -0
  125. data/test/workbook/worksheet/table/tc_table.rb~ +0 -72
  126. data/test/workbook/worksheet/tc_cfvo.rb~ +0 -20
  127. data/test/workbook/worksheet/tc_col.rb~ +0 -10
  128. data/test/workbook/worksheet/tc_color_scale.rb~ +0 -0
  129. data/test/workbook/worksheet/tc_data_bar.rb~ +0 -0
  130. data/test/workbook/worksheet/tc_icon_set.rb~ +0 -0
@@ -1,40 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- module Axlsx
3
-
4
- #This class specifies data for a particular data point.
5
- class NumVal < StrVal
6
-
7
- # A string representing the format code to apply. For more information see see the SpreadsheetML numFmt element's (§18.8.30) formatCode attribute.
8
- # @return [String]
9
- attr_reader :format_code
10
-
11
- # creates a new NumVal object
12
- # @option options [String] formatCode
13
- # @option options [Integer] v
14
- def initialize(options={})
15
- @format_code = "General"
16
- @v = @idx = 0
17
- options.each do |o|
18
- self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
19
- end
20
- end
21
-
22
- # @see format_code
23
- def format_code=(v='General')
24
- Axlsx::validate_string(v)
25
- @format_code = v
26
- end
27
-
28
- # @see v
29
- def v=(v)
30
- Axlsx::validate_int(v)
31
- @v = v
32
- end
33
-
34
- # serialize the object
35
- def to_xml_string(idx, str = "")
36
- Axlsx::validate_unsigned_int(idx)
37
- str << '<c:pt idx="' << idx.to_s << '" formatCode="' << format_code << '"><c:v>' << v.to_s << '</c:v></c:pt>'
38
- end
39
- end
40
- end
@@ -1,36 +0,0 @@
1
- module Axlsx
2
- # The picture locking class defines the locking properties for pictures in your workbook.
3
- class PictureLocking
4
-
5
-
6
- attr_reader :noGrp
7
- attr_reader :noSelect
8
- attr_reader :noRot
9
- attr_reader :noChangeAspect
10
- attr_reader :noMove
11
- attr_reader :noResize
12
- attr_reader :noEditPoints
13
- attr_reader :noAdjustHandles
14
- attr_reader :noChangeArrowheads
15
- attr_reader :noChangeShapeType
16
-
17
- # Creates a new PictureLocking object
18
- # @option options [Boolean] noGrp
19
- # @option options [Boolean] noSelect
20
- # @option options [Boolean] noRot
21
- # @option options [Boolean] noChangeAspect
22
- # @option options [Boolean] noMove
23
- # @option options [Boolean] noResize
24
- # @option options [Boolean] noEditPoints
25
- # @option options [Boolean] noAdjustHandles
26
- # @option options [Boolean] noChangeArrowheads
27
- # @option options [Boolean] noChangeShapeType
28
- def initialize(options={})
29
- options.each do |o|
30
- self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
31
- end
32
- end
33
-
34
-
35
- end
36
- end
@@ -1,41 +0,0 @@
1
- module Axlsx
2
-
3
- # Base class for xVal, yVal and val data sources
4
- class DataSource
5
-
6
- def self.allowed_tag_names
7
- [:yVal, :xVal, :val]
8
- end
9
-
10
- def self.allowed_types
11
- [NumData, StrData]
12
- end
13
-
14
- attr_reader :tag_name
15
-
16
- attr_reader :data
17
-
18
- def initialize(type, data=[])
19
- Axlsx::RestrictionValidator.validate "#{self.class.name}", self.class.allowed_types, type
20
- @data = type.new
21
- end
22
-
23
- def f
24
-
25
- end
26
-
27
- def is_literal?
28
-
29
- end
30
-
31
- def is_reference?
32
-
33
- end
34
-
35
- def to_xml_string(str = '')
36
-
37
- end
38
-
39
- end
40
-
41
- end
@@ -1,58 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- module Axlsx
3
-
4
- #This specifies the last string data used for a chart. (e.g. strLit and strCache)
5
- # This class is extended for NumData to include the formatCode attribute required for numLit and numCache
6
- class StrData
7
-
8
- def self.allowed_tag_names
9
- [:strCache, :strLit]
10
- end
11
-
12
- # A list of NumVal objects
13
- # @return [SimpleTypedList]
14
- attr_reader :pt
15
-
16
- # The tag name to use when serializing this object.
17
- # this is restricted to the values returnd by self.allowed_tag_names
18
- attr_reader :tag_name
19
-
20
- # creates a new StrVal object
21
- # @option options [Array] :data
22
- # @option options [String] :tag_name
23
- def initialize(options={})
24
- @tag_prefix = :str
25
- @type = StrVal
26
- @pt = SimpleTypedList.new(@type)
27
- options.each do |o|
28
- self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
29
- end
30
- end
31
-
32
- def data=(values)
33
- # raise ArgumentError, 'data assignation must be done with an array' unless values.is_a?(Array)
34
- @tag_name = values.first.is_a?(Cell) ? "#{@tag_prefix.to_s}Cache".to_sym : "#{@tag_prefix.to_s}Lit".to_sym
35
- values.each do |value|
36
- v = value.is_a?(Cell)? v.value : value
37
- @pt << @type.new(:v => v)
38
- end
39
- end
40
-
41
- def tag_name=(v)
42
- Axlsx::RestrictionValidator.validate "#{self.class.name}.tag_name", self.class.allowed_tag_names, v
43
- @tag_name = v
44
- end
45
-
46
- # serialize the object
47
- def to_xml_string(idx, str = "")
48
- str << '<c:' << tag_name.to_s << '>'
49
- str << '<c:ptCount val="' << @pt.size.to_s << '"/>'
50
- pt.each_with_index do |value, index|
51
- value.to_xml_string index, str
52
- end
53
- str << '</c:' << tag_name.to_s << '>'
54
- end
55
-
56
- end
57
-
58
- end
@@ -1,35 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- module Axlsx
3
-
4
- #This class specifies data for a particular data point.
5
- class StrVal
6
-
7
- # a string value.
8
- # @return [String]
9
- attr_reader :v
10
-
11
- # creates a new StrVal object
12
- # @option options [String] v
13
- def initialize(options={})
14
- @v = ""
15
- @idx = 0
16
- options.each do |o|
17
- self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
18
- end
19
-
20
- end
21
- # @see v
22
- def v=(v)
23
- Axlsx::validate_string(v)
24
- @v = v
25
- end
26
-
27
- # serialize the object
28
- def to_xml_string(idx, str = "")
29
- Axlsx::validate_unsigned_int(idx)
30
- str << '<c:pt idx="' << idx.to_s << '"><c:v>' << v.to_s << '</c:v></c:pt>'
31
- end
32
-
33
- end
34
-
35
- end
@@ -1,6 +0,0 @@
1
- module Axlsx
2
-
3
-
4
- class VmlDrawing
5
- end
6
- end
@@ -1,61 +0,0 @@
1
- module Axlsx
2
- class VmlShape
3
-
4
- attr_reader :row
5
-
6
- attr_reader :column
7
-
8
- attr_reader :left_column
9
- attr_reader :left_offset
10
- attr_reader :top_row
11
- attr_reader :top_offset
12
- attr_reader :right_column
13
- attr_reader :right_offset
14
- attr_reader :bottom_row
15
- attr_reader :bottom_offset
16
-
17
- def initialize(comment, options={})
18
- @row = @column = 0
19
- @left_column = 0
20
- @left_offset = 15
21
- @top_row = 0
22
- @top_offset = 2
23
- @right_column = 0
24
- @right_offset = 50
25
- @bottom_row = 0
26
- @bottom_offset = 5
27
- options.each do |o|
28
- self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
29
- end
30
-
31
-
32
- end
33
-
34
- def xml_to_string(str ='') str << <<SHAME_ON_YOU
35
-
36
- <v:shape id="_x0000_s#{@comments.worksheet.index+1}07#{index+1}" type="#_x0000_t202"
37
- style='position:absolute;margin-left:104pt;margin-top:2pt;width:800px;height:27pt;z-index:1;mso-wrap-style:tight'
38
- fillcolor="#ffffa1 [80]" o:insetmode="auto">
39
- <v:fill color2="#ffffa1 [80]"/>
40
- <v:shadow on="t" obscured="t"/>
41
- <v:path o:connecttype="none"/>
42
- <v:textbox style='mso-fit-text-with-word-wrap:t'>
43
- <div style='text-align:left'></div>
44
- </v:textbox>
45
-
46
- <x:ClientData ObjectType="Note">
47
- <x:MoveWithCells/>
48
- <x:SizeWithCells/>
49
- # LeftColumn, LeftOffset, TopRow, TopOffset, RightColumn, RightOffset, BottomRow, BottomOffset.
50
- <x:Anchor>#{comment.comments.worksheet[comment.ref].index + 1}, 15, #{comment.comments.worksheet[comment.ref].row.index}, 2, #{comment.comments.worksheet[comment.ref].index + 5}, 50, #{comment.comments.worksheet[comment.ref].row.index + 5}, 5</x:Anchor>
51
- <x:AutoFill>False</x:AutoFill>
52
- <x:Row>#{comment.comments.worksheet[comment.ref].row.index}</x:Row>
53
- <x:Column>#{comment.comments.worksheet[comment.ref].index}</x:Column>
54
- <x:Visible/>
55
- </x:ClientData>
56
- </v:shape>
57
- SHAME_ON_YOU
58
-
59
- end
60
- end
61
- end
@@ -1,333 +0,0 @@
1
- # encoding: UTF-8
2
- module Axlsx
3
-
4
- # The Cfb class is a MS-OFF-CRYPTOGRAPHY specific OLE (MS-CBF) writer implementation. No attempt is made to re-invent the wheel for read/write of compound binary files.
5
- class Cbf
6
-
7
- # the serialization for the CBF FAT
8
- FAT_PACKING = "s128"
9
-
10
- # the serialization for the MS-OFF-CRYPTO version stream
11
- VERSION_PACKING = 'l s30 l3'
12
-
13
- # The serialization for the MS-OFF-CRYPTO dataspace map stream
14
- DATA_SPACE_MAP_PACKING = 'l6 s16 l s25 x2'
15
-
16
- # The serialization for the MS-OFF-CRYPTO strong encrytion data space stream
17
- STRONG_ENCRYPTION_DATA_SPACE_PACKING = 'l3 s26'
18
-
19
- # The serialization for the MS-OFF-CRYPTO primary stream
20
- PRIMARY_PACKING = 'l3 s38 l s40 l3 x12 l'
21
-
22
- # The cutoff size that determines if a stream should be in the mini-fat or the fat
23
- MINI_CUTOFF = 4096
24
-
25
- # The serialization for CBF header
26
- HEADER_PACKING = "q x16 l s3 x10 l l x4 l*"
27
-
28
- # Creates a new Cbf object based on the ms_off_crypto object provided.
29
- # @param [MsOffCrypto] ms_off_crypto
30
- def initialize(ms_off_crypto)
31
- @file_name = ms_off_crypto.file_name
32
- @ms_off_crypto = ms_off_crypto
33
- create_storages
34
- mini_fat_stream
35
- mini_fat
36
- fat
37
- header
38
- end
39
-
40
- # creates or returns the version storage
41
- # @return [Storage]
42
- def version
43
- @version ||= create_version
44
- end
45
-
46
- # returns the data space map storage
47
- # @return [Storage]
48
- def data_space_map
49
- @data_space_map ||= create_data_space_map
50
- end
51
-
52
- # returns the primary storage
53
- # @return [Storgae]
54
- def primary
55
- @primary ||= create_primary
56
- end
57
-
58
- # returns the summary information storage
59
- # @return [Storage]
60
- def summary_information
61
- @summary_information ||= create_summary_information
62
- end
63
-
64
- # returns the document summary information
65
- # @return [Storage]
66
- def document_summary_information
67
- @document_summary_information ||= create_document_summary_information
68
- end
69
-
70
- # returns the stream of data allocated in the fat
71
- # @return [String]
72
- def fat_stream
73
- @fat_stream ||= create_fat_stream
74
- end
75
-
76
- # returns the stream allocated in the mini fat.
77
- # return [String]
78
- def mini_fat_stream
79
- @mini_fat_stream ||= create_mini_fat_stream
80
- end
81
-
82
- # returns the mini fat
83
- # return [String]
84
- def mini_fat
85
- @mini_fat ||= create_mini_fat
86
- end
87
-
88
- # returns the fat
89
- # @return [String]
90
- def fat
91
- @fat ||= create_fat
92
- end
93
-
94
- # returns the CFB header
95
- # @return [String]
96
- def header
97
- @header ||= create_header
98
- end
99
-
100
- # returns the encryption info from the ms_off_crypt object provided during intialization
101
- # @return [String] encryption info
102
- def encryption_info
103
- @ms_off_crypto.encryption_info
104
- end
105
-
106
- # returns the encrypted package from the ms_off_crypt object provided during initalization
107
- # @return [String] encrypted package
108
- def encrypted_package
109
- @ms_off_crypto.encrypted_package
110
- end
111
-
112
- # writes the compound binary file to disk
113
- def save
114
- ole = File.open(@file_name, 'w')
115
- ole << header
116
- ole << fat
117
- @storages.each { |s| ole << s.to_s }
118
- ole << Array.new((512-(ole.pos % 512)), 0).pack('c*')
119
- ole << mini_fat
120
- ole << mini_fat_stream
121
- ole << fat_stream
122
- ole.close
123
- end
124
-
125
- private
126
-
127
- # Generates the storages required for ms-office-cryptography cfb
128
- def create_storages
129
- @storages = []
130
- @encryption_info = @ms_off_crypto.encryption_info
131
- @encrypted_package = @ms_off_crypto.encrypted_package
132
-
133
- @storages << Storage.new('EncryptionInfo', :data=>encryption_info, :left=>3, :right=>11) # example shows right child. do we need the summary info????
134
- @storages << Storage.new('EncryptedPackage', :data=>encrypted_package, :color=>Storage::COLORS[:red])
135
- @storages << Storage.new([6].pack("c")+"DataSpaces", :child=>5, :modified =>129685612740945580, :created=>129685612740819979)
136
- @storages << version
137
- @storages << data_space_map
138
- @storages << Storage.new('DataSpaceInfo', :right=>8, :child=>7, :created=>129685612740828880,:modified=>129685612740831800)
139
- @storages << strong_encryption_data_space
140
- @storages << Storage.new('TransformInfo', :color => Storage::COLORS[:red], :child=>9, :created=>129685612740834130, :modified=>129685612740943959)
141
- @storages << Storage.new('StrongEncryptionTransform', :child=>10, :created=>129685612740834169, :modified=>129685612740942280)
142
- @storages << primary
143
- # @storages << summary_information
144
- # @storages << document_summary_information
145
-
146
- # we do this at the end as we need to build the minifat stream to determine the size. #HOWEVER - it looks like the size should not include the padding?
147
- @storages.unshift Storage.new('Root Entry', :type=>Storage::TYPES[:root], :color=>Storage::COLORS[:red], :child=>1, :data => mini_fat_stream)
148
-
149
- end
150
-
151
- # generates the mini fat stream
152
- # @return [String]
153
- def create_mini_fat_stream
154
- mfs = []
155
- @storages.select{ |s| s.type == Storage::TYPES[:stream] && s.size < MINI_CUTOFF}.each_with_index do |stream, index|
156
- puts "#{stream.name.pack('c*')}: #{stream.data.size}"
157
- mfs.concat stream.data
158
- mfs.concat Array.new(64 - (mfs.size % 64), 0) if mfs.size % 64 > 0
159
- puts "mini fat stream size: #{mfs.size}"
160
- end
161
- mfs.concat(Array.new(512 - (mfs.size % 512), 0))
162
- mfs.pack 'c*'
163
- end
164
-
165
- # generates the fat stream.
166
- # @return [String]
167
- def create_fat_stream
168
- mfs = []
169
- @storages.select{ |s| s.type == Storage::TYPES[:stream] && s.size >= MINI_CUTOFF}.each_with_index do |stream, index|
170
- mfs.concat stream.data
171
- mfs.concat Array.new(512 - (mfs.size % 512), 0) if mfs.size % 512 > 0
172
- end
173
- mfs.pack 'c*'
174
- end
175
-
176
- # creates the mini fat
177
- # @return [String]
178
- def create_mini_fat
179
- v_mf = []
180
- @storages.select{ |s| s.type == Storage::TYPES[:stream] && s.size < MINI_CUTOFF}.each do |stream|
181
- allocate_stream(v_mf, stream, 64)
182
- end
183
- v_mf.concat Array.new(128 - v_mf.size, -1)
184
- v_mf.pack 'l*'
185
- end
186
-
187
- # creates the fat
188
- # @return [String]
189
- def create_fat
190
- v_fat = [-3]
191
- # storages four per sector, allocation forces directories to start at sector ID 0
192
- allocate_stream(v_fat, @storages, 4)
193
- # fat entry for minifat
194
- allocate_stream(v_fat, 0, 512)
195
- # fat entry for minifat stream
196
- @storages[0].sector = v_fat.size
197
- allocate_stream(v_fat, mini_fat_stream, 512)
198
- # fat entries for encrypted package storage
199
- # what to do about DIFAT for larger packages...
200
- if @encrypted_package.size > (109 - v_fat.size) * 512
201
- raise ArgumentError, "Your package is too big!"
202
- end
203
-
204
- if @encrypted_package.size >= MINI_CUTOFF
205
- allocate_stream(v_fat, @encrypted_package, 512)
206
- end
207
-
208
- v_fat.concat Array.new(128 - v_fat.size, -1) if v_fat.size < 128 #pack in unused sectors
209
- v_fat.pack 'l*'
210
- end
211
-
212
- # Creates the version storage
213
- # @return [Storage]
214
- def create_version
215
- v_stream= [60, "Microsoft.Container.DataSpaces".bytes.to_a, 1, 1, 1].flatten!.pack VERSION_PACKING
216
- Storage.new('Version', :data=>v_stream, :size=>v_stream.size)
217
- end
218
-
219
- # returns the strong encryption data space storage
220
- # @return [Storgae]
221
- def strong_encryption_data_space
222
- @strong_encryption_data_space ||= create_strong_encryption_data_space
223
- end
224
-
225
- # Creates the data space map storage
226
- # @return [Storgae]
227
- def create_data_space_map
228
- v_stream = [8,1,104, 1,0, 32, "EncryptedPackage".bytes.to_a, 50, "StrongEncryptionDataSpace".bytes.to_a].flatten!.pack DATA_SPACE_MAP_PACKING
229
- Storage.new('DataSpaceMap', :data=>v_stream, :left => 4, :right => 6, :size=>v_stream.size)
230
- end
231
-
232
-
233
- # creates the stron encryption data space storage
234
- # @return [Storgae]
235
- def create_strong_encryption_data_space
236
- v_stream = [8,1,50,"StrongEncryptionTransform".bytes.to_a,0].flatten.pack STRONG_ENCRYPTION_DATA_SPACE_PACKING
237
- Storage.new("StrongEncryptionDataSpace", :data=>v_stream, :size => v_stream.size)
238
- end
239
-
240
- # creates the primary storage
241
- # @return [Storgae]
242
- def create_primary
243
- v_stream = [88,1,76,"{FF9A3F03-56EF-4613-BDD5-5A41C1D07246}".bytes.to_a].flatten
244
- v_stream.concat [78, "Microsoft.Container.EncryptionTransform".bytes.to_a,0,1,1,1,4].flatten
245
- v_stream = v_stream.pack PRIMARY_PACKING
246
- Storage.new([6].pack("c")+"Primary", :data=>v_stream)
247
- end
248
-
249
-
250
- # creates the summary information storage
251
- # @return [Storage]
252
- def create_summary_information
253
- v_stream = []
254
- v_stream.concat [0xFEFF, 0x0000, 0x030A, 0x0100, 0x0000, 0x0000, 0x0000, 0x0000]
255
- v_stream.concat [0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0xE085, 0x9FF2]
256
- v_stream.concat [0xF94F, 0x6810, 0xAB91, 0x0800, 0x2B27, 0xB3D9, 0x3000, 0x0000]
257
- v_stream.concat [0xAC00, 0x0000, 0x0700, 0x0000, 0x0100, 0x0000, 0x4000, 0x0000]
258
- v_stream.concat [0x0400, 0x0000, 0x4800, 0x0000, 0x0800, 0x0000, 0x5800, 0x0000]
259
- v_stream.concat [0x1200, 0x0000, 0x6800, 0x0000, 0x0C00, 0x0000, 0x8C00, 0x0000]
260
- v_stream.concat [0x0D00, 0x0000, 0x9800, 0x0000, 0x1300, 0x0000, 0xA400, 0x0000]
261
- v_stream.concat [0x0200, 0x0000, 0xE9FD, 0x0000, 0x1E00, 0x0000, 0x0800, 0x0000]
262
- v_stream.concat [0x7261, 0x6E64, 0x796D, 0x0000, 0x1E00, 0x0000, 0x0800, 0x0000]
263
- v_stream.concat [0x7261, 0x6E64, 0x796D, 0x0000, 0x1E00, 0x0000, 0x1C00, 0x0000]
264
- v_stream.concat [0x4D69, 0x6372, 0x6F73, 0x6F66, 0x7420, 0x4D61, 0x6369, 0x6E74]
265
- v_stream.concat [0x6F73, 0x6820, 0x4578, 0x6365, 0x6C00, 0x0000, 0x4000, 0x0000]
266
- v_stream.concat [0x10AC, 0x5396, 0x60BC, 0xCC01, 0x4000, 0x0000, 0x40F4, 0xFDAF]
267
- v_stream.concat [0x60BC, 0xCC01, 0x0300, 0x0000, 0x0100, 0x0000]
268
-
269
- v_stream = v_stream.pack "s*"
270
-
271
- Storage.new([5].pack('c')+"SummaryInformation", :data=>v_stream, :left => 2)
272
- end
273
-
274
-
275
- # creates the document summary information storage
276
- # @return [Storage]
277
- def create_document_summary_information
278
- v_stream = []
279
- v_stream.concat [0xFEFF, 0x0000, 0x030A, 0x0100, 0x0000, 0x0000, 0x0000, 0x0000]
280
- v_stream.concat [0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x02D5, 0xCDD5]
281
- v_stream.concat [0x9C2E, 0x1B10, 0x9397, 0x0800, 0x2B2C, 0xF9AE, 0x3000, 0x0000]
282
- v_stream.concat [0xCC00, 0x0000, 0x0900, 0x0000, 0x0100, 0x0000, 0x5000, 0x0000]
283
- v_stream.concat [0x0F00, 0x0000, 0x5800, 0x0000, 0x1700, 0x0000, 0x6400, 0x0000]
284
- v_stream.concat [0x0B00, 0x0000, 0x6C00, 0x0000, 0x1000, 0x0000, 0x7400, 0x0000]
285
- v_stream.concat [0x1300, 0x0000, 0x7C00, 0x0000, 0x1600, 0x0000, 0x8400, 0x0000]
286
- v_stream.concat [0x0D00, 0x0000, 0x8C00, 0x0000, 0x0C00, 0x0000, 0x9F00, 0x0000]
287
- v_stream.concat [0x0200, 0x0000, 0xE9FD, 0x0000, 0x1E00, 0x0000, 0x0400, 0x0000]
288
- v_stream.concat [0x0000, 0x0000, 0x0300, 0x0000, 0x0000, 0x0C00, 0x0B00, 0x0000]
289
- v_stream.concat [0x0000, 0x0000, 0x0B00, 0x0000, 0x0000, 0x0000, 0x0B00, 0x0000]
290
- v_stream.concat [0x0000, 0x0000, 0x0B00, 0x0000, 0x0000, 0x0000, 0x1E10, 0x0000]
291
- v_stream.concat [0x0100, 0x0000, 0x0700, 0x0000, 0x5368, 0x6565, 0x7431, 0x000C]
292
- v_stream.concat [0x1000, 0x0002, 0x0000, 0x001E, 0x0000, 0x0013, 0x0000, 0x00E3]
293
- v_stream.concat [0x83AF, 0xE383, 0xBCE3, 0x82AF, 0xE382, 0xB7E3, 0x83BC, 0xE383]
294
- v_stream.concat [0x8800, 0x0300, 0x0000, 0x0100, 0x0000, 0x0000]
295
- v_stream = v_stream.pack 'c*'
296
- Storage.new([5].pack('c')+"DocumentSummaryInformation", :data=>v_stream)
297
- end
298
-
299
- # Creates the header
300
- # @return [String]
301
- def create_header
302
- header = []
303
- header << -2226271756974174256 # identifier pack as q
304
- header << 196670 # version pack as L
305
- header << 65534 # byte order pack as s
306
- header << 9 # sector shift
307
- header << 6 # mini-sector shift
308
- header << (fat.size/512.0).ceil # this is the number of FAT sectors in the file at index 6 pack as L
309
- header << header.last # this is the first directory sector, index of 7 pack as L
310
- header << MINI_CUTOFF # minfat cutoff pack as L
311
- # MiniFat starts after directories
312
- header << (fat.size/512.0).ceil + (@storages.size/4.0).ceil # this is the sector id for the first minifat index 10 pack as L
313
- header << (mini_fat.size/512.0).ceil # minifat sector count index 11 pack as L
314
- header << -2 # the first DIFAT - set to end of chain until we exceed a single FAT pack as L
315
- header << 0 # number of DIFAT sectors, unless we go beyond 109 FAT sectors this will always be 0 pack as L
316
- header << 0 # first FAT sector defined in the DIFAT pack as L
317
- header.concat Array.new(108, -1) # Difat sectors pack as L108
318
- header.pack(HEADER_PACKING)
319
- end
320
-
321
- # Allocates sector chains in a allocation table based on the sector size and stream provided
322
- # If a storage obeject is provided, the starting sector value for the storage is updated based on the allocation performed here.
323
- # @param [Array] table Allocation table array
324
- # @param [Storage | String] stream
325
- # @param [Integer] size The cutoff size for the stream.
326
- def allocate_stream(table, stream, size)
327
- stream.sector = table.size if stream.respond_to?(:sector)
328
- ((stream.size / size.to_f).ceil).times { table << table.size }
329
- table[table.size-1] = -2 # this is the CBF chain terminator
330
- end
331
-
332
- end
333
- end