Mercurial > hg > rr-repo
comparison sites/all/libraries/ARC2/arc/sparqlscript/ARC2_SPARQLScriptProcessor.php @ 4:ce11bbd8f642
added modules
author | danieleb <danielebarchiesi@me.com> |
---|---|
date | Thu, 19 Sep 2013 10:38:44 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
3:b28be78d8160 | 4:ce11bbd8f642 |
---|---|
1 <?php | |
2 /** | |
3 * ARC2 SPARQLScript Processor | |
4 * | |
5 * @author Benjamin Nowack <bnowack@semsol.com> | |
6 * @license http://arc.semsol.org/license | |
7 * @package ARC2 | |
8 * @version 2010-11-16 | |
9 */ | |
10 | |
11 ARC2::inc('Class'); | |
12 | |
13 class ARC2_SPARQLScriptProcessor extends ARC2_Class { | |
14 | |
15 function __construct($a, &$caller) { | |
16 parent::__construct($a, $caller); | |
17 } | |
18 | |
19 function __init() { | |
20 parent::__init(); | |
21 $this->max_operations = $this->v('sparqlscript_max_operations', 0, $this->a); | |
22 $this->max_queries = $this->v('sparqlscript_max_queries', 0, $this->a); | |
23 $this->return = 0; | |
24 $this->script_hash = ''; | |
25 $this->env = array( | |
26 'endpoint' => '', | |
27 'vars' => array(), | |
28 'output' => '', | |
29 'operation_count' => 0, | |
30 'query_count' => 0, | |
31 'query_log' => array() | |
32 ); | |
33 } | |
34 | |
35 function reset() { | |
36 $this->__init(); | |
37 } | |
38 | |
39 /* */ | |
40 | |
41 function processScript($s) { | |
42 $this->script_hash = abs(crc32($s)); | |
43 $parser = $this->getParser(); | |
44 $parser->parse($s); | |
45 $blocks = $parser->getScriptBlocks(); | |
46 if ($parser->getErrors()) return 0; | |
47 foreach ($blocks as $block) { | |
48 $this->processBlock($block); | |
49 if ($this->return) return 0; | |
50 if ($this->getErrors()) return 0; | |
51 } | |
52 } | |
53 | |
54 function getResult() { | |
55 if ($this->return) { | |
56 return $this->getVarValue('__return_value__'); | |
57 } | |
58 else { | |
59 return $this->env['output']; | |
60 } | |
61 } | |
62 | |
63 /* */ | |
64 | |
65 function getParser() { | |
66 ARC2::inc('SPARQLScriptParser'); | |
67 return new ARC2_SPARQLScriptParser($this->a, $this); | |
68 } | |
69 | |
70 /* */ | |
71 | |
72 function setVar($name, $val, $type = 'literal', $meta = '') { | |
73 /* types: literal, var, rows, bool, doc, http_response, undefined, ? */ | |
74 $this->env['vars'][$name] = array( | |
75 'value_type' => $type, | |
76 'value' => $val, | |
77 'meta' => $meta ? $meta : array() | |
78 ); | |
79 } | |
80 | |
81 function getVar($name) { | |
82 return isset($this->env['vars'][$name]) ? $this->env['vars'][$name] : ''; | |
83 } | |
84 | |
85 function getVarValue($name) { | |
86 return ($v = $this->getVar($name)) ? (isset($v['value']) ? $v['value'] : $v ) : ''; | |
87 } | |
88 | |
89 /* */ | |
90 | |
91 function replacePlaceholders($val, $context = '', $return_string = 1, $loop = 0) { | |
92 do { | |
93 $old_val = $val; | |
94 if (preg_match_all('/(\{(?:[^{}]+|(?R))*\})/', $val, $m)) { | |
95 foreach ($m[1] as $match) { | |
96 if (strpos($val, '$' . $match) === false) {/* just some container brackets, recurse */ | |
97 $val = str_replace($match, '{' . $this->replacePlaceholders(substr($match, 1, -1), $context, $return_string, $loop + 1) . '}', $val); | |
98 } | |
99 else { | |
100 $ph = substr($match, 1, -1); | |
101 $sub_val = $this->getPlaceholderValue($ph); | |
102 if (is_array($sub_val)) { | |
103 $sub_val = $this->getArraySerialization($sub_val, $context); | |
104 } | |
105 $val = str_replace('${' . $ph . '}', $sub_val, $val); | |
106 } | |
107 } | |
108 } | |
109 } while (($old_val != $val) && ($loop < 10)); | |
110 return $val; | |
111 } | |
112 | |
113 function getPlaceholderValue($ph) { | |
114 /* simple vars */ | |
115 if (isset($this->env['vars'][$ph])) { | |
116 return $this->v('value', $this->env['vars'][$ph], $this->env['vars'][$ph]); | |
117 } | |
118 /* GET/POST */ | |
119 if (preg_match('/^(GET|POST)\.([^\.]+)(.*)$/', $ph, $m)) { | |
120 $vals = strtoupper($m[1]) == 'GET' ? $_GET : $POST; | |
121 $r = isset($vals[$m[2]]) ? $vals[$m[2]] : ''; | |
122 return $m[3] ? $this->getPropertyValue(array('value' => $r, 'value_type' => '?'), ltrim($m[3], '.')) : $r; | |
123 } | |
124 /* NOW */ | |
125 if (preg_match('/^NOW(.*)$/', $ph, $m)) { | |
126 $rest = $m[1]; | |
127 /* may have sub-phs */ | |
128 $rest = $this->replacePlaceholders($rest); | |
129 $r_struct = array( | |
130 'y' => date('Y'), | |
131 'mo' => date('m'), | |
132 'd' => date('d'), | |
133 'h' => date('H'), | |
134 'mi' => date('i'), | |
135 's' => date('s') | |
136 ); | |
137 if (preg_match('/(\+|\-)\s*([0-9]+)(y|mo|d|h|mi|s)[a-z]*(.*)/is', trim($rest), $m2)) { | |
138 eval('$r_struct[$m2[3]] ' . $m2[1] . '= (int)' . $m2[2] . ';'); | |
139 $rest = $m2[4]; | |
140 } | |
141 $uts = mktime($r_struct['h'], $r_struct['mi'], $r_struct['s'], $r_struct['mo'], $r_struct['d'], $r_struct['y']); | |
142 $uts -= date('Z', $uts); /* timezone offset */ | |
143 $r = date('Y-m-d\TH:i:s\Z', $uts); | |
144 if (preg_match('/^\.(.+)$/', $rest, $m)) { | |
145 return $this->getPropertyValue(array('value' => $r), $m[1]); | |
146 } | |
147 return $r; | |
148 } | |
149 /* property */ | |
150 if (preg_match('/^([^\.]+)\.(.+)$/', $ph, $m)) { | |
151 list($var, $path) = array($m[1], $m[2]); | |
152 if (isset($this->env['vars'][$var])) { | |
153 return $this->getPropertyValue($this->env['vars'][$var], $path); | |
154 } | |
155 } | |
156 return ''; | |
157 } | |
158 | |
159 function getPropertyValue($obj, $path) { | |
160 $val = isset($obj['value']) ? $obj['value'] : $obj; | |
161 $path = $this->replacePlaceholders($path, 'property_value', 0); | |
162 /* reserved */ | |
163 if ($path == 'size') { | |
164 if ($obj['value_type'] == 'rows') return count($val); | |
165 if ($obj['value_type'] == 'literal') return strlen($val); | |
166 } | |
167 if (preg_match('/^replace\([\'\"](\/.*\/[a-z]*)[\'\"],\s*[\'\"](.*)[\'\"]\)$/is', $path, $m)) { | |
168 return @preg_replace($m[1], str_replace('$', '\\', $m[2]), $val); | |
169 } | |
170 if (preg_match('/^match\([\'\"](\/.*\/[a-z]*)[\'\"]\)$/is', $path, $m)) { | |
171 return @preg_match($m[1], $val, $m) ? $m : ''; | |
172 } | |
173 if (preg_match('/^urlencode\([\'\"]?(get|post|.*)[\'\"]?\)$/is', $path, $m)) { | |
174 return (strtolower($m[1]) == 'post') ? rawurlencode($val) : urlencode($val); | |
175 } | |
176 if (preg_match('/^toDataURI\([^\)]*\)$/is', $path, $m)) { | |
177 return 'data:text/plain;charset=utf-8,' . rawurlencode($val); | |
178 } | |
179 if (preg_match('/^fromDataURI\([^\)]*\)$/is', $path, $m)) { | |
180 return rawurldecode(str_replace('data:text/plain;charset=utf-8,', '', $val)); | |
181 } | |
182 if (preg_match('/^toPrettyDate\([^\)]*\)$/is', $path, $m)) { | |
183 $uts = strtotime(preg_replace('/(T|\+00\:00)/', ' ', $val)); | |
184 return date('D j M H:i', $uts); | |
185 } | |
186 if (preg_match('/^render\(([^\)]*)\)$/is', $path, $m)) { | |
187 $src_format = trim($m[1], '"\''); | |
188 return $this->render($val, $src_format); | |
189 } | |
190 /* struct */ | |
191 if (is_array($val)) { | |
192 if (isset($val[$path])) return $val[$path]; | |
193 $exp_path = $this->expandPName($path); | |
194 if (isset($val[$exp_path])) return $val[$exp_path]; | |
195 if (preg_match('/^([^\.]+)\.(.+)$/', $path, $m)) { | |
196 list($var, $path) = array($m[1], $m[2]); | |
197 if (isset($val[$var])) { | |
198 return $this->getPropertyValue(array('value' => $val[$var]), $path); | |
199 } | |
200 /* qname */ | |
201 $exp_var = $this->expandPName($var); | |
202 if (isset($val[$exp_var])) { | |
203 return $this->getPropertyValue(array('value' => $val[$exp_var]), $path); | |
204 } | |
205 return ''; | |
206 } | |
207 } | |
208 /* meta */ | |
209 if (preg_match('/^\_/', $path) && isset($obj['meta']) && isset($obj['meta'][substr($path, 1)])) { | |
210 return $obj['meta'][substr($path, 1)]; | |
211 } | |
212 return ''; | |
213 } | |
214 | |
215 function render($val, $src_format = '') { | |
216 if ($src_format) { | |
217 $mthd = 'render' . $this->camelCase($src_format); | |
218 if (method_exists($this, $mthd)) { | |
219 return $this->$mthd($val); | |
220 } | |
221 else { | |
222 return 'No rendering method found for "' . $src_format. '"'; | |
223 } | |
224 } | |
225 /* try RDF */ | |
226 return $this->getArraySerialization($val); | |
227 } | |
228 | |
229 function renderObjects($os) { | |
230 $r = ''; | |
231 foreach ($os as $o) { | |
232 $r .= $r ? ', ' : ''; | |
233 $r .= $o['value']; | |
234 } | |
235 return $r; | |
236 } | |
237 | |
238 /* */ | |
239 | |
240 function getArraySerialization($v, $context) { | |
241 $v_type = ARC2::getStructType($v);/* string|array|triples|index */ | |
242 $pf = ARC2::getPreferredFormat(); | |
243 /* string */ | |
244 if ($v_type == 'string') return $v; | |
245 /* simple array (e.g. from SELECT) */ | |
246 if ($v_type == 'array') { | |
247 return join(', ', $v); | |
248 $m = method_exists($this, 'toLegacy' . $pf) ? 'toLegacy' . $pf : 'toLegacyXML'; | |
249 } | |
250 /* rdf */ | |
251 if (($v_type == 'triples') || ($v_type == 'index')) { | |
252 $m = method_exists($this, 'to' . $pf) ? 'to' . $pf : ($context == 'query' ? 'toNTriples' : 'toRDFXML'); | |
253 } | |
254 /* else */ | |
255 return $this->$m($v); | |
256 } | |
257 | |
258 /* */ | |
259 | |
260 function processBlock($block) { | |
261 if ($this->max_operations && ($this->env['operation_count'] >= $this->max_operations)) return $this->addError('Number of ' . $this->max_operations . ' allowed operations exceeded.'); | |
262 if ($this->return) return 0; | |
263 $this->env['operation_count']++; | |
264 $type = $block['type']; | |
265 $m = 'process' . $this->camelCase($type) . 'Block'; | |
266 if (method_exists($this, $m)) { | |
267 return $this->$m($block); | |
268 } | |
269 return $this->addError('Unsupported block type "' . $type . '"'); | |
270 } | |
271 | |
272 /* */ | |
273 | |
274 function processEndpointDeclBlock($block) { | |
275 $this->env['endpoint'] = $block['endpoint']; | |
276 return $this->env; | |
277 } | |
278 | |
279 /* */ | |
280 | |
281 function processQueryBlock($block) { | |
282 if ($this->max_queries && ($this->env['query_count'] >= $this->max_queries)) return $this->addError('Number of ' . $this->max_queries . ' allowed queries exceeded.'); | |
283 $this->env['query_count']++; | |
284 $ep_uri = $this->replacePlaceholders($this->env['endpoint'], 'endpoint'); | |
285 /* q */ | |
286 $prologue = 'BASE <' . $block['base']. '>'; | |
287 $q = $this->replacePlaceholders($block['query'], 'query'); | |
288 /* prefixes */ | |
289 $ns = isset($this->a['ns']) ? array_merge($this->a['ns'], $block['prefixes']) : $block['prefixes']; | |
290 $q = $prologue . "\n" . $this->completeQuery($q, $ns); | |
291 $this->env['query_log'][] = '(' . $ep_uri . ') ' . $q; | |
292 if ($store = $this->getStore($ep_uri)) { | |
293 $sub_r = $this->v('is_remote', '', $store) ? $store->query($q, '', $ep_uri) : $store->query($q); | |
294 /* ignore socket errors */ | |
295 if (($errs = $this->getErrors()) && preg_match('/socket/', $errs[0])) { | |
296 $this->warnings[] = $errs[0]; | |
297 $this->errors = array(); | |
298 $sub_r = array(); | |
299 } | |
300 return $sub_r; | |
301 } | |
302 else { | |
303 return $this->addError("no store (" . $ep_uri . ")"); | |
304 } | |
305 } | |
306 | |
307 function getStore($ep_uri) { | |
308 /* local store */ | |
309 if ((!$ep_uri || $ep_uri == ARC2::getScriptURI()) && ($this->v('sparqlscript_default_endpoint', '', $this->a) == 'local')) { | |
310 if (!isset($this->local_store)) $this->local_store = ARC2::getStore($this->a);/* @@todo error checking */ | |
311 return $this->local_store; | |
312 } | |
313 elseif ($ep_uri) { | |
314 ARC2::inc('RemoteStore'); | |
315 $conf = array_merge($this->a, array('remote_store_endpoint' => $ep_uri, 'reader_timeout' => 10)); | |
316 return new ARC2_RemoteStore($conf, $this); | |
317 } | |
318 return 0; | |
319 } | |
320 | |
321 /* */ | |
322 | |
323 function processAssignmentBlock($block) { | |
324 $sub_type = $block['sub_type']; | |
325 $m = 'process' . $this->camelCase($sub_type) . 'AssignmentBlock'; | |
326 if (!method_exists($this, $m)) return $this->addError('Unknown method "' . $m . '"'); | |
327 return $this->$m($block); | |
328 } | |
329 | |
330 function processQueryAssignmentBlock($block) { | |
331 $qr = $this->processQueryBlock($block['query']); | |
332 if ($this->getErrors() || !isset($qr['query_type'])) return 0; | |
333 $qt = $qr['query_type']; | |
334 $vts = array('ask' => 'bool', 'select' => 'rows', 'desribe' => 'doc', 'construct' => 'doc'); | |
335 $r = array( | |
336 'value_type' => isset($vts[$qt]) ? $vts[$qt] : $qt . ' result', | |
337 'value' => ($qt == 'select') ? $this->v('rows', array(), $qr['result']) : $qr['result'], | |
338 ); | |
339 $this->env['vars'][$block['var']['value']] = $r; | |
340 } | |
341 | |
342 function processStringAssignmentBlock($block) { | |
343 $r = array('value_type' => 'literal', 'value' => $this->replacePlaceholders($block['string']['value'])); | |
344 $this->env['vars'][$block['var']['value']] = $r; | |
345 } | |
346 | |
347 function processVarAssignmentBlock($block) { | |
348 if (isset($this->env['vars'][$block['var2']['value']])) { | |
349 $this->env['vars'][$block['var']['value']] = $this->env['vars'][$block['var2']['value']]; | |
350 } | |
351 else { | |
352 $this->env['vars'][$block['var']['value']] = array('value_type' => 'undefined', 'value' => ''); | |
353 } | |
354 } | |
355 | |
356 function processPlaceholderAssignmentBlock($block) { | |
357 $ph_val = $this->getPlaceholderValue($block['placeholder']['value']); | |
358 $this->env['vars'][$block['var']['value']] = array('value_type' => 'undefined', 'value' => $ph_val); | |
359 } | |
360 | |
361 function processVarMergeAssignmentBlock($block) { | |
362 $val1 = isset($this->env['vars'][$block['var2']['value']]) ? $this->env['vars'][$block['var2']['value']] : array('value_type' => 'undefined', 'value' => ''); | |
363 $val2 = isset($this->env['vars'][$block['var3']['value']]) ? $this->env['vars'][$block['var3']['value']] : array('value_type' => 'undefined', 'value' => ''); | |
364 if (is_array($val1) && is_array($val2)) { | |
365 $this->env['vars'][$block['var']['value']] = array('value_type' => $val2['value_type'], 'value' => array_merge($val1['value'], $val2['value'])); | |
366 } | |
367 elseif (is_numeric($val1) && is_numeric($val2)) { | |
368 $this->env['vars'][$block['var']['value']] = $val1 + $val2; | |
369 } | |
370 } | |
371 | |
372 function processFunctionCallAssignmentBlock($block) { | |
373 $sub_r = $this->processFunctionCallBlock($block['function_call']); | |
374 if ($this->getErrors()) return 0; | |
375 $this->env['vars'][$block['var']['value']] = $sub_r; | |
376 } | |
377 | |
378 /* */ | |
379 | |
380 function processReturnBlock($block) { | |
381 $sub_type = $block['sub_type']; | |
382 $m = 'process' . $this->camelCase($sub_type) . 'AssignmentBlock'; | |
383 if (!method_exists($this, $m)) return $this->addError('Unknown method "' . $m . '"'); | |
384 $sub_r = $this->$m($block); | |
385 $this->return = 1; | |
386 return $sub_r; | |
387 } | |
388 | |
389 /* */ | |
390 | |
391 function processIfblockBlock($block) { | |
392 if ($this->testCondition($block['condition'])) { | |
393 $blocks = $block['blocks']; | |
394 } | |
395 else { | |
396 $blocks = $block['else_blocks']; | |
397 } | |
398 foreach ($blocks as $block) { | |
399 $sub_r = $this->processBlock($block); | |
400 if ($this->getErrors()) return 0; | |
401 } | |
402 } | |
403 | |
404 function testCondition($cond) { | |
405 $m = 'test' . $this->camelCase($cond['type']) . 'Condition'; | |
406 if (!method_exists($this, $m)) return $this->addError('Unknown method "' . $m . '"'); | |
407 return $this->$m($cond); | |
408 } | |
409 | |
410 function testVarCondition($cond) { | |
411 $r = 0; | |
412 $vn = $cond['value']; | |
413 if (isset($this->env['vars'][$vn])) $r = $this->env['vars'][$vn]['value']; | |
414 $op = $this->v('operator', '', $cond); | |
415 if ($op == '!') $r = !$r; | |
416 return $r ? true : false; | |
417 } | |
418 | |
419 function testPlaceholderCondition($cond) { | |
420 $val = $this->getPlaceholderValue($cond['value']); | |
421 $r = $val ? true : false; | |
422 $op = $this->v('operator', '', $cond); | |
423 if ($op == '!') $r = !$r; | |
424 return $r; | |
425 } | |
426 | |
427 function testExpressionCondition($cond) { | |
428 $m = 'test' . $this->camelCase($cond['sub_type']) . 'ExpressionCondition'; | |
429 if (!method_exists($this, $m)) return $this->addError('Unknown method "' . $m . '"'); | |
430 return $this->$m($cond); | |
431 } | |
432 | |
433 function testRelationalExpressionCondition($cond) { | |
434 $op = $cond['operator']; | |
435 if ($op == '=') $op = '=='; | |
436 $val1 = $this->getPatternValue($cond['patterns'][0]); | |
437 $val2 = $this->getPatternValue($cond['patterns'][1]); | |
438 eval('$result = ($val1 ' . $op . ' $val2) ? 1 : 0;'); | |
439 return $result; | |
440 } | |
441 | |
442 function testAndExpressionCondition($cond) { | |
443 foreach ($cond['patterns'] as $pattern) { | |
444 if (!$this->testCondition($pattern)) return false; | |
445 } | |
446 return true; | |
447 } | |
448 | |
449 function getPatternValue($pattern) { | |
450 $m = 'get' . $this->camelCase($pattern['type']) . 'PatternValue'; | |
451 if (!method_exists($this, $m)) return ''; | |
452 return $this->$m($pattern); | |
453 } | |
454 | |
455 function getLiteralPatternValue($pattern) { | |
456 return $pattern['value']; | |
457 } | |
458 | |
459 function getPlaceholderPatternValue($pattern) { | |
460 return $this->getPlaceholderValue($pattern['value']); | |
461 } | |
462 | |
463 /* */ | |
464 | |
465 function processForblockBlock($block) { | |
466 $set = $this->v($block['set'], array('value' => array()), $this->env['vars']); | |
467 $entries = isset($set['value']) ? $set['value'] : $set; | |
468 $iterator = $block['iterator']; | |
469 $blocks = $block['blocks']; | |
470 if (!is_array($entries)) return 0; | |
471 $rc = count($entries); | |
472 foreach ($entries as $i => $entry) { | |
473 $val_type = $this->v('value_type', 'set', $set) . ' entry'; | |
474 $this->env['vars'][$iterator] = array( | |
475 'value' => $entry, | |
476 'value_type' => $val_type, | |
477 'meta' => array( | |
478 'pos' => $i, | |
479 'odd_even' => ($i % 2) ? 'even' : 'odd' | |
480 ) | |
481 ); | |
482 foreach ($blocks as $block) { | |
483 $this->processBlock($block); | |
484 if ($this->getErrors()) return 0; | |
485 } | |
486 } | |
487 } | |
488 | |
489 /* */ | |
490 | |
491 function processLiteralBlock($block) { | |
492 $this->env['output'] .= $this->replacePlaceholders($block['value'], 'output'); | |
493 } | |
494 | |
495 /* */ | |
496 | |
497 function processFunctionCallBlock($block) { | |
498 $uri = $this->replacePlaceholders($block['uri'], 'function_call'); | |
499 /* built-ins */ | |
500 if (strpos($uri, $this->a['ns']['sps']) === 0) { | |
501 return $this->processBuiltinFunctionCallBlock($block); | |
502 } | |
503 /* remote functions */ | |
504 } | |
505 | |
506 function processBuiltinFunctionCallBlock($block) { | |
507 $fnc_uri = $this->replacePlaceholders($block['uri'], 'function_call'); | |
508 $fnc_name = substr($fnc_uri, strlen($this->a['ns']['sps'])); | |
509 if (preg_match('/^(get|post)$/i', $fnc_name, $m)) { | |
510 return $this->processHTTPCall($block, strtoupper($m[1])); | |
511 } | |
512 if ($fnc_name == 'eval') { | |
513 return $this->processEvalCall($block); | |
514 } | |
515 } | |
516 | |
517 function processEvalCall($block) { | |
518 if (!$block['args']) return 0; | |
519 $arg = $block['args'][0]; | |
520 $script = ''; | |
521 if ($arg['type'] == 'placeholder') $script = $this->getPlaceholderValue($arg['value']); | |
522 if ($arg['type'] == 'literal') $script = $arg['value']; | |
523 if ($arg['type'] == 'var') $script = $this->getVarValue($arg['value']); | |
524 //echo "\n" . $script . $arg['type']; | |
525 $this->processScript($script); | |
526 } | |
527 | |
528 function processHTTPCall($block, $mthd = 'GET') { | |
529 ARC2::inc('Reader'); | |
530 $reader = new ARC2_Reader($this->a, $this); | |
531 $url = $this->replacePlaceholders($block['args'][0]['value'], 'function_call'); | |
532 if ($mthd != 'GET') { | |
533 $reader->setHTTPMethod($mthd); | |
534 $reader->setCustomHeaders("Content-Type: application/x-www-form-urlencoded"); | |
535 } | |
536 $to = $this->v('remote_call_timeout', 0, $this->a); | |
537 $reader->activate($url, '', 0, $to); | |
538 $format = $reader->getFormat(); | |
539 $resp = ''; | |
540 while ($d = $reader->readStream()) { | |
541 $resp .= $d; | |
542 } | |
543 $reader->closeStream(); | |
544 unset($this->reader); | |
545 return array('value_type' => 'http_response', 'value' => $resp); | |
546 } | |
547 | |
548 /* */ | |
549 | |
550 function extractVars($pattern, $input = '') { | |
551 $vars = array(); | |
552 /* replace PHs, track ()s */ | |
553 $regex = $pattern; | |
554 $vars = array(); | |
555 if (preg_match_all('/([\?\$]\{([^\}]+)\}|\([^\)]+\))/', $regex, $m)) { | |
556 $matches = $m[1]; | |
557 $pre_vars = $m[2]; | |
558 foreach ($matches as $i => $match) { | |
559 $vars[] = $pre_vars[$i]; | |
560 if ($pre_vars[$i]) {/* placeholder */ | |
561 $regex = str_replace($match, '(.+)', $regex); | |
562 } | |
563 else {/* parentheses, but may contain placeholders */ | |
564 $sub_regex = $match; | |
565 while (preg_match('/([\?\$]\{([^\}]+)\})/', $sub_regex, $m)) { | |
566 $sub_regex = str_replace($m[1], '(.+)', $sub_regex); | |
567 $vars[] = $m[2]; | |
568 } | |
569 $regex = str_replace($match, $sub_regex, $regex); | |
570 } | |
571 } | |
572 /* eval regex */ | |
573 if (@preg_match('/' . $regex . '/is', $input, $m)) { | |
574 $vals = $m; | |
575 } | |
576 else { | |
577 return 0; | |
578 } | |
579 for ($i = 0; $i < count($vars); $i++) { | |
580 if ($vars[$i]) { | |
581 $this->setVar($vars[$i], isset($vals[$i + 1]) ? $vals[$i + 1] : ''); | |
582 } | |
583 } | |
584 return 1; | |
585 } | |
586 /* no placeholders */ | |
587 return ($pattern == $input) ? 1 : 0; | |
588 } | |
589 | |
590 /* */ | |
591 | |
592 } |