diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/axlsx/workbook/worksheet/sheet_protection.rb | 52 |
1 files changed, 38 insertions, 14 deletions
diff --git a/lib/axlsx/workbook/worksheet/sheet_protection.rb b/lib/axlsx/workbook/worksheet/sheet_protection.rb index a11ba49d..d8855008 100644 --- a/lib/axlsx/workbook/worksheet/sheet_protection.rb +++ b/lib/axlsx/workbook/worksheet/sheet_protection.rb @@ -103,8 +103,7 @@ module Axlsx # @return [Boolean] # @default true attr_reader :sort - - + # Password hash # @return [String] # @default nil @@ -133,46 +132,71 @@ module Axlsx @objects = @scenarios = @select_locked_cells = @select_unlocked_cells = false @sheet = @format_cells = @format_rows = @format_columns = @insert_columns = @insert_rows = @insert_hyperlinks = @delete_columns = @delete_rows = @sort = @auto_filter = @pivot_tables = true @password = nil - + options.each do |o| self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" end end - [:sheet, :objects, :scenarios, :select_locked_cells, :sort, + + # create validating setters for boolean values + # @return [Boolean] + [:sheet, :objects, :scenarios, :select_locked_cells, :sort, :select_unlocked_cells, :format_cells, :format_rows, :format_columns, - :insert_columns, :insert_rows, :insert_hyperlinks, :delete_columns, + :insert_columns, :insert_rows, :insert_hyperlinks, :delete_columns, :delete_rows, :auto_filter, :pivot_tables].each do |f_name| - define_method "#{f_name.to_s}=".to_sym do |v| + define_method "#{f_name.to_s}=".to_sym do |v| Axlsx::validate_boolean(v) instance_variable_set "@#{f_name.to_s}".to_sym, v end end + # This block is intended to implement the salt_value, hash_value and spin count as per the ECMA-376 standard. + # However, it does not seem to actually work in EXCEL - instead they are using their old retro algorithm shown below + # defined in the transitional portion of the speck. I am leaving this code in in the hope that someday Ill be able to + # figure out why it does not work, and if Excel even supports it. +# def propper_password=(v) +# @algorithm_name = v == nil ? nil : 'SHA-1' +# @salt_value = @spin_count = @hash_value = v if v == nil +# return if v == nil +# require 'digest/sha1' +# @spin_count = 10000 +# @salt_value = Digest::SHA1.hexdigest(rand(36**8).to_s(36)) +# @spin_count.times do |count| +# @hash_value = Digest::SHA1.hexdigest((@hash_value ||= (@salt_value + v.to_s)) + Array(count).pack('V')) +# end +# end + + + + # encodes password for protection locking def password=(v) return if v == nil @password = create_password_hash(v) end + # Serialize the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '<sheetProtection ' str << instance_values.map{ |k,v| k.gsub(/_(.)/){ $1.upcase } << %{="#{v.to_s}"} }.join(' ') str << '/>' end - + private # Creates a password hash for a given password # @return [String] def create_password_hash(password) encoded_password = encode_password(password) - + password_as_hex = [encoded_password].pack("v") password_as_string = password_as_hex.unpack("H*").first.upcase - + password_as_string[2..3] + password_as_string[0..1] end - - + + # Encodes a given password # Based on the algorithm provided by Daniel Rentz of OpenOffice. # http://www.openoffice.org/sc/excelfileformat.pdf, Revision 1.42, page 115 (21.05.2012) @@ -181,16 +205,16 @@ module Axlsx i = 0 chars = password.split(//) count = chars.size - + chars.collect! do |char| i += 1 - char = char.ord << i + char = char.unpack('c')[0] << i #ord << i low_15 = char & 0x7fff high_15 = char & 0x7fff << 15 high_15 = high_15 >> 15 char = low_15 | high_15 end - + encoded_password = 0x0000 chars.each { |c| encoded_password ^= c } encoded_password ^= count |
