diff options
-rw-r--r-- | it_dbi.class | 3 | ||||
-rw-r--r-- | it_html.class | 4 | ||||
-rw-r--r-- | it_url.class | 14 | ||||
-rw-r--r-- | itjs.php | 10 | ||||
-rwxr-xr-x | test/it_pipe.t | 8 | ||||
-rwxr-xr-x | test/it_url.t | 21 |
6 files changed, 37 insertions, 23 deletions
diff --git a/it_dbi.class b/it_dbi.class index d4722e9..12a4ef1 100644 --- a/it_dbi.class +++ b/it_dbi.class @@ -85,6 +85,9 @@ function __construct($p = array(), $query = null, ...$args) if ($p['table']) # Standard use: create a table object { + if (it::match('[^a-z0-9_.]', $p['table'])) + $this->_fatal("_construct: invalid table name '{$p['table']}''"); + if (!isset($GLOBALS[static::$_global_key])) new static::$_global_key; diff --git a/it_html.class b/it_html.class index af2ef8c..9780d5d 100644 --- a/it_html.class +++ b/it_html.class @@ -165,7 +165,7 @@ function html($args) $p += $this->p; foreach (array('class', 'manifest') as $attr) - $attrs .= $p[$attr] ? " $attr=" . '"' . Q($p[$attr]) . '"' : ""; + $attrs .= $p[$attr] ? " $attr=" . '"' . htmlspecialchars($p[$attr], ENT_COMPAT, $GLOBALS['it_html']->p['charset']) . '"' : ""; $html = ($p['doctype'] ? $p['doctype'] : $this->doctypes[$p['htmltype']]) . "\n" . '<html ' . ($p['htmltype'] == "xhtml" ? 'xmlns="http://www.w3.org/1999/xhtml" ' : '') . ($p['htmltype'] == "xhtml-mobile" ? 'xml:lang' : 'lang') . "=\"{$p['lang']}\"$attrs>\n" . $data . ($p['omit_endhtml'] ? '' : "</html>\n"); @@ -215,7 +215,7 @@ function head($args = array()) $header .= tag('link', array('rel' => "stylesheet", 'type' => "text/css", 'href' => $url) + (is_int($type) ? array() : array('media' => $type))); if (!empty($p['cssinline'])) - $header .= tag('style', array('type' => "text/css", "\n" . preg_replace(array('/\s*\/\*[^\*]+\*\//Um', '/\s*\{\s*/', '/;\s+/'), array('', '{', ';'), $p['cssinline']))); + $header .= tag('style', array("\n" . preg_replace(array('/\s*\/\*[^\*]+\*\//Um', '/\s*\{\s*/', '/;\s+/'), array('', '{', ';'), $p['cssinline']))); $header .= $p['head'] . ($p['title'] ? tag('title', Q($p['title'])) : ""); diff --git a/it_url.class b/it_url.class index c122aeb..fac7e0c 100644 --- a/it_url.class +++ b/it_url.class @@ -108,7 +108,7 @@ static function _postprocess($data, $p) * @param $p['safety'] DEPRECATED. 0 = ignore errors, 1 = errors, 2 = fatals * @param $p['it_error'] extra arguments for it_error or false to ignore errors * @param $p['fetchsleep'] Number of seconds to wait after fetch, fractions ok - * @param $p['body_on_fail'] Return body of page even if http status code is >= 400 + * @param $p['body_on_fail'] Return body of page even if http status code is >= 400, e.g. some JSON APIs return 404 with JSON data * * Result processing * @param $p['assoc'] Return [ 'data' => string, 'status' => int, 'cookies' => array, 'headers' => array, 'errstr' => string ] instead of just data @@ -116,7 +116,7 @@ static function _postprocess($data, $p) * @param $p['postprocess'] function called with content and $p which has it_error. returns content or null (which triggers retry) * @param $p['followlocation']Follow redirects [true] * - * @return Content of resulting page (considering redirects, excluding headers or false on error) or array (empty on error) if 'assoc' => true + * @return Content of resulting page (considering redirects, excluding headers or false on error) or array if 'assoc' => true */ static function get($p = []) { @@ -360,11 +360,7 @@ function request($p=array()) } else { - # FIXME 2024-06 CS Send a notice in cases where changing the default to body_on_fail=false would change result for text results - if ($url->result >= 400 && $url->data && !$p['assoc'] && !isset($p['body_on_fail']) && it::match('^text/', $url->headers['Content-Type'])) - it::error(['to' => 'schneider@search.ch', 'title' => 'Failing it_url::get() without body_on_fail but non-empty data', 'body' => ['p' => $p, 'url' => $url]]); - - if ($url->result >= 400 && ((isset($p['body_on_fail']) && !$p['body_on_fail']) || $p['empty_on_fail'] || $p['keepfailed'])) # FIXME 2024-06 CS Remove deprecated empty_on_fail support + if ($url->result >= 400 && (!$p['body_on_fail'] || $p['keepfailed'])) $got = $url->data = false; $result =& $url->data; $this->errstr = "HTTP Status " . $url->result; @@ -385,7 +381,7 @@ function request($p=array()) if ($got === false && $p['retries'] <= 0) { - it::error((array)$p['it_error'] + ['title' => "problem " . ($p['method'] ?: "gett") . "ing $url->url with curl: " . curl_strerror(curl_errno($curl)) . " (" . curl_errno($curl) . ") " . curl_error($curl), 'body' => curl_getinfo($curl) + ($p['verbose'] ? ['verbose' => $this->verbose] : [])]); + it::error((array)$p['it_error'] + ['title' => "problem " . ($p['method'] ?: "gett") . "ing $url->url with curl: " . curl_strerror(curl_errno($curl)) . " (" . curl_errno($curl) . ") " . curl_error($curl), 'body' => ['Error description' => $this->errstr] + curl_getinfo($curl) + ($p['verbose'] ? ['verbose' => $this->verbose] : [])]); } return $result; @@ -707,7 +703,7 @@ static function get_cache($p = array()) { it::file_put($p['cachedir'] . "/cleaned", ""); # touch could have permission problems $maxagemin = intval($p['maxage']/60); - exec("nohup bash -c 'cd {$p['cachedir']} && for i in ??; do sleep 20; ionice -c 3 find \$i -mmin +$maxagemin -type f -delete; done' </dev/null >/dev/null 2>&1 &"); + exec("nohup bash -c 'cd {$p['cachedir']} && for i in [0-9a-f][0-9a-f]; do sleep 20; ionice -c 3 find \$i -mmin +$maxagemin -type f -delete; done' </dev/null >/dev/null 2>&1 &"); } if (EDC('getcachelog')) @@ -68,11 +68,6 @@ else if (it::match('\.css', $lastfile)) ), $data ); - if ((($ie = it::match('MSIE (\d+)', $_SERVER['HTTP_USER_AGENT'])) && intval($ie) < 9) || EDC('iecompat')) - $data = it::replace(array( - '([;{]\s*)(background-size:[^;}])' => '\1behavior:url(/itjs/ie-backgroundsize-min.htc);\2'), - $data - ); } else if (it::match('\.htc$', $lastfile)) { @@ -88,4 +83,7 @@ else if ($files && !it::match('\.html$', $lastfile)) if (strpos($data, "<?php") !== false) it::error("sending php source?!"); -echo $nostrip ? $data : itjs::strip($data); +if (strlen($content = $nostrip ? $data : itjs::strip($data))) + echo $content; +else + http_response_code(404); diff --git a/test/it_pipe.t b/test/it_pipe.t index 72847d1..0a36d1c 100755 --- a/test/it_pipe.t +++ b/test/it_pipe.t @@ -11,10 +11,10 @@ is(it::pipe(['foo'])->lines(), ["foo"]); foreach(it::pipe(['a','b','a']) as $i) $x1 .= $i; is($x1, "aba"); -foreach(it::pipe(['a','b','a'])->filter(fn($x) => $x == 'a') as $i) $x2 .= $i; -is($x2, "aa"); -foreach(it::pipe(['a','b','a'])->grep('a') as $i) $x3 .= $i; -is($x3, "aa"); +foreach(it::pipe(['a','b','a'])->filter(fn($x) => $x == 'a') as $k => $v) $x2 .= "$k$v"; +is($x2, "0a1a"); +foreach(it::pipe(['a','b','a'])->grep('a') as $k => $v) $x3 .= "$k$v"; +is($x3, "0a1a"); # csv() diff --git a/test/it_url.t b/test/it_url.t index b6ef5ba..2e7d4f2 100755 --- a/test/it_url.t +++ b/test/it_url.t @@ -192,6 +192,14 @@ handle_server( handle_server( is( + it::filter_keys(it_url::get(['url' => "http://$host/", 'maxlength' => 5, 'it_error' => false, 'assoc' => true]), 'status,data'), + ['status' => 204, 'data' => null], + 'it_url::get() static call with port and too small maxlength' + ) +); + +handle_server( + is( it_url::get("http://$host/temp_redirect"), "Testserver output after temporary redirect", 'it_url::get() follows temproary redirect' @@ -263,14 +271,23 @@ $output = handle_server( ); $output = handle_server( - ok( - !it_url::get(['url' => "http://$host/not_found_with_body", 'body_on_fail' => false, 'it_error' => false]), + is( + it_url::get(['url' => "http://$host/not_found_with_body", 'body_on_fail' => false, 'it_error' => false]), + false, 'it_url::get() on 404 with body and body_on_fail' ) ); $output = handle_server( is( + it_url::get(['url' => "http://$host/not_found_with_body", 'it_error' => false]), + false, + 'it_url::get() on 404 with body and default for body_on_fail' + ) +); + +$output = handle_server( + is( it::filter_keys(it_url::get(['url' => "http://$host/not_found_with_body", 'body_on_fail' => false, 'it_error' => false, 'assoc' => true]), 'status,data'), ['status' => 404, 'data' => null], 'it_url::get() on 404 with body, body_on_fail and assoc' |