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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +11 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +13 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +133 -0
  9. data/Rakefile +30 -0
  10. data/dependencies.yml +3 -0
  11. data/ext/nokogiri_ext_xmlsec/extconf.rb +489 -0
  12. data/ext/nokogiri_ext_xmlsec/init.c +46 -0
  13. data/ext/nokogiri_ext_xmlsec/nokogiri_decrypt_with_key.c +124 -0
  14. data/ext/nokogiri_ext_xmlsec/nokogiri_encrypt_with_key.c +182 -0
  15. data/ext/nokogiri_ext_xmlsec/nokogiri_helpers_set_attribute_id.c +43 -0
  16. data/ext/nokogiri_ext_xmlsec/nokogiri_init.c +32 -0
  17. data/ext/nokogiri_ext_xmlsec/nokogiri_sign_certificate.c +104 -0
  18. data/ext/nokogiri_ext_xmlsec/nokogiri_sign_rsa.c +95 -0
  19. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_certificates.c +96 -0
  20. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_named_keys.c +106 -0
  21. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_rsa.c +56 -0
  22. data/ext/nokogiri_ext_xmlsec/shutdown.c +12 -0
  23. data/ext/nokogiri_ext_xmlsec/xmlsecrb.h +39 -0
  24. data/lib/nokogiri-xmlsec.rb +1 -0
  25. data/lib/xmlsec.rb +110 -0
  26. data/lib/xmlsec/version.rb +3 -0
  27. data/nokogiri-xmlsec1.gemspec +46 -0
  28. data/ports/patches/libxml2/0001-Fix-parser-local-buffers-size-problems.patch +265 -0
  29. data/ports/patches/libxml2/0002-Fix-entities-local-buffers-size-problems.patch +102 -0
  30. data/ports/patches/libxml2/0003-Fix-an-error-in-previous-commit.patch +26 -0
  31. data/ports/patches/libxml2/0004-Fix-potential-out-of-bound-access.patch +26 -0
  32. data/ports/patches/libxml2/0005-Detect-excessive-entities-expansion-upon-replacement.patch +158 -0
  33. data/ports/patches/libxml2/0006-Do-not-fetch-external-parsed-entities.patch +78 -0
  34. data/ports/patches/libxml2/0007-Enforce-XML_PARSER_EOF-state-handling-through-the-pa.patch +480 -0
  35. data/ports/patches/libxml2/0008-Improve-handling-of-xmlStopParser.patch +315 -0
  36. data/ports/patches/libxml2/0009-Fix-a-couple-of-return-without-value.patch +37 -0
  37. data/ports/patches/libxml2/0010-Keep-non-significant-blanks-node-in-HTML-parser.patch +2006 -0
  38. data/ports/patches/libxml2/0011-Do-not-fetch-external-parameter-entities.patch +39 -0
  39. data/ports/patches/libxslt/0001-Adding-doc-update-related-to-1.1.28.patch +222 -0
  40. data/ports/patches/libxslt/0002-Fix-a-couple-of-places-where-f-printf-parameters-wer.patch +53 -0
  41. data/ports/patches/libxslt/0003-Initialize-pseudo-random-number-generator-with-curre.patch +60 -0
  42. data/ports/patches/libxslt/0004-EXSLT-function-str-replace-is-broken-as-is.patch +42 -0
  43. data/ports/patches/libxslt/0006-Fix-str-padding-to-work-with-UTF-8-strings.patch +164 -0
  44. data/ports/patches/libxslt/0007-Separate-function-for-predicate-matching-in-patterns.patch +587 -0
  45. data/ports/patches/libxslt/0008-Fix-direct-pattern-matching.patch +80 -0
  46. data/ports/patches/libxslt/0009-Fix-certain-patterns-with-predicates.patch +185 -0
  47. data/ports/patches/libxslt/0010-Fix-handling-of-UTF-8-strings-in-EXSLT-crypto-module.patch +126 -0
  48. data/ports/patches/libxslt/0013-Memory-leak-in-xsltCompileIdKeyPattern-error-path.patch +25 -0
  49. data/ports/patches/libxslt/0014-Fix-for-bug-436589.patch +43 -0
  50. data/ports/patches/libxslt/0015-Fix-mkdir-for-mingw.patch +41 -0
  51. data/ports/patches/xmlsec1/.keep +0 -0
  52. data/spec/fixtures/cert/server.crt +14 -0
  53. data/spec/fixtures/cert/server.csr +11 -0
  54. data/spec/fixtures/cert/server.key.decrypted +15 -0
  55. data/spec/fixtures/cert/server.key.encrypted +18 -0
  56. data/spec/fixtures/rsa.pem +15 -0
  57. data/spec/fixtures/rsa.pub +6 -0
  58. data/spec/fixtures/sign2-doc.xml +6 -0
  59. data/spec/fixtures/sign2-result.xml +24 -0
  60. data/spec/fixtures/sign3-result.xml +37 -0
  61. data/spec/lib/nokogiri/xml/document/encryption_and_decryption_spec.rb +22 -0
  62. data/spec/lib/nokogiri/xml/document/signing_and_verifying_spec.rb +77 -0
  63. data/spec/spec_helper.rb +10 -0
  64. metadata +251 -0
@@ -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
@@ -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
@@ -0,0 +1,2 @@
1
+ --color
2
+
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.2
6
+ - ruby-head
7
+ - rbx
8
+
9
+ matrix:
10
+ allow_failures:
11
+ - rvm: rbx
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in xmlsec.gemspec
4
+ gemspec
@@ -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
@@ -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.
@@ -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.
@@ -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
@@ -0,0 +1,3 @@
1
+ libxml2: "2.8.0"
2
+ libxslt: "1.1.28"
3
+ xmlsec1: "1.2.20"
@@ -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: