summaryrefslogtreecommitdiffhomepage
path: root/lib/axlsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/axlsx')
-rw-r--r--lib/axlsx/workbook/worksheet/sheet_protection.rb52
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