summaryrefslogtreecommitdiffhomepage
path: root/lib
diff options
context:
space:
mode:
authorRandy Morgan <[email protected]>2012-05-19 13:30:26 +0900
committerRandy Morgan <[email protected]>2012-05-19 13:30:26 +0900
commit0aede23fd2d8649bce223b36c28e5c77bf3749c4 (patch)
tree043c7851d8a776f19778f05c55e3c7ab9732f361 /lib
parent5101c6f96ff1ec34ccbf8006f6e192fd45005602 (diff)
downloadcaxlsx-0aede23fd2d8649bce223b36c28e5c77bf3749c4.tar.gz
caxlsx-0aede23fd2d8649bce223b36c28e5c77bf3749c4.zip
first run at sheet_protection to provide password protection locking for sheets.
Diffstat (limited to 'lib')
-rw-r--r--lib/axlsx/workbook/workbook.rb1
-rw-r--r--lib/axlsx/workbook/worksheet/sheet_protection.rb182
-rw-r--r--lib/axlsx/workbook/worksheet/worksheet.rb10
3 files changed, 192 insertions, 1 deletions
diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb
index fc9fbc51..fe3128c9 100644
--- a/lib/axlsx/workbook/workbook.rb
+++ b/lib/axlsx/workbook/workbook.rb
@@ -16,6 +16,7 @@ require 'axlsx/workbook/worksheet/row.rb'
require 'axlsx/workbook/worksheet/col.rb'
require 'axlsx/workbook/worksheet/comments.rb'
require 'axlsx/workbook/worksheet/comment.rb'
+require 'axlsx/workbook/worksheet/sheet_protection.rb'
require 'axlsx/workbook/worksheet/worksheet.rb'
require 'axlsx/workbook/shared_strings_table.rb'
require 'axlsx/workbook/worksheet/table.rb'
diff --git a/lib/axlsx/workbook/worksheet/sheet_protection.rb b/lib/axlsx/workbook/worksheet/sheet_protection.rb
new file mode 100644
index 00000000..66687f75
--- /dev/null
+++ b/lib/axlsx/workbook/worksheet/sheet_protection.rb
@@ -0,0 +1,182 @@
+# encoding: UTF-8
+module Axlsx
+
+ # The SheetProtection object manages worksheet protection options per sheet.
+ class SheetProtection
+
+ # Specifies the specific cryptographic hashing algorithm which shall be used along
+ # with the salt attribute and input password in order to compute the hash value.
+ # This value is automatically set to 'SHA-1' when password= is called.
+ # @note only SHA-1 is supported.
+ # @return [String]
+ attr_reader :algorithm_name
+
+
+ # If 1 or true then AutoFilters should not be allowed to operate when the sheet is protected.
+ # If 0 or false then AutoFilters should be allowed to operate when the sheet is protected.
+ # @return [Boolean]
+ # @default true
+ attr_reader :auto_filter
+
+ # If 1 or true then deleting columns should not be allowed when the sheet is protected.
+ # If 0 or false then deleting columns should be allowed when the sheet is protected.
+ # @return [Boolean]
+ # @default true
+ attr_reader :delete_columns
+
+ # If 1 or true then deleting rows should not be allowed when the sheet is protected.
+ # If 0 or false then deleting rows should be allowed when the sheet is protected.
+ # @return [Boolean]
+ # @default true
+ attr_reader :delete_rows
+
+ # If 1 or true then formatting cells should not be allowed when the sheet is protected.
+ # If 0 or false then formatting cells should be allowed when the sheet is protected.
+ # @return [Boolean]
+ # @default true
+ attr_reader :format_cells
+
+ # If 1 or true then formatting columns should not be allowed when the sheet is protected.
+ # If 0 or false then formatting columns should be allowed when the sheet is protected.
+ # @return [Boolean]
+ # @default true
+ attr_reader :format_columns
+
+ # If 1 or true then formatting rows should not be allowed when the sheet is protected.
+ # If 0 or false then formatting rows should be allowed when the sheet is protected.
+ # @return [Boolean]
+ # @default true
+ attr_reader :format_rows
+
+ # Specifies the hash value for the password required to edit this worksheet.
+ # @return [String]
+ attr_reader :hash_value
+
+ # If 1 or true then inserting columns should not be allowed when the sheet is protected.
+ # If 0 or false then inserting columns should be allowed when the sheet is protected.
+ # @return [Boolean]
+ # @default true
+ attr_reader :insert_columns
+
+ # If 1 or true then inserting hyperlinks should not be allowed when the sheet is protected.
+ # If 0 or false then inserting hyperlinks should be allowed when the sheet is protected.
+ # @return [Boolean]
+ # @default true
+ attr_reader :insert_hyperlinks
+
+ # If 1 or true then inserting rows should not be allowed when the sheet is protected.
+ # If 0 or false then inserting rows should be allowed when the sheet is protected.
+ # @return [Boolean]
+ # @default true
+ attr_reader :insert_rows
+
+ # If 1 or true then editing of objects should not be allowed when the sheet is protected.
+ # If 0 or false then objects are allowed to be edited when the sheet is protected.
+ # @return [Boolean]
+ # @default false
+ attr_reader :objects
+
+ # If 1 or true then PivotTables should not be allowed to operate when the sheet is protected.
+ # If 0 or false then PivotTables should be allowed to operate when the sheet is protected.
+ # @return [Boolean]
+ # @default true
+ attr_reader :pivot_tables
+
+ # Specifies the salt which was prepended to the user-supplied password before it was hashed using the hashing algorithm
+ # @return [String]
+ attr_reader :salt_value
+
+ # If 1 or true then Scenarios should not be edited when the sheet is protected.
+ # If 0 or false then Scenarios are allowed to be edited when the sheet is protected.
+ # @return [Boolean]
+ # default false
+ attr_reader :scenarios
+
+ # If 1 or true then selection of locked cells should not be allowed when the sheet is protected.
+ # If 0 or false then selection of locked cells should be allowed when the sheet is protected.
+ # @return [Boolean]
+ # default false
+ attr_reader :select_locked_cells
+
+ # If 1 or true then selection of unlocked cells should not be allowed when the sheet is protected.
+ # If 0 or false then selection of unlocked cells should be allowed when the sheet is protected.
+ # @return [Boolean]
+ # default false
+ attr_reader :select_unlocked_cells
+
+ # If 1 or true then the sheet is protected.
+ # If 0 or false then the sheet is not protected.
+ # @return [Boolean]
+ # default false
+ attr_reader :sheet
+
+ # If 1 or true then sorting should not be allowed when the sheet is protected.
+ # If 0 or false then sorting should be allowed when the sheet is protected.
+ # @return [Boolean]
+ # default true
+ attr_reader :sort
+
+ # Specifies the number of times the hashing function shall be iteratively run
+ # @return [Integer]
+ # @default 10000
+ attr_reader :spin_count
+
+ # Creates a new SheetProtection instance
+ # @option options [Boolean] sheet @see SheetProtection#sheet
+ # @option options [Boolean] objects @see SheetProtection#objects
+ # @option options [Boolean] scenarios @see SheetProtection#scenarios
+ # @option options [Boolean] format_cells @see SheetProtection#objects
+ # @option options [Boolean] format_columns @see SheetProtection#format_columns
+ # @option options [Boolean] format_rows @see SheetProtection#format_rows
+ # @option options [Boolean] insert_columns @see SheetProtection#insert_columns
+ # @option options [Boolean] insert_rows @see SheetProtection#insert_rows
+ # @option options [Boolean] insert_hyperlinks @see SheetProtection#insert_hyperlinks
+ # @option options [Boolean] delete_columns @see SheetProtection#delete_columns
+ # @option options [Boolean] delete_rows @see SheetProtection#delete_rows
+ # @option options [Boolean] select_locked_cells @see SheetProtection#select_locked_cells
+ # @option options [Boolean] sort @see SheetProtection#sort
+ # @option options [Boolean] auto_filter @see SheetProtection#auto_filter
+ # @option options [Boolean] pivot_tables @see SheetProtection#pivot_tables
+ # @option options [Boolean] select_unlocked_cells @see SheetProtection#select_unlocked_cells
+ # @option options [String] password. The password required for unlocking. @see SheetProtection#password=
+ # @option options [Boolean] objects @see SheetProtection#objects
+ def initialize(options={})
+ @sheet = @objects = @scenarios = @select_locked_cells = @select_unlocked_cells = false
+ @format_cells = @format_rows = @format_columns = @insert_columns = @insert_rows = @insert_hyperlinks = @delete_columns = @delete_rows = @sort = @auto_filter = @pivot_tables = true
+ 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,
+ :select_unlocked_cells, :format_cells, :format_rows, :format_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|
+ Axlsx::validate_boolean(v)
+ instance_variable_set "@#{f_name.to_s}".to_sym, v
+ end
+ end
+
+ def 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))
+
+ salty = @salt_value + v.to_s
+ @hash_value = Digest::SHA1.hexdigest(salty)
+ @spin_count.times do |count|
+ @hash_value = Digest::SHA1.hexdigest(@hash_value) + count.to_s
+ end
+ end
+
+ def to_xml_string(str = '')
+ str << '<sheetProtection '
+ str << instance_values.map{ |k,v| k.gsub(/_(.)/){ $1.upcase } << %{="#{v}"} }.join(' ')
+ str << '/>'
+ end
+ end
+end
diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb
index 57d96861..43275ba0 100644
--- a/lib/axlsx/workbook/worksheet/worksheet.rb
+++ b/lib/axlsx/workbook/worksheet/worksheet.rb
@@ -8,6 +8,13 @@ module Axlsx
# @return [String]
attr_reader :name
+ # The sheet protection object for this workbook
+ # @return [SheetProtection]
+ # @see SheetProtection
+ def sheet_protection
+ @sheet_protection ||= SheetProtection.new
+ end
+
# The workbook that owns this worksheet
# @return [Workbook]
attr_reader :workbook
@@ -151,7 +158,7 @@ module Axlsx
self.workbook = wb
@workbook.worksheets << self
@page_marging = @page_setup = @print_options = nil
- @drawing = @page_margins = @auto_filter = nil
+ @drawing = @page_margins = @auto_filter = @sheet_protection = nil
@merged_cells = []
@auto_fit_data = []
@conditional_formattings = []
@@ -482,6 +489,7 @@ module Axlsx
@rows.each_with_index { |row, index| row.to_xml_string(index, str) }
str.concat '</sheetData>'
str.concat "<autoFilter ref='%s'></autoFilter>" % @auto_filter if @auto_filter
+ @sheet_protection.to_xml_string(str) if @sheet_protection
str.concat "<mergeCells count='%s'>%s</mergeCells>" % [@merged_cells.size, @merged_cells.reduce('') { |memo, obj| memo += "<mergeCell ref='%s'></mergeCell>" % obj } ] unless @merged_cells.empty?
print_options.to_xml_string(str) if @print_options
page_margins.to_xml_string(str) if @page_margins