nokogiri 1.14.2 → 1.16.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.

Potentially problematic release.


This version of nokogiri might be problematic. Click here for more details.

Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +19 -15
  3. data/README.md +4 -1
  4. data/dependencies.yml +9 -8
  5. data/ext/nokogiri/extconf.rb +69 -26
  6. data/ext/nokogiri/html4_document.c +1 -2
  7. data/ext/nokogiri/html4_element_description.c +19 -14
  8. data/ext/nokogiri/html4_sax_parser_context.c +10 -16
  9. data/ext/nokogiri/html4_sax_push_parser.c +3 -3
  10. data/ext/nokogiri/nokogiri.c +46 -24
  11. data/ext/nokogiri/nokogiri.h +23 -5
  12. data/ext/nokogiri/test_global_handlers.c +1 -1
  13. data/ext/nokogiri/xml_attr.c +1 -1
  14. data/ext/nokogiri/xml_cdata.c +30 -17
  15. data/ext/nokogiri/xml_comment.c +1 -1
  16. data/ext/nokogiri/xml_document.c +113 -25
  17. data/ext/nokogiri/xml_document_fragment.c +1 -1
  18. data/ext/nokogiri/xml_dtd.c +1 -1
  19. data/ext/nokogiri/xml_element_content.c +32 -29
  20. data/ext/nokogiri/xml_element_decl.c +5 -5
  21. data/ext/nokogiri/xml_encoding_handler.c +12 -4
  22. data/ext/nokogiri/xml_entity_reference.c +1 -1
  23. data/ext/nokogiri/xml_namespace.c +11 -16
  24. data/ext/nokogiri/xml_node.c +13 -16
  25. data/ext/nokogiri/xml_node_set.c +125 -105
  26. data/ext/nokogiri/xml_processing_instruction.c +1 -1
  27. data/ext/nokogiri/xml_reader.c +61 -74
  28. data/ext/nokogiri/xml_relax_ng.c +66 -79
  29. data/ext/nokogiri/xml_sax_parser.c +24 -5
  30. data/ext/nokogiri/xml_sax_parser_context.c +50 -25
  31. data/ext/nokogiri/xml_sax_push_parser.c +30 -9
  32. data/ext/nokogiri/xml_schema.c +94 -115
  33. data/ext/nokogiri/xml_syntax_error.c +3 -3
  34. data/ext/nokogiri/xml_text.c +26 -13
  35. data/ext/nokogiri/xml_xpath_context.c +153 -83
  36. data/ext/nokogiri/xslt_stylesheet.c +111 -53
  37. data/gumbo-parser/Makefile +18 -0
  38. data/gumbo-parser/src/error.c +8 -4
  39. data/gumbo-parser/src/foreign_attrs.c +13 -14
  40. data/gumbo-parser/src/foreign_attrs.gperf +1 -1
  41. data/gumbo-parser/src/parser.c +21 -5
  42. data/gumbo-parser/src/tokenizer.c +1 -0
  43. data/lib/nokogiri/css/parser_extras.rb +1 -1
  44. data/lib/nokogiri/css/xpath_visitor.rb +3 -23
  45. data/lib/nokogiri/extension.rb +1 -1
  46. data/lib/nokogiri/html4/document.rb +1 -1
  47. data/lib/nokogiri/html4/document_fragment.rb +1 -1
  48. data/lib/nokogiri/html4/element_description_defaults.rb +1821 -353
  49. data/lib/nokogiri/html4/encoding_reader.rb +1 -1
  50. data/lib/nokogiri/html5/document_fragment.rb +1 -1
  51. data/lib/nokogiri/html5/node.rb +5 -0
  52. data/lib/nokogiri/html5.rb +0 -63
  53. data/lib/nokogiri/jruby/nokogiri_jars.rb +9 -9
  54. data/lib/nokogiri/version/constant.rb +1 -1
  55. data/lib/nokogiri/version/info.rb +6 -5
  56. data/lib/nokogiri/xml/attr.rb +2 -2
  57. data/lib/nokogiri/xml/attribute_decl.rb +4 -2
  58. data/lib/nokogiri/xml/document.rb +4 -5
  59. data/lib/nokogiri/xml/document_fragment.rb +3 -3
  60. data/lib/nokogiri/xml/element_content.rb +10 -2
  61. data/lib/nokogiri/xml/element_decl.rb +4 -2
  62. data/lib/nokogiri/xml/entity_decl.rb +4 -2
  63. data/lib/nokogiri/xml/namespace.rb +1 -2
  64. data/lib/nokogiri/xml/node/save_options.rb +8 -0
  65. data/lib/nokogiri/xml/node.rb +53 -37
  66. data/lib/nokogiri/xml/node_set.rb +3 -3
  67. data/lib/nokogiri/xml/pp/node.rb +23 -12
  68. data/lib/nokogiri/xml/reader.rb +10 -9
  69. data/lib/nokogiri/xml/sax/document.rb +1 -1
  70. data/lib/nokogiri/xml/searchable.rb +21 -13
  71. data/lib/nokogiri/xml/syntax_error.rb +1 -1
  72. data/lib/nokogiri/xml.rb +1 -1
  73. data/lib/nokogiri/xslt/stylesheet.rb +29 -7
  74. data/lib/nokogiri/xslt.rb +74 -4
  75. data/lib/nokogiri.rb +13 -5
  76. data/lib/xsd/xmlparser/nokogiri.rb +1 -1
  77. data/patches/libxml2/0010-update-config.guess-and-config.sub-for-libxml2.patch +224 -0
  78. data/patches/libxml2/0011-rip-out-libxml2-s-libc_single_threaded-support.patch +30 -0
  79. data/patches/libxslt/0001-update-config.guess-and-config.sub-for-libxslt.patch +224 -0
  80. data/ports/archives/libxml2-2.12.8.tar.xz +0 -0
  81. data/ports/archives/libxslt-1.1.39.tar.xz +0 -0
  82. metadata +16 -12
  83. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +0 -3037
  84. data/ports/archives/libxml2-2.10.3.tar.xz +0 -0
  85. data/ports/archives/libxslt-1.1.37.tar.xz +0 -0
@@ -5,12 +5,40 @@ VALUE cNokogiriXmlSaxParserContext ;
5
5
  static ID id_read;
6
6
 
7
7
  static void
8
- deallocate(xmlParserCtxtPtr ctxt)
8
+ xml_sax_parser_context_free(void *data)
9
9
  {
10
+ xmlParserCtxtPtr ctxt = data;
10
11
  ctxt->sax = NULL;
11
12
  xmlFreeParserCtxt(ctxt);
12
13
  }
13
14
 
15
+ /*
16
+ * note that htmlParserCtxtPtr == xmlParserCtxtPtr and xmlFreeParserCtxt() == htmlFreeParserCtxt()
17
+ * so we use this type for both XML::SAX::ParserContext and HTML::SAX::ParserContext
18
+ */
19
+ static const rb_data_type_t xml_sax_parser_context_type = {
20
+ .wrap_struct_name = "Nokogiri::XML::SAX::ParserContext",
21
+ .function = {
22
+ .dfree = xml_sax_parser_context_free,
23
+ },
24
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
25
+ };
26
+
27
+ xmlParserCtxtPtr
28
+ noko_xml_sax_parser_context_unwrap(VALUE rb_context)
29
+ {
30
+ xmlParserCtxtPtr c_context;
31
+ TypedData_Get_Struct(rb_context, xmlParserCtxt, &xml_sax_parser_context_type, c_context);
32
+ return c_context;
33
+ }
34
+
35
+ VALUE
36
+ noko_xml_sax_parser_context_wrap(VALUE klass, xmlParserCtxtPtr c_context)
37
+ {
38
+ return TypedData_Wrap_Struct(klass, &xml_sax_parser_context_type, c_context);
39
+ }
40
+
41
+
14
42
  /*
15
43
  * call-seq:
16
44
  * parse_io(io, encoding)
@@ -31,12 +59,16 @@ parse_io(VALUE klass, VALUE io, VALUE encoding)
31
59
  (xmlInputReadCallback)noko_io_read,
32
60
  (xmlInputCloseCallback)noko_io_close,
33
61
  (void *)io, enc);
62
+ if (!ctxt) {
63
+ rb_raise(rb_eRuntimeError, "failed to create xml sax parser context");
64
+ }
65
+
34
66
  if (ctxt->sax) {
35
67
  xmlFree(ctxt->sax);
36
68
  ctxt->sax = NULL;
37
69
  }
38
70
 
39
- return Data_Wrap_Struct(klass, NULL, deallocate, ctxt);
71
+ return noko_xml_sax_parser_context_wrap(klass, ctxt);
40
72
  }
41
73
 
42
74
  /*
@@ -49,7 +81,13 @@ static VALUE
49
81
  parse_file(VALUE klass, VALUE filename)
50
82
  {
51
83
  xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt(StringValueCStr(filename));
52
- return Data_Wrap_Struct(klass, NULL, deallocate, ctxt);
84
+
85
+ if (ctxt->sax) {
86
+ xmlFree(ctxt->sax);
87
+ ctxt->sax = NULL;
88
+ }
89
+
90
+ return noko_xml_sax_parser_context_wrap(klass, ctxt);
53
91
  }
54
92
 
55
93
  /*
@@ -76,7 +114,7 @@ parse_memory(VALUE klass, VALUE data)
76
114
  ctxt->sax = NULL;
77
115
  }
78
116
 
79
- return Data_Wrap_Struct(klass, NULL, deallocate, ctxt);
117
+ return noko_xml_sax_parser_context_wrap(klass, ctxt);
80
118
  }
81
119
 
82
120
  static VALUE
@@ -116,13 +154,8 @@ parse_with(VALUE self, VALUE sax_handler)
116
154
  rb_raise(rb_eArgError, "argument must be a Nokogiri::XML::SAX::Parser");
117
155
  }
118
156
 
119
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
120
- Data_Get_Struct(sax_handler, xmlSAXHandler, sax);
121
-
122
- /* Free the sax handler since we'll assign our own */
123
- if (ctxt->sax && ctxt->sax != (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) {
124
- xmlFree(ctxt->sax);
125
- }
157
+ ctxt = noko_xml_sax_parser_context_unwrap(self);
158
+ sax = noko_sax_handler_unwrap(sax_handler);
126
159
 
127
160
  ctxt->sax = sax;
128
161
  ctxt->userData = (void *)NOKOGIRI_SAX_TUPLE_NEW(ctxt, sax_handler);
@@ -144,8 +177,7 @@ parse_with(VALUE self, VALUE sax_handler)
144
177
  static VALUE
145
178
  set_replace_entities(VALUE self, VALUE value)
146
179
  {
147
- xmlParserCtxtPtr ctxt;
148
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
180
+ xmlParserCtxtPtr ctxt = noko_xml_sax_parser_context_unwrap(self);
149
181
 
150
182
  if (Qfalse == value) {
151
183
  ctxt->replaceEntities = 0;
@@ -166,8 +198,7 @@ set_replace_entities(VALUE self, VALUE value)
166
198
  static VALUE
167
199
  get_replace_entities(VALUE self)
168
200
  {
169
- xmlParserCtxtPtr ctxt;
170
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
201
+ xmlParserCtxtPtr ctxt = noko_xml_sax_parser_context_unwrap(self);
171
202
 
172
203
  if (0 == ctxt->replaceEntities) {
173
204
  return Qfalse;
@@ -184,10 +215,8 @@ get_replace_entities(VALUE self)
184
215
  static VALUE
185
216
  line(VALUE self)
186
217
  {
187
- xmlParserCtxtPtr ctxt;
188
218
  xmlParserInputPtr io;
189
-
190
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
219
+ xmlParserCtxtPtr ctxt = noko_xml_sax_parser_context_unwrap(self);
191
220
 
192
221
  io = ctxt->input;
193
222
  if (io) {
@@ -205,11 +234,9 @@ line(VALUE self)
205
234
  static VALUE
206
235
  column(VALUE self)
207
236
  {
208
- xmlParserCtxtPtr ctxt;
237
+ xmlParserCtxtPtr ctxt = noko_xml_sax_parser_context_unwrap(self);
209
238
  xmlParserInputPtr io;
210
239
 
211
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
212
-
213
240
  io = ctxt->input;
214
241
  if (io) {
215
242
  return INT2NUM(io->col);
@@ -228,8 +255,7 @@ column(VALUE self)
228
255
  static VALUE
229
256
  set_recovery(VALUE self, VALUE value)
230
257
  {
231
- xmlParserCtxtPtr ctxt;
232
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
258
+ xmlParserCtxtPtr ctxt = noko_xml_sax_parser_context_unwrap(self);
233
259
 
234
260
  if (value == Qfalse) {
235
261
  ctxt->recovery = 0;
@@ -250,8 +276,7 @@ set_recovery(VALUE self, VALUE value)
250
276
  static VALUE
251
277
  get_recovery(VALUE self)
252
278
  {
253
- xmlParserCtxtPtr ctxt;
254
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
279
+ xmlParserCtxtPtr ctxt = noko_xml_sax_parser_context_unwrap(self);
255
280
 
256
281
  if (ctxt->recovery == 0) {
257
282
  return Qfalse;
@@ -3,18 +3,35 @@
3
3
  VALUE cNokogiriXmlSaxPushParser ;
4
4
 
5
5
  static void
6
- deallocate(xmlParserCtxtPtr ctx)
6
+ xml_sax_push_parser_free(void *data)
7
7
  {
8
+ xmlParserCtxtPtr ctx = data;
8
9
  if (ctx != NULL) {
9
10
  NOKOGIRI_SAX_TUPLE_DESTROY(ctx->userData);
10
11
  xmlFreeParserCtxt(ctx);
11
12
  }
12
13
  }
13
14
 
15
+ static const rb_data_type_t xml_sax_push_parser_type = {
16
+ .wrap_struct_name = "Nokogiri::XML::SAX::PushParser",
17
+ .function = {
18
+ .dfree = xml_sax_push_parser_free,
19
+ },
20
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
21
+ };
22
+
14
23
  static VALUE
15
24
  allocate(VALUE klass)
16
25
  {
17
- return Data_Wrap_Struct(klass, NULL, deallocate, NULL);
26
+ return TypedData_Wrap_Struct(klass, &xml_sax_push_parser_type, NULL);
27
+ }
28
+
29
+ xmlParserCtxtPtr
30
+ noko_xml_sax_push_parser_unwrap(VALUE rb_parser)
31
+ {
32
+ xmlParserCtxtPtr c_parser;
33
+ TypedData_Get_Struct(rb_parser, xmlParserCtxt, &xml_sax_push_parser_type, c_parser);
34
+ return c_parser;
18
35
  }
19
36
 
20
37
  /*
@@ -31,7 +48,7 @@ native_write(VALUE self, VALUE _chunk, VALUE _last_chunk)
31
48
  int size = 0;
32
49
 
33
50
 
34
- Data_Get_Struct(self, xmlParserCtxt, ctx);
51
+ ctx = noko_xml_sax_push_parser_unwrap(self);
35
52
 
36
53
  if (Qnil != _chunk) {
37
54
  chunk = StringValuePtr(_chunk);
@@ -42,7 +59,7 @@ native_write(VALUE self, VALUE _chunk, VALUE _last_chunk)
42
59
 
43
60
  if (xmlParseChunk(ctx, chunk, size, Qtrue == _last_chunk ? 1 : 0)) {
44
61
  if (!(ctx->options & XML_PARSE_RECOVER)) {
45
- xmlErrorPtr e = xmlCtxtGetLastError(ctx);
62
+ xmlErrorConstPtr e = xmlCtxtGetLastError(ctx);
46
63
  Nokogiri_error_raise(NULL, e);
47
64
  }
48
65
  }
@@ -63,7 +80,7 @@ initialize_native(VALUE self, VALUE _xml_sax, VALUE _filename)
63
80
  const char *filename = NULL;
64
81
  xmlParserCtxtPtr ctx;
65
82
 
66
- Data_Get_Struct(_xml_sax, xmlSAXHandler, sax);
83
+ sax = noko_sax_handler_unwrap(_xml_sax);
67
84
 
68
85
  if (_filename != Qnil) { filename = StringValueCStr(_filename); }
69
86
 
@@ -89,7 +106,8 @@ static VALUE
89
106
  get_options(VALUE self)
90
107
  {
91
108
  xmlParserCtxtPtr ctx;
92
- Data_Get_Struct(self, xmlParserCtxt, ctx);
109
+
110
+ ctx = noko_xml_sax_push_parser_unwrap(self);
93
111
 
94
112
  return INT2NUM(ctx->options);
95
113
  }
@@ -98,7 +116,8 @@ static VALUE
98
116
  set_options(VALUE self, VALUE options)
99
117
  {
100
118
  xmlParserCtxtPtr ctx;
101
- Data_Get_Struct(self, xmlParserCtxt, ctx);
119
+
120
+ ctx = noko_xml_sax_push_parser_unwrap(self);
102
121
 
103
122
  if (xmlCtxtUseOptions(ctx, (int)NUM2INT(options)) != 0) {
104
123
  rb_raise(rb_eRuntimeError, "Cannot set XML parser context options");
@@ -118,7 +137,8 @@ static VALUE
118
137
  get_replace_entities(VALUE self)
119
138
  {
120
139
  xmlParserCtxtPtr ctx;
121
- Data_Get_Struct(self, xmlParserCtxt, ctx);
140
+
141
+ ctx = noko_xml_sax_push_parser_unwrap(self);
122
142
 
123
143
  if (0 == ctx->replaceEntities) {
124
144
  return Qfalse;
@@ -138,7 +158,8 @@ static VALUE
138
158
  set_replace_entities(VALUE self, VALUE value)
139
159
  {
140
160
  xmlParserCtxtPtr ctx;
141
- Data_Get_Struct(self, xmlParserCtxt, ctx);
161
+
162
+ ctx = noko_xml_sax_push_parser_unwrap(self);
142
163
 
143
164
  if (Qfalse == value) {
144
165
  ctx->replaceEntities = 0;
@@ -3,11 +3,20 @@
3
3
  VALUE cNokogiriXmlSchema;
4
4
 
5
5
  static void
6
- dealloc(xmlSchemaPtr schema)
6
+ xml_schema_deallocate(void *data)
7
7
  {
8
+ xmlSchemaPtr schema = data;
8
9
  xmlSchemaFree(schema);
9
10
  }
10
11
 
12
+ static const rb_data_type_t xml_schema_type = {
13
+ .wrap_struct_name = "Nokogiri::XML::Schema",
14
+ .function = {
15
+ .dfree = xml_schema_deallocate,
16
+ },
17
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
18
+ };
19
+
11
20
  /*
12
21
  * call-seq:
13
22
  * validate_document(document)
@@ -22,8 +31,8 @@ validate_document(VALUE self, VALUE document)
22
31
  xmlSchemaValidCtxtPtr valid_ctxt;
23
32
  VALUE errors;
24
33
 
25
- Data_Get_Struct(self, xmlSchema, schema);
26
- Noko_Node_Get_Struct(document, xmlDoc, doc);
34
+ TypedData_Get_Struct(self, xmlSchema, &xml_schema_type, schema);
35
+ doc = noko_xml_document_unwrap(document);
27
36
 
28
37
  errors = rb_ary_new();
29
38
 
@@ -63,7 +72,7 @@ validate_file(VALUE self, VALUE rb_filename)
63
72
  const char *filename ;
64
73
  VALUE errors;
65
74
 
66
- Data_Get_Struct(self, xmlSchema, schema);
75
+ TypedData_Get_Struct(self, xmlSchema, &xml_schema_type, schema);
67
76
  filename = (const char *)StringValueCStr(rb_filename) ;
68
77
 
69
78
  errors = rb_ary_new();
@@ -90,60 +99,54 @@ validate_file(VALUE self, VALUE rb_filename)
90
99
  return errors;
91
100
  }
92
101
 
93
- /*
94
- * call-seq:
95
- * read_memory(string)
96
- *
97
- * Create a new Schema from the contents of +string+
98
- */
99
102
  static VALUE
100
- read_memory(int argc, VALUE *argv, VALUE klass)
103
+ xml_schema_parse_schema(
104
+ VALUE klass,
105
+ xmlSchemaParserCtxtPtr c_parser_context,
106
+ VALUE rb_parse_options
107
+ )
101
108
  {
102
- VALUE content;
103
- VALUE parse_options;
109
+ VALUE rb_errors;
104
110
  int parse_options_int;
105
- xmlSchemaParserCtxtPtr ctx;
106
- xmlSchemaPtr schema;
107
- VALUE errors;
108
- VALUE rb_schema;
109
- int scanned_args = 0;
111
+ xmlSchemaPtr c_schema;
110
112
  xmlExternalEntityLoader old_loader = 0;
113
+ VALUE rb_schema;
111
114
 
112
- scanned_args = rb_scan_args(argc, argv, "11", &content, &parse_options);
113
- if (scanned_args == 1) {
114
- parse_options = rb_const_get_at(rb_const_get_at(mNokogiriXml, rb_intern("ParseOptions")), rb_intern("DEFAULT_SCHEMA"));
115
+ if (NIL_P(rb_parse_options)) {
116
+ rb_parse_options = rb_const_get_at(
117
+ rb_const_get_at(mNokogiriXml, rb_intern("ParseOptions")),
118
+ rb_intern("DEFAULT_SCHEMA")
119
+ );
115
120
  }
116
- parse_options_int = (int)NUM2INT(rb_funcall(parse_options, rb_intern("to_i"), 0));
117
121
 
118
- ctx = xmlSchemaNewMemParserCtxt((const char *)StringValuePtr(content), (int)RSTRING_LEN(content));
119
-
120
- errors = rb_ary_new();
121
- xmlSetStructuredErrorFunc((void *)errors, Nokogiri_error_array_pusher);
122
+ rb_errors = rb_ary_new();
123
+ xmlSetStructuredErrorFunc((void *)rb_errors, Nokogiri_error_array_pusher);
122
124
 
123
125
  #ifdef HAVE_XMLSCHEMASETPARSERSTRUCTUREDERRORS
124
126
  xmlSchemaSetParserStructuredErrors(
125
- ctx,
127
+ c_parser_context,
126
128
  Nokogiri_error_array_pusher,
127
- (void *)errors
129
+ (void *)rb_errors
128
130
  );
129
131
  #endif
130
132
 
133
+ parse_options_int = (int)NUM2INT(rb_funcall(rb_parse_options, rb_intern("to_i"), 0));
131
134
  if (parse_options_int & XML_PARSE_NONET) {
132
135
  old_loader = xmlGetExternalEntityLoader();
133
136
  xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
134
137
  }
135
138
 
136
- schema = xmlSchemaParse(ctx);
139
+ c_schema = xmlSchemaParse(c_parser_context);
137
140
 
138
141
  if (old_loader) {
139
142
  xmlSetExternalEntityLoader(old_loader);
140
143
  }
141
144
 
142
145
  xmlSetStructuredErrorFunc(NULL, NULL);
143
- xmlSchemaFreeParserCtxt(ctx);
146
+ xmlSchemaFreeParserCtxt(c_parser_context);
144
147
 
145
- if (NULL == schema) {
146
- xmlErrorPtr error = xmlGetLastError();
148
+ if (NULL == c_schema) {
149
+ xmlErrorConstPtr error = xmlGetLastError();
147
150
  if (error) {
148
151
  Nokogiri_error_raise(NULL, error);
149
152
  } else {
@@ -153,118 +156,94 @@ read_memory(int argc, VALUE *argv, VALUE klass)
153
156
  return Qnil;
154
157
  }
155
158
 
156
- rb_schema = Data_Wrap_Struct(klass, 0, dealloc, schema);
157
- rb_iv_set(rb_schema, "@errors", errors);
158
- rb_iv_set(rb_schema, "@parse_options", parse_options);
159
+ rb_schema = TypedData_Wrap_Struct(klass, &xml_schema_type, c_schema);
160
+ rb_iv_set(rb_schema, "@errors", rb_errors);
161
+ rb_iv_set(rb_schema, "@parse_options", rb_parse_options);
159
162
 
160
163
  return rb_schema;
161
164
  }
162
165
 
163
- /* Schema creation will remove and deallocate "blank" nodes.
164
- * If those blank nodes have been exposed to Ruby, they could get freed
165
- * out from under the VALUE pointer. This function checks to see if any of
166
- * those nodes have been exposed to Ruby, and if so we should raise an exception.
166
+ /*
167
+ * call-seq:
168
+ * read_memory(string) Nokogiri::XML::Schema
169
+ *
170
+ * Create a new schema parsed from the contents of +string+
171
+ *
172
+ * [Parameters]
173
+ * - +string+: String containing XML to be parsed as a schema
174
+ *
175
+ * [Returns] Nokogiri::XML::Schema
167
176
  */
168
- static int
169
- has_blank_nodes_p(VALUE cache)
177
+ static VALUE
178
+ read_memory(int argc, VALUE *argv, VALUE klass)
170
179
  {
171
- long i;
180
+ VALUE rb_content;
181
+ VALUE rb_parse_options;
182
+ xmlSchemaParserCtxtPtr c_parser_context;
172
183
 
173
- if (NIL_P(cache)) {
174
- return 0;
175
- }
184
+ rb_scan_args(argc, argv, "11", &rb_content, &rb_parse_options);
176
185
 
177
- for (i = 0; i < RARRAY_LEN(cache); i++) {
178
- xmlNodePtr node;
179
- VALUE element = rb_ary_entry(cache, i);
180
- Noko_Node_Get_Struct(element, xmlNode, node);
181
- if (xmlIsBlankNode(node)) {
182
- return 1;
183
- }
184
- }
186
+ c_parser_context = xmlSchemaNewMemParserCtxt(
187
+ (const char *)StringValuePtr(rb_content),
188
+ (int)RSTRING_LEN(rb_content)
189
+ );
185
190
 
186
- return 0;
191
+ return xml_schema_parse_schema(klass, c_parser_context, rb_parse_options);
187
192
  }
188
193
 
189
194
  /*
190
195
  * call-seq:
191
- * from_document(doc)
196
+ * from_document(document) → Nokogiri::XML::Schema
192
197
  *
193
- * Create a new Schema from the Nokogiri::XML::Document +doc+
198
+ * Create a new schema parsed from the +document+.
199
+ *
200
+ * [Parameters]
201
+ * - +document+: Nokogiri::XML::Document to be parsed
202
+ *
203
+ * [Returns] Nokogiri::XML::Schema
194
204
  */
195
205
  static VALUE
196
- from_document(int argc, VALUE *argv, VALUE klass)
206
+ rb_xml_schema_s_from_document(int argc, VALUE *argv, VALUE klass)
197
207
  {
198
- VALUE document;
199
- VALUE parse_options;
200
- int parse_options_int;
201
- xmlDocPtr doc;
202
- xmlSchemaParserCtxtPtr ctx;
203
- xmlSchemaPtr schema;
204
- VALUE errors;
208
+ VALUE rb_document;
209
+ VALUE rb_parse_options;
205
210
  VALUE rb_schema;
206
- int scanned_args = 0;
207
- xmlExternalEntityLoader old_loader = 0;
211
+ xmlDocPtr c_document;
212
+ xmlSchemaParserCtxtPtr c_parser_context;
213
+ int defensive_copy_p = 0;
208
214
 
209
- scanned_args = rb_scan_args(argc, argv, "11", &document, &parse_options);
215
+ rb_scan_args(argc, argv, "11", &rb_document, &rb_parse_options);
210
216
 
211
- Noko_Node_Get_Struct(document, xmlDoc, doc);
212
- doc = doc->doc; /* In case someone passes us a node. ugh. */
213
-
214
- if (scanned_args == 1) {
215
- parse_options = rb_const_get_at(rb_const_get_at(mNokogiriXml, rb_intern("ParseOptions")), rb_intern("DEFAULT_SCHEMA"));
217
+ if (!rb_obj_is_kind_of(rb_document, cNokogiriXmlNode)) {
218
+ rb_raise(rb_eTypeError,
219
+ "expected parameter to be a Nokogiri::XML::Document, received %"PRIsVALUE,
220
+ rb_obj_class(rb_document));
216
221
  }
217
- parse_options_int = (int)NUM2INT(rb_funcall(parse_options, rb_intern("to_i"), 0));
218
222
 
219
- if (has_blank_nodes_p(DOC_NODE_CACHE(doc))) {
220
- rb_raise(rb_eArgError, "Creating a schema from a document that has blank nodes exposed to Ruby is dangerous");
223
+ if (!rb_obj_is_kind_of(rb_document, cNokogiriXmlDocument)) {
224
+ xmlNodePtr deprecated_node_type_arg;
225
+ NOKO_WARN_DEPRECATION("Passing a Node as the first parameter to Schema.from_document is deprecated. Please pass a Document instead. This will become an error in Nokogiri v1.17.0."); // TODO: deprecated in v1.15.3, remove in v1.17.0
226
+ Noko_Node_Get_Struct(rb_document, xmlNode, deprecated_node_type_arg);
227
+ c_document = deprecated_node_type_arg->doc;
228
+ } else {
229
+ c_document = noko_xml_document_unwrap(rb_document);
221
230
  }
222
231
 
223
- ctx = xmlSchemaNewDocParserCtxt(doc);
224
-
225
- errors = rb_ary_new();
226
- xmlSetStructuredErrorFunc((void *)errors, Nokogiri_error_array_pusher);
227
-
228
- #ifdef HAVE_XMLSCHEMASETPARSERSTRUCTUREDERRORS
229
- xmlSchemaSetParserStructuredErrors(
230
- ctx,
231
- Nokogiri_error_array_pusher,
232
- (void *)errors
233
- );
234
- #endif
235
-
236
- if (parse_options_int & XML_PARSE_NONET) {
237
- old_loader = xmlGetExternalEntityLoader();
238
- xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
232
+ if (noko_xml_document_has_wrapped_blank_nodes_p(c_document)) {
233
+ // see https://github.com/sparklemotion/nokogiri/pull/2001
234
+ c_document = xmlCopyDoc(c_document, 1);
235
+ defensive_copy_p = 1;
239
236
  }
240
237
 
241
- schema = xmlSchemaParse(ctx);
238
+ c_parser_context = xmlSchemaNewDocParserCtxt(c_document);
239
+ rb_schema = xml_schema_parse_schema(klass, c_parser_context, rb_parse_options);
242
240
 
243
- if (old_loader) {
244
- xmlSetExternalEntityLoader(old_loader);
245
- }
246
-
247
- xmlSetStructuredErrorFunc(NULL, NULL);
248
- xmlSchemaFreeParserCtxt(ctx);
249
-
250
- if (NULL == schema) {
251
- xmlErrorPtr error = xmlGetLastError();
252
- if (error) {
253
- Nokogiri_error_raise(NULL, error);
254
- } else {
255
- rb_raise(rb_eRuntimeError, "Could not parse document");
256
- }
257
-
258
- return Qnil;
241
+ if (defensive_copy_p) {
242
+ xmlFreeDoc(c_document);
243
+ c_document = NULL;
259
244
  }
260
245
 
261
- rb_schema = Data_Wrap_Struct(klass, 0, dealloc, schema);
262
- rb_iv_set(rb_schema, "@errors", errors);
263
- rb_iv_set(rb_schema, "@parse_options", parse_options);
264
-
265
246
  return rb_schema;
266
-
267
- return Qnil;
268
247
  }
269
248
 
270
249
  void
@@ -275,7 +254,7 @@ noko_init_xml_schema(void)
275
254
  rb_undef_alloc_func(cNokogiriXmlSchema);
276
255
 
277
256
  rb_define_singleton_method(cNokogiriXmlSchema, "read_memory", read_memory, -1);
278
- rb_define_singleton_method(cNokogiriXmlSchema, "from_document", from_document, -1);
257
+ rb_define_singleton_method(cNokogiriXmlSchema, "from_document", rb_xml_schema_s_from_document, -1);
279
258
 
280
259
  rb_define_private_method(cNokogiriXmlSchema, "validate_document", validate_document, 1);
281
260
  rb_define_private_method(cNokogiriXmlSchema, "validate_file", validate_file, 1);
@@ -26,7 +26,7 @@ Nokogiri_structured_error_func_restore(libxmlStructuredErrorHandlerState *handle
26
26
  }
27
27
 
28
28
  void
29
- Nokogiri_error_array_pusher(void *ctx, xmlErrorPtr error)
29
+ Nokogiri_error_array_pusher(void *ctx, xmlErrorConstPtr error)
30
30
  {
31
31
  VALUE list = (VALUE)ctx;
32
32
  Check_Type(list, T_ARRAY);
@@ -34,13 +34,13 @@ Nokogiri_error_array_pusher(void *ctx, xmlErrorPtr error)
34
34
  }
35
35
 
36
36
  void
37
- Nokogiri_error_raise(void *ctx, xmlErrorPtr error)
37
+ Nokogiri_error_raise(void *ctx, xmlErrorConstPtr error)
38
38
  {
39
39
  rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
40
40
  }
41
41
 
42
42
  VALUE
43
- Nokogiri_wrap_xml_syntax_error(xmlErrorPtr error)
43
+ Nokogiri_wrap_xml_syntax_error(xmlErrorConstPtr error)
44
44
  {
45
45
  VALUE msg, e, klass;
46
46
 
@@ -9,25 +9,38 @@ VALUE cNokogiriXmlText ;
9
9
  * Create a new Text element on the +document+ with +content+
10
10
  */
11
11
  static VALUE
12
- new (int argc, VALUE *argv, VALUE klass)
12
+ rb_xml_text_s_new(int argc, VALUE *argv, VALUE klass)
13
13
  {
14
- xmlDocPtr doc;
15
- xmlNodePtr node;
16
- VALUE string;
17
- VALUE document;
18
- VALUE rest;
14
+ xmlDocPtr c_document;
15
+ xmlNodePtr c_node;
16
+ VALUE rb_string;
17
+ VALUE rb_document;
18
+ VALUE rb_rest;
19
19
  VALUE rb_node;
20
20
 
21
- rb_scan_args(argc, argv, "2*", &string, &document, &rest);
21
+ rb_scan_args(argc, argv, "2*", &rb_string, &rb_document, &rb_rest);
22
22
 
23
- Noko_Node_Get_Struct(document, xmlDoc, doc);
23
+ if (!rb_obj_is_kind_of(rb_document, cNokogiriXmlNode)) {
24
+ rb_raise(rb_eTypeError,
25
+ "expected second parameter to be a Nokogiri::XML::Document, received %"PRIsVALUE,
26
+ rb_obj_class(rb_document));
27
+ }
24
28
 
25
- node = xmlNewText((xmlChar *)StringValueCStr(string));
26
- node->doc = doc->doc;
29
+ if (!rb_obj_is_kind_of(rb_document, cNokogiriXmlDocument)) {
30
+ xmlNodePtr deprecated_node_type_arg;
31
+ NOKO_WARN_DEPRECATION("Passing a Node as the second parameter to Text.new is deprecated. Please pass a Document instead. This will become an error in Nokogiri v1.17.0."); // TODO: deprecated in v1.15.3, remove in v1.17.0
32
+ Noko_Node_Get_Struct(rb_document, xmlNode, deprecated_node_type_arg);
33
+ c_document = deprecated_node_type_arg->doc;
34
+ } else {
35
+ c_document = noko_xml_document_unwrap(rb_document);
36
+ }
27
37
 
28
- noko_xml_document_pin_node(node);
38
+ c_node = xmlNewText((xmlChar *)StringValueCStr(rb_string));
39
+ c_node->doc = c_document;
29
40
 
30
- rb_node = noko_xml_node_wrap(klass, node) ;
41
+ noko_xml_document_pin_node(c_node);
42
+
43
+ rb_node = noko_xml_node_wrap(klass, c_node) ;
31
44
  rb_obj_call_init(rb_node, argc, argv);
32
45
 
33
46
  if (rb_block_given_p()) { rb_yield(rb_node); }
@@ -44,5 +57,5 @@ noko_init_xml_text(void)
44
57
  */
45
58
  cNokogiriXmlText = rb_define_class_under(mNokogiriXml, "Text", cNokogiriXmlCharacterData);
46
59
 
47
- rb_define_singleton_method(cNokogiriXmlText, "new", new, -1);
60
+ rb_define_singleton_method(cNokogiriXmlText, "new", rb_xml_text_s_new, -1);
48
61
  }