summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--it.class6
-rw-r--r--it_html.class11
-rw-r--r--it_mail.class11
-rw-r--r--it_url.class2
-rwxr-xr-xtest/it_html.t12
-rw-r--r--test/it_url.testserver.php4
-rwxr-xr-xtest/it_url_slow.t7
7 files changed, 35 insertions, 18 deletions
diff --git a/it.class b/it.class
index 5de9087..e43b794 100644
--- a/it.class
+++ b/it.class
@@ -1050,8 +1050,8 @@ static function time()
/**
* Output formatted and localized date
- * @param format optional format (default is 2007-01-02 03:04:05).
- * Other formats are "date", "datetime", "time".
+ * @param format optional format to be passed to date(), default "Y-m-d H:i:s"
+ * Other formats are "date", "datetime" and "time" in local language
* Formats can be qualified with language, e.g. "date:en"
* Special formats without language support are "icsdate", "icsdatetime".
* @param stamp optional unix timestamp (default is now).
@@ -1266,7 +1266,7 @@ static function json_encode($data, $p = [])
*/
static function json_decode($json, $p = [])
{
- return ($data = json_decode($json, $p['assoc'])) === null && trim($json) != 'null' ? it::error((array)$p['it_error'] + ['title' => "invalid json: " . json_last_error(), 'body' => $json]) : $data;
+ return ($data = json_decode($json, $p['assoc'])) === null && trim($json) != 'null' ? it::error((array)$p['it_error'] + ['title' => "invalid json: " . json_last_error_msg(), 'body' => $json]) : $data;
}
/**
diff --git a/it_html.class b/it_html.class
index e3053b6..9bb8e7a 100644
--- a/it_html.class
+++ b/it_html.class
@@ -393,32 +393,33 @@ static function sanitize($html)
if ($charset == "utf-8")
$html = it::any2utf8($html);
$html = it::replace(array('[\0\s]+' => " "), $html); # \s also matches \r and \n
- $urlpattern = 'https?://[^">]+';
+ $urlpattern = '(?:https?://|mailto:)[^">]+';
+ $placeholder = bin2hex(random_bytes(16));
if ($tag = it::match("(.*?)<(div|p|ol|ul|li|i|b|strong|h[1-6])\b[^>]*>(.*?)</\\2>(.*)", $html))
{
# Simple tags with content, no attributes kept
list($head, $tagname, $content, $tail) = $tag;
$tagname = strtolower($tagname);
- $result .= it_html::sanitize($head) . "<$tagname>" . it_html::sanitize($content) . "</$tagname>" . it_html::sanitize($tail);
+ $result .= it::replace([$placeholder => "<$tagname>" . it_html::sanitize($content) . "</$tagname>"], it_html::sanitize("$head$placeholder$tail"));
}
else if ($tag = it::match('(.*)<a\b[^>]+?\bhref\s*=\s*"(' . $urlpattern . ')"[^>]*?>(.*?)</a>(.*)', $html))
{
# Link tags, keeps only href attribute
list($head, $href, $content, $tail) = $tag;
- $result .= it_html::sanitize($head) . '<a href="' . it_html::Q(it_html::U(html_entity_decode($href, ENT_COMPAT, $charset))) . '">' . it_html::sanitize($content) . "</a>" . it_html::sanitize($tail);
+ $result .= it::replace([$placeholder => '<a href="' . it_html::Q(it_html::U(html_entity_decode($href, ENT_COMPAT, $charset))) . '">' . it_html::sanitize($content) . "</a>"], it_html::sanitize("$head$placeholder$tail"));
}
else if ($tag = it::match('(.*)<img\b[^>]+?\bsrc\s*=\s*"(' . $urlpattern . ')"[^>]*?>(.*)', $html))
{
# Image tags, keeps only src attribute
list($head, $src, $tail) = $tag;
- $result .= it_html::sanitize($head) . '<img src="' . it_html::Q(it_html::U(html_entity_decode($src, ENT_COMPAT, $charset))) . '" alt="" />' . it_html::sanitize($tail);
+ $result .= it::replace([$placeholder => '<img src="' . it_html::Q(it_html::U(html_entity_decode($src, ENT_COMPAT, $charset))) . '" alt="" />'], it_html::sanitize("$head$placeholder$tail"));
}
else if ($tag = it::match("(.*)<(br|/tr)\b[^>]*>(.*)", $html))
{
# brs and table rows are converted so simple line breaks
list($head, $tagname, $tail) = $tag;
- $result .= it_html::sanitize($head) . "<br />" . it_html::sanitize($tail);
+ $result .= it::replace([$placeholder => "<br />"], it_html::sanitize("$head$placeholder$tail"));
}
else
$result = it::replace(array('&amp;(#\d+;)' => '&$1'), it_html::Q(html_entity_decode(strip_tags($html), ENT_COMPAT, $charset)));
diff --git a/it_mail.class b/it_mail.class
index 11a4252..3d57bc3 100644
--- a/it_mail.class
+++ b/it_mail.class
@@ -575,22 +575,17 @@ static function check_email($email, $checkmailbox = false)
$finished = false;
$connected = 0;
- if (function_exists('stream_set_timeout'))
- $timeout = 'stream_set_timeout';
- else
- $timeout = 'socket_set_timeout';
-
foreach ($mx as $mxhost => $dummy_weight)
{
if ($fp = @fsockopen($mxhost, $port, $dummy_errno, $dummy_errstr, 5))
{
$connected++;
- $timeout($fp, 45);
+ stream_set_timeout($fp, 45);
$answer = '';
if (it_mail::send_smtp_cmd($fp, '', $answer) && it_mail::send_smtp_cmd($fp, "HELO $fromdomain", $answer) && it_mail::send_smtp_cmd($fp, "MAIL FROM: <$from>", $answer))
{
- $timeout($fp, 2);
+ stream_set_timeout($fp, 2);
$timeoutok = ($domain != 'bluewin.ch');
if (it_mail::send_smtp_cmd($fp, "RCPT TO: <$email>", $answer, $timeoutok, 500)) # 450 is often used for Greylisting
@@ -602,7 +597,7 @@ static function check_email($email, $checkmailbox = false)
$finished = true;
}
- $timeout($fp, 0, 1);
+ stream_set_timeout($fp, 0, 1);
it_mail::send_smtp_cmd($fp, 'RSET', $answer);
diff --git a/it_url.class b/it_url.class
index 8af61ae..c814261 100644
--- a/it_url.class
+++ b/it_url.class
@@ -314,8 +314,6 @@ function request($p=array())
curl_setopt($curl, CURLOPT_URL, $url->url);
}
-
- # FIXME 2025-01 NG just use CURLOPT_MAXFILESIZE if we have curl 8.4
$content = "";
if ($p['maxlength'] && !$p['writefunction'])
{
diff --git a/test/it_html.t b/test/it_html.t
index 15f444d..20ab65f 100755
--- a/test/it_html.t
+++ b/test/it_html.t
@@ -260,6 +260,18 @@ is(
);
is(
+ it_html::sanitize('<a href="http://search.ch/"><strong>foo</strong></a>'),
+ '<a href="http://search.ch/"><strong>foo</strong></a>',
+ 'it_html::sanitize handle nesting of tags inside <a>'
+);
+
+is(
+ it_html::sanitize('<a href="mailto:neuman@example.com">foo</a>'),
+ '<a href="mailto:neuman@example.com">foo</a>',
+ 'it_html::sanitize handle mailto links'
+);
+
+is(
it_html::sanitize("<a href='http://search.ch/'>foo</a>"),
'<a href="http://search.ch/">foo</a>',
'TODO it_html::sanitize handle anchors with single quotes at attribute value'
diff --git a/test/it_url.testserver.php b/test/it_url.testserver.php
index ca5300c..e59a81a 100644
--- a/test/it_url.testserver.php
+++ b/test/it_url.testserver.php
@@ -66,8 +66,12 @@ switch ($_SERVER['PHP_SELF'])
break;
case "/repeat":
+ if ($_REQUEST['compressed'])
+ ob_start('ob_gzhandler');
for ($i = 0; $i < $_REQUEST['num']; $i++)
echo $_REQUEST['string'];
+ if ($_REQUEST['compressed'])
+ ob_end_flush();
break;
case "/empty":
diff --git a/test/it_url_slow.t b/test/it_url_slow.t
index 00bbc2f..a5fd348 100755
--- a/test/it_url_slow.t
+++ b/test/it_url_slow.t
@@ -69,6 +69,13 @@ if (!$res || !$res2)
handle_server(
ok(
+ !it_url::get(['url' => "http://$host/repeat?string=abcdefghijklmnop&num=10&compressed", 'maxlength' => 100, 'retries' => 0, 'it_error' => false]),
+ 'it_url::get() fails for response larger than maxlength even if compressed response is smaller'
+ )
+);
+
+handle_server(
+ ok(
it_url::get(U("http://$host/repeat", ['string' => "abc", 'num' => 1024 * 1024])) == str_repeat("abc", 1024 * 1024),
'it_url::get() handles large response'
)