nokogiri 1.9.1 → 1.15.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (226) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +45 -0
  3. data/LICENSE-DEPENDENCIES.md +1636 -1024
  4. data/LICENSE.md +5 -28
  5. data/README.md +203 -89
  6. data/bin/nokogiri +63 -50
  7. data/dependencies.yml +33 -61
  8. data/ext/nokogiri/depend +38 -358
  9. data/ext/nokogiri/extconf.rb +864 -418
  10. data/ext/nokogiri/gumbo.c +594 -0
  11. data/ext/nokogiri/html4_document.c +165 -0
  12. data/ext/nokogiri/html4_element_description.c +299 -0
  13. data/ext/nokogiri/html4_entity_lookup.c +37 -0
  14. data/ext/nokogiri/html4_sax_parser_context.c +108 -0
  15. data/ext/nokogiri/html4_sax_push_parser.c +95 -0
  16. data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
  17. data/ext/nokogiri/nokogiri.c +251 -105
  18. data/ext/nokogiri/nokogiri.h +215 -90
  19. data/ext/nokogiri/test_global_handlers.c +40 -0
  20. data/ext/nokogiri/xml_attr.c +17 -17
  21. data/ext/nokogiri/xml_attribute_decl.c +22 -22
  22. data/ext/nokogiri/xml_cdata.c +40 -31
  23. data/ext/nokogiri/xml_comment.c +20 -27
  24. data/ext/nokogiri/xml_document.c +401 -240
  25. data/ext/nokogiri/xml_document_fragment.c +13 -17
  26. data/ext/nokogiri/xml_dtd.c +64 -58
  27. data/ext/nokogiri/xml_element_content.c +63 -55
  28. data/ext/nokogiri/xml_element_decl.c +31 -31
  29. data/ext/nokogiri/xml_encoding_handler.c +54 -21
  30. data/ext/nokogiri/xml_entity_decl.c +37 -35
  31. data/ext/nokogiri/xml_entity_reference.c +17 -19
  32. data/ext/nokogiri/xml_namespace.c +135 -61
  33. data/ext/nokogiri/xml_node.c +1346 -677
  34. data/ext/nokogiri/xml_node_set.c +246 -216
  35. data/ext/nokogiri/xml_processing_instruction.c +18 -20
  36. data/ext/nokogiri/xml_reader.c +347 -212
  37. data/ext/nokogiri/xml_relax_ng.c +86 -77
  38. data/ext/nokogiri/xml_sax_parser.c +149 -124
  39. data/ext/nokogiri/xml_sax_parser_context.c +145 -103
  40. data/ext/nokogiri/xml_sax_push_parser.c +64 -36
  41. data/ext/nokogiri/xml_schema.c +138 -81
  42. data/ext/nokogiri/xml_syntax_error.c +42 -21
  43. data/ext/nokogiri/xml_text.c +36 -26
  44. data/ext/nokogiri/xml_xpath_context.c +366 -178
  45. data/ext/nokogiri/xslt_stylesheet.c +335 -189
  46. data/gumbo-parser/CHANGES.md +63 -0
  47. data/gumbo-parser/Makefile +111 -0
  48. data/gumbo-parser/THANKS +27 -0
  49. data/gumbo-parser/src/Makefile +34 -0
  50. data/gumbo-parser/src/README.md +41 -0
  51. data/gumbo-parser/src/ascii.c +75 -0
  52. data/gumbo-parser/src/ascii.h +115 -0
  53. data/gumbo-parser/src/attribute.c +42 -0
  54. data/gumbo-parser/src/attribute.h +17 -0
  55. data/gumbo-parser/src/char_ref.c +22225 -0
  56. data/gumbo-parser/src/char_ref.h +29 -0
  57. data/gumbo-parser/src/char_ref.rl +2154 -0
  58. data/gumbo-parser/src/error.c +630 -0
  59. data/gumbo-parser/src/error.h +148 -0
  60. data/gumbo-parser/src/foreign_attrs.c +103 -0
  61. data/gumbo-parser/src/foreign_attrs.gperf +27 -0
  62. data/gumbo-parser/src/insertion_mode.h +33 -0
  63. data/gumbo-parser/src/macros.h +91 -0
  64. data/gumbo-parser/src/nokogiri_gumbo.h +944 -0
  65. data/gumbo-parser/src/parser.c +4891 -0
  66. data/gumbo-parser/src/parser.h +41 -0
  67. data/gumbo-parser/src/replacement.h +33 -0
  68. data/gumbo-parser/src/string_buffer.c +103 -0
  69. data/gumbo-parser/src/string_buffer.h +68 -0
  70. data/gumbo-parser/src/string_piece.c +48 -0
  71. data/gumbo-parser/src/svg_attrs.c +174 -0
  72. data/gumbo-parser/src/svg_attrs.gperf +77 -0
  73. data/gumbo-parser/src/svg_tags.c +137 -0
  74. data/gumbo-parser/src/svg_tags.gperf +55 -0
  75. data/gumbo-parser/src/tag.c +223 -0
  76. data/gumbo-parser/src/tag_lookup.c +382 -0
  77. data/gumbo-parser/src/tag_lookup.gperf +170 -0
  78. data/gumbo-parser/src/tag_lookup.h +13 -0
  79. data/gumbo-parser/src/token_buffer.c +79 -0
  80. data/gumbo-parser/src/token_buffer.h +71 -0
  81. data/gumbo-parser/src/token_type.h +17 -0
  82. data/gumbo-parser/src/tokenizer.c +3463 -0
  83. data/gumbo-parser/src/tokenizer.h +112 -0
  84. data/gumbo-parser/src/tokenizer_states.h +339 -0
  85. data/gumbo-parser/src/utf8.c +245 -0
  86. data/gumbo-parser/src/utf8.h +164 -0
  87. data/gumbo-parser/src/util.c +66 -0
  88. data/gumbo-parser/src/util.h +34 -0
  89. data/gumbo-parser/src/vector.c +111 -0
  90. data/gumbo-parser/src/vector.h +45 -0
  91. data/lib/nokogiri/class_resolver.rb +67 -0
  92. data/lib/nokogiri/css/node.rb +10 -8
  93. data/lib/nokogiri/css/parser.rb +397 -377
  94. data/lib/nokogiri/css/parser.y +250 -245
  95. data/lib/nokogiri/css/parser_extras.rb +54 -49
  96. data/lib/nokogiri/css/syntax_error.rb +3 -1
  97. data/lib/nokogiri/css/tokenizer.rb +107 -104
  98. data/lib/nokogiri/css/tokenizer.rex +3 -2
  99. data/lib/nokogiri/css/xpath_visitor.rb +224 -95
  100. data/lib/nokogiri/css.rb +56 -17
  101. data/lib/nokogiri/decorators/slop.rb +9 -7
  102. data/lib/nokogiri/encoding_handler.rb +57 -0
  103. data/lib/nokogiri/extension.rb +32 -0
  104. data/lib/nokogiri/gumbo.rb +15 -0
  105. data/lib/nokogiri/html.rb +38 -27
  106. data/lib/nokogiri/{html → html4}/builder.rb +4 -2
  107. data/lib/nokogiri/html4/document.rb +214 -0
  108. data/lib/nokogiri/html4/document_fragment.rb +54 -0
  109. data/lib/nokogiri/{html → html4}/element_description.rb +3 -1
  110. data/lib/nokogiri/html4/element_description_defaults.rb +2040 -0
  111. data/lib/nokogiri/html4/encoding_reader.rb +121 -0
  112. data/lib/nokogiri/{html → html4}/entity_lookup.rb +4 -2
  113. data/lib/nokogiri/{html → html4}/sax/parser.rb +17 -16
  114. data/lib/nokogiri/html4/sax/parser_context.rb +20 -0
  115. data/lib/nokogiri/{html → html4}/sax/push_parser.rb +12 -11
  116. data/lib/nokogiri/html4.rb +47 -0
  117. data/lib/nokogiri/html5/document.rb +168 -0
  118. data/lib/nokogiri/html5/document_fragment.rb +90 -0
  119. data/lib/nokogiri/html5/node.rb +103 -0
  120. data/lib/nokogiri/html5.rb +392 -0
  121. data/lib/nokogiri/jruby/dependencies.rb +3 -0
  122. data/lib/nokogiri/jruby/nokogiri_jars.rb +43 -0
  123. data/lib/nokogiri/syntax_error.rb +2 -0
  124. data/lib/nokogiri/version/constant.rb +6 -0
  125. data/lib/nokogiri/version/info.rb +223 -0
  126. data/lib/nokogiri/version.rb +3 -108
  127. data/lib/nokogiri/xml/attr.rb +55 -3
  128. data/lib/nokogiri/xml/attribute_decl.rb +6 -2
  129. data/lib/nokogiri/xml/builder.rb +98 -54
  130. data/lib/nokogiri/xml/cdata.rb +3 -1
  131. data/lib/nokogiri/xml/character_data.rb +2 -0
  132. data/lib/nokogiri/xml/document.rb +312 -126
  133. data/lib/nokogiri/xml/document_fragment.rb +93 -48
  134. data/lib/nokogiri/xml/dtd.rb +4 -2
  135. data/lib/nokogiri/xml/element_content.rb +12 -2
  136. data/lib/nokogiri/xml/element_decl.rb +6 -2
  137. data/lib/nokogiri/xml/entity_decl.rb +7 -3
  138. data/lib/nokogiri/xml/entity_reference.rb +2 -0
  139. data/lib/nokogiri/xml/namespace.rb +45 -0
  140. data/lib/nokogiri/xml/node/save_options.rb +23 -8
  141. data/lib/nokogiri/xml/node.rb +1088 -418
  142. data/lib/nokogiri/xml/node_set.rb +173 -63
  143. data/lib/nokogiri/xml/notation.rb +13 -0
  144. data/lib/nokogiri/xml/parse_options.rb +145 -52
  145. data/lib/nokogiri/xml/pp/character_data.rb +9 -6
  146. data/lib/nokogiri/xml/pp/node.rb +42 -30
  147. data/lib/nokogiri/xml/pp.rb +4 -2
  148. data/lib/nokogiri/xml/processing_instruction.rb +4 -1
  149. data/lib/nokogiri/xml/reader.rb +21 -28
  150. data/lib/nokogiri/xml/relax_ng.rb +8 -2
  151. data/lib/nokogiri/xml/sax/document.rb +45 -49
  152. data/lib/nokogiri/xml/sax/parser.rb +39 -36
  153. data/lib/nokogiri/xml/sax/parser_context.rb +8 -3
  154. data/lib/nokogiri/xml/sax/push_parser.rb +6 -5
  155. data/lib/nokogiri/xml/sax.rb +6 -4
  156. data/lib/nokogiri/xml/schema.rb +19 -9
  157. data/lib/nokogiri/xml/searchable.rb +120 -72
  158. data/lib/nokogiri/xml/syntax_error.rb +6 -4
  159. data/lib/nokogiri/xml/text.rb +2 -0
  160. data/lib/nokogiri/xml/xpath/syntax_error.rb +4 -2
  161. data/lib/nokogiri/xml/xpath.rb +15 -4
  162. data/lib/nokogiri/xml/xpath_context.rb +3 -3
  163. data/lib/nokogiri/xml.rb +38 -37
  164. data/lib/nokogiri/xslt/stylesheet.rb +3 -1
  165. data/lib/nokogiri/xslt.rb +101 -22
  166. data/lib/nokogiri.rb +59 -75
  167. data/lib/xsd/xmlparser/nokogiri.rb +29 -25
  168. data/patches/libxml2/0001-Remove-script-macro-support.patch +40 -0
  169. data/patches/libxml2/0002-Update-entities-to-remove-handling-of-ssi.patch +44 -0
  170. data/patches/libxml2/0003-libxml2.la-is-in-top_builddir.patch +25 -0
  171. data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
  172. data/patches/libxml2/0010-update-config.guess-and-config.sub-for-libxml2.patch +224 -0
  173. data/patches/libxml2/0011-rip-out-libxml2-s-libc_single_threaded-support.patch +30 -0
  174. data/patches/libxslt/0001-update-config.guess-and-config.sub-for-libxslt.patch +224 -0
  175. data/ports/archives/libxml2-2.11.4.tar.xz +0 -0
  176. data/ports/archives/libxslt-1.1.38.tar.xz +0 -0
  177. metadata +128 -265
  178. data/ext/nokogiri/html_document.c +0 -170
  179. data/ext/nokogiri/html_document.h +0 -10
  180. data/ext/nokogiri/html_element_description.c +0 -279
  181. data/ext/nokogiri/html_element_description.h +0 -10
  182. data/ext/nokogiri/html_entity_lookup.c +0 -32
  183. data/ext/nokogiri/html_entity_lookup.h +0 -8
  184. data/ext/nokogiri/html_sax_parser_context.c +0 -116
  185. data/ext/nokogiri/html_sax_parser_context.h +0 -11
  186. data/ext/nokogiri/html_sax_push_parser.c +0 -87
  187. data/ext/nokogiri/html_sax_push_parser.h +0 -9
  188. data/ext/nokogiri/xml_attr.h +0 -9
  189. data/ext/nokogiri/xml_attribute_decl.h +0 -9
  190. data/ext/nokogiri/xml_cdata.h +0 -9
  191. data/ext/nokogiri/xml_comment.h +0 -9
  192. data/ext/nokogiri/xml_document.h +0 -23
  193. data/ext/nokogiri/xml_document_fragment.h +0 -10
  194. data/ext/nokogiri/xml_dtd.h +0 -10
  195. data/ext/nokogiri/xml_element_content.h +0 -10
  196. data/ext/nokogiri/xml_element_decl.h +0 -9
  197. data/ext/nokogiri/xml_encoding_handler.h +0 -8
  198. data/ext/nokogiri/xml_entity_decl.h +0 -10
  199. data/ext/nokogiri/xml_entity_reference.h +0 -9
  200. data/ext/nokogiri/xml_io.c +0 -61
  201. data/ext/nokogiri/xml_io.h +0 -11
  202. data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
  203. data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
  204. data/ext/nokogiri/xml_namespace.h +0 -14
  205. data/ext/nokogiri/xml_node.h +0 -13
  206. data/ext/nokogiri/xml_node_set.h +0 -12
  207. data/ext/nokogiri/xml_processing_instruction.h +0 -9
  208. data/ext/nokogiri/xml_reader.h +0 -10
  209. data/ext/nokogiri/xml_relax_ng.h +0 -9
  210. data/ext/nokogiri/xml_sax_parser.h +0 -39
  211. data/ext/nokogiri/xml_sax_parser_context.h +0 -10
  212. data/ext/nokogiri/xml_sax_push_parser.h +0 -9
  213. data/ext/nokogiri/xml_schema.h +0 -9
  214. data/ext/nokogiri/xml_syntax_error.h +0 -13
  215. data/ext/nokogiri/xml_text.h +0 -9
  216. data/ext/nokogiri/xml_xpath_context.h +0 -10
  217. data/ext/nokogiri/xslt_stylesheet.h +0 -14
  218. data/lib/nokogiri/html/document.rb +0 -335
  219. data/lib/nokogiri/html/document_fragment.rb +0 -49
  220. data/lib/nokogiri/html/element_description_defaults.rb +0 -671
  221. data/lib/nokogiri/html/sax/parser_context.rb +0 -16
  222. data/patches/libxml2/0001-Revert-Do-not-URI-escape-in-server-side-includes.patch +0 -78
  223. data/patches/libxml2/0002-Fix-nullptr-deref-with-XPath-logic-ops.patch +0 -54
  224. data/patches/libxml2/0003-Fix-infinite-loop-in-LZMA-decompression.patch +0 -50
  225. data/ports/archives/libxml2-2.9.8.tar.gz +0 -0
  226. data/ports/archives/libxslt-1.1.32.tar.gz +0 -0
@@ -1,298 +1,486 @@
1
- #include <xml_xpath_context.h>
1
+ #include <nokogiri.h>
2
2
 
3
- int vasprintf (char **strp, const char *fmt, va_list ap);
3
+ VALUE cNokogiriXmlXpathContext;
4
+
5
+ /*
6
+ * these constants have matching declarations in
7
+ * ext/java/nokogiri/internals/NokogiriNamespaceContext.java
8
+ */
9
+ static const xmlChar *NOKOGIRI_PREFIX = (const xmlChar *)"nokogiri";
10
+ static const xmlChar *NOKOGIRI_URI = (const xmlChar *)"http://www.nokogiri.org/default_ns/ruby/extensions_functions";
11
+ static const xmlChar *NOKOGIRI_BUILTIN_PREFIX = (const xmlChar *)"nokogiri-builtin";
12
+ static const xmlChar *NOKOGIRI_BUILTIN_URI = (const xmlChar *)"https://www.nokogiri.org/default_ns/ruby/builtins";
4
13
 
5
- static void deallocate(xmlXPathContextPtr ctx)
14
+ static void
15
+ xml_xpath_context_deallocate(void *data)
6
16
  {
7
- NOKOGIRI_DEBUG_START(ctx);
8
- xmlXPathFreeContext(ctx);
9
- NOKOGIRI_DEBUG_END(ctx);
17
+ xmlXPathContextPtr c_context = data;
18
+ xmlXPathFreeContext(c_context);
10
19
  }
11
20
 
21
+ static const rb_data_type_t xml_xpath_context_type = {
22
+ .wrap_struct_name = "Nokogiri::XML::XPathContext",
23
+ .function = {
24
+ .dfree = xml_xpath_context_deallocate,
25
+ },
26
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
27
+ };
28
+
29
+ /* find a CSS class in an HTML element's `class` attribute */
30
+ static const xmlChar *
31
+ builtin_css_class(const xmlChar *str, const xmlChar *val)
32
+ {
33
+ int val_len;
34
+
35
+ if (str == NULL) { return (NULL); }
36
+ if (val == NULL) { return (NULL); }
37
+
38
+ val_len = xmlStrlen(val);
39
+ if (val_len == 0) { return (str); }
40
+
41
+ while (*str != 0) {
42
+ if ((*str == *val) && !xmlStrncmp(str, val, val_len)) {
43
+ const xmlChar *next_byte = str + val_len;
44
+
45
+ /* only match if the next byte is whitespace or end of string */
46
+ if ((*next_byte == 0) || (IS_BLANK_CH(*next_byte))) {
47
+ return ((const xmlChar *)str);
48
+ }
49
+ }
50
+
51
+ /* advance str to whitespace */
52
+ while ((*str != 0) && !IS_BLANK_CH(*str)) {
53
+ str++;
54
+ }
55
+
56
+ /* advance str to start of next word or end of string */
57
+ while ((*str != 0) && IS_BLANK_CH(*str)) {
58
+ str++;
59
+ }
60
+ }
61
+
62
+ return (NULL);
63
+ }
64
+
65
+ /* xmlXPathFunction to wrap builtin_css_class() */
66
+ static void
67
+ xpath_builtin_css_class(xmlXPathParserContextPtr ctxt, int nargs)
68
+ {
69
+ xmlXPathObjectPtr hay, needle;
70
+
71
+ CHECK_ARITY(2);
72
+
73
+ CAST_TO_STRING;
74
+ needle = valuePop(ctxt);
75
+ if ((needle == NULL) || (needle->type != XPATH_STRING)) {
76
+ xmlXPathFreeObject(needle);
77
+ XP_ERROR(XPATH_INVALID_TYPE);
78
+ }
79
+
80
+ CAST_TO_STRING;
81
+ hay = valuePop(ctxt);
82
+ if ((hay == NULL) || (hay->type != XPATH_STRING)) {
83
+ xmlXPathFreeObject(hay);
84
+ xmlXPathFreeObject(needle);
85
+ XP_ERROR(XPATH_INVALID_TYPE);
86
+ }
87
+
88
+ if (builtin_css_class(hay->stringval, needle->stringval)) {
89
+ valuePush(ctxt, xmlXPathNewBoolean(1));
90
+ } else {
91
+ valuePush(ctxt, xmlXPathNewBoolean(0));
92
+ }
93
+
94
+ xmlXPathFreeObject(hay);
95
+ xmlXPathFreeObject(needle);
96
+ }
97
+
98
+
99
+ /* xmlXPathFunction to select nodes whose local name matches, for HTML5 CSS queries that should
100
+ * ignore namespaces */
101
+ static void
102
+ xpath_builtin_local_name_is(xmlXPathParserContextPtr ctxt, int nargs)
103
+ {
104
+ xmlXPathObjectPtr element_name;
105
+
106
+ assert(ctxt->context->node);
107
+
108
+ CHECK_ARITY(1);
109
+ CAST_TO_STRING;
110
+ CHECK_TYPE(XPATH_STRING);
111
+ element_name = valuePop(ctxt);
112
+
113
+ valuePush(
114
+ ctxt,
115
+ xmlXPathNewBoolean(xmlStrEqual(ctxt->context->node->name, element_name->stringval))
116
+ );
117
+
118
+ xmlXPathFreeObject(element_name);
119
+ }
120
+
121
+
12
122
  /*
13
123
  * call-seq:
14
- * register_ns(prefix, uri)
124
+ * register_ns(prefix, uri) → Nokogiri::XML::XPathContext
15
125
  *
16
- * Register the namespace with +prefix+ and +uri+.
126
+ * Register the namespace with +prefix+ and +uri+ for use in future queries.
127
+ *
128
+ * [Returns] +self+
17
129
  */
18
- static VALUE register_ns(VALUE self, VALUE prefix, VALUE uri)
130
+ static VALUE
131
+ rb_xml_xpath_context_register_ns(VALUE rb_context, VALUE prefix, VALUE uri)
19
132
  {
20
- xmlXPathContextPtr ctx;
21
- Data_Get_Struct(self, xmlXPathContext, ctx);
133
+ xmlXPathContextPtr c_context;
22
134
 
23
- xmlXPathRegisterNs( ctx,
24
- (const xmlChar *)StringValueCStr(prefix),
25
- (const xmlChar *)StringValueCStr(uri)
135
+ TypedData_Get_Struct(
136
+ rb_context,
137
+ xmlXPathContext,
138
+ &xml_xpath_context_type,
139
+ c_context
26
140
  );
27
- return self;
141
+
142
+ xmlXPathRegisterNs(c_context,
143
+ (const xmlChar *)StringValueCStr(prefix),
144
+ (const xmlChar *)StringValueCStr(uri)
145
+ );
146
+ return rb_context;
28
147
  }
29
148
 
30
149
  /*
31
150
  * call-seq:
32
- * register_variable(name, value)
151
+ * register_variable(name, value) → Nokogiri::XML::XPathContext
152
+ *
153
+ * Register the variable +name+ with +value+ for use in future queries.
33
154
  *
34
- * Register the variable +name+ with +value+.
155
+ * [Returns] +self+
35
156
  */
36
- static VALUE register_variable(VALUE self, VALUE name, VALUE value)
157
+ static VALUE
158
+ rb_xml_xpath_context_register_variable(VALUE rb_context, VALUE name, VALUE value)
37
159
  {
38
- xmlXPathContextPtr ctx;
39
- xmlXPathObjectPtr xmlValue;
40
- Data_Get_Struct(self, xmlXPathContext, ctx);
160
+ xmlXPathContextPtr c_context;
161
+ xmlXPathObjectPtr xmlValue;
162
+
163
+ TypedData_Get_Struct(
164
+ rb_context,
165
+ xmlXPathContext,
166
+ &xml_xpath_context_type,
167
+ c_context
168
+ );
41
169
 
42
- xmlValue = xmlXPathNewCString(StringValueCStr(value));
170
+ xmlValue = xmlXPathNewCString(StringValueCStr(value));
43
171
 
44
- xmlXPathRegisterVariable( ctx,
45
- (const xmlChar *)StringValueCStr(name),
46
- xmlValue
47
- );
172
+ xmlXPathRegisterVariable(
173
+ c_context,
174
+ (const xmlChar *)StringValueCStr(name),
175
+ xmlValue
176
+ );
48
177
 
49
- return self;
178
+ return rb_context;
50
179
  }
51
180
 
52
- void Nokogiri_marshal_xpath_funcall_and_return_values(xmlXPathParserContextPtr ctx, int nargs, VALUE handler, const char* function_name)
181
+
182
+ /*
183
+ * convert an XPath object into a Ruby object of the appropriate type.
184
+ * returns Qundef if no conversion was possible.
185
+ */
186
+ static VALUE
187
+ xpath2ruby(xmlXPathObjectPtr c_xpath_object, xmlXPathContextPtr c_context)
53
188
  {
54
- int i;
55
- VALUE result, doc;
189
+ VALUE rb_retval;
190
+
191
+ assert(c_context->doc);
192
+ assert(DOC_RUBY_OBJECT_TEST(c_context->doc));
193
+
194
+ switch (c_xpath_object->type) {
195
+ case XPATH_STRING:
196
+ rb_retval = NOKOGIRI_STR_NEW2(c_xpath_object->stringval);
197
+ xmlFree(c_xpath_object->stringval);
198
+ return rb_retval;
199
+
200
+ case XPATH_NODESET:
201
+ return noko_xml_node_set_wrap(
202
+ c_xpath_object->nodesetval,
203
+ DOC_RUBY_OBJECT(c_context->doc)
204
+ );
205
+
206
+ case XPATH_NUMBER:
207
+ return rb_float_new(c_xpath_object->floatval);
208
+
209
+ case XPATH_BOOLEAN:
210
+ return (c_xpath_object->boolval == 1) ? Qtrue : Qfalse;
211
+
212
+ default:
213
+ return Qundef;
214
+ }
215
+ }
216
+
217
+ void
218
+ Nokogiri_marshal_xpath_funcall_and_return_values(
219
+ xmlXPathParserContextPtr ctxt,
220
+ int argc,
221
+ VALUE rb_xpath_handler,
222
+ const char *method_name
223
+ )
224
+ {
225
+ VALUE rb_retval;
56
226
  VALUE *argv;
57
- VALUE node_set = Qnil;
58
- xmlNodeSetPtr xml_node_set = NULL;
59
- xmlXPathObjectPtr obj;
227
+ VALUE rb_node_set = Qnil;
228
+ xmlNodeSetPtr c_node_set = NULL;
229
+ xmlXPathObjectPtr c_xpath_object;
60
230
 
61
- assert(ctx->context->doc);
62
- assert(DOC_RUBY_OBJECT_TEST(ctx->context->doc));
231
+ assert(ctxt->context->doc);
232
+ assert(DOC_RUBY_OBJECT_TEST(ctxt->context->doc));
63
233
 
64
- argv = (VALUE *)calloc((size_t)nargs, sizeof(VALUE));
65
- for (i = 0 ; i < nargs ; ++i) {
66
- rb_gc_register_address(&argv[i]);
234
+ argv = (VALUE *)ruby_xcalloc((size_t)argc, sizeof(VALUE));
235
+ for (int j = 0 ; j < argc ; ++j) {
236
+ rb_gc_register_address(&argv[j]);
67
237
  }
68
238
 
69
- doc = DOC_RUBY_OBJECT(ctx->context->doc);
70
-
71
- if (nargs > 0) {
72
- i = nargs - 1;
73
- do {
74
- obj = valuePop(ctx);
75
- switch(obj->type) {
76
- case XPATH_STRING:
77
- argv[i] = NOKOGIRI_STR_NEW2(obj->stringval);
78
- break;
79
- case XPATH_BOOLEAN:
80
- argv[i] = obj->boolval == 1 ? Qtrue : Qfalse;
81
- break;
82
- case XPATH_NUMBER:
83
- argv[i] = rb_float_new(obj->floatval);
84
- break;
85
- case XPATH_NODESET:
86
- argv[i] = Nokogiri_wrap_xml_node_set(obj->nodesetval, doc);
87
- break;
88
- default:
89
- argv[i] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(obj));
90
- }
91
- xmlXPathFreeNodeSetList(obj);
92
- } while(i-- > 0);
239
+ for (int j = argc - 1 ; j >= 0 ; --j) {
240
+ c_xpath_object = valuePop(ctxt);
241
+ argv[j] = xpath2ruby(c_xpath_object, ctxt->context);
242
+ if (argv[j] == Qundef) {
243
+ argv[j] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(c_xpath_object));
244
+ }
245
+ xmlXPathFreeNodeSetList(c_xpath_object);
93
246
  }
94
247
 
95
- result = rb_funcall2(handler, rb_intern((const char*)function_name), nargs, argv);
248
+ rb_retval = rb_funcall2(
249
+ rb_xpath_handler,
250
+ rb_intern((const char *)method_name),
251
+ argc,
252
+ argv
253
+ );
96
254
 
97
- for (i = 0 ; i < nargs ; ++i) {
98
- rb_gc_unregister_address(&argv[i]);
255
+ for (int j = 0 ; j < argc ; ++j) {
256
+ rb_gc_unregister_address(&argv[j]);
99
257
  }
100
- free(argv);
258
+ ruby_xfree(argv);
101
259
 
102
- switch(TYPE(result)) {
260
+ switch (TYPE(rb_retval)) {
103
261
  case T_FLOAT:
104
262
  case T_BIGNUM:
105
263
  case T_FIXNUM:
106
- xmlXPathReturnNumber(ctx, NUM2DBL(result));
264
+ xmlXPathReturnNumber(ctxt, NUM2DBL(rb_retval));
107
265
  break;
108
266
  case T_STRING:
109
- xmlXPathReturnString(
110
- ctx,
111
- xmlCharStrdup(StringValueCStr(result))
112
- );
267
+ xmlXPathReturnString(ctxt, xmlCharStrdup(StringValueCStr(rb_retval)));
113
268
  break;
114
269
  case T_TRUE:
115
- xmlXPathReturnTrue(ctx);
270
+ xmlXPathReturnTrue(ctxt);
116
271
  break;
117
272
  case T_FALSE:
118
- xmlXPathReturnFalse(ctx);
273
+ xmlXPathReturnFalse(ctxt);
119
274
  break;
120
275
  case T_NIL:
121
276
  break;
122
- case T_ARRAY:
123
- {
124
- VALUE args[2];
125
- args[0] = doc;
126
- args[1] = result;
127
- node_set = rb_class_new_instance(2, args, cNokogiriXmlNodeSet);
128
- Data_Get_Struct(node_set, xmlNodeSet, xml_node_set);
129
- xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set));
130
- }
277
+ case T_ARRAY: {
278
+ VALUE construct_args[2] = { DOC_RUBY_OBJECT(ctxt->context->doc), rb_retval };
279
+ rb_node_set = rb_class_new_instance(2, construct_args, cNokogiriXmlNodeSet);
280
+ c_node_set = noko_xml_node_set_unwrap(rb_node_set);
281
+ xmlXPathReturnNodeSet(ctxt, xmlXPathNodeSetMerge(NULL, c_node_set));
282
+ }
131
283
  break;
132
284
  case T_DATA:
133
- if(rb_obj_is_kind_of(result, cNokogiriXmlNodeSet)) {
134
- Data_Get_Struct(result, xmlNodeSet, xml_node_set);
285
+ if (rb_obj_is_kind_of(rb_retval, cNokogiriXmlNodeSet)) {
286
+ c_node_set = noko_xml_node_set_unwrap(rb_retval);
135
287
  /* Copy the node set, otherwise it will get GC'd. */
136
- xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set));
288
+ xmlXPathReturnNodeSet(ctxt, xmlXPathNodeSetMerge(NULL, c_node_set));
137
289
  break;
138
290
  }
139
291
  default:
140
292
  rb_raise(rb_eRuntimeError, "Invalid return type");
141
- }
293
+ }
142
294
  }
143
295
 
144
- static void ruby_funcall(xmlXPathParserContextPtr ctx, int nargs)
296
+ static void
297
+ method_caller(xmlXPathParserContextPtr ctxt, int argc)
145
298
  {
146
- VALUE handler = Qnil;
147
- const char *function = NULL ;
148
-
149
- assert(ctx);
150
- assert(ctx->context);
151
- assert(ctx->context->userData);
152
- assert(ctx->context->function);
153
-
154
- handler = (VALUE)(ctx->context->userData);
155
- function = (const char*)(ctx->context->function);
156
-
157
- Nokogiri_marshal_xpath_funcall_and_return_values(ctx, nargs, handler, function);
299
+ VALUE rb_xpath_handler = Qnil;
300
+ const char *method_name = NULL ;
301
+
302
+ assert(ctxt);
303
+ assert(ctxt->context);
304
+ assert(ctxt->context->userData);
305
+ assert(ctxt->context->function);
306
+
307
+ rb_xpath_handler = (VALUE)(ctxt->context->userData);
308
+ method_name = (const char *)(ctxt->context->function);
309
+
310
+ Nokogiri_marshal_xpath_funcall_and_return_values(
311
+ ctxt,
312
+ argc,
313
+ rb_xpath_handler,
314
+ method_name
315
+ );
158
316
  }
159
317
 
160
- static xmlXPathFunction lookup( void *ctx,
161
- const xmlChar * name,
162
- const xmlChar* ns_uri )
318
+ static xmlXPathFunction
319
+ handler_lookup(void *data, const xmlChar *c_name, const xmlChar *c_ns_uri)
163
320
  {
164
- VALUE xpath_handler = (VALUE)ctx;
165
- if(rb_respond_to(xpath_handler, rb_intern((const char *)name)))
166
- return ruby_funcall;
321
+ VALUE rb_handler = (VALUE)data;
322
+ if (rb_respond_to(rb_handler, rb_intern((const char *)c_name))) {
323
+ if (c_ns_uri == NULL) {
324
+ NOKO_WARN_DEPRECATION(
325
+ "A custom XPath or CSS handler function named '%s' is being invoked without a namespace."
326
+ " Please update your query to reference this function as 'nokogiri:%s'."
327
+ " Invoking custom handler functions without a namespace is deprecated and support will be removed in a future release of Nokogiri.",
328
+ c_name, c_name);
329
+ }
330
+ return method_caller;
331
+ }
167
332
 
168
333
  return NULL;
169
334
  }
170
335
 
171
- NORETURN(static void xpath_generic_exception_handler(void * ctx, const char *msg, ...));
172
- static void xpath_generic_exception_handler(void * ctx, const char *msg, ...)
336
+ PRINTFLIKE_DECL(2, 3)
337
+ static void
338
+ generic_exception_pusher(void *data, const char *msg, ...)
173
339
  {
174
- char * message;
340
+ VALUE rb_errors = (VALUE)data;
341
+ VALUE rb_message;
342
+ VALUE rb_exception;
343
+
344
+ Check_Type(rb_errors, T_ARRAY);
175
345
 
346
+ #ifdef TRUFFLERUBY_NOKOGIRI_SYSTEM_LIBRARIES
347
+ /* It is not currently possible to pass var args from native
348
+ functions to sulong, so we work around the issue here. */
349
+ rb_message = rb_sprintf("generic_exception_pusher: %s", msg);
350
+ #else
176
351
  va_list args;
177
352
  va_start(args, msg);
178
- vasprintf(&message, msg, args);
353
+ rb_message = rb_vsprintf(msg, args);
179
354
  va_end(args);
355
+ #endif
180
356
 
181
- rb_raise(rb_eRuntimeError, "%s", message);
357
+ rb_exception = rb_exc_new_str(cNokogiriXmlXpathSyntaxError, rb_message);
358
+ rb_ary_push(rb_errors, rb_exception);
182
359
  }
183
360
 
184
361
  /*
185
362
  * call-seq:
186
- * evaluate(search_path, handler = nil)
363
+ * evaluate(search_path, handler = nil) → Object
187
364
  *
188
- * Evaluate the +search_path+ returning an XML::XPath object.
365
+ * Evaluate the +search_path+ query.
366
+ *
367
+ * [Returns] an object of the appropriate type for the query, which could be +NodeSet+, a +String+,
368
+ * a +Float+, or a boolean.
189
369
  */
190
- static VALUE evaluate(int argc, VALUE *argv, VALUE self)
370
+ static VALUE
371
+ rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE rb_context)
191
372
  {
192
373
  VALUE search_path, xpath_handler;
193
- VALUE thing = Qnil;
194
- xmlXPathContextPtr ctx;
374
+ VALUE retval = Qnil;
375
+ xmlXPathContextPtr c_context;
195
376
  xmlXPathObjectPtr xpath;
196
377
  xmlChar *query;
378
+ VALUE errors = rb_ary_new();
197
379
 
198
- Data_Get_Struct(self, xmlXPathContext, ctx);
380
+ TypedData_Get_Struct(
381
+ rb_context,
382
+ xmlXPathContext,
383
+ &xml_xpath_context_type,
384
+ c_context
385
+ );
199
386
 
200
- if(rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1)
387
+ if (rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1) {
201
388
  xpath_handler = Qnil;
389
+ }
202
390
 
203
391
  query = (xmlChar *)StringValueCStr(search_path);
204
392
 
205
- if(Qnil != xpath_handler) {
393
+ if (Qnil != xpath_handler) {
206
394
  /* FIXME: not sure if this is the correct place to shove private data. */
207
- ctx->userData = (void *)xpath_handler;
208
- xmlXPathRegisterFuncLookup(ctx, lookup, (void *)xpath_handler);
395
+ c_context->userData = (void *)xpath_handler;
396
+ xmlXPathRegisterFuncLookup(
397
+ c_context,
398
+ handler_lookup,
399
+ (void *)xpath_handler
400
+ );
209
401
  }
210
402
 
211
- xmlResetLastError();
212
- xmlSetStructuredErrorFunc(NULL, Nokogiri_error_raise);
403
+ xmlSetStructuredErrorFunc((void *)errors, Nokogiri_error_array_pusher);
404
+ xmlSetGenericErrorFunc((void *)errors, generic_exception_pusher);
213
405
 
214
- /* For some reason, xmlXPathEvalExpression will blow up with a generic error */
215
- /* when there is a non existent function. */
216
- xmlSetGenericErrorFunc(NULL, xpath_generic_exception_handler);
406
+ xpath = xmlXPathEvalExpression(query, c_context);
217
407
 
218
- xpath = xmlXPathEvalExpression(query, ctx);
219
408
  xmlSetStructuredErrorFunc(NULL, NULL);
220
409
  xmlSetGenericErrorFunc(NULL, NULL);
221
410
 
222
- if(xpath == NULL) {
223
- xmlErrorPtr error = xmlGetLastError();
224
- rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
411
+ if (xpath == NULL) {
412
+ rb_exc_raise(rb_ary_entry(errors, 0));
225
413
  }
226
414
 
227
- assert(ctx->doc);
228
- assert(DOC_RUBY_OBJECT_TEST(ctx->doc));
229
-
230
- switch(xpath->type) {
231
- case XPATH_STRING:
232
- thing = NOKOGIRI_STR_NEW2(xpath->stringval);
233
- xmlFree(xpath->stringval);
234
- break;
235
- case XPATH_NODESET:
236
- thing = Nokogiri_wrap_xml_node_set(xpath->nodesetval,
237
- DOC_RUBY_OBJECT(ctx->doc));
238
- break;
239
- case XPATH_NUMBER:
240
- thing = rb_float_new(xpath->floatval);
241
- break;
242
- case XPATH_BOOLEAN:
243
- thing = xpath->boolval == 1 ? Qtrue : Qfalse;
244
- break;
245
- default:
246
- thing = Nokogiri_wrap_xml_node_set(NULL, DOC_RUBY_OBJECT(ctx->doc));
415
+ retval = xpath2ruby(xpath, c_context);
416
+ if (retval == Qundef) {
417
+ retval = noko_xml_node_set_wrap(NULL, DOC_RUBY_OBJECT(c_context->doc));
247
418
  }
248
419
 
249
420
  xmlXPathFreeNodeSetList(xpath);
250
421
 
251
- return thing;
422
+ return retval;
252
423
  }
253
424
 
254
425
  /*
255
426
  * call-seq:
256
- * new(node)
427
+ * new(node)
257
428
  *
258
- * Create a new XPathContext with +node+ as the reference point.
429
+ * Create a new XPathContext with +node+ as the context node.
259
430
  */
260
- static VALUE new(VALUE klass, VALUE nodeobj)
431
+ static VALUE
432
+ rb_xml_xpath_context_new(VALUE klass, VALUE rb_node)
261
433
  {
262
434
  xmlNodePtr node;
263
- xmlXPathContextPtr ctx;
264
- VALUE self;
435
+ xmlXPathContextPtr c_context;
436
+ VALUE rb_context;
265
437
 
266
- xmlXPathInit();
438
+ Noko_Node_Get_Struct(rb_node, xmlNode, node);
267
439
 
268
- Data_Get_Struct(nodeobj, xmlNode, node);
440
+ #if LIBXML_VERSION < 21000
441
+ /* deprecated in 40483d0 */
442
+ xmlXPathInit();
443
+ #endif
444
+
445
+ c_context = xmlXPathNewContext(node->doc);
446
+ c_context->node = node;
447
+
448
+ xmlXPathRegisterNs(c_context, NOKOGIRI_PREFIX, NOKOGIRI_URI);
449
+ xmlXPathRegisterNs(c_context, NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);
450
+ xmlXPathRegisterFuncNS(
451
+ c_context,
452
+ (const xmlChar *)"css-class",
453
+ NOKOGIRI_BUILTIN_URI,
454
+ xpath_builtin_css_class
455
+ );
456
+ xmlXPathRegisterFuncNS(
457
+ c_context,
458
+ (const xmlChar *)"local-name-is",
459
+ NOKOGIRI_BUILTIN_URI,
460
+ xpath_builtin_local_name_is
461
+ );
269
462
 
270
- ctx = xmlXPathNewContext(node->doc);
271
- ctx->node = node;
272
- self = Data_Wrap_Struct(klass, 0, deallocate, ctx);
273
- /*rb_iv_set(self, "@xpath_handler", Qnil); */
274
- return self;
463
+ rb_context = TypedData_Wrap_Struct(
464
+ klass,
465
+ &xml_xpath_context_type,
466
+ c_context
467
+ );
468
+ return rb_context;
275
469
  }
276
470
 
277
- VALUE cNokogiriXmlXpathContext;
278
- void init_xml_xpath_context(void)
471
+ void
472
+ noko_init_xml_xpath_context(void)
279
473
  {
280
- VALUE module = rb_define_module("Nokogiri");
281
-
282
474
  /*
283
- * Nokogiri::XML
475
+ * XPathContext is the entry point for searching a +Document+ by using XPath.
284
476
  */
285
- VALUE xml = rb_define_module_under(module, "XML");
477
+ cNokogiriXmlXpathContext = rb_define_class_under(mNokogiriXml, "XPathContext", rb_cObject);
286
478
 
287
- /*
288
- * XPathContext is the entry point for searching a Document by using XPath.
289
- */
290
- VALUE klass = rb_define_class_under(xml, "XPathContext", rb_cObject);
479
+ rb_undef_alloc_func(cNokogiriXmlXpathContext);
291
480
 
292
- cNokogiriXmlXpathContext = klass;
481
+ rb_define_singleton_method(cNokogiriXmlXpathContext, "new", rb_xml_xpath_context_new, 1);
293
482
 
294
- rb_define_singleton_method(klass, "new", new, 1);
295
- rb_define_method(klass, "evaluate", evaluate, -1);
296
- rb_define_method(klass, "register_variable", register_variable, 2);
297
- rb_define_method(klass, "register_ns", register_ns, 2);
483
+ rb_define_method(cNokogiriXmlXpathContext, "evaluate", rb_xml_xpath_context_evaluate, -1);
484
+ rb_define_method(cNokogiriXmlXpathContext, "register_variable", rb_xml_xpath_context_register_variable, 2);
485
+ rb_define_method(cNokogiriXmlXpathContext, "register_ns", rb_xml_xpath_context_register_ns, 2);
298
486
  }