' . htmlspecialchars($text) . ''); } @@ -337,7 +337,7 @@ function forHTML($text, $doPrint = false) { * @param object The document or node to which the child nodes should be appended * @param array An associative multidimensional array of elements and values */ - function fromArray (&$node, &$myArray) { + public static function fromArray (&$node, &$myArray) { if ($node->nodeType == DOMIT_DOCUMENT_NODE) { $docNode =& $node; } @@ -369,8 +369,8 @@ function fromArray (&$node, &$myArray) { } } //fromArray - function parseAttributes() { + public static function parseAttributes() { } //parseAttributes } //DOMIT_Utilities -?> \ No newline at end of file +?> diff --git a/htdocs/applications/scielo-org/classes/domit-1/xml_saxy_lite_parser.php b/htdocs/applications/scielo-org/classes/domit-1/xml_saxy_lite_parser.php index 936c88369..45f2467ba 100644 --- a/htdocs/applications/scielo-org/classes/domit-1/xml_saxy_lite_parser.php +++ b/htdocs/applications/scielo-org/classes/domit-1/xml_saxy_lite_parser.php @@ -36,10 +36,14 @@ class SAXY_Lite_Parser extends SAXY_Parser_Base { /** * Constructor for SAX parser */ - function SAXY_Lite_Parser() { - $this->SAXY_Parser_Base(); - $this->state = SAXY_STATE_NONE; - } //SAXY_Lite_Parser + function SAXY_Lite_Parser() { + $this->SAXY_Parser_Base(); + $this->state = SAXY_STATE_NONE; + } //SAXY_Lite_Parser + + function __construct() { + $this->SAXY_Lite_Parser(); + } /** * Returns the current version of SAXY Lite diff --git a/htdocs/applications/scielo-org/classes/domit-1/xml_saxy_shared.php b/htdocs/applications/scielo-org/classes/domit-1/xml_saxy_shared.php index 36b0cdcfb..7421c3da6 100644 --- a/htdocs/applications/scielo-org/classes/domit-1/xml_saxy_shared.php +++ b/htdocs/applications/scielo-org/classes/domit-1/xml_saxy_shared.php @@ -56,9 +56,13 @@ class SAXY_Parser_Base { /** * Constructor for SAX parser */ - function SAXY_Parser_Base() { - $this->charContainer = ''; - } //SAXY_Parser_Base + function SAXY_Parser_Base() { + $this->charContainer = ''; + } //SAXY_Parser_Base + + function __construct() { + $this->SAXY_Parser_Base(); + } /** * Sets a reference to the handler for the start element event diff --git a/htdocs/applications/scielo-org/classes/services/AccessServiceBar.php b/htdocs/applications/scielo-org/classes/services/AccessServiceBar.php index 38cd93f8b..9b978e46a 100644 --- a/htdocs/applications/scielo-org/classes/services/AccessServiceBar.php +++ b/htdocs/applications/scielo-org/classes/services/AccessServiceBar.php @@ -44,7 +44,13 @@ function getStats(){ } function buildGraphic($stats){ - $stat = $stats->getRequests(); + $stat = is_object($stats) && method_exists($stats, 'getRequests') + ? $stats->getRequests() + : array(); + if (!is_array($stat) && !($stat instanceof Traversable)) { + $stat = array(); + } + $values = array(); foreach ($stat as $s){ $mes = intval($s->getMonth()); $ano = intval($s->getYear()); @@ -173,12 +179,20 @@ function buildGraphic($stats){ * @return int[] $anos * **/ - function getYears($stats) - { - // Recebe os dados estatisticos de um artigo - $stat = $stats->getRequests(); - $ano = array(); - + function getYears($stats) + { + // Recebe os dados estatisticos de um artigo + $stat = is_object($stats) && method_exists($stats, 'getRequests') + ? $stats->getRequests() + : array(); + if (!is_array($stat) && !($stat instanceof Traversable)) { + $stat = array(); + } + $ano = array(); + if (!is_array($stat)) { + return $ano; + } + for($i = 0, $j = 0; $i
| =ARTICLE_TITLE?> | -=getTitle($article->getTitle());?> | +=scielo_escape_html(getTitle($article->getTitle()));?> |
|
diff --git a/htdocs/classRequestVars.php b/htdocs/classRequestVars.php
index 827fa78c7..8ebec8b4e 100644
--- a/htdocs/classRequestVars.php
+++ b/htdocs/classRequestVars.php
@@ -46,8 +46,17 @@ function RequestVars ()
$this->_request = array_merge($_GET, $_POST);
}
- if (!isset($this->_request['lng']) || strpos("|en|pt|es|", $this->_request['lng']) == 0) {
- $this->_request['lng'] = "en";
+ if (isset($this->_request['lng'])) {
+ if (!is_string($this->_request['lng'])) {
+ unset($this->_request['lng']);
+ } else {
+ $language = strtolower(trim($this->_request['lng']));
+ if (in_array($language, array('en', 'pt', 'es'), true)) {
+ $this->_request['lng'] = $language;
+ } else {
+ unset($this->_request['lng']);
+ }
+ }
}
}
diff --git a/htdocs/classScielo.php b/htdocs/classScielo.php
index b6cfa9a08..c931b55a7 100644
--- a/htdocs/classScielo.php
+++ b/htdocs/classScielo.php
@@ -50,11 +50,13 @@ function loadPreviousUrlWhichContainsOldPid()
}
}
- function GenerateIsisScriptUrl()
- {
-
- $this->_request->getRequestValue ("lng", $lng);
- $this->_request->getRequestValue ("nrm", $nrm);
+ function GenerateIsisScriptUrl()
+ {
+
+ $lng = '';
+ $nrm = '';
+ $this->_request->getRequestValue ("lng", $lng);
+ $this->_request->getRequestValue ("nrm", $nrm);
$url = "http://";
$url .= $this->_def->getKeyValue("SERVER_SCIELO");
diff --git a/htdocs/security.php b/htdocs/security.php
index 55947e83b..15795a702 100644
--- a/htdocs/security.php
+++ b/htdocs/security.php
@@ -68,6 +68,154 @@ function scielo_audit_event($action, $result, $resource, $resourceId = null, $ex
error_log(json_encode($entry, JSON_UNESCAPED_SLASHES));
}
+function scielo_escape_html($value)
+{
+ return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
+}
+
+function scielo_validate_language($value, $default = 'en')
+{
+ $allowed = array('pt', 'en', 'es');
+ return in_array($value, $allowed, true) ? $value : $default;
+}
+
+function scielo_validate_article_pid($value)
+{
+ if (!is_string($value) || strlen($value) > 64) {
+ return false;
+ }
+
+ return preg_match('/^S[0-9]{4}-[0-9]{3}[0-9Xx][A-Za-z0-9.()_-]{1,40}$/D', $value)
+ ? $value
+ : false;
+}
+
+function scielo_validate_email_address($value)
+{
+ if (!is_string($value) || strlen($value) > 254 || preg_match('/[\r\n]/', $value)) {
+ return false;
+ }
+
+ $value = trim($value);
+ return filter_var($value, FILTER_VALIDATE_EMAIL) ? $value : false;
+}
+
+function scielo_validate_person_name($value)
+{
+ if (!is_string($value)) {
+ return false;
+ }
+
+ $value = trim($value);
+ if (!preg_match('/^[\p{L}\p{M}\p{N} .,\x27-]{1,100}$/u', $value)) {
+ return false;
+ }
+
+ return $value;
+}
+
+function scielo_validate_comment($value)
+{
+ if (!is_string($value) || strlen($value) > 1000
+ || preg_match('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', $value)) {
+ return false;
+ }
+
+ return trim($value);
+}
+
+function scielo_start_secure_session()
+{
+ if (session_status() === PHP_SESSION_ACTIVE) {
+ return;
+ }
+
+ session_set_cookie_params(array(
+ 'lifetime' => 0,
+ 'path' => '/',
+ 'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
+ 'httponly' => true,
+ 'samesite' => 'Lax',
+ ));
+ session_start();
+}
+
+function scielo_csrf_token()
+{
+ scielo_start_secure_session();
+
+ if (empty($_SESSION['scielo_csrf_token'])) {
+ $_SESSION['scielo_csrf_token'] = bin2hex(random_bytes(32));
+ }
+
+ return $_SESSION['scielo_csrf_token'];
+}
+
+function scielo_csrf_token_is_valid($token)
+{
+ scielo_start_secure_session();
+
+ return is_string($token)
+ && isset($_SESSION['scielo_csrf_token'])
+ && hash_equals($_SESSION['scielo_csrf_token'], $token);
+}
+
+function scielo_rate_limit($bucket, $limit, $windowSeconds)
+{
+ $ipAddress = isset($_SERVER['REMOTE_ADDR'])
+ && filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP)
+ ? $_SERVER['REMOTE_ADDR']
+ : null;
+
+ if ($ipAddress === null || !is_string($bucket) || $bucket === ''
+ || $limit < 1 || $windowSeconds < 1) {
+ return array('allowed' => false, 'retry_after' => $windowSeconds);
+ }
+
+ $directory = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR)
+ . DIRECTORY_SEPARATOR . 'scielo-rate-limit';
+ if (!is_dir($directory) && !mkdir($directory, 0700, true) && !is_dir($directory)) {
+ return array('allowed' => false, 'retry_after' => $windowSeconds);
+ }
+
+ $filename = $directory . DIRECTORY_SEPARATOR
+ . hash('sha256', $bucket . '|' . $ipAddress) . '.json';
+ $handle = fopen($filename, 'c+');
+ if ($handle === false || !flock($handle, LOCK_EX)) {
+ if (is_resource($handle)) {
+ fclose($handle);
+ }
+ return array('allowed' => false, 'retry_after' => $windowSeconds);
+ }
+
+ $now = time();
+ $contents = stream_get_contents($handle);
+ $timestamps = json_decode($contents, true);
+ if (!is_array($timestamps)) {
+ $timestamps = array();
+ }
+ $timestamps = array_values(array_filter($timestamps, function ($timestamp) use ($now, $windowSeconds) {
+ return is_int($timestamp) && $timestamp > ($now - $windowSeconds);
+ }));
+
+ $allowed = count($timestamps) < $limit;
+ $retryAfter = 0;
+ if ($allowed) {
+ $timestamps[] = $now;
+ } else {
+ $retryAfter = max(1, $windowSeconds - ($now - min($timestamps)));
+ }
+
+ rewind($handle);
+ ftruncate($handle, 0);
+ fwrite($handle, json_encode($timestamps));
+ fflush($handle);
+ flock($handle, LOCK_UN);
+ fclose($handle);
+
+ return array('allowed' => $allowed, 'retry_after' => $retryAfter);
+}
+
function scielo_is_loopback_request()
{
$remoteAddress = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
diff --git a/htdocs/statjournal.php b/htdocs/statjournal.php
index 945288f4a..e8ce85e3b 100644
--- a/htdocs/statjournal.php
+++ b/htdocs/statjournal.php
@@ -1,7 +1,10 @@
-')>0) {
+')>0) {
$r = substr($s, strpos($s,'<'.$TAG.'>'));
$r = substr($r, strlen('<'.$TAG.'>'));
$r = substr($r, 0, strpos($r,''.$TAG.'>'));
@@ -9,35 +12,51 @@ function x($s, $TAG){
$r = str_replace(']]>','',$r);
}
return $r;
- }
- $DEF = parse_ini_file("scielo.def.php", true);
-
- if ($_GET['lang'] != 'en' && $_GET['lang'] != 'es' && $_GET['lang'] != 'pt') $_GET['lang'] = $DEF['SITE_INFO']['STANDARD_LANG'];
-
- if ( strpos($DEF['SCIELO']['STAT_SERVER'],$DEF['SCIELO']['SERVER_SCIELO'])>0) {
+ }
+ $DEF = parse_ini_file("scielo.def.php", true);
+
+ $defaultLang = isset($DEF['SITE_INFO']['STANDARD_LANG'])
+ ? scielo_validate_language($DEF['SITE_INFO']['STANDARD_LANG'], 'en')
+ : 'en';
+ $lang = scielo_validate_language(isset($_GET['lang']) ? $_GET['lang'] : '', $defaultLang);
+ $issn = isset($_GET['issn']) && is_string($_GET['issn']) ? $_GET['issn'] : '';
+ $collection = isset($_GET['collection']) && is_string($_GET['collection'])
+ ? $_GET['collection']
+ : '';
+
+ if (!preg_match('/^[0-9]{4}-?[0-9]{3}[0-9Xx]$/D', $issn)
+ || !preg_match('/^[A-Za-z0-9._-]{1,64}$/D', $collection)) {
+ http_response_code(400);
+ exit('Invalid request');
+ }
+
+ $_GET['lang'] = $lang;
+ $_GET['issn'] = $issn;
+ $internalHost = scielo_internal_host_from_config($DEF);
+ $collectionEncoded = rawurlencode($collection);
+
+ if ( strpos($DEF['SCIELO']['STAT_SERVER'],$DEF['SCIELO']['SERVER_SCIELO'])>0) {
$xml = 'xml='.$DEF['SCIELO']['STAT_SERVER'].'/stat_biblio/xml/';
} else {
$xml = 'no=';
}
- $journalInfo = file_get_contents('http://'.$DEF['SCIELO']['SERVER_SCIELO'].'/scielo.php?script=sci_serial&pid='.$_GET['issn'].'&debug=xml');
+ $journalInfo = file_get_contents('http://' . $internalHost . '/scielo.php?' . http_build_query(array(
+ 'script' => 'sci_serial',
+ 'pid' => $issn,
+ 'debug' => 'xml',
+ )));
$error = x($journalInfo,'CODE');
- if ($error){
- header("Location: ".'http://'.$DEF['SCIELO']['SERVER_SCIELO'].'/scielo.php?script=sci_serial&pid='.$_GET['issn']);
+ if ($error){
+ header("Location: ".'http://'.$DEF['SCIELO']['SERVER_SCIELO'].'/scielo.php?script=sci_serial&pid='.$_GET['issn']);
+ exit;
}
$journalInfo = x($journalInfo,'TITLEGROUP');
$j['title'] = x($journalInfo,'TITLE');
$j['acron'] = x($journalInfo,'SIGLUM');
- foreach ($_GET as $g){
- $g = str_replace('/','',$g);
- $g = str_replace(':','',$g);
- $g = str_replace('\\','',$g);
- $g = str_replace('*','',$g);
- $g = str_replace('.','',$g);
- }
- switch ($_GET['lang']){
+ switch ($_GET['lang']){
case "en":
$LABELS = array('LANG_1'=> 'i',
'LANG'=>$_GET['lang'],
@@ -144,7 +163,7 @@ function x($s, $TAG){
?>
- | ||
|
-
+
|