axlsx 1.1.7 → 1.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +41 -5
- data/Rakefile +3 -2
- data/examples/chart_colors.rb +18 -3
- data/examples/example.rb +100 -46
- data/examples/extractive.pdf +0 -0
- data/lib/axlsx.rb +7 -6
- data/lib/axlsx/content_type/content_type.rb +2 -0
- data/lib/axlsx/content_type/default.rb +21 -12
- data/lib/axlsx/content_type/override.rb +22 -11
- data/lib/axlsx/doc_props/app.rb +36 -32
- data/lib/axlsx/doc_props/core.rb +9 -5
- data/lib/axlsx/drawing/ax_data_source.rb +7 -6
- data/lib/axlsx/drawing/axis.rb +48 -27
- data/lib/axlsx/drawing/bar_3D_chart.rb +47 -37
- data/lib/axlsx/drawing/bar_series.rb +1 -0
- data/lib/axlsx/drawing/cat_axis.rb +42 -38
- data/lib/axlsx/drawing/chart.rb +34 -27
- data/lib/axlsx/drawing/drawing.rb +5 -4
- data/lib/axlsx/drawing/line_3D_chart.rb +1 -1
- data/lib/axlsx/drawing/num_data_source.rb +1 -1
- data/lib/axlsx/drawing/pie_3D_chart.rb +7 -7
- data/lib/axlsx/drawing/two_cell_anchor.rb +3 -8
- data/lib/axlsx/drawing/view_3D.rb +41 -31
- data/lib/axlsx/drawing/vml_drawing.rb +1 -1
- data/lib/axlsx/package.rb +11 -11
- data/lib/axlsx/rels/relationship.rb +3 -3
- data/lib/axlsx/stylesheet/styles.rb +1 -1
- data/lib/axlsx/util/constants.rb +4 -0
- data/lib/axlsx/util/simple_typed_list.rb +2 -2
- data/lib/axlsx/util/validators.rb +2 -2
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/workbook.rb +1 -2
- data/lib/axlsx/workbook/worksheet/cell.rb +1 -1
- data/lib/axlsx/workbook/worksheet/data_bar.rb +1 -1
- data/lib/axlsx/workbook/worksheet/page_setup.rb +9 -0
- data/lib/axlsx/workbook/worksheet/protected_range.rb +46 -0
- data/lib/axlsx/workbook/worksheet/worksheet.rb +180 -56
- data/test/content_type/tc_content_type.rb +1 -6
- data/test/doc_props/tc_core.rb +1 -1
- data/test/drawing/tc_axis.rb +8 -0
- data/test/drawing/tc_bar_3D_chart.rb +12 -12
- data/test/drawing/tc_bar_series.rb +0 -1
- data/test/drawing/tc_chart.rb +1 -5
- data/test/drawing/tc_pie_3D_chart.rb +3 -7
- data/test/drawing/tc_view_3D.rb +18 -18
- data/test/tc_package.rb +2 -0
- data/test/workbook/worksheet/tc_page_setup.rb +20 -3
- data/test/workbook/worksheet/tc_protected_range.rb +18 -0
- data/test/workbook/worksheet/tc_selection.rb +1 -1
- data/test/workbook/worksheet/tc_worksheet.rb +39 -18
- metadata +54 -103
- data/examples/axis-titles.xlsx +0 -0
- data/examples/basic_charts.xlsx +0 -0
- data/examples/chart_colors.xlsx +0 -0
- data/examples/charts.xlsx +0 -0
- data/examples/conditional_formatting/getting_barred.xlsx +0 -0
- data/examples/doc/_index.html +0 -84
- data/examples/doc/class_list.html +0 -47
- data/examples/doc/css/common.css +0 -1
- data/examples/doc/css/full_list.css +0 -55
- data/examples/doc/css/style.css +0 -322
- data/examples/doc/file_list.html +0 -46
- data/examples/doc/frames.html +0 -13
- data/examples/doc/index.html +0 -84
- data/examples/doc/js/app.js +0 -205
- data/examples/doc/js/full_list.js +0 -173
- data/examples/doc/js/jquery.js +0 -16
- data/examples/doc/method_list.html +0 -46
- data/examples/doc/top-level-namespace.html +0 -95
- data/examples/example.xlsx +0 -0
- data/examples/example_streamed.xlsx +0 -0
- data/examples/examples_saved.xlsx +0 -0
- data/examples/extractive.xlsx +0 -0
- data/examples/fish.xlsx +0 -0
- data/examples/no-use_autowidth.xlsx +0 -0
- data/examples/pareto.rb +0 -28
- data/examples/pareto.xlsx +0 -0
- data/examples/pie_chart_excel.xlsx +0 -0
- data/examples/pie_chart_saved.xlsx +0 -0
- data/examples/shared_strings_example.xlsx +0 -0
- data/examples/sheet_protection.xlsx +0 -0
- data/examples/sheet_view.xlsx +0 -0
- data/examples/two_cell_anchor_image.xlsx +0 -0
- data/examples/~$example.xlsx +0 -0
- data/lib/axlsx/drawing/ax_data_source.rb~ +0 -55
- data/lib/axlsx/drawing/data_source.rb~ +0 -51
- data/lib/axlsx/drawing/hlink_click.rb~ +0 -0
- data/lib/axlsx/drawing/hyperlink.rb~ +0 -64
- data/lib/axlsx/drawing/num_data.rb~ +0 -51
- data/lib/axlsx/drawing/num_data_source.rb~ +0 -54
- data/lib/axlsx/drawing/num_val.rb~ +0 -40
- data/lib/axlsx/drawing/picture_locking.rb~ +0 -36
- data/lib/axlsx/drawing/ref.rb~ +0 -41
- data/lib/axlsx/drawing/str_data.rb~ +0 -58
- data/lib/axlsx/drawing/str_val.rb~ +0 -35
- data/lib/axlsx/drawing/vml_drawing.rb~ +0 -6
- data/lib/axlsx/drawing/vml_shape.rb~ +0 -61
- data/lib/axlsx/util/cbf.rb +0 -333
- data/lib/axlsx/util/cfb.rb~ +0 -201
- data/lib/axlsx/util/font_tables.rb~ +0 -0
- data/lib/axlsx/util/ms_off_crypto.rb +0 -189
- data/lib/axlsx/util/ms_off_crypto.rb~ +0 -3
- data/lib/axlsx/util/ms_offcrypto.rb~ +0 -0
- data/lib/axlsx/util/parser.rb~ +0 -6
- data/lib/axlsx/util/storage.rb~ +0 -0
- data/lib/axlsx/workbook/shared_strings_table.rb~ +0 -69
- data/lib/axlsx/workbook/worksheet/cfvo.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/col.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/color_scale.rb~ +0 -46
- data/lib/axlsx/workbook/worksheet/comment.rb~ +0 -91
- data/lib/axlsx/workbook/worksheet/comments.rb~ +0 -86
- data/lib/axlsx/workbook/worksheet/data_bar.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/icon_set.rb~ +0 -95
- data/lib/axlsx/workbook/worksheet/shared_strings_table.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/table.rb~ +0 -97
- data/lib/schema/dc.xsd~ +0 -118
- data/lib/schema/dcterms.xsd~ +0 -331
- data/lib/schema/opc-coreProperties.xsd~ +0 -50
- data/test/drawing/tc_data_source.rb~ +0 -30
- data/test/drawing/tc_num_data.rb~ +0 -35
- data/test/drawing/tc_num_val.rb~ +0 -29
- data/test/drawing/tc_str_data.rb~ +0 -30
- data/test/drawing/tc_str_val.rb~ +0 -26
- data/test/drawing/tc_vml_drawing.rb~ +0 -0
- data/test/workbook/worksheet/table/tc_table.rb~ +0 -72
- data/test/workbook/worksheet/tc_cfvo.rb~ +0 -20
- data/test/workbook/worksheet/tc_col.rb~ +0 -10
- data/test/workbook/worksheet/tc_color_scale.rb~ +0 -0
- data/test/workbook/worksheet/tc_data_bar.rb~ +0 -0
- 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
|
data/lib/axlsx/drawing/ref.rb~
DELETED
@@ -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,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
|
data/lib/axlsx/util/cbf.rb
DELETED
@@ -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
|