axlsx 1.1.3 → 1.2.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.
Files changed (187) hide show
  1. data/.yardopts +5 -2
  2. data/CHANGELOG.md +60 -0
  3. data/LICENSE +1 -1
  4. data/README.md +115 -415
  5. data/Rakefile +11 -3
  6. data/examples/basic_charts.rb +54 -0
  7. data/examples/chart_colors.rb +88 -0
  8. data/examples/data_validation.rb +50 -0
  9. data/examples/example.rb +299 -155
  10. data/examples/example.xlsx +0 -0
  11. data/examples/example_streamed.xlsx +0 -0
  12. data/examples/extractive.pdf +0 -0
  13. data/examples/extractive.rb +45 -0
  14. data/examples/no-use_autowidth.xlsx +0 -0
  15. data/examples/scraping_html.rb +91 -0
  16. data/examples/shared_strings_example.xlsx +0 -0
  17. data/examples/sheet_protection.rb +10 -0
  18. data/examples/sheet_view.rb +34 -0
  19. data/examples/two_cell_anchor_image.rb +11 -0
  20. data/lib/axlsx/content_type/content_type.rb +2 -0
  21. data/lib/axlsx/content_type/default.rb +30 -15
  22. data/lib/axlsx/content_type/override.rb +29 -14
  23. data/lib/axlsx/doc_props/app.rb +161 -104
  24. data/lib/axlsx/doc_props/core.rb +9 -5
  25. data/lib/axlsx/drawing/ax_data_source.rb +26 -0
  26. data/lib/axlsx/drawing/axis.rb +92 -37
  27. data/lib/axlsx/drawing/bar_3D_chart.rb +49 -45
  28. data/lib/axlsx/drawing/bar_series.rb +25 -7
  29. data/lib/axlsx/drawing/cat_axis.rb +50 -22
  30. data/lib/axlsx/drawing/chart.rb +69 -56
  31. data/lib/axlsx/drawing/d_lbls.rb +100 -0
  32. data/lib/axlsx/drawing/drawing.rb +28 -12
  33. data/lib/axlsx/drawing/graphic_frame.rb +2 -1
  34. data/lib/axlsx/drawing/line_3D_chart.rb +3 -10
  35. data/lib/axlsx/drawing/line_series.rb +20 -4
  36. data/lib/axlsx/drawing/num_data.rb +52 -0
  37. data/lib/axlsx/drawing/num_data_source.rb +61 -0
  38. data/lib/axlsx/drawing/num_val.rb +32 -0
  39. data/lib/axlsx/drawing/pic.rb +44 -4
  40. data/lib/axlsx/drawing/pie_3D_chart.rb +10 -7
  41. data/lib/axlsx/drawing/pie_series.rb +18 -4
  42. data/lib/axlsx/drawing/scatter_chart.rb +2 -8
  43. data/lib/axlsx/drawing/scatter_series.rb +28 -2
  44. data/lib/axlsx/drawing/ser_axis.rb +1 -1
  45. data/lib/axlsx/drawing/series.rb +1 -1
  46. data/lib/axlsx/drawing/str_data.rb +42 -0
  47. data/lib/axlsx/drawing/str_val.rb +33 -0
  48. data/lib/axlsx/drawing/title.rb +21 -9
  49. data/lib/axlsx/drawing/two_cell_anchor.rb +46 -9
  50. data/lib/axlsx/drawing/view_3D.rb +44 -31
  51. data/lib/axlsx/drawing/vml_drawing.rb +42 -0
  52. data/lib/axlsx/drawing/vml_shape.rb +125 -0
  53. data/lib/axlsx/package.rb +44 -16
  54. data/lib/axlsx/rels/relationship.rb +3 -3
  55. data/lib/axlsx/rels/relationships.rb +1 -11
  56. data/lib/axlsx/stylesheet/gradient_fill.rb +1 -1
  57. data/lib/axlsx/stylesheet/styles.rb +1 -1
  58. data/lib/axlsx/stylesheet/table_style.rb +3 -3
  59. data/lib/axlsx/util/constants.rb +28 -0
  60. data/lib/axlsx/util/simple_typed_list.rb +15 -21
  61. data/lib/axlsx/util/validators.rb +81 -8
  62. data/lib/axlsx/version.rb +2 -7
  63. data/lib/axlsx/workbook/defined_name.rb +174 -0
  64. data/lib/axlsx/workbook/defined_names.rb +21 -0
  65. data/lib/axlsx/workbook/workbook.rb +65 -13
  66. data/lib/axlsx/workbook/worksheet/auto_filter.rb +34 -0
  67. data/lib/axlsx/workbook/worksheet/cell.rb +35 -7
  68. data/lib/axlsx/workbook/worksheet/col.rb +17 -1
  69. data/lib/axlsx/workbook/worksheet/cols.rb +20 -0
  70. data/lib/axlsx/workbook/worksheet/comment.rb +101 -0
  71. data/lib/axlsx/workbook/worksheet/comments.rb +85 -0
  72. data/lib/axlsx/workbook/worksheet/conditional_formattings.rb +25 -0
  73. data/lib/axlsx/workbook/worksheet/data_bar.rb +1 -1
  74. data/lib/axlsx/workbook/worksheet/data_validation.rb +245 -0
  75. data/lib/axlsx/workbook/worksheet/data_validations.rb +28 -0
  76. data/lib/axlsx/workbook/worksheet/dimension.rb +65 -0
  77. data/lib/axlsx/workbook/worksheet/merged_cells.rb +35 -0
  78. data/lib/axlsx/workbook/worksheet/page_setup.rb +113 -0
  79. data/lib/axlsx/workbook/worksheet/pane.rb +144 -0
  80. data/lib/axlsx/workbook/worksheet/print_options.rb +63 -0
  81. data/lib/axlsx/workbook/worksheet/protected_range.rb +46 -0
  82. data/lib/axlsx/workbook/worksheet/protected_ranges.rb +34 -0
  83. data/lib/axlsx/workbook/worksheet/row.rb +67 -12
  84. data/lib/axlsx/workbook/worksheet/selection.rb +111 -0
  85. data/lib/axlsx/workbook/worksheet/sheet_data.rb +25 -0
  86. data/lib/axlsx/workbook/worksheet/sheet_pr.rb +24 -0
  87. data/lib/axlsx/workbook/worksheet/sheet_protection.rb +224 -0
  88. data/lib/axlsx/workbook/worksheet/sheet_view.rb +379 -0
  89. data/lib/axlsx/workbook/worksheet/table.rb +3 -3
  90. data/lib/axlsx/workbook/worksheet/tables.rb +31 -0
  91. data/lib/axlsx/workbook/worksheet/worksheet.rb +377 -255
  92. data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +57 -0
  93. data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +64 -0
  94. data/lib/axlsx.rb +30 -15
  95. data/test/content_type/tc_content_type.rb +1 -6
  96. data/test/doc_props/tc_app.rb +31 -1
  97. data/test/doc_props/tc_core.rb +3 -1
  98. data/test/drawing/tc_axis.rb +38 -3
  99. data/test/drawing/tc_bar_3D_chart.rb +12 -12
  100. data/test/drawing/tc_bar_series.rb +17 -13
  101. data/test/drawing/tc_cat_axis.rb +3 -3
  102. data/test/drawing/tc_cat_axis_data.rb +23 -13
  103. data/test/drawing/tc_chart.rb +29 -11
  104. data/test/drawing/tc_d_lbls.rb +47 -0
  105. data/test/drawing/tc_data_source.rb +17 -0
  106. data/test/drawing/tc_drawing.rb +11 -5
  107. data/test/drawing/tc_hyperlink.rb +4 -5
  108. data/test/drawing/tc_line_series.rb +9 -11
  109. data/test/drawing/tc_named_axis_data.rb +27 -0
  110. data/test/drawing/tc_num_data.rb +31 -0
  111. data/test/drawing/tc_num_val.rb +29 -0
  112. data/test/drawing/tc_pic.rb +22 -2
  113. data/test/drawing/tc_pie_3D_chart.rb +4 -8
  114. data/test/drawing/tc_pie_series.rb +11 -13
  115. data/test/drawing/tc_scatter_chart.rb +6 -1
  116. data/test/drawing/tc_scatter_series.rb +6 -5
  117. data/test/drawing/tc_series.rb +1 -1
  118. data/test/drawing/tc_str_data.rb +18 -0
  119. data/test/drawing/tc_str_val.rb +21 -0
  120. data/test/drawing/tc_title.rb +16 -0
  121. data/test/drawing/tc_two_cell_anchor.rb +2 -3
  122. data/test/drawing/tc_view_3D.rb +18 -18
  123. data/test/drawing/tc_vml_drawing.rb +25 -0
  124. data/test/drawing/tc_vml_shape.rb +100 -0
  125. data/test/rels/tc_relationship.rb +1 -0
  126. data/test/stylesheet/tc_gradient_fill.rb +8 -0
  127. data/test/stylesheet/tc_pattern_fill.rb +7 -1
  128. data/test/stylesheet/tc_styles.rb +3 -4
  129. data/test/stylesheet/tc_table_style.rb +8 -0
  130. data/test/stylesheet/tc_table_style_element.rb +10 -1
  131. data/test/tc_helper.rb +1 -0
  132. data/test/tc_package.rb +93 -17
  133. data/test/util/tc_simple_typed_list.rb +13 -0
  134. data/test/util/tc_validators.rb +95 -9
  135. data/test/workbook/tc_defined_name.rb +41 -0
  136. data/test/workbook/tc_workbook.rb +5 -3
  137. data/test/workbook/worksheet/table/tc_table.rb +3 -11
  138. data/test/workbook/worksheet/tc_cell.rb +30 -6
  139. data/test/workbook/worksheet/tc_col.rb +9 -0
  140. data/test/workbook/worksheet/tc_comment.rb +57 -0
  141. data/test/workbook/worksheet/tc_comments.rb +57 -0
  142. data/test/workbook/worksheet/tc_conditional_formatting.rb +44 -0
  143. data/test/workbook/worksheet/tc_data_bar.rb +1 -1
  144. data/test/workbook/worksheet/tc_data_validation.rb +265 -0
  145. data/test/workbook/worksheet/tc_page_setup.rb +138 -0
  146. data/test/workbook/worksheet/tc_pane.rb +94 -0
  147. data/test/workbook/worksheet/tc_print_options.rb +72 -0
  148. data/test/workbook/worksheet/tc_protected_range.rb +17 -0
  149. data/test/workbook/worksheet/tc_row.rb +36 -12
  150. data/test/workbook/worksheet/tc_selection.rb +94 -0
  151. data/test/workbook/worksheet/tc_sheet_protection.rb +117 -0
  152. data/test/workbook/worksheet/tc_sheet_view.rb +214 -0
  153. data/test/workbook/worksheet/tc_worksheet.rb +138 -48
  154. metadata +164 -52
  155. data/examples/example.csv +0 -1000
  156. data/lib/axlsx/drawing/cat_axis_data.rb +0 -34
  157. data/lib/axlsx/drawing/hlink_click.rb~ +0 -0
  158. data/lib/axlsx/drawing/hyperlink.rb~ +0 -64
  159. data/lib/axlsx/drawing/named_axis_data.rb +0 -36
  160. data/lib/axlsx/drawing/picture_locking.rb~ +0 -36
  161. data/lib/axlsx/drawing/val_axis_data.rb +0 -27
  162. data/lib/axlsx/util/cbf.rb +0 -333
  163. data/lib/axlsx/util/cfb.rb~ +0 -201
  164. data/lib/axlsx/util/font_tables.rb~ +0 -0
  165. data/lib/axlsx/util/ms_off_crypto.rb +0 -189
  166. data/lib/axlsx/util/ms_off_crypto.rb~ +0 -3
  167. data/lib/axlsx/util/ms_offcrypto.rb~ +0 -0
  168. data/lib/axlsx/util/parser.rb~ +0 -6
  169. data/lib/axlsx/util/storage.rb~ +0 -0
  170. data/lib/axlsx/workbook/shared_strings_table.rb~ +0 -69
  171. data/lib/axlsx/workbook/worksheet/cfvo.rb~ +0 -0
  172. data/lib/axlsx/workbook/worksheet/col.rb~ +0 -0
  173. data/lib/axlsx/workbook/worksheet/color_scale.rb~ +0 -46
  174. data/lib/axlsx/workbook/worksheet/data_bar.rb~ +0 -0
  175. data/lib/axlsx/workbook/worksheet/icon_set.rb~ +0 -95
  176. data/lib/axlsx/workbook/worksheet/shared_strings_table.rb~ +0 -0
  177. data/lib/axlsx/workbook/worksheet/table.rb~ +0 -97
  178. data/lib/schema/dc.xsd~ +0 -118
  179. data/lib/schema/dcterms.xsd~ +0 -331
  180. data/lib/schema/opc-coreProperties.xsd~ +0 -50
  181. data/test/drawing/tc_val_axis_data.rb +0 -17
  182. data/test/workbook/worksheet/table/tc_table.rb~ +0 -72
  183. data/test/workbook/worksheet/tc_cfvo.rb~ +0 -20
  184. data/test/workbook/worksheet/tc_col.rb~ +0 -10
  185. data/test/workbook/worksheet/tc_color_scale.rb~ +0 -0
  186. data/test/workbook/worksheet/tc_data_bar.rb~ +0 -0
  187. data/test/workbook/worksheet/tc_icon_set.rb~ +0 -0
@@ -1,34 +0,0 @@
1
- # encoding: UTF-8
2
- module Axlsx
3
- # The CatAxisData class serializes the category axis data for a chart
4
- class CatAxisData < SimpleTypedList
5
-
6
- # Create a new CatAxisData object
7
- # @param [Array, SimpleTypedList] data the data for this category axis. This can be a simple array or a simple typed list of cells.
8
- def initialize(data=[])
9
- super Object
10
- @list.concat data if data.is_a?(Array)
11
- data.each { |i| @list << i } if data.is_a?(SimpleTypedList)
12
- end
13
-
14
- # Serializes the object
15
- # @param [String] str
16
- # @return [String]
17
- def to_xml_string(str = '')
18
- str << '<c:cat>'
19
- str << '<c:strRef>'
20
- str << '<c:f>' << Axlsx::cell_range(@list) << '</c:f>'
21
- str << '<c:strCache>'
22
- str << '<c:ptCount val="' << size.to_s << '"/>'
23
- each_with_index do |item, index|
24
- v = item.is_a?(Cell) ? item.value.to_s : item
25
- str << '<c:pt idx="' << index.to_s << '"><c:v>' << v << '</c:v></c:pt>'
26
- end
27
- str << '</c:strCache>'
28
- str << '</c:strRef>'
29
- str << '</c:cat>'
30
- end
31
-
32
- end
33
-
34
- end
File without changes
@@ -1,64 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- module Axlsx
3
- # a hlinkClick object adds a click behaviour to a drawing object.
4
- # using the hlink_click method on a drawing object is the recommended way to manage hlinks
5
- # @see Pic#link_to
6
- class Hyperlink
7
-
8
- # the type of hyper link defines the onclick or mouseover trigger.
9
- # type must be one of :hlinkClick or :hlinkMouse
10
- def type
11
- @type ||= :hlinkClick
12
- end
13
-
14
- # sets the type of the object.
15
- # @param [Symbol] type one of :hlinkClick or hlinkMouse
16
- def type(v) RestrictionValidator.validate "Hyperlink.type", [:hlinkClick, :hlinkMouse], v; @type = v end
17
-
18
- # The destination of the hyperlink
19
- # This value is actually stored in the drawings .rels. doc as a relationship.
20
- attr_accessor :href
21
-
22
- # The docs say:
23
- # Specifies the URL when it has been determined by the generating application that the URL is invalid. That is the generating application can still store the URL but it is known that this URL is not correct.
24
- attr_accessor :invalidUrl
25
-
26
- # Specifies the target frame that is to be used when opening this hyperlink. When the hyperlink is activated this attribute is used to determine if a new window is launched for viewing or if an existing one can be used. If this attribute is omitted, than a new window is opened.
27
- attr_accessor :tgtFrame
28
-
29
- # Specifies the tooltip that should be displayed when the hyperlink text is hovered over with the mouse. If this attribute is omitted, than the hyperlink text itself can be displayed.
30
- attr_accessor :tooltip
31
-
32
- #Creates a hyperlink object
33
- # parent must be a Pic for now, although I expect that other object support this tag and its cNvPr parent
34
- # @param [Pic] parent
35
- # @option [String] tooltip message shown when hyperlinked object is hovered over with mouse.
36
- # @option [String] tgtFrame Target frame for opening hyperlink
37
- # @option [String] invalidUrl supposedly use to store the href when we know it is an invalid resource.
38
- # @option [String] href the target resource this hyperlink links to.
39
- def initialize(parent, options=>{})
40
- DataTypeValidator.validate "Hyperlink.parent", [Pic], parent
41
- @parent = parent
42
- options.each do |o|
43
- self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
44
- end
45
- end
46
-
47
- # The index of this hyperlink in the owning document's hyperlinks collection
48
- # @returns [Integer]
49
- def index
50
- self.parent.anchor.drawing.hyperlinks.index(self)
51
- end
52
-
53
- # The relational ID for this hyperlink
54
- # @returns [String]
55
- def r:id
56
- reference_count = self.parent.anchor.drawing.charts.size + self.parent.anchor.drawing.images.size + index
57
-
58
- end
59
-
60
- def to_xml(xml)
61
- xml.send(type,
62
- end
63
- end
64
- end
@@ -1,36 +0,0 @@
1
- # encoding: UTF-8
2
- # TODO: review cat, val and named access data to extend this and reduce replicated code.
3
- module Axlsx
4
- # The ValAxisData class manages the values for a chart value series.
5
- class NamedAxisData < CatAxisData
6
-
7
- # creates a new NamedAxisData Object
8
- # @param [String] name The serialized node name for the axis data object
9
- # @param [Array] The data to associate with the axis data object
10
- def initialize(name, data=[])
11
- super(data)
12
- @name = name
13
- end
14
-
15
- # Serializes the object
16
- # @param [String] str
17
- # @return [String]
18
- def to_xml_string(str = '')
19
- str << '<c:' << @name.to_s << '>'
20
- str << '<c:numRef>'
21
- str << '<c:f>' << Axlsx::cell_range(@list) << '</c:f>'
22
- str << '<c:numCache>'
23
- str << '<c:formatCode>General</c:formatCode>'
24
- str << '<c:ptCount val="' << size.to_s << '"/>'
25
- each_with_index do |item, index|
26
- v = item.is_a?(Cell) ? item.value.to_s : item
27
- str << '<c:pt idx="' << index.to_s << '"><c:v>' << v << '</c:v></c:pt>'
28
- end
29
- str << '</c:numCache>'
30
- str << '</c:numRef>'
31
- str << '</c:' << @name.to_s << '>'
32
- end
33
-
34
- end
35
-
36
- 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,27 +0,0 @@
1
- # encoding: UTF-8
2
- module Axlsx
3
- # The ValAxisData class manages the values for a chart value series.
4
- class ValAxisData < CatAxisData
5
-
6
- # Serializes the object
7
- # @param [String] str
8
- # @return [String]
9
- def to_xml_string(str = '')
10
- str << '<c:val>'
11
- str << '<c:numRef>'
12
- str << '<c:f>' << Axlsx::cell_range(@list) << '</c:f>'
13
- str << '<c:numCache>'
14
- str << '<c:formatCode>General</c:formatCode>'
15
- str << '<c:ptCount val="' << size.to_s << '"/>'
16
- each_with_index do |item, index|
17
- v = item.is_a?(Cell) ? item.value.to_s : item
18
- str << '<c:pt idx="' << index.to_s << '"><c:v>' << v << '</c:v></c:pt>'
19
- end
20
- str << '</c:numCache>'
21
- str << '</c:numRef>'
22
- str << '</c:val>'
23
- end
24
-
25
- end
26
-
27
- 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