nokogiri-xmlsec1 0.0.6
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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.travis.yml +11 -0
- data/Gemfile +4 -0
- data/Guardfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +133 -0
- data/Rakefile +30 -0
- data/dependencies.yml +3 -0
- data/ext/nokogiri_ext_xmlsec/extconf.rb +489 -0
- data/ext/nokogiri_ext_xmlsec/init.c +46 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_decrypt_with_key.c +124 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_encrypt_with_key.c +182 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_helpers_set_attribute_id.c +43 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_init.c +32 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_sign_certificate.c +104 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_sign_rsa.c +95 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_certificates.c +96 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_named_keys.c +106 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_rsa.c +56 -0
- data/ext/nokogiri_ext_xmlsec/shutdown.c +12 -0
- data/ext/nokogiri_ext_xmlsec/xmlsecrb.h +39 -0
- data/lib/nokogiri-xmlsec.rb +1 -0
- data/lib/xmlsec.rb +110 -0
- data/lib/xmlsec/version.rb +3 -0
- data/nokogiri-xmlsec1.gemspec +46 -0
- data/ports/patches/libxml2/0001-Fix-parser-local-buffers-size-problems.patch +265 -0
- data/ports/patches/libxml2/0002-Fix-entities-local-buffers-size-problems.patch +102 -0
- data/ports/patches/libxml2/0003-Fix-an-error-in-previous-commit.patch +26 -0
- data/ports/patches/libxml2/0004-Fix-potential-out-of-bound-access.patch +26 -0
- data/ports/patches/libxml2/0005-Detect-excessive-entities-expansion-upon-replacement.patch +158 -0
- data/ports/patches/libxml2/0006-Do-not-fetch-external-parsed-entities.patch +78 -0
- data/ports/patches/libxml2/0007-Enforce-XML_PARSER_EOF-state-handling-through-the-pa.patch +480 -0
- data/ports/patches/libxml2/0008-Improve-handling-of-xmlStopParser.patch +315 -0
- data/ports/patches/libxml2/0009-Fix-a-couple-of-return-without-value.patch +37 -0
- data/ports/patches/libxml2/0010-Keep-non-significant-blanks-node-in-HTML-parser.patch +2006 -0
- data/ports/patches/libxml2/0011-Do-not-fetch-external-parameter-entities.patch +39 -0
- data/ports/patches/libxslt/0001-Adding-doc-update-related-to-1.1.28.patch +222 -0
- data/ports/patches/libxslt/0002-Fix-a-couple-of-places-where-f-printf-parameters-wer.patch +53 -0
- data/ports/patches/libxslt/0003-Initialize-pseudo-random-number-generator-with-curre.patch +60 -0
- data/ports/patches/libxslt/0004-EXSLT-function-str-replace-is-broken-as-is.patch +42 -0
- data/ports/patches/libxslt/0006-Fix-str-padding-to-work-with-UTF-8-strings.patch +164 -0
- data/ports/patches/libxslt/0007-Separate-function-for-predicate-matching-in-patterns.patch +587 -0
- data/ports/patches/libxslt/0008-Fix-direct-pattern-matching.patch +80 -0
- data/ports/patches/libxslt/0009-Fix-certain-patterns-with-predicates.patch +185 -0
- data/ports/patches/libxslt/0010-Fix-handling-of-UTF-8-strings-in-EXSLT-crypto-module.patch +126 -0
- data/ports/patches/libxslt/0013-Memory-leak-in-xsltCompileIdKeyPattern-error-path.patch +25 -0
- data/ports/patches/libxslt/0014-Fix-for-bug-436589.patch +43 -0
- data/ports/patches/libxslt/0015-Fix-mkdir-for-mingw.patch +41 -0
- data/ports/patches/xmlsec1/.keep +0 -0
- data/spec/fixtures/cert/server.crt +14 -0
- data/spec/fixtures/cert/server.csr +11 -0
- data/spec/fixtures/cert/server.key.decrypted +15 -0
- data/spec/fixtures/cert/server.key.encrypted +18 -0
- data/spec/fixtures/rsa.pem +15 -0
- data/spec/fixtures/rsa.pub +6 -0
- data/spec/fixtures/sign2-doc.xml +6 -0
- data/spec/fixtures/sign2-result.xml +24 -0
- data/spec/fixtures/sign3-result.xml +37 -0
- data/spec/lib/nokogiri/xml/document/encryption_and_decryption_spec.rb +22 -0
- data/spec/lib/nokogiri/xml/document/signing_and_verifying_spec.rb +77 -0
- data/spec/spec_helper.rb +10 -0
- metadata +251 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c07016a5857118879d16b8be6611ec84ca176c70
|
4
|
+
data.tar.gz: 575ccb28ced4c1774cda99086ba9984e2f75052b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cf48ed1086682b75a90ee4d62bb5171bcb2ec784f5e2018fb72367f1ad4c9d1379cca35d42b8b1d299fbadb26e2fe46ba55653310c8f36e9e9f3e40d2b14b42b
|
7
|
+
data.tar.gz: 3224de060fa1f0d6253069e0368f2900ac149b7c46a6287c6adec38b3f36acddd1eaf13cb75af7cd6a4809cced59920625fa7e56af674b203cb66a778b9e151b
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
ports/archives
|
14
|
+
ports/*-*-*
|
15
|
+
ports/*.installed
|
16
|
+
rdoc
|
17
|
+
spec/reports
|
18
|
+
test/tmp
|
19
|
+
test/version_tmp
|
20
|
+
tmp
|
21
|
+
spec/old
|
22
|
+
*.so
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rake', :task => 'default' do
|
5
|
+
watch(/^ext\//)
|
6
|
+
end
|
7
|
+
|
8
|
+
guard 'rspec' do
|
9
|
+
watch(%r{^spec/.+_spec\.rb$})
|
10
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
11
|
+
watch('spec/spec_helper.rb') { "spec" }
|
12
|
+
# watch(/^ext\//) { "spec" }
|
13
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 TODO: Write your name
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# nokogiri-xmlsec1
|
2
|
+
|
3
|
+
This is a fork of nokogiri-xmlsec. This fork uses mini_portile to improve code
|
4
|
+
predictiveness and allow heroku deploys.
|
5
|
+
|
6
|
+
This gem adds support to Ruby for encrypting, decrypting, signing and validating
|
7
|
+
the signatures of XML documents, according to the [XML Encryption Syntax and
|
8
|
+
Processing](http://www.w3.org/TR/xmlenc-core/) standard, by wrapping around the
|
9
|
+
[xmlsec1](http://www.aleksey.com/xmlsec) C library and adding relevant methods
|
10
|
+
to `Nokogiri::XML::Document`.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
gem 'nokogiri-xmlsec1'
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
$ bundle
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
$ gem install nokogiri-xmlsec1
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
Several methods are added to `Nokogiri::XML::Document` which expose this gem's
|
29
|
+
functionality.
|
30
|
+
|
31
|
+
### Signing
|
32
|
+
|
33
|
+
The `sign!` method adds a digital signature to the XML document so that it can
|
34
|
+
later be determined whether the document itself has been tampered with. If the
|
35
|
+
document changes, the signature will be invalid.
|
36
|
+
|
37
|
+
Signing a document will add XML nodes directly to the document itself, and
|
38
|
+
then returns itself.
|
39
|
+
|
40
|
+
# First, get an XML document
|
41
|
+
doc = Nokogiri::XML("<doc><greeting>Hello, World!</greeting></doc>")
|
42
|
+
|
43
|
+
# Sign the document with a certificate, a key, and a key name
|
44
|
+
doc.sign! certificate: 'certificate data',
|
45
|
+
key: 'private key data',
|
46
|
+
name: 'private key name'
|
47
|
+
|
48
|
+
You only need one of `certificate` or `key`, but you can pass both. If you do,
|
49
|
+
the certificate will be included as part of the signature, so that it can be
|
50
|
+
later verified by certificate instead of by key.
|
51
|
+
|
52
|
+
The `name` is implicitly converted into a string. Thus it is effectively
|
53
|
+
optional, since `nil` converts to `""`, and its value only matters if you plan
|
54
|
+
to verify the signature with any of a set of keys, as in the following example:
|
55
|
+
|
56
|
+
### Signature verification
|
57
|
+
|
58
|
+
Verification of signatures always returns `true` if successful, `false`
|
59
|
+
otherwise.
|
60
|
+
|
61
|
+
# Verify the document's signature to ensure it has not been tampered with
|
62
|
+
doc.verify_with({
|
63
|
+
'key-name-1' => 'public key contents',
|
64
|
+
'key-name-2' => 'another public key content'
|
65
|
+
})
|
66
|
+
|
67
|
+
In the above example, the `name` field from the signing process will be used
|
68
|
+
to determine which key to validate with. If you plan to always verify with the
|
69
|
+
same key, you can do it like so, effectively ignoring the `name` value:
|
70
|
+
|
71
|
+
# Verify the document's signature with a specific key
|
72
|
+
doc.verify_with key: 'public key contents'
|
73
|
+
|
74
|
+
Finally, you can also verify with a certificate:
|
75
|
+
|
76
|
+
# Verify the document's signature with a single certificate
|
77
|
+
doc.verify_with certificate: 'certificate data'
|
78
|
+
|
79
|
+
# Verify the document's signature with multiple certificates. Any one match
|
80
|
+
# will pass verification.
|
81
|
+
doc.verify_with certificates: [ 'cert1', 'cert2', 'cert3' ]
|
82
|
+
|
83
|
+
If the certificate has been installed to your system certificates, then you can
|
84
|
+
verify signatures like so:
|
85
|
+
|
86
|
+
# Verify with installed CA certificates
|
87
|
+
doc.verify_signature
|
88
|
+
|
89
|
+
### Encryption & Decryption
|
90
|
+
|
91
|
+
Encrypted documents can only be decrypted with the private key that corresponds
|
92
|
+
to the public key that was used to encrypt it. Thus, the party that encrypted
|
93
|
+
the document can be sure that the document will only be readable by its intended
|
94
|
+
recipient.
|
95
|
+
|
96
|
+
Both encryption and decryption of a document manipulates the XML nodes of the
|
97
|
+
document in-place. Both methods return the original document, after the changes
|
98
|
+
have been made to it.
|
99
|
+
|
100
|
+
To encrypt a document, use a public key:
|
101
|
+
|
102
|
+
doc.encrypt! key: 'public key content'
|
103
|
+
|
104
|
+
To decrypt a document, use a private key:
|
105
|
+
|
106
|
+
doc.decrypt! key: 'private key content'
|
107
|
+
|
108
|
+
|
109
|
+
## Limitations and Known Issues
|
110
|
+
|
111
|
+
Following is a list of limitations and/or issues I know about, but have no
|
112
|
+
immediate plan to resolve. This is probably because I haven't needed the
|
113
|
+
functionality, and no one has sent a pull request. (Hint, hint!)
|
114
|
+
|
115
|
+
- Currently, it is not possible to operate on individual XML nodes. The
|
116
|
+
`nokogiri-xmlsec1` operations must be performed on the entire document.
|
117
|
+
- Support for jruby and rubinius.
|
118
|
+
|
119
|
+
## Contributing
|
120
|
+
|
121
|
+
First of all, **thank you** for wanting to help and reading this!
|
122
|
+
|
123
|
+
1. [Fork the project](https://help.github.com/articles/fork-a-repo).
|
124
|
+
2. Create a feature branch - `git checkout -b adding_magic`
|
125
|
+
3. Add some tests, and make your changes!
|
126
|
+
4. Check that the tests pass - `bundle exec rake`
|
127
|
+
5. Commit your changes - `git commit -am "Added some magic"`
|
128
|
+
6. Push the branch to Github - `git push origin adding_magic`
|
129
|
+
7. Send a [pull request](https://help.github.com/articles/using-pull-requests)! :heart: :sparkling_heart: :heart:
|
130
|
+
|
131
|
+
## License
|
132
|
+
|
133
|
+
MIT. See [LICENSE.txt](LICENSE.txt) for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rake/extensiontask'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
|
5
|
+
Rake::ExtensionTask.new('nokogiri_ext_xmlsec')
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new :rspec
|
8
|
+
|
9
|
+
desc 'clean out build files'
|
10
|
+
task :clean do
|
11
|
+
rm_rf File.expand_path('../tmp', __FILE__)
|
12
|
+
end
|
13
|
+
|
14
|
+
task :default => [:clean, :compile, :rspec]
|
15
|
+
|
16
|
+
desc 'code statistics, cause im a stats junky'
|
17
|
+
task :stats do
|
18
|
+
def count(glob)
|
19
|
+
Dir[glob].inject(0) do |count, fi|
|
20
|
+
next unless File.file?(fi)
|
21
|
+
count + File.read(fi).lines.length
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
rb_lines = count 'lib/**/*.rb'
|
26
|
+
c_lines = count 'ext/**/*.{c,h}'
|
27
|
+
|
28
|
+
puts "Lines of Ruby: #{rb_lines}"
|
29
|
+
puts "Lines of C: #{c_lines}"
|
30
|
+
end
|
data/dependencies.yml
ADDED
@@ -0,0 +1,489 @@
|
|
1
|
+
# :stopdoc:
|
2
|
+
|
3
|
+
require 'mkmf'
|
4
|
+
|
5
|
+
ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
|
6
|
+
|
7
|
+
################################################################################
|
8
|
+
# functions
|
9
|
+
|
10
|
+
def lib_a(ldflag)
|
11
|
+
case ldflag
|
12
|
+
when /\A-l(.+)/
|
13
|
+
"lib#{$1}.#{$LIBEXT}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def asplode(lib)
|
18
|
+
abort "-----\n#{lib} is missing."
|
19
|
+
end
|
20
|
+
|
21
|
+
def do_help
|
22
|
+
print <<HELP
|
23
|
+
usage: ruby #{$0} [options]
|
24
|
+
|
25
|
+
--disable-static
|
26
|
+
Do not statically link bundled libraries.
|
27
|
+
|
28
|
+
--with-iconv-dir=DIR
|
29
|
+
Use the iconv library placed under DIR.
|
30
|
+
|
31
|
+
--with-zlib-dir=DIR
|
32
|
+
Use the zlib library placed under DIR.
|
33
|
+
|
34
|
+
--use-system-libraries
|
35
|
+
Use system libraries intead of building and using the bundled
|
36
|
+
libraries.
|
37
|
+
|
38
|
+
--with-xmlsec1-dir=DIR / --with-xmlsec1-config=CONFIG
|
39
|
+
--with-xml2-dir=DIR / --with-xml2-config=CONFIG
|
40
|
+
--with-xslt-dir=DIR / --with-xslt-config=CONFIG
|
41
|
+
--with-exslt-dir=DIR / --with-exslt-config=CONFIG
|
42
|
+
Use xmlsec1/libxml2/libxslt/libexslt as specified.
|
43
|
+
|
44
|
+
--enable-cross-build
|
45
|
+
Do cross-build.
|
46
|
+
HELP
|
47
|
+
exit! 0
|
48
|
+
end
|
49
|
+
|
50
|
+
def do_clean
|
51
|
+
exit! 0
|
52
|
+
end
|
53
|
+
|
54
|
+
def preserving_globals
|
55
|
+
values = [
|
56
|
+
$arg_config,
|
57
|
+
$CFLAGS, $CPPFLAGS,
|
58
|
+
$LDFLAGS, $LIBPATH, $libs
|
59
|
+
].map(&:dup)
|
60
|
+
yield
|
61
|
+
ensure
|
62
|
+
$arg_config,
|
63
|
+
$CFLAGS, $CPPFLAGS,
|
64
|
+
$LDFLAGS, $LIBPATH, $libs =
|
65
|
+
values
|
66
|
+
end
|
67
|
+
|
68
|
+
def have_iconv?
|
69
|
+
have_header('iconv.h') or return false
|
70
|
+
%w{ iconv_open libiconv_open }.any? do |method|
|
71
|
+
have_func(method, 'iconv.h') or
|
72
|
+
have_library('iconv', method, 'iconv.h')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def each_iconv_idir
|
77
|
+
# If --with-iconv-dir or --with-opt-dir is given, it should be
|
78
|
+
# the first priority
|
79
|
+
%w[iconv opt].each { |config|
|
80
|
+
idir = preserving_globals {
|
81
|
+
dir_config(config)
|
82
|
+
}.first and yield idir
|
83
|
+
}
|
84
|
+
|
85
|
+
# Try the system default
|
86
|
+
yield "/usr/include"
|
87
|
+
|
88
|
+
cflags, = preserving_globals {
|
89
|
+
pkg_config('libiconv')
|
90
|
+
}
|
91
|
+
if cflags
|
92
|
+
cflags.shellsplit.each { |arg|
|
93
|
+
arg.sub!(/\A-I/, '') and
|
94
|
+
yield arg
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
nil
|
99
|
+
end
|
100
|
+
|
101
|
+
def iconv_prefix
|
102
|
+
# Make sure libxml2 is built with iconv
|
103
|
+
each_iconv_idir { |idir|
|
104
|
+
next unless File.file?(File.join(idir, 'iconv.h'))
|
105
|
+
|
106
|
+
prefix, dir = File.split(idir)
|
107
|
+
next unless dir == 'include'
|
108
|
+
|
109
|
+
preserving_globals {
|
110
|
+
# Follow the way libxml2's configure uses a value given with
|
111
|
+
# --with-iconv[=DIR]
|
112
|
+
$CPPFLAGS = "-I#{idir}".quote << ' ' << $CPPFLAGS
|
113
|
+
$LIBPATH.unshift(File.join(prefix, "lib"))
|
114
|
+
have_iconv?
|
115
|
+
} and break prefix
|
116
|
+
} or asplode "libiconv"
|
117
|
+
end
|
118
|
+
|
119
|
+
def message!(important_message)
|
120
|
+
message important_message
|
121
|
+
if !$stdout.tty? && File.chardev?('/dev/tty')
|
122
|
+
File.open('/dev/tty', 'w') { |tty|
|
123
|
+
tty.print important_message
|
124
|
+
}
|
125
|
+
end
|
126
|
+
rescue Errno::ENXIO
|
127
|
+
end
|
128
|
+
|
129
|
+
def process_recipe(name, version, static_p, cross_p)
|
130
|
+
MiniPortile.new(name, version).tap do |recipe|
|
131
|
+
recipe.target = portsdir = File.join(ROOT, "ports")
|
132
|
+
# Prefer host_alias over host in order to use i586-mingw32msvc as
|
133
|
+
# correct compiler prefix for cross build, but use host if not set.
|
134
|
+
recipe.host = RbConfig::CONFIG["host_alias"].empty? ? RbConfig::CONFIG["host"] : RbConfig::CONFIG["host_alias"]
|
135
|
+
recipe.patch_files = Dir[File.join(portsdir, "patches", name, "*.patch")].sort
|
136
|
+
|
137
|
+
yield recipe
|
138
|
+
|
139
|
+
env = Hash.new { |hash, key|
|
140
|
+
hash[key] = "#{ENV[key]}" # (ENV[key].dup rescue '')
|
141
|
+
}
|
142
|
+
|
143
|
+
recipe.configure_options.flatten!
|
144
|
+
|
145
|
+
recipe.configure_options.delete_if { |option|
|
146
|
+
case option.shellsplit.first
|
147
|
+
when /\A(\w+)=(.*)\z/
|
148
|
+
env[$1] = $2
|
149
|
+
true
|
150
|
+
else
|
151
|
+
false
|
152
|
+
end
|
153
|
+
}
|
154
|
+
|
155
|
+
if static_p
|
156
|
+
recipe.configure_options += [
|
157
|
+
"--disable-shared",
|
158
|
+
"--enable-static",
|
159
|
+
]
|
160
|
+
env['CFLAGS'] = "-fPIC #{env['CFLAGS']}"
|
161
|
+
else
|
162
|
+
recipe.configure_options += [
|
163
|
+
"--enable-shared",
|
164
|
+
"--disable-static",
|
165
|
+
]
|
166
|
+
end
|
167
|
+
|
168
|
+
if cross_p
|
169
|
+
recipe.configure_options += [
|
170
|
+
"--target=#{recipe.host}",
|
171
|
+
"--host=#{recipe.host}",
|
172
|
+
]
|
173
|
+
end
|
174
|
+
|
175
|
+
if RbConfig::CONFIG['target_cpu'] == 'universal'
|
176
|
+
%w[CFLAGS LDFLAGS].each { |key|
|
177
|
+
unless env[key].shellsplit.include?('-arch')
|
178
|
+
env[key] << ' ' << RbConfig::CONFIG['ARCH_FLAG']
|
179
|
+
end
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
183
|
+
recipe.configure_options += env.map { |key, value|
|
184
|
+
"#{key}=#{value}".shellescape
|
185
|
+
}
|
186
|
+
|
187
|
+
if recipe.patch_files.empty?
|
188
|
+
message! "Building #{name}-#{version} for nokogiri-xmlsec1.\n"
|
189
|
+
else
|
190
|
+
message! "Building #{name}-#{version} for nokogiri-xmlsec1 with the following patches applied:\n"
|
191
|
+
|
192
|
+
recipe.patch_files.each { |patch|
|
193
|
+
message! "\t- %s\n" % File.basename(patch)
|
194
|
+
}
|
195
|
+
end
|
196
|
+
|
197
|
+
message! <<-"EOS"
|
198
|
+
************************************************************************
|
199
|
+
IMPORTANT! nokogiri-xmlsec1 builds and uses a packaged version of #{name}.
|
200
|
+
|
201
|
+
If this is a concern for you and you want to use the system library
|
202
|
+
instead, abort this installation process and reinstall nokogiri-xmlsec1
|
203
|
+
as follows:
|
204
|
+
|
205
|
+
gem install nokogiri-xmlsec1 -- --use-system-libraries
|
206
|
+
|
207
|
+
If you are using Bundler, tell it to use the option:
|
208
|
+
|
209
|
+
bundle config build.nokogiri-xmlsec1 --use-system-libraries
|
210
|
+
bundle install
|
211
|
+
************************************************************************
|
212
|
+
EOS
|
213
|
+
|
214
|
+
checkpoint = "#{recipe.target}/#{recipe.name}-#{recipe.version}-#{recipe.host}.installed"
|
215
|
+
unless File.exist?(checkpoint)
|
216
|
+
recipe.cook
|
217
|
+
FileUtils.touch checkpoint
|
218
|
+
end
|
219
|
+
recipe.activate
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Workaround for nokogiri issue #1102
|
224
|
+
def monkey_patch_mini_portile
|
225
|
+
MiniPortile.class_eval do
|
226
|
+
def patch
|
227
|
+
@patch_files.each do |full_path|
|
228
|
+
next unless File.exists?(full_path)
|
229
|
+
output "Running patch with #{full_path}..."
|
230
|
+
execute('patch', %Q(patch -p1 < #{full_path}))
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
################################################################################
|
237
|
+
# main
|
238
|
+
|
239
|
+
case
|
240
|
+
when arg_config('--help')
|
241
|
+
do_help
|
242
|
+
when arg_config('--clean')
|
243
|
+
do_clean
|
244
|
+
end
|
245
|
+
|
246
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
247
|
+
|
248
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'macruby'
|
249
|
+
$LIBRUBYARG_STATIC.gsub!(/-static/, '')
|
250
|
+
end
|
251
|
+
|
252
|
+
$CFLAGS << " #{ENV["CFLAGS"]}"
|
253
|
+
$LIBS << " #{ENV["LIBS"]}"
|
254
|
+
|
255
|
+
case RbConfig::CONFIG['target_os']
|
256
|
+
when 'mingw32', /mswin/
|
257
|
+
windows_p = true
|
258
|
+
$CFLAGS << " -DXP_WIN -DXP_WIN32 -DUSE_INCLUDED_VASPRINTF"
|
259
|
+
when /solaris/
|
260
|
+
$CFLAGS << " -DUSE_INCLUDED_VASPRINTF"
|
261
|
+
else
|
262
|
+
$CFLAGS << " -g -DXP_UNIX"
|
263
|
+
end
|
264
|
+
|
265
|
+
if RUBY_PLATFORM =~ /mingw/i
|
266
|
+
# Work around a character escaping bug in MSYS by passing an arbitrary
|
267
|
+
# double quoted parameter to gcc. See https://sourceforge.net/p/mingw/bugs/2142
|
268
|
+
$CPPFLAGS << ' "-Idummypath"'
|
269
|
+
end
|
270
|
+
|
271
|
+
if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
|
272
|
+
$CFLAGS << " -O3" unless $CFLAGS[/-O\d/]
|
273
|
+
$CFLAGS << " -Wall -Wwrite-strings -Wmissing-noreturn -Winline"
|
274
|
+
end
|
275
|
+
|
276
|
+
case
|
277
|
+
when arg_config('--use-system-libraries', !!ENV['NOKOGIRI_XMLSEC_USE_SYSTEM_LIBRARIES'])
|
278
|
+
message! "Building nokogiri-xmlsec1 using system libraries.\n"
|
279
|
+
|
280
|
+
dir_config('zlib')
|
281
|
+
|
282
|
+
# Using system libraries means we rely on the system libxml2 with
|
283
|
+
# regard to the iconv support.
|
284
|
+
|
285
|
+
dir_config('xml2').any? or pkg_config('libxml-2.0')
|
286
|
+
dir_config('xslt').any? or pkg_config('libxslt')
|
287
|
+
dir_config('exslt').any? or pkg_config('libexslt')
|
288
|
+
dir_config('xmlsec1').any? or pkg_config('xmlsec-openssl')
|
289
|
+
|
290
|
+
try_cpp(<<-SRC) or abort "libxml2 version 2.6.21 or later is required!"
|
291
|
+
#include <libxml/xmlversion.h>
|
292
|
+
|
293
|
+
#if LIBXML_VERSION < 20621
|
294
|
+
#error libxml2 is too old
|
295
|
+
#endif
|
296
|
+
SRC
|
297
|
+
|
298
|
+
try_cpp(<<-SRC) or warn "libxml2 version 2.9.0 and later is not yet supported, but proceeding anyway."
|
299
|
+
#include <libxml/xmlversion.h>
|
300
|
+
|
301
|
+
#if LIBXML_VERSION >= 20900
|
302
|
+
#error libxml2 is too new
|
303
|
+
#endif
|
304
|
+
SRC
|
305
|
+
else
|
306
|
+
message! "Building nokogiri-xmlsec1 using packaged libraries.\n"
|
307
|
+
|
308
|
+
require 'mini_portile'
|
309
|
+
monkey_patch_mini_portile
|
310
|
+
require 'yaml'
|
311
|
+
|
312
|
+
static_p = enable_config('static', true) or
|
313
|
+
message! "Static linking is disabled.\n"
|
314
|
+
|
315
|
+
dependencies = YAML.load_file(File.join(ROOT, "dependencies.yml"))
|
316
|
+
|
317
|
+
cross_build_p = enable_config("cross-build")
|
318
|
+
if cross_build_p || windows_p
|
319
|
+
zlib_recipe = process_recipe("zlib", dependencies["zlib"], static_p, cross_build_p) do |recipe|
|
320
|
+
recipe.files = ["http://zlib.net/#{recipe.name}-#{recipe.version}.tar.gz"]
|
321
|
+
class << recipe
|
322
|
+
attr_accessor :cross_build_p
|
323
|
+
|
324
|
+
def configure
|
325
|
+
Dir.chdir work_path do
|
326
|
+
mk = File.read 'win32/Makefile.gcc'
|
327
|
+
File.open 'win32/Makefile.gcc', 'wb' do |f|
|
328
|
+
f.puts "BINARY_PATH = #{path}/bin"
|
329
|
+
f.puts "LIBRARY_PATH = #{path}/lib"
|
330
|
+
f.puts "INCLUDE_PATH = #{path}/include"
|
331
|
+
mk.sub!(/^PREFIX\s*=\s*$/, "PREFIX = #{host}-") if cross_build_p
|
332
|
+
f.puts mk
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def configured?
|
338
|
+
Dir.chdir work_path do
|
339
|
+
!! (File.read('win32/Makefile.gcc') =~ /^BINARY_PATH/)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
def compile
|
344
|
+
execute "compile", "make -f win32/Makefile.gcc"
|
345
|
+
end
|
346
|
+
|
347
|
+
def install
|
348
|
+
execute "install", "make -f win32/Makefile.gcc install"
|
349
|
+
end
|
350
|
+
end
|
351
|
+
recipe.cross_build_p = cross_build_p
|
352
|
+
end
|
353
|
+
|
354
|
+
libiconv_recipe = process_recipe("libiconv", dependencies["libiconv"], static_p, cross_build_p) do |recipe|
|
355
|
+
recipe.files = ["http://ftp.gnu.org/pub/gnu/libiconv/#{recipe.name}-#{recipe.version}.tar.gz"]
|
356
|
+
recipe.configure_options += [
|
357
|
+
"CPPFLAGS='-Wall'",
|
358
|
+
"CFLAGS='-O2 -g'",
|
359
|
+
"CXXFLAGS='-O2 -g'",
|
360
|
+
"LDFLAGS="
|
361
|
+
]
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
libxml2_recipe = process_recipe("libxml2", dependencies["libxml2"], static_p, cross_build_p) do |recipe|
|
366
|
+
recipe.files = ["ftp://ftp.xmlsoft.org/libxml2/#{recipe.name}-#{recipe.version}.tar.gz"]
|
367
|
+
recipe.configure_options += [
|
368
|
+
"--without-python",
|
369
|
+
"--without-readline",
|
370
|
+
"--with-iconv=#{libiconv_recipe ? libiconv_recipe.path : iconv_prefix}",
|
371
|
+
"--with-c14n",
|
372
|
+
"--with-debug",
|
373
|
+
"--with-threads"
|
374
|
+
]
|
375
|
+
end
|
376
|
+
|
377
|
+
libxslt_recipe = process_recipe("libxslt", dependencies["libxslt"], static_p, cross_build_p) do |recipe|
|
378
|
+
recipe.files = ["ftp://ftp.xmlsoft.org/libxml2/#{recipe.name}-#{recipe.version}.tar.gz"]
|
379
|
+
recipe.configure_options += [
|
380
|
+
"--without-python",
|
381
|
+
"--without-crypto",
|
382
|
+
"--with-debug",
|
383
|
+
"--with-libxml-prefix=#{libxml2_recipe.path}"
|
384
|
+
]
|
385
|
+
end
|
386
|
+
|
387
|
+
xmlsec1_recipe = process_recipe("xmlsec1", dependencies["xmlsec1"], static_p, cross_build_p) do |recipe|
|
388
|
+
recipe.files = ["http://www.aleksey.com/xmlsec/download/#{recipe.name}-#{recipe.version}.tar.gz"]
|
389
|
+
recipe.configure_options += [
|
390
|
+
"--with-libxml=#{libxml2_recipe.path}",
|
391
|
+
"--with-libxslt=#{libxslt_recipe.path}",
|
392
|
+
"--disable-crypto-dl",
|
393
|
+
"--disable-apps-crypto-dl"
|
394
|
+
]
|
395
|
+
end
|
396
|
+
|
397
|
+
have_lzma = preserving_globals {
|
398
|
+
have_library('lzma')
|
399
|
+
}
|
400
|
+
|
401
|
+
$libs = $libs.shellsplit.tap { |libs|
|
402
|
+
[libxml2_recipe, libxslt_recipe, xmlsec1_recipe].each { |recipe|
|
403
|
+
libname = recipe.name[/\Alib(.+)\z/, 1] || recipe.name
|
404
|
+
File.join(recipe.path, "bin", "#{libname}-config").tap { |config|
|
405
|
+
# call config scripts explicit with 'sh' for compat with Windows
|
406
|
+
$CPPFLAGS = `sh #{config} --cflags`.strip << ' ' << $CPPFLAGS
|
407
|
+
`sh #{config} --libs`.strip.shellsplit.each { |arg|
|
408
|
+
case arg
|
409
|
+
when /\A-L(.+)\z/
|
410
|
+
# Prioritize ports' directories
|
411
|
+
if $1.start_with?(ROOT + '/')
|
412
|
+
$LIBPATH = [$1] | $LIBPATH
|
413
|
+
else
|
414
|
+
$LIBPATH = $LIBPATH | [$1]
|
415
|
+
end
|
416
|
+
when /\A-l./
|
417
|
+
libs.unshift(arg)
|
418
|
+
else
|
419
|
+
$LDFLAGS << ' ' << arg.shellescape
|
420
|
+
end
|
421
|
+
}
|
422
|
+
}
|
423
|
+
|
424
|
+
case libname
|
425
|
+
when 'xml2'
|
426
|
+
# xslt-config --libs or pkg-config libxslt --libs does not include
|
427
|
+
# -llzma, so we need to add it manually when linking statically.
|
428
|
+
if static_p && have_lzma
|
429
|
+
# Add it at the end; GH #988
|
430
|
+
libs << '-llzma'
|
431
|
+
end
|
432
|
+
when 'xslt'
|
433
|
+
# xslt-config does not have a flag to emit options including
|
434
|
+
# -lexslt, so add it manually.
|
435
|
+
libs.unshift('-lexslt')
|
436
|
+
end
|
437
|
+
}
|
438
|
+
}.shelljoin
|
439
|
+
|
440
|
+
if static_p
|
441
|
+
$libs = $libs.shellsplit.map { |arg|
|
442
|
+
case arg
|
443
|
+
when '-lxml2'
|
444
|
+
File.join(libxml2_recipe.path, 'lib', lib_a(arg))
|
445
|
+
when '-lxslt', '-lexslt'
|
446
|
+
File.join(libxslt_recipe.path, 'lib', lib_a(arg))
|
447
|
+
else
|
448
|
+
arg
|
449
|
+
end
|
450
|
+
}.shelljoin
|
451
|
+
end
|
452
|
+
|
453
|
+
end
|
454
|
+
|
455
|
+
{
|
456
|
+
"xml2" => ['xmlParseDoc', 'libxml/parser.h'],
|
457
|
+
"xslt" => ['xsltParseStylesheetDoc', 'libxslt/xslt.h'],
|
458
|
+
"exslt" => ['exsltFuncRegister', 'libexslt/exslt.h']
|
459
|
+
}.each { |lib, (func, header)|
|
460
|
+
have_func(func, header) ||
|
461
|
+
have_library(lib, func, header) ||
|
462
|
+
have_library("lib#{lib}", func, header) or
|
463
|
+
asplode("lib#{lib}")
|
464
|
+
}
|
465
|
+
|
466
|
+
xmlsec1_config = File.join(xmlsec1_recipe.path, "bin", "xmlsec1-config")
|
467
|
+
xmlsec1_crypto_lib = `sh #{xmlsec1_config} --crypto`.strip
|
468
|
+
|
469
|
+
["xmlsec1-#{xmlsec1_crypto_lib}", 'ruby.h'].each { |lib_or_header|
|
470
|
+
have_library(lib_or_header) ||
|
471
|
+
have_header(lib_or_header) or
|
472
|
+
asplode(lib_or_header)
|
473
|
+
}
|
474
|
+
|
475
|
+
create_makefile('nokogiri_ext_xmlsec')
|
476
|
+
|
477
|
+
if enable_config('clean', true)
|
478
|
+
# Do not clean if run in a development work tree.
|
479
|
+
File.open('Makefile', 'at') { |mk|
|
480
|
+
mk.print <<EOF
|
481
|
+
all: clean-ports
|
482
|
+
|
483
|
+
clean-ports: $(DLLIB)
|
484
|
+
-$(Q)$(RUBY) $(srcdir)/extconf.rb --clean --#{static_p ? 'enable' : 'disable'}-static
|
485
|
+
EOF
|
486
|
+
}
|
487
|
+
end
|
488
|
+
|
489
|
+
# :startdoc:
|