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.
- 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
data/lib/axlsx/util/cfb.rb~
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
module Axlsx
|
|
2
|
-
|
|
3
|
-
# 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.
|
|
4
|
-
class Cbf
|
|
5
|
-
|
|
6
|
-
# the serialization for the CBF FAT
|
|
7
|
-
FAT_PACKING = "s128"
|
|
8
|
-
|
|
9
|
-
# the serialization for the MS-OFF-CRYPTO version stream
|
|
10
|
-
VERSION_PACKING = 'l s30 l3'
|
|
11
|
-
|
|
12
|
-
# The serialization for the MS-OFF-CRYPTO dataspace map stream
|
|
13
|
-
DATA_SPACE_MAP_PACKING = 'l6 s16 l s25'
|
|
14
|
-
|
|
15
|
-
# The serialization for the MS-OFF-CRYPTO strong encrytion data space stream
|
|
16
|
-
STRONG_ENCRYPTION_DATA_SPACE_PACKING = 'l3 s25'
|
|
17
|
-
|
|
18
|
-
# The serialization for the MS-OFF-CRYPTO primary stream
|
|
19
|
-
PRIMARY_PACKING = 'l3 s38 l s39 l3 x12 l x2'
|
|
20
|
-
|
|
21
|
-
# The cutoff size that determines if a stream should be in the mini-fat or the fat
|
|
22
|
-
MINI_CUTOFF = 4096
|
|
23
|
-
|
|
24
|
-
# Creates a new Cbf object based on a package.
|
|
25
|
-
def initialize(ms_off_crypto)
|
|
26
|
-
@file_name = ms_off_crypto.file_name
|
|
27
|
-
@storages = []
|
|
28
|
-
@encryption_info = ms_off_crypto.encryption_info
|
|
29
|
-
@encrypted_package = ms_off_crypto.encrypted_package
|
|
30
|
-
@storages << Storage.new('R', :type=>Storage::TYPES[:root], :color=>Storage::COLORS[:red], :child=>1, :modified=>129685612742510730)
|
|
31
|
-
@storages.last.name_size = 2
|
|
32
|
-
@storages << Storage.new('EncryptionInfo', :data=>@encryption_info, :left=>3, :size => @encryption_info.size) # example shows right child. do we need the summary info????
|
|
33
|
-
@storages << Storage.new('EncryptedPackage', :data=>@encrypted_package, :color=>Storage::COLORS[:red], :size=>@encrypted_package.size)
|
|
34
|
-
@storages << Storage.new([6].pack("c")+"DataSpaces", :child=>5, :modified =>129685612740945580, :created=>129685612740819979)
|
|
35
|
-
@storages << version
|
|
36
|
-
@storages << data_space_map
|
|
37
|
-
@storages << Storage.new('DataSpaceInfo', :right=>8, :child=>7, :created=>129685612740828880,:modified=>129685612740831800)
|
|
38
|
-
@storages << strong_encryption_data_space
|
|
39
|
-
@storages << Storage.new('TransformInfo', :color => Storage::COLORS[:red], :child=>9, :created=>129685612740834130, :modified=>129685612740943959)
|
|
40
|
-
@storages << Storage.new('StrongEncryptionTransform', :child=>10, :created=>129685612740834169, :modified=>129685612740942280)
|
|
41
|
-
@storages << primary
|
|
42
|
-
mini_fat_stream
|
|
43
|
-
mini_fat
|
|
44
|
-
fat
|
|
45
|
-
header
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def version
|
|
49
|
-
@version ||= create_version
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def data_space_map
|
|
53
|
-
@data_space_map ||= create_data_space_map
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def strong_encryption_data_space
|
|
57
|
-
@strong_encryption_data_space ||= create_strong_encryption_data_space
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def primary
|
|
61
|
-
@primary ||= create_primary
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def create_primary
|
|
66
|
-
v_stream = [88,1,76,"{FF9A3F03-56EF-4613-BDD5-5A41C1D07246}".bytes.to_a].flatten
|
|
67
|
-
v_stream.concat [78, "Microsoft.Container.EncryptionTransform".bytes.to_a,1,1,1,4].flatten
|
|
68
|
-
v_stream = v_stream.pack PRIMARY_PACKING
|
|
69
|
-
Storage.new([6].pack("c")+"Primary", :data=>v_stream, :size=>v_stream.size)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def create_strong_encryption_data_space
|
|
73
|
-
v_stream = [8,1,50,"StrongEncryptionTransform".bytes.to_a].flatten.pack STRONG_ENCRYPTION_DATA_SPACE_PACKING
|
|
74
|
-
Storage.new("StrongEncryptionDataSpace", :data=>v_stream, :size => v_stream.size)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# Create the version storage
|
|
78
|
-
def create_version
|
|
79
|
-
v_stream= [60, "Microsoft.Container.DataSpaces".bytes.to_a, 1, 1, 1].flatten!.pack VERSION_PACKING
|
|
80
|
-
Storage.new('Version', :data=>v_stream, :size=>v_stream.size)
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def create_data_space_map
|
|
84
|
-
v_stream = [8,1,104, 1,0, 32, "EncryptedPackage".bytes.to_a, 50, "StrongEncryptionDataSpace".bytes.to_a].flatten!.pack DATA_SPACE_MAP_PACKING
|
|
85
|
-
Storage.new('DataSpaceMap', :data=>v_stream, :left => 4, :right => 6, :size=>v_stream.size)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def allocate_stream(table, stream, size)
|
|
89
|
-
stream.sector = table.size if stream.respond_to?(:sector)
|
|
90
|
-
((stream.size / size.to_f).ceil).times { table << table.size }
|
|
91
|
-
table[table.size-1] = -2
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def fat_stream
|
|
95
|
-
@fat_stream ||= create_fat_stream
|
|
96
|
-
end
|
|
97
|
-
def create_fat_stream
|
|
98
|
-
mfs = []
|
|
99
|
-
@storages.select{ |s| s.type == Storage::TYPES[:stream] && s.size >= MINI_CUTOFF}.each_with_index do |stream, index|
|
|
100
|
-
mfs.concat stream.data
|
|
101
|
-
mfs.concat Array.new(512 - (mfs.size % 512), 0) if mfs.size % 512
|
|
102
|
-
end
|
|
103
|
-
mfs.pack 'c*'
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def mini_fat_stream
|
|
107
|
-
@mini_fat_stream ||= create_mini_fat_stream
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def create_mini_fat_stream
|
|
111
|
-
mfs = []
|
|
112
|
-
@storages.select{ |s| s.type == Storage::TYPES[:stream] && s.size < MINI_CUTOFF}.each_with_index do |stream, index|
|
|
113
|
-
mfs.concat stream.data
|
|
114
|
-
mfs.concat Array.new(64 - (mfs.size % 64), 0) if mfs.size % 64
|
|
115
|
-
end
|
|
116
|
-
@storages[0].size = mfs.size
|
|
117
|
-
mfs.concat(Array.new(512 - (mfs.size % 512), 0))
|
|
118
|
-
mfs.pack 'c*'
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def mini_fat
|
|
122
|
-
@mini_fat ||= create_mini_fat
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def create_mini_fat
|
|
126
|
-
v_mf = []
|
|
127
|
-
@storages.select{ |s| s.type == Storage::TYPES[:stream] && s.size < MINI_CUTOFF}.each do |stream|
|
|
128
|
-
allocate_stream(v_mf, stream, 64)
|
|
129
|
-
end
|
|
130
|
-
v_mf.concat Array.new(128 - v_mf.size, -1)
|
|
131
|
-
v_mf.pack 'l*'
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def fat
|
|
135
|
-
@fat ||= create_fat
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def create_fat
|
|
139
|
-
v_fat = [-3]
|
|
140
|
-
# storages four per sector, allocation forces directories to start at sector ID 0
|
|
141
|
-
allocate_stream(v_fat, @storages, 4)
|
|
142
|
-
# fat entry for minifat
|
|
143
|
-
allocate_stream(v_fat, 0, 512)
|
|
144
|
-
# fat entry for minifat stream
|
|
145
|
-
@storages[0].sector = v_fat.size
|
|
146
|
-
allocate_stream(v_fat, mini_fat_stream, 512)
|
|
147
|
-
# fat entries for encrypted package storage
|
|
148
|
-
# what to do about DIFAT for larger packages...
|
|
149
|
-
if @encrypted_package.size > (109 - v_fat.size) * 512
|
|
150
|
-
raise ArgumentError, "Your package is too big!"
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
if @encrypted_package.size >= MINI_CUTOFF
|
|
154
|
-
allocate_stream(v_fat, @encrypted_package, 512)
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
v_fat.concat Array.new(128 - v_fat.size, -1) if v_fat.size < 128 #pack in unused sectors
|
|
158
|
-
v_fat.pack 'l*'
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def header
|
|
162
|
-
@header ||= create_header
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
# The serialization for CBF header
|
|
166
|
-
HEADER_PACKING = "q x16 l s3 x10 l l x4 l*"
|
|
167
|
-
|
|
168
|
-
def create_header
|
|
169
|
-
header = []
|
|
170
|
-
header << -2226271756974174256 # identifier pack as q
|
|
171
|
-
header << 196670 # version pack as L
|
|
172
|
-
header << 65534 # byte order pack as s
|
|
173
|
-
header << 9 # sector shift
|
|
174
|
-
header << 6 # mini-sector shift
|
|
175
|
-
header << (fat.size/512.0).ceil # this is the number of FAT sectors in the file at index 6 pack as L
|
|
176
|
-
header << header.last # this is the first directory sector, index of 7 pack as L
|
|
177
|
-
header << MINI_CUTOFF # minfat cutoff pack as L
|
|
178
|
-
# MiniFat starts after directories
|
|
179
|
-
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
|
|
180
|
-
header << (mini_fat.size/512.0).ceil # minifat sector count index 11 pack as L
|
|
181
|
-
header << -2 # the first DIFAT - set to end of chain until we exceed a single FAT pack as L
|
|
182
|
-
header << 0 # number of DIFAT sectors, unless we go beyond 109 FAT sectors this will always be 0 pack as L
|
|
183
|
-
header << 0 # first FAT sector defined in the DIFAT pack as L
|
|
184
|
-
header.concat Array.new(108, -1) # Difat sectors pack as L108
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
def save
|
|
188
|
-
|
|
189
|
-
ole = File.open(@file_name, 'w')
|
|
190
|
-
ole << header.pack(HEADER_PACKING)
|
|
191
|
-
ole << fat
|
|
192
|
-
@storages.each { |s| ole << s.to_s }
|
|
193
|
-
ole << Array.new((512-(ole.pos % 512)), 0).pack('c*')
|
|
194
|
-
ole << mini_fat
|
|
195
|
-
ole << mini_fat_stream
|
|
196
|
-
ole << fat_stream
|
|
197
|
-
ole.close
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
end
|
|
201
|
-
end
|
|
File without changes
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
# encoding: UTF-8
|
|
2
|
-
require 'digest'
|
|
3
|
-
require 'base64'
|
|
4
|
-
require 'openssl'
|
|
5
|
-
|
|
6
|
-
module Axlsx
|
|
7
|
-
|
|
8
|
-
# The MsOffCrypto class implements ECMA-367 encryption based on the MS-OFF-CRYPTO specification
|
|
9
|
-
class MsOffCrypto
|
|
10
|
-
|
|
11
|
-
# Creates a new MsOffCrypto Object
|
|
12
|
-
# @param [String] file_name the location of the file you want to encrypt
|
|
13
|
-
# @param [String] pwd the password to use when encrypting the file
|
|
14
|
-
def initialize(file_name, pwd)
|
|
15
|
-
self.password = pwd
|
|
16
|
-
self.file_name = file_name
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Generates a new CBF file based on this instance of ms-off-crypto and overwrites the unencrypted file.
|
|
20
|
-
def save
|
|
21
|
-
cfb = Cbf.new(self)
|
|
22
|
-
cfb.save
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# returns the raw password used in encryption
|
|
26
|
-
# @return [String]
|
|
27
|
-
attr_reader :password
|
|
28
|
-
|
|
29
|
-
# sets the password to be used for encryption
|
|
30
|
-
# @param [String] v the password, @default 'password'
|
|
31
|
-
# @return [String]
|
|
32
|
-
def password=(v)
|
|
33
|
-
@password = v || 'password'
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# retruns the file name of the archive to be encrypted
|
|
37
|
-
# @return [String]
|
|
38
|
-
attr_reader :file_name
|
|
39
|
-
|
|
40
|
-
# sets the filename
|
|
41
|
-
# @return [String]
|
|
42
|
-
def file_name=(v)
|
|
43
|
-
#TODO verfify that the file specified exists and is an unencrypted xlsx archive
|
|
44
|
-
@file_name = v
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
# encrypts and returns the package specified by the file name
|
|
49
|
-
# @return [String]
|
|
50
|
-
def encrypted_package
|
|
51
|
-
@encrypted_package ||= encrypt_package(file_name)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# returns the encryption info for this instance of ms-off-crypto
|
|
55
|
-
# @return [String]
|
|
56
|
-
def encryption_info
|
|
57
|
-
@encryption_info ||= create_encryption_info
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# returns a random salt
|
|
61
|
-
# @return [String]
|
|
62
|
-
def salt
|
|
63
|
-
@salt ||= Digest::SHA1.digest(rand(16**16).to_s)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# returns a random verifier
|
|
67
|
-
# @return [String]
|
|
68
|
-
def verifier
|
|
69
|
-
@verifier ||= rand(16**16).to_s
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# returns the verifier encrytped
|
|
73
|
-
# @return [String]
|
|
74
|
-
def encrypted_verifier
|
|
75
|
-
@encrypted_verifier ||= encrypt(verifier)
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# returns the verifier hash encrypted
|
|
79
|
-
# @return [String]
|
|
80
|
-
def encrypted_verifier_hash
|
|
81
|
-
@encrypted_verifier_hash ||= encrypt(verifier_hash)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# returns a verifier hash
|
|
85
|
-
# @return [String]
|
|
86
|
-
def verifier_hash
|
|
87
|
-
@verifier_hash ||= create_verifier_hash
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# returns an encryption key
|
|
91
|
-
# @return [String]
|
|
92
|
-
def key
|
|
93
|
-
@key ||= create_key
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# size of unencrypted package? concated with encrypted package
|
|
97
|
-
def encrypt_package(file_name)
|
|
98
|
-
package = File.open(file_name, 'r')
|
|
99
|
-
crypt_pack = encrypt(package.read)
|
|
100
|
-
[crypt_pack.size].pack('q') + crypt_pack
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Generates an encryption info structure
|
|
104
|
-
# @return [String]
|
|
105
|
-
def create_encryption_info
|
|
106
|
-
header = [3, 0, 2, 0] # version
|
|
107
|
-
# Header flags copy
|
|
108
|
-
header.concat [0x24, 0, 0, 0] #flags -- VERY UNSURE ABOUT THIS STILL
|
|
109
|
-
# header.concat [0, 0, 0, 0] #unused
|
|
110
|
-
header.concat [0xA4, 0, 0, 0] #length
|
|
111
|
-
# Header
|
|
112
|
-
header.concat [0x24, 0, 0, 0] #flags again
|
|
113
|
-
# header.concat [0, 0, 0, 0] #unused again,
|
|
114
|
-
header.concat [0x0E, 0x66, 0, 0] #alg id
|
|
115
|
-
header.concat [0x04, 0x80, 0, 0] #alg hash id
|
|
116
|
-
header.concat [key.size, 0, 0, 0] #key size
|
|
117
|
-
header.concat [0x18, 0, 0, 0] #provider type
|
|
118
|
-
# header.concat [0, 0, 0, 0] #reserved 1
|
|
119
|
-
# header.concat [0, 0, 0, 0] #reserved 2
|
|
120
|
-
header.concat [0xA0, 0xC7, 0xDC, 0x2, 0, 0, 0, 0]
|
|
121
|
-
header.concat "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)".bytes.to_a.pack('s*').bytes.to_a
|
|
122
|
-
header.concat [0, 0] #null terminator
|
|
123
|
-
|
|
124
|
-
#Salt Size
|
|
125
|
-
header.concat [salt.bytes.to_a.size].pack('l').bytes.to_a
|
|
126
|
-
#Salt
|
|
127
|
-
header.concat salt.bytes.to_a.pack('c*').bytes.to_a
|
|
128
|
-
# encryption verifier
|
|
129
|
-
header.concat encrypted_verifier.bytes.to_a.pack('c*').bytes.to_a
|
|
130
|
-
|
|
131
|
-
# verifier hash size -- MUST BE 32 bytes
|
|
132
|
-
header.concat [verifier_hash.bytes.to_a.size].pack('l').bytes.to_a
|
|
133
|
-
|
|
134
|
-
#encryption verifier hash
|
|
135
|
-
header.concat encrypted_verifier_hash.bytes.to_a.pack('c*').bytes.to_a
|
|
136
|
-
|
|
137
|
-
header.flatten!
|
|
138
|
-
header.pack('c*')
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
# 2.3.3
|
|
142
|
-
def create_verifier_hash
|
|
143
|
-
vh = Digest::SHA1.digest(verifier)
|
|
144
|
-
vh << Array.new(32 - vh.size, 0).join('')
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
# 2.3.4.7 ECMA-376 Document Encryption Key Generation (Standard Encryption)
|
|
148
|
-
def create_key
|
|
149
|
-
sha = Digest::SHA1.new() << (salt + @password)
|
|
150
|
-
(0..49999).each { |i| sha.update(i.to_s+sha.to_s) }
|
|
151
|
-
key = sha.update(sha.to_s+'0').digest
|
|
152
|
-
a = key.bytes.each_with_index.map { |item, i| 0x36 ^ item }
|
|
153
|
-
x1 = Digest::SHA1.digest((a.concat Array.new(64 - key.size, 0x36)).to_s)
|
|
154
|
-
a = key.bytes.each_with_index.map { |item, i| 0x5C ^ item }
|
|
155
|
-
x2 = Digest::SHA1.digest( (a.concat Array.new(64 - key.size, 0x5C) ).to_s)
|
|
156
|
-
x3 = x1 + x2
|
|
157
|
-
x3.bytes.to_a[(0..31)].pack('c*')
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
# ensures that the a hashed decryption of the encryption verifier matches the decrypted verifier hash.
|
|
161
|
-
# @return [Boolean]
|
|
162
|
-
def verify_password
|
|
163
|
-
v = Digest::SHA1.digest decrypt(@encrypted_verifier)
|
|
164
|
-
vh = decrypt(@encrypted_verifier_hash)
|
|
165
|
-
vh[0..15] == v[0..15]
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
# encrypts the data proved
|
|
169
|
-
# @param [String] data
|
|
170
|
-
# @return [String] the encrypted data
|
|
171
|
-
def encrypt(data)
|
|
172
|
-
aes = OpenSSL::Cipher.new("AES-128-ECB")
|
|
173
|
-
aes.encrypt
|
|
174
|
-
aes.key = key
|
|
175
|
-
aes.update(data) << aes.final
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
# dencrypts the data proved
|
|
179
|
-
# @param [String] data
|
|
180
|
-
# @return [String] the dencrypted data
|
|
181
|
-
def decrypt(data)
|
|
182
|
-
aes = OpenSSL::Cipher.new("AES-128-ECB")
|
|
183
|
-
aes.decrypt
|
|
184
|
-
aes.key = key
|
|
185
|
-
aes.update(data) << aes.final
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
end
|
|
189
|
-
end
|
|
File without changes
|
data/lib/axlsx/util/parser.rb~
DELETED
data/lib/axlsx/util/storage.rb~
DELETED
|
File without changes
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# encoding: UTF--8
|
|
2
|
-
module Axlsx
|
|
3
|
-
|
|
4
|
-
# The Shared String Table class is responsible for managing and serializing common strings in a workbook.
|
|
5
|
-
# While the ECMA-376 spec allows for both inline and shared strings it seems that at least some applications like Numbers (Mac)
|
|
6
|
-
# and Google Docs require that the shared string table is populated in order to interoperate properly.
|
|
7
|
-
# As a developer, you should never need to directly work against this class. Simply set 'use_shared_strings'
|
|
8
|
-
# on the package or workbook to generate a package that uses the shared strings table instead of inline strings.
|
|
9
|
-
# @note Serialization performance is affected by using this serialization method so if you do not need interoperability
|
|
10
|
-
# it is recomended that you use the default inline string method of serialization.
|
|
11
|
-
class SharedStringsTable
|
|
12
|
-
|
|
13
|
-
# The total number of strings in the workbook including duplicates
|
|
14
|
-
# Empty cells are treated as blank strings
|
|
15
|
-
# @return [Integer]
|
|
16
|
-
attr_reader :count
|
|
17
|
-
|
|
18
|
-
# The total number of unique strings in the workbook.
|
|
19
|
-
# @return [Integer]
|
|
20
|
-
def unique_count
|
|
21
|
-
@unique_cells.size
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# An array of unique cells. Multiple attributes of the cell are used in comparison
|
|
25
|
-
# each of these unique cells is parsed into the shared string table.
|
|
26
|
-
# @see Cell#sharable
|
|
27
|
-
attr_reader :unique_cells
|
|
28
|
-
|
|
29
|
-
# Creates a new Shared Strings Table agains an array of cells
|
|
30
|
-
# @param [Array] cells This is an array of all of the cells in the workbook
|
|
31
|
-
def initialize(cells)
|
|
32
|
-
cells = cells.reject { |c| c.type != :string }
|
|
33
|
-
@count = cells.size
|
|
34
|
-
@unique_cells = []
|
|
35
|
-
resolve cells
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# Interate over all of the cells in the array.
|
|
39
|
-
# if our unique cells array does not contain a sharable cell,
|
|
40
|
-
# add the cell to our unique cells array and set the ssti attribute on the index of this cell in the shared strings table
|
|
41
|
-
# if a sharable cell already exists in our unique_cells array, set the ssti attribute of the cell and move on.
|
|
42
|
-
# @return [Array] unique cells
|
|
43
|
-
def resolve(cells)
|
|
44
|
-
cells.each do |cell|
|
|
45
|
-
index = @unique_cells.index { |item| item.sharable(cell) }
|
|
46
|
-
if index == nil
|
|
47
|
-
cell.ssti = @unique_cells.size
|
|
48
|
-
@unique_cells << cell
|
|
49
|
-
else
|
|
50
|
-
cell.ssti = index
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# Generate the xml document for the Shared Strings Table
|
|
56
|
-
# @return [String]
|
|
57
|
-
def to_xml
|
|
58
|
-
builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml|
|
|
59
|
-
xml.sst(:xmlns => Axlsx::XML_NS, :count => count, :uniqueCount => unique_count) {
|
|
60
|
-
@unique_cells.each do |cell|
|
|
61
|
-
xml.si { xml.t cell.value.to_s }
|
|
62
|
-
end
|
|
63
|
-
}
|
|
64
|
-
end
|
|
65
|
-
builder.to_xml(:save_with => 0)
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
end
|