axlsx 1.0.14 → 1.0.15
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 +12 -4
- data/lib/axlsx.rb +3 -2
- data/lib/axlsx/package.rb +6 -0
- data/lib/axlsx/stylesheet/styles.rb +2 -0
- data/lib/axlsx/util/cbf.rb +297 -0
- data/lib/axlsx/util/cfb.rb~ +201 -0
- data/lib/axlsx/util/ms_off_crypto.rb +141 -40
- data/lib/axlsx/util/simple_typed_list.rb +12 -8
- data/lib/axlsx/util/storage.rb +146 -0
- data/lib/axlsx/{#cfb.xlsx# → util/storage.rb~} +0 -0
- data/lib/axlsx/version.rb +4 -1
- data/lib/axlsx/workbook/worksheet/cell.rb +4 -4
- metadata +95 -142
@@ -1,61 +1,152 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
1
2
|
require 'digest'
|
2
3
|
require 'base64'
|
3
4
|
require 'openssl'
|
5
|
+
|
4
6
|
module Axlsx
|
7
|
+
|
8
|
+
# The MsOffCrypto class implements ECMA-367 encryption based on the MS-OFF-CRYPTO specification
|
5
9
|
class MsOffCrypto
|
6
10
|
|
7
|
-
|
8
|
-
|
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
|
9
24
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
@key_size = 0x100
|
14
|
-
@verifier = rand(16**16).to_s
|
25
|
+
# returns the raw password used in encryption
|
26
|
+
# @return [String]
|
27
|
+
attr_reader :password
|
15
28
|
|
16
|
-
|
17
|
-
|
18
|
-
|
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'
|
19
34
|
end
|
20
35
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
header.concat [20, 0,0,0]
|
31
|
-
header.concat encrypted_verifier_hash.bytes.to_a.pack('c*').bytes.to_a
|
32
|
-
header.flatten!
|
33
|
-
header.pack('c*')
|
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
|
34
45
|
end
|
35
46
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
:encrypted_verifier_hash => encrypted_verifier_hash}
|
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, password)
|
42
52
|
end
|
43
53
|
|
44
|
-
#
|
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]
|
45
74
|
def encrypted_verifier
|
46
|
-
@encrypted_verifier ||= encrypt(
|
75
|
+
@encrypted_verifier ||= encrypt(verifier)
|
47
76
|
end
|
48
77
|
|
49
|
-
#
|
78
|
+
# returns the verifier hash encrypted
|
79
|
+
# @return [String]
|
50
80
|
def encrypted_verifier_hash
|
51
|
-
verifier_hash = Digest::SHA1.digest(@verifier)
|
52
|
-
verifier_hash << Array.new(32 - verifier_hash.size, 0).join('')
|
53
81
|
@encrypted_verifier_hash ||= encrypt(verifier_hash)
|
54
82
|
end
|
55
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, password)
|
98
|
+
package = File.open(file_name, 'r')
|
99
|
+
package_text = package.read
|
100
|
+
[package_text.bytes.to_a.size].pack('q') + encrypt(package_text)
|
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
|
+
|
56
147
|
# 2.3.4.7 ECMA-376 Document Encryption Key Generation (Standard Encryption)
|
57
|
-
def
|
58
|
-
sha = Digest::SHA1.new() << (
|
148
|
+
def create_key
|
149
|
+
sha = Digest::SHA1.new() << (salt + @password)
|
59
150
|
(0..49999).each { |i| sha.update(i.to_s+sha.to_s) }
|
60
151
|
key = sha.update(sha.to_s+'0').digest
|
61
152
|
a = key.bytes.each_with_index.map { |item, i| 0x36 ^ item }
|
@@ -63,25 +154,35 @@ module Axlsx
|
|
63
154
|
a = key.bytes.each_with_index.map { |item, i| 0x5C ^ item }
|
64
155
|
x2 = Digest::SHA1.digest( (a.concat Array.new(64 - key.size, 0x5C) ).to_s)
|
65
156
|
x3 = x1 + x2
|
66
|
-
|
157
|
+
x3.bytes.to_a[(0..31)].pack('c*')
|
67
158
|
end
|
68
159
|
|
160
|
+
# ensures that the a hashed decryption of the encryption verifier matches the decrypted verifier hash.
|
161
|
+
# @return [Boolean]
|
69
162
|
def verify_password
|
70
|
-
|
163
|
+
v = Digest::SHA1.digest decrypt(@encrypted_verifier)
|
164
|
+
vh = decrypt(@encrypted_verifier_hash)
|
165
|
+
vh[0..15] == v[0..15]
|
71
166
|
end
|
72
167
|
|
168
|
+
# encrypts the data proved
|
169
|
+
# @param [String] data
|
170
|
+
# @return [String] the encrypted data
|
73
171
|
def encrypt(data)
|
74
172
|
aes = OpenSSL::Cipher.new("AES-128-ECB")
|
75
173
|
aes.encrypt
|
76
174
|
aes.key = key
|
77
|
-
aes.update(data)
|
175
|
+
aes.update(data) << aes.final
|
78
176
|
end
|
79
177
|
|
178
|
+
# dencrypts the data proved
|
179
|
+
# @param [String] data
|
180
|
+
# @return [String] the dencrypted data
|
80
181
|
def decrypt(data)
|
81
182
|
aes = OpenSSL::Cipher.new("AES-128-ECB")
|
82
183
|
aes.decrypt
|
83
184
|
aes.key = key
|
84
|
-
aes.update(data)
|
185
|
+
aes.update(data) << aes.final
|
85
186
|
end
|
86
187
|
|
87
188
|
end
|
@@ -132,14 +132,18 @@ module Axlsx
|
|
132
132
|
# :drop_while
|
133
133
|
# :delete_if
|
134
134
|
# :clear
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
135
|
+
DESTRUCTIVE = ['replace', 'insert', 'collect!', 'map!', 'pop', 'delete_if',
|
136
|
+
'reverse!', 'shift', 'shuffle!', 'slice!', 'sort!', 'uniq!',
|
137
|
+
'unshift', 'zip', 'flatten!', 'fill', 'drop', 'drop_while',
|
138
|
+
'delete_if', 'clear']
|
139
|
+
DELEGATES = Array.instance_methods - self.instance_methods - DESTRUCTIVE
|
140
|
+
|
141
|
+
DELEGATES.each do |method|
|
142
|
+
class_eval %{
|
143
|
+
def #{method}(*args, &block)
|
144
|
+
@list.send(:#{method}, *args, &block)
|
145
|
+
end
|
146
|
+
}
|
143
147
|
end
|
144
148
|
|
145
149
|
# Serializes the list
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module Axlsx
|
2
|
+
|
3
|
+
# The Storage class represents a storage object or stream in a compound file.
|
4
|
+
class Storage
|
5
|
+
|
6
|
+
# Packing for the Storage when pushing an array of items into a byte stream
|
7
|
+
# Name, name length, type, color, left sibling, right sibling, child, classid, state, created, modified, sector, size
|
8
|
+
PACKING = "s32 s1 c2 l3 x16 x4 q2 l q"
|
9
|
+
|
10
|
+
# storage types
|
11
|
+
TYPES = {
|
12
|
+
:root=>5,
|
13
|
+
:stream=>2,
|
14
|
+
:storage=>1
|
15
|
+
}
|
16
|
+
|
17
|
+
# Creates a byte string for this storage
|
18
|
+
# @return [String]
|
19
|
+
def to_s
|
20
|
+
data = [@name.concat(Array.new(32-@name.size, 0)),
|
21
|
+
@name_size,
|
22
|
+
@type,
|
23
|
+
@color,
|
24
|
+
@left,
|
25
|
+
@right,
|
26
|
+
@child,
|
27
|
+
@created,
|
28
|
+
@modified,
|
29
|
+
@sector,
|
30
|
+
@size].flatten
|
31
|
+
puts data.inspect
|
32
|
+
data.pack(PACKING)
|
33
|
+
end
|
34
|
+
|
35
|
+
# storage colors
|
36
|
+
COLORS = {
|
37
|
+
:red=>0,
|
38
|
+
:black=>1
|
39
|
+
}
|
40
|
+
|
41
|
+
# The color of this node in the directory tree. Defaults to black if not specified
|
42
|
+
# @return [Integer] color
|
43
|
+
attr_reader :color
|
44
|
+
|
45
|
+
# Sets the color for this storage
|
46
|
+
# @param [Integer] v Must be one of the COLORS constant hash values
|
47
|
+
def color=(v)
|
48
|
+
RestrictionValidator.validate "Storage.color", COLORS.values, v
|
49
|
+
@color = v
|
50
|
+
end
|
51
|
+
|
52
|
+
# The size of the name for this node.
|
53
|
+
# interesting to see that office actually uses 'R' for the root directory and lists the size as 2 bytes - thus is it *NOT* null
|
54
|
+
# terminated. I am making this r/w so that I can override the size
|
55
|
+
# @return [Integer] color
|
56
|
+
attr_reader :name_size
|
57
|
+
|
58
|
+
# the name of the stream
|
59
|
+
attr_reader :name
|
60
|
+
|
61
|
+
# sets the name of the stream.
|
62
|
+
# This will automatically set the name_size attribute
|
63
|
+
# @return [String] name
|
64
|
+
def name=(v)
|
65
|
+
@name = v.bytes.to_a << 0
|
66
|
+
@name_size = @name.size * 2
|
67
|
+
@name
|
68
|
+
end
|
69
|
+
|
70
|
+
# The size of the stream
|
71
|
+
attr_reader :size
|
72
|
+
|
73
|
+
# The stream associated with this storage
|
74
|
+
attr_reader :data
|
75
|
+
|
76
|
+
# Set the data associated with the stream. If the stream type is undefined, we automatically specify the storage as a stream type. # with the exception of storages that are type root, all storages with data should be type stream.
|
77
|
+
# @param [String] v The data for this storages stream
|
78
|
+
# @return [Array]
|
79
|
+
def data=(v)
|
80
|
+
Axlsx::validate_string(v)
|
81
|
+
self.type = TYPES[:stream] unless @type
|
82
|
+
@size = v.size
|
83
|
+
@data = v.bytes.to_a
|
84
|
+
end
|
85
|
+
|
86
|
+
# The starting sector for the stream. If this storage is not a stream, or the root node this is nil
|
87
|
+
# @return [Integer] sector
|
88
|
+
attr_accessor :sector
|
89
|
+
|
90
|
+
# The 0 based index in the directoies chain for this the left sibling of this storage.
|
91
|
+
|
92
|
+
# @return [Integer] left
|
93
|
+
attr_accessor :left
|
94
|
+
|
95
|
+
# The 0 based index in the directoies chain for this the right sibling of this storage.
|
96
|
+
# @return [Integer] right
|
97
|
+
attr_accessor :right
|
98
|
+
|
99
|
+
# The 0 based index in the directoies chain for the child of this storage.
|
100
|
+
# @return [Integer] child
|
101
|
+
attr_accessor :child
|
102
|
+
|
103
|
+
# The created attribute for the storage
|
104
|
+
# @return [Integer] created
|
105
|
+
attr_accessor :created
|
106
|
+
|
107
|
+
# The modified attribute for the storage
|
108
|
+
# @return [Integer] modified
|
109
|
+
attr_accessor :modified
|
110
|
+
|
111
|
+
# The type of storage
|
112
|
+
# see TYPES
|
113
|
+
# @return [Integer] type
|
114
|
+
attr_reader :type
|
115
|
+
|
116
|
+
# Sets the type for this storage.
|
117
|
+
# @param [Integer] v the type to specify must be one of the TYPES constant hash values.
|
118
|
+
def type=(v)
|
119
|
+
RestrictionValidator.validate "Storage.type", TYPES.values, v
|
120
|
+
@type = v
|
121
|
+
end
|
122
|
+
|
123
|
+
# Creates a new storage object.
|
124
|
+
# @param [String] name the name of the storage
|
125
|
+
# @option options [Integer] color @default black
|
126
|
+
# @option options [Integer] type @default storage
|
127
|
+
# @option options [String] data
|
128
|
+
# @option options [Integer] left @default -1
|
129
|
+
# @option options [Integer] right @default -1
|
130
|
+
# @option options [Integer] child @default -1
|
131
|
+
# @option options [Integer] created @default 0
|
132
|
+
# @option options [Integer] modified @default 0
|
133
|
+
# @option options [Integer] sector @default 0
|
134
|
+
def initialize(name, options= {})
|
135
|
+
@left = @right = @child = -1
|
136
|
+
@sector = @size = @created = @modified = 0
|
137
|
+
options.each do |o|
|
138
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
139
|
+
end
|
140
|
+
@color ||= COLORS[:black]
|
141
|
+
@type ||= (data.nil? ? TYPES[:storage] : TYPES[:stream])
|
142
|
+
self.name = name
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
File without changes
|
data/lib/axlsx/version.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
module Axlsx
|
2
2
|
# version
|
3
|
-
|
3
|
+
# When using bunle exec rake and referencing the gem on github or locally
|
4
|
+
# it will use the gemspec, which preloads this constant for the gem's version.
|
5
|
+
# We check to make sure that it has not already been loaded
|
6
|
+
VERSION="1.0.15" unless Axlsx.const_defined? :VERSION
|
4
7
|
end
|
@@ -48,7 +48,7 @@ module Axlsx
|
|
48
48
|
def type=(v)
|
49
49
|
RestrictionValidator.validate "Cell.type", [:time, :float, :integer, :string], v
|
50
50
|
@type=v
|
51
|
-
self.value = @value
|
51
|
+
self.value = @value unless @value.nil?
|
52
52
|
end
|
53
53
|
|
54
54
|
|
@@ -175,14 +175,14 @@ module Axlsx
|
|
175
175
|
# @option options [String] color an 8 letter rgb specification
|
176
176
|
# @option options [Symbol] scheme must be one of :none, major, :minor
|
177
177
|
def initialize(row, value="", options={})
|
178
|
-
self.row=row
|
178
|
+
self.row=row
|
179
179
|
@styles = row.worksheet.workbook.styles
|
180
|
-
@style = 0
|
181
|
-
@type = cell_type_from_value(value)
|
182
180
|
@row.cells << self
|
183
181
|
options.each do |o|
|
184
182
|
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
185
183
|
end
|
184
|
+
@style ||= 0
|
185
|
+
@type ||= cell_type_from_value(value)
|
186
186
|
@value = cast_value(value)
|
187
187
|
end
|
188
188
|
|
metadata
CHANGED
@@ -1,168 +1,128 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: axlsx
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.15
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
- 14
|
10
|
-
version: 1.0.14
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Randy Morgan
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
date: 2012-01-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nokogiri
|
16
|
+
requirement: &2155999180 !ruby/object:Gem::Requirement
|
22
17
|
none: false
|
23
|
-
requirements:
|
24
|
-
- -
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
hash: 5
|
27
|
-
segments:
|
28
|
-
- 1
|
29
|
-
- 4
|
30
|
-
- 1
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
31
21
|
version: 1.4.1
|
32
|
-
requirement: *id001
|
33
22
|
type: :runtime
|
34
23
|
prerelease: false
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
|
24
|
+
version_requirements: *2155999180
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activesupport
|
27
|
+
requirement: &2155993560 !ruby/object:Gem::Requirement
|
38
28
|
none: false
|
39
|
-
requirements:
|
40
|
-
- -
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
hash: 17
|
43
|
-
segments:
|
44
|
-
- 2
|
45
|
-
- 3
|
46
|
-
- 9
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
47
32
|
version: 2.3.9
|
48
|
-
requirement: *id002
|
49
33
|
type: :runtime
|
50
34
|
prerelease: false
|
51
|
-
|
52
|
-
- !ruby/object:Gem::Dependency
|
53
|
-
|
35
|
+
version_requirements: *2155993560
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: i18n
|
38
|
+
requirement: &2153146240 !ruby/object:Gem::Requirement
|
54
39
|
none: false
|
55
|
-
requirements:
|
56
|
-
- -
|
57
|
-
- !ruby/object:Gem::Version
|
58
|
-
hash: 7
|
59
|
-
segments:
|
60
|
-
- 0
|
61
|
-
- 6
|
62
|
-
- 0
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
63
43
|
version: 0.6.0
|
64
|
-
requirement: *id003
|
65
44
|
type: :runtime
|
66
45
|
prerelease: false
|
67
|
-
|
68
|
-
- !ruby/object:Gem::Dependency
|
69
|
-
|
46
|
+
version_requirements: *2153146240
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rmagick
|
49
|
+
requirement: &2153145780 !ruby/object:Gem::Requirement
|
70
50
|
none: false
|
71
|
-
requirements:
|
72
|
-
- -
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
hash: 59
|
75
|
-
segments:
|
76
|
-
- 2
|
77
|
-
- 12
|
78
|
-
- 2
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
79
54
|
version: 2.12.2
|
80
|
-
requirement: *id004
|
81
55
|
type: :runtime
|
82
56
|
prerelease: false
|
83
|
-
|
84
|
-
- !ruby/object:Gem::Dependency
|
85
|
-
|
57
|
+
version_requirements: *2153145780
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rubyzip
|
60
|
+
requirement: &2153145320 !ruby/object:Gem::Requirement
|
86
61
|
none: false
|
87
|
-
requirements:
|
62
|
+
requirements:
|
88
63
|
- - ~>
|
89
|
-
- !ruby/object:Gem::Version
|
90
|
-
|
91
|
-
segments:
|
92
|
-
- 0
|
93
|
-
- 9
|
94
|
-
version: "0.9"
|
95
|
-
requirement: *id005
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0.9'
|
96
66
|
type: :runtime
|
97
67
|
prerelease: false
|
98
|
-
|
99
|
-
- !ruby/object:Gem::Dependency
|
100
|
-
|
68
|
+
version_requirements: *2153145320
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: &2153144780 !ruby/object:Gem::Requirement
|
101
72
|
none: false
|
102
|
-
requirements:
|
73
|
+
requirements:
|
103
74
|
- - ~>
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
|
106
|
-
segments:
|
107
|
-
- 0
|
108
|
-
- 9
|
109
|
-
version: "0.9"
|
110
|
-
requirement: *id006
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0.9'
|
111
77
|
type: :development
|
112
78
|
prerelease: false
|
113
|
-
|
114
|
-
- !ruby/object:Gem::Dependency
|
115
|
-
|
79
|
+
version_requirements: *2153144780
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: yard
|
82
|
+
requirement: &2153144400 !ruby/object:Gem::Requirement
|
116
83
|
none: false
|
117
|
-
requirements:
|
118
|
-
- -
|
119
|
-
- !ruby/object:Gem::Version
|
120
|
-
|
121
|
-
segments:
|
122
|
-
- 0
|
123
|
-
version: "0"
|
124
|
-
requirement: *id007
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
125
88
|
type: :development
|
126
89
|
prerelease: false
|
90
|
+
version_requirements: *2153144400
|
91
|
+
- !ruby/object:Gem::Dependency
|
127
92
|
name: yard
|
128
|
-
|
129
|
-
version_requirements: &id008 !ruby/object:Gem::Requirement
|
93
|
+
requirement: &2153143940 !ruby/object:Gem::Requirement
|
130
94
|
none: false
|
131
|
-
requirements:
|
132
|
-
- -
|
133
|
-
- !ruby/object:Gem::Version
|
134
|
-
|
135
|
-
segments:
|
136
|
-
- 0
|
137
|
-
version: "0"
|
138
|
-
requirement: *id008
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
139
99
|
type: :development
|
140
100
|
prerelease: false
|
141
|
-
|
142
|
-
- !ruby/object:Gem::Dependency
|
143
|
-
|
101
|
+
version_requirements: *2153143940
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: rdiscount
|
104
|
+
requirement: &2153143520 !ruby/object:Gem::Requirement
|
144
105
|
none: false
|
145
|
-
requirements:
|
146
|
-
- -
|
147
|
-
- !ruby/object:Gem::Version
|
148
|
-
|
149
|
-
segments:
|
150
|
-
- 0
|
151
|
-
version: "0"
|
152
|
-
requirement: *id009
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
153
110
|
type: :development
|
154
111
|
prerelease: false
|
155
|
-
|
156
|
-
description:
|
112
|
+
version_requirements: *2153143520
|
113
|
+
description: ! ' xlsx generation with charts, images, automated column width, customizable
|
114
|
+
styles and full schema validation. Axlsx excels at helping you generate beautiful
|
115
|
+
Office Open XML Spreadsheet documents without having to understand the entire ECMA
|
116
|
+
specification. Check out the README for some examples of how easy it is. Best of
|
117
|
+
all, you can validate your xlsx file before serialization so you know for sure that
|
118
|
+
anything generated is going to load on your client''s machine.
|
119
|
+
|
120
|
+
'
|
157
121
|
email: digital.ipseity@gmail.com
|
158
122
|
executables: []
|
159
|
-
|
160
123
|
extensions: []
|
161
|
-
|
162
124
|
extra_rdoc_files: []
|
163
|
-
|
164
|
-
files:
|
165
|
-
- lib/axlsx/#cfb.xlsx#
|
125
|
+
files:
|
166
126
|
- lib/axlsx/content_type/content_type.rb
|
167
127
|
- lib/axlsx/content_type/default.rb
|
168
128
|
- lib/axlsx/content_type/override.rb
|
@@ -214,6 +174,8 @@ files:
|
|
214
174
|
- lib/axlsx/stylesheet/table_style_element.rb
|
215
175
|
- lib/axlsx/stylesheet/table_styles.rb
|
216
176
|
- lib/axlsx/stylesheet/xf.rb
|
177
|
+
- lib/axlsx/util/cbf.rb
|
178
|
+
- lib/axlsx/util/cfb.rb~
|
217
179
|
- lib/axlsx/util/constants.rb
|
218
180
|
- lib/axlsx/util/ms_off_crypto.rb
|
219
181
|
- lib/axlsx/util/ms_off_crypto.rb~
|
@@ -221,6 +183,8 @@ files:
|
|
221
183
|
- lib/axlsx/util/parser.rb
|
222
184
|
- lib/axlsx/util/parser.rb~
|
223
185
|
- lib/axlsx/util/simple_typed_list.rb
|
186
|
+
- lib/axlsx/util/storage.rb
|
187
|
+
- lib/axlsx/util/storage.rb~
|
224
188
|
- lib/axlsx/util/validators.rb
|
225
189
|
- lib/axlsx/version.rb
|
226
190
|
- lib/axlsx/workbook/workbook.rb
|
@@ -337,40 +301,29 @@ files:
|
|
337
301
|
- test/workbook/worksheet/tc_worksheet.rb
|
338
302
|
homepage: https://github.com/randym/axlsx
|
339
303
|
licenses: []
|
340
|
-
|
341
304
|
post_install_message:
|
342
305
|
rdoc_options: []
|
343
|
-
|
344
|
-
require_paths:
|
306
|
+
require_paths:
|
345
307
|
- lib
|
346
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
308
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
347
309
|
none: false
|
348
|
-
requirements:
|
349
|
-
- -
|
350
|
-
- !ruby/object:Gem::Version
|
351
|
-
hash: 57
|
352
|
-
segments:
|
353
|
-
- 1
|
354
|
-
- 8
|
355
|
-
- 7
|
310
|
+
requirements:
|
311
|
+
- - ! '>='
|
312
|
+
- !ruby/object:Gem::Version
|
356
313
|
version: 1.8.7
|
357
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
314
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
358
315
|
none: false
|
359
|
-
requirements:
|
360
|
-
- -
|
361
|
-
- !ruby/object:Gem::Version
|
362
|
-
|
363
|
-
segments:
|
364
|
-
- 0
|
365
|
-
version: "0"
|
316
|
+
requirements:
|
317
|
+
- - ! '>='
|
318
|
+
- !ruby/object:Gem::Version
|
319
|
+
version: '0'
|
366
320
|
requirements: []
|
367
|
-
|
368
321
|
rubyforge_project:
|
369
322
|
rubygems_version: 1.8.10
|
370
323
|
signing_key:
|
371
324
|
specification_version: 3
|
372
325
|
summary: excel OOXML (xlsx) with charts, styles, images and autowidth columns.
|
373
|
-
test_files:
|
326
|
+
test_files:
|
374
327
|
- test/content_type/tc_content_type.rb
|
375
328
|
- test/content_type/tc_default.rb
|
376
329
|
- test/content_type/tc_override.rb
|