nokogiri-xmlsec1 0.0.6

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