nokogiri-xmlsec1 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|