/** * @see Filter::process() * @param $citationString string * @return MetadataDescription */ function &process($citationString) { $nullVar = null; $queryParams = array('demo' => '3', 'textlines' => $citationString); // Parscit web form - the result is (mal-formed) HTML if (is_null($result = $this->callWebService(PARSCIT_WEBSERVICE, $queryParams, XSL_TRANSFORMER_DOCTYPE_STRING, 'POST'))) { return $nullVar; } $result = html_entity_decode($result); // Detect errors. if (!String::regexp_match('/.*<algorithm[^>]+>.*<\\/algorithm>.*/s', $result)) { $translationParams = array('filterName' => $this->getDisplayName()); $this->addError(Locale::translate('submission.citations.filter.webserviceResultTransformationError', $translationParams)); return $nullVar; } // Screen-scrape the tagged portion and turn it into XML. $xmlResult = String::regexp_replace('/.*<algorithm[^>]+>(.*)<\\/algorithm>.*/s', '\\1', $result); $xmlResult = String::regexp_replace('/&/', '&', $xmlResult); // Transform the result into an array of meta-data. if (is_null($metadata = $this->transformWebServiceResults($xmlResult, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'parscit.xsl'))) { return $nullVar; } // Extract a publisher from the place string if possible. $metadata =& $this->fixPublisherNameAndLocation($metadata); return $this->getNlm30CitationDescriptionFromMetadataArray($metadata); }
/** * @see TypeDescription::parseTypeName() */ function parseTypeName($typeName) { // Standard validators are based on string input. parent::parseTypeName('string'); // Split the type name into validator name and arguments. $typeNameParts = explode('(', $typeName, 2); switch (count($typeNameParts)) { case 1: // no argument $this->_validatorArgs = ''; break; case 2: // parse arguments (no UTF8-treatment necessary) if (substr($typeNameParts[1], -1) != ')') { return false; } // FIXME: Escape for PHP code inclusion? $this->_validatorArgs = substr($typeNameParts[1], 0, -1); break; } // Validator name must start with a lower case letter // and may contain only alphanumeric letters. if (!String::regexp_match('/^[a-z][a-zA-Z0-9]+$/', $typeNameParts[0])) { return false; } // Translate the validator name into a validator class name. $this->_validatorClassName = 'Validator' . String::ucfirst($typeNameParts[0]); return true; }
/** * Validate against a localized email field. * @return boolean */ function isValid() { if ($this->isEmptyAndOptional()) { return true; } $value = $this->form->getData($this->field); $primaryLocale = Locale::getPrimaryLocale(); return is_array($value) && !empty($value[$primaryLocale]) && String::regexp_match($this->regExp, $value[$primaryLocale]); }
/** * Retrieve the export as an XML string. * @param $pluginUrl string the url to be requested for export. * @param $postParams array additional post parameters * @return string */ protected function getXmlOnExport($pluginUrl, $postParams = array()) { // Prepare HTTP session. $curlCh = curl_init(); curl_setopt($curlCh, CURLOPT_POST, true); // Create a cookie file (required for log-in). $cookies = tempnam(sys_get_temp_dir(), 'curlcookies'); // Log in. $loginUrl = $this->baseUrl . '/index.php/test/login/signIn'; // Bug #8518 safety work-around if ($this->password[0] == '@') { die('CURL parameters may not begin with @.'); } $loginParams = array('username' => 'admin', 'password' => $this->password); curl_setopt($curlCh, CURLOPT_URL, $loginUrl); curl_setopt($curlCh, CURLOPT_POSTFIELDS, $loginParams); curl_setopt($curlCh, CURLOPT_COOKIEJAR, $cookies); self::assertTrue(curl_exec($curlCh)); // Request export document. $exportUrl = $this->baseUrl . '/index.php/test/manager/importexport/plugin/' . $pluginUrl; curl_setopt($curlCh, CURLOPT_URL, $exportUrl); // Bug #8518 safety work-around foreach ($postParams as $paramValue) { if ($paramValue[0] == '@') { die('CURL parameters may not begin with @.'); } } curl_setopt($curlCh, CURLOPT_POSTFIELDS, $postParams); curl_setopt($curlCh, CURLOPT_HTTPHEADER, array('Accept: application/xml, application/x-gtar, */*')); curl_setopt($curlCh, CURLOPT_RETURNTRANSFER, true); curl_setopt($curlCh, CURLOPT_HEADER, true); $response = curl_exec($curlCh); do { list($header, $response) = explode("\r\n\r\n", $response, 2); } while (String::regexp_match('#HTTP/.*100#', $header)); // Check whether we got a tar file. if (String::regexp_match('#Content-Type: application/x-gtar#', $header)) { // Save the data to a temporary file. $tempfile = tempnam(sys_get_temp_dir(), 'tst'); file_put_contents($tempfile, $response); // Recursively extract tar file. $result = $this->extractTarFile($tempfile); unlink($tempfile); } else { $matches = null; String::regexp_match_get('#filename="([^"]+)"#', $header, $matches); self::assertTrue(isset($matches[1])); $result = array($matches[1] => $response); } // Destroy HTTP session. curl_close($curlCh); unlink($cookies); return $result; }
function elementsAreEmails($elements) { if (!is_array($elements)) { return false; } $regexp = FormValidatorEmail::getRegexp(); foreach ($elements as $element) { if (!String::regexp_match($regexp, $element)) { echo "{$element} failed {$regexp}<br/>\n"; return false; } } return true; }
/** * @see Filter::supports() * @param $input mixed * @param $output mixed * @return boolean */ function supports(&$input, &$output) { // Check input type if (!is_string($input)) { return false; } // Check output type if (is_null($output)) { return true; } if (!is_string($output)) { return false; } // Check whether the output is correctly formatted return (bool) String::regexp_match("/\\d{4}(-\\d{2}(-\\d{2})?)?/", $output); }
/** * Checks whether the given version file exists and whether it * contains valid data. Returns a Version object if everything * is ok, otherwise null. * * @param $versionFile string * @param $templateMgr TemplateManager * @return Version or null if invalid or missing version file */ function &getValidPluginVersionInfo($versionFile, &$templateMgr) { $nullVar = null; if (FileManager::fileExists($versionFile)) { $versionInfo =& VersionCheck::parseVersionXML($versionFile); } else { $templateMgr->assign('message', 'manager.plugins.versionFileNotFound'); return $nullVar; } $pluginVersion =& $versionInfo['version']; // Validate plugin name and type to avoid abuse $productType = explode(".", $versionInfo['type']); if (count($productType) != 2 || $productType[0] != 'plugins') { return $nullVar; $templateMgr->assign('message', 'manager.plugins.versionFileInvalid'); } $namesToValidate = array($pluginVersion->getProduct(), $productType[1]); foreach ($namesToValidate as $nameToValidate) { if (!String::regexp_match('/[a-z][a-zA-Z0-9]+/', $nameToValidate)) { return $nullVar; $templateMgr->assign('message', 'manager.plugins.versionFileInvalid'); } } return $pluginVersion; }
/** * Insert an entry into metrics table. * * @param $record array * @param $errorMsg string */ function insertRecord(&$record, &$errorMsg) { $recordToStore = array(); // Required dimensions. $requiredDimensions = array('load_id', 'assoc_type', 'assoc_id', 'metric_type'); foreach ($requiredDimensions as $requiredDimension) { if (!isset($record[$requiredDimension])) { $errorMsg = 'Cannot load record: missing dimension "' . $requiredDimension . '".'; return false; } $recordToStore[$requiredDimension] = $record[$requiredDimension]; } $recordToStore['assoc_type'] = (int) $recordToStore['assoc_type']; $recordToStore['assoc_id'] = (int) $recordToStore['assoc_id']; // Foreign key lookup for the publication object dimension. $isArticleFile = false; switch ($recordToStore['assoc_type']) { case ASSOC_TYPE_GALLEY: case ASSOC_TYPE_SUPP_FILE: if ($recordToStore['assoc_type'] == ASSOC_TYPE_GALLEY) { $galleyDao =& DAORegistry::getDAO('ArticleGalleyDAO'); /* @var $galleyDao ArticleGalleyDAO */ $articleFile =& $galleyDao->getGalley($recordToStore['assoc_id']); if (!is_a($articleFile, 'ArticleGalley')) { $errorMsg = 'Cannot load record: invalid galley id.'; return false; } } else { $suppFileDao =& DAORegistry::getDAO('SuppFileDAO'); /* @var $suppFileDao SuppFileDAO */ $articleFile =& $suppFileDao->getSuppFile($recordToStore['assoc_id']); if (!is_a($articleFile, 'SuppFile')) { $errorMsg = 'Cannot load record: invalid supplementary file id.'; return false; } } $articleId = $articleFile->getArticleId(); $isArticleFile = true; // Don't break but go on to retrieve the article. // Don't break but go on to retrieve the article. case ASSOC_TYPE_ARTICLE: if (!$isArticleFile) { $articleId = $recordToStore['assoc_id']; } $publishedArticleDao =& DAORegistry::getDAO('PublishedArticleDAO'); /* @var $publishedArticleDao PublishedArticleDAO */ $article =& $publishedArticleDao->getPublishedArticleByArticleId($articleId, null, true); if (is_a($article, 'PublishedArticle')) { $issueId = $article->getIssueId(); } else { $issueId = null; $articleDao =& DAORegistry::getDAO('ArticleDAO'); /* @var $articleDao ArticleDAO */ $article =& $articleDao->getArticle($articleId, null, true); } if (!is_a($article, 'Article')) { $errorMsg = 'Cannot load record: invalid article id.'; return false; } $journalId = $article->getJournalId(); break; case ASSOC_TYPE_ISSUE_GALLEY: $articleId = null; $issueGalleyDao =& DAORegistry::getDAO('IssueGalleyDAO'); /* @var $issueGalleyDao IssueGalleyDAO */ $issueGalley =& $issueGalleyDao->getGalley($recordToStore['assoc_id']); if (!is_a($issueGalley, 'IssueGalley')) { $errorMsg = 'Cannot load record: invalid issue galley id.'; return false; } $issueId = $issueGalley->getIssueId(); $issueDao =& DAORegistry::getDAO('IssueDAO'); /* @var $issueDao IssueDAO */ $issue =& $issueDao->getIssueById($issueId, null, true); if (!is_a($issue, 'Issue')) { $errorMsg = 'Cannot load record: issue galley without issue.'; return false; } $journalId = $issue->getJournalId(); break; case ASSOC_TYPE_ISSUE: $articleId = null; $issueId = $recordToStore['assoc_id']; $issueDao =& DAORegistry::getDAO('IssueDAO'); $issue =& $issueDao->getIssueByPubId('publisher-id', $issueId, null, true); /* @var $issue Issue */ if (!$issue) { $issue =& $issueDao->getIssueById($issueId, null, true); } if (!is_a($issue, 'Issue')) { $errorMsg = 'Cannot load record: invalid issue id.'; return false; } $journalId = $issue->getJournalId(); break; case ASSOC_TYPE_JOURNAL: $articleId = $issueId = null; $journalDao =& DAORegistry::getDAO('JournalDAO'); /* @var $journalDao JournalDAO */ $journal =& $journalDao->getById($recordToStore['assoc_id']); if (!$journal) { $errorMsg = 'Cannot load record: invalid journal id.'; return false; } $journalId = $recordToStore['assoc_id']; break; default: $errorMsg = 'Cannot load record: invalid association type.'; return false; } $recordToStore['context_id'] = $journalId; $recordToStore['issue_id'] = $issueId; $recordToStore['submission_id'] = $articleId; // We require either month or day in the time dimension. if (isset($record['day'])) { if (!String::regexp_match('/[0-9]{8}/', $record['day'])) { $errorMsg = 'Cannot load record: invalid date.'; return false; } $recordToStore['day'] = $record['day']; $recordToStore['month'] = substr($record['day'], 0, 6); if (isset($record['month']) && $recordToStore['month'] != $record['month']) { $errorMsg = 'Cannot load record: invalid month.'; return false; } } elseif (isset($record['month'])) { if (!String::regexp_match('/[0-9]{6}/', $record['month'])) { $errorMsg = 'Cannot load record: invalid month.'; return false; } $recordToStore['month'] = $record['month']; } else { $errorMsg = 'Cannot load record: Missing time dimension.'; return false; } // File type is optional. if (isset($record['file_type']) && $record['file_type']) { $recordToStore['file_type'] = (int) $record['file_type']; } // Geolocation is optional. if (isset($record['country_id'])) { $recordToStore['country_id'] = (string) $record['country_id']; } if (isset($record['region'])) { $recordToStore['region'] = (string) $record['region']; } if (isset($record['city'])) { $recordToStore['city'] = (string) $record['city']; } // The metric must be set. If it is 0 we ignore the record. if (!isset($record['metric'])) { $errorMsg = 'Cannot load record: metric is missing.'; return false; } if (!is_numeric($record['metric'])) { $errorMsg = 'Cannot load record: invalid metric.'; return false; } $recordToStore['metric'] = (int) $record['metric']; // Save the record to the database. $fields = implode(', ', array_keys($recordToStore)); $placeholders = implode(', ', array_pad(array(), count($recordToStore), '?')); $params = array_values($recordToStore); return $this->update("INSERT INTO metrics ({$fields}) VALUES ({$placeholders})", $params); }
/** * Helper method that configures and optionally * installs a filter based on the given XML node * which represents a <filter> element. * @param $filterNode XMLNode * @param $persist boolean whether to install the filter * @return PersistableFilter the installed filter. */ function &configureFilter($filterNode, $persist = true) { // Install filters. $filterDao =& DAORegistry::getDAO('FilterDAO'); /* @var $filterDao FilterDAO */ $filterGroupSymbolic = $filterNode->getAttribute('inGroup'); $filterClassName = $filterNode->getAttribute('class'); $isTemplate = $filterNode->getAttribute('isTemplate'); // We have to include the filter class before going on // so that all required constants are defined before they // might be used in settings. if (String::regexp_match('/^[a-zA-Z0-9.]+$/', $filterClassName)) { import($filterClassName); } // Go through the filter sub-nodes. This can be nested // filters or filter settings. $subNodes = $filterNode->getChildren(); $settings = array(); $subFilters = array(); foreach ($subNodes as $subNode) { /* @var $subNode XMLNode */ switch ($subNode->getName()) { case 'setting': // Get the filter setting. list($name, $value) = $this->getFilterSetting($subNode); $settings[$name] = $value; unset($name, $value); break; case 'filter': // Recursively configure sub-filters. $subFilter =& $this->configureFilter($subNode, false); $subFilters[] =& $subFilter; unset($subFilter); break; } } // We ensure idempotence of plug-in installation by checking // for existing identical filters. $similarFilterFactory =& $filterDao->getObjectsByGroupAndClass($filterGroupSymbolic, $filterClassName, 0, $isTemplate); if ($similarFilterFactory->getCount() > 0) { // 1) Find similar filters. $similarFilters =& $similarFilterFactory->toArray(); // 2) Go through similar filters and eliminate them // if they don't have the exact same settings. foreach ($similarFilters as $index => $similarFilter) { /* @var $similarFilter PersistableFilter */ if (!$this->compareFilters($similarFilter, $settings, $subFilters)) { unset($similarFilters[$index]); } } // There can be a maximum of exactly one identical transformation // in the database otherwise we've somehow installed a duplicate filter. $identicalFilters = count($similarFilters); assert($identicalFilters <= 1); // 3) If the filter has been installed before then return the existing filter. if ($identicalFilters) { $existingFilter = array_pop($similarFilters); return $existingFilter; } } // Configure (and optionally install) the filter. $installedFilter =& $filterDao->configureObject($filterClassName, $filterGroupSymbolic, $settings, $isTemplate, 0, $subFilters, $persist); assert(is_a($installedFilter, 'PersistableFilter')); return $installedFilter; }
/** * Converts a string with multiple persons * to an array of NLM name descriptions. * * @param $personsString string * @param $title boolean true to parse for title * @param $degrees boolean true to parse for degrees * @return array an array of NLM name descriptions or null * if the string could not be converted */ function &_parsePersonsString($personsString, $title, $degrees) { // Remove "et al" $personsString = String::regexp_replace('/et ?al$/', '', $personsString); // Remove punctuation $personsString = trim($personsString, ':;,'); // Cut the authors string into pieces $personStrings = String::iterativeExplode(array(':', ';'), $personsString); // Only try to cut by comma if the pieces contain more // than one word to avoid splitting between last name and // first name. if (count($personStrings) == 1) { if (String::regexp_match('/^((\\w+\\s+)+\\w+\\s*,)+\\s*((\\w+\\s+)+\\w+)$/i', $personStrings[0])) { $personStrings = explode(',', $personStrings[0]); } } // Parse persons $persons = array(); foreach ($personStrings as $personString) { $persons[] =& $this->_parsePersonString($personString, $title, $degrees); } return $persons; }
/** * Do the actual web service request. * @param $action string * @param $arg string * @param $attachment array * @return boolean|string True for success, an error message otherwise. */ function _doRequest($action, $arg, $attachment = null) { // Build the multipart SOAP message from scratch. $soapMessage = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" ' . 'xmlns:med="http://www.medra.org">' . '<SOAP-ENV:Header/>' . '<SOAP-ENV:Body>' . "<med:{$action}>{$arg}</med:{$action}>" . '</SOAP-ENV:Body>' . '</SOAP-ENV:Envelope>'; $soapMessageId = $this->_getContentId($action); if ($attachment) { assert(count($attachment) == 1); $request = "--MIME_boundary\r\n" . $this->_getMimePart($soapMessageId, $soapMessage) . "--MIME_boundary\r\n" . $this->_getMimePart(key($attachment), current($attachment)) . "--MIME_boundary--\r\n"; $contentType = 'multipart/related; type="text/xml"; boundary="MIME_boundary"'; } else { $request = $soapMessage; $contentType = 'text/xml'; } // Prepare HTTP session. $curlCh = curl_init(); curl_setopt($curlCh, CURLOPT_RETURNTRANSFER, true); curl_setopt($curlCh, CURLOPT_POST, true); // Set up basic authentication. curl_setopt($curlCh, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($curlCh, CURLOPT_USERPWD, $this->_auth); // Set up SSL. curl_setopt($curlCh, CURLOPT_SSLVERSION, 3); curl_setopt($curlCh, CURLOPT_SSL_VERIFYPEER, false); // Make SOAP request. curl_setopt($curlCh, CURLOPT_URL, $this->_endpoint); $extraHeaders = array('SOAPAction: "' . $action . '"', 'Content-Type: ' . $contentType, 'UserAgent: OJS-mEDRA'); curl_setopt($curlCh, CURLOPT_HTTPHEADER, $extraHeaders); curl_setopt($curlCh, CURLOPT_POSTFIELDS, $request); $result = true; $response = curl_exec($curlCh); // We do not localize our error messages as they are all // fatal errors anyway and must be analyzed by technical staff. if ($response === false) { $result = 'OJS-mEDRA: Expected string response.'; } if ($result === true && ($status = curl_getinfo($curlCh, CURLINFO_HTTP_CODE)) != MEDRA_WS_RESPONSE_OK) { $result = 'OJS-mEDRA: Expected ' . MEDRA_WS_RESPONSE_OK . ' response code, got ' . $status . ' instead.'; } curl_close($curlCh); // Check SOAP response by simple string manipulation rather // than instantiating a DOM. if (is_string($response)) { $matches = array(); String::regexp_match_get('#<faultstring>([^<]*)</faultstring>#', $response, $matches); if (empty($matches)) { if ($attachment) { assert(String::regexp_match('#<returnCode>success</returnCode>#', $response)); } else { $parts = explode("\r\n\r\n", $response); $result = array_pop($parts); $result = String::regexp_replace('/>[^>]*$/', '>', $result); } } else { $result = 'mEDRA: ' . $status . ' - ' . $matches[1]; } } else { $result = 'OJS-mEDRA: Expected string response.'; } return $result; }
/** * Checks whether the given version file exists and whether it * contains valid data. Returns a Version object if everything * is ok, otherwise null. If $returnErroMsg is true, returns the * error message. * * @param $versionFile string * @param $returnErrorMesg boolean * @return Version or null/string if invalid or missing version file */ function &getValidPluginVersionInfo($versionFile, $returnErrorMsg = false) { $nullVar = null; $errorMsg = null; $fileManager = new FileManager(); if ($fileManager->fileExists($versionFile)) { $versionInfo =& VersionCheck::parseVersionXML($versionFile); } else { $errorMsg = 'manager.plugins.versionFileNotFound'; } // Validate plugin name and type to avoid abuse if (is_null($errorMsg)) { $productType = explode(".", $versionInfo['type']); if (count($productType) != 2 || $productType[0] != 'plugins') { $errorMsg = 'manager.plugins.versionFileInvalid'; } } if (is_null($errorMsg)) { $pluginVersion =& $versionInfo['version']; $namesToValidate = array($pluginVersion->getProduct(), $productType[1]); foreach ($namesToValidate as $nameToValidate) { if (!String::regexp_match('/[a-z][a-zA-Z0-9]+/', $nameToValidate)) { $errorMsg = 'manager.plugins.versionFileInvalid'; break; } } } if ($errorMsg) { if ($returnErrorMsg) { return $errorMsg; } else { $templateMgr =& TemplateManager::getManager(); $templateMgr->assign('message', $errorMsg); return $nullVar; } } else { return $pluginVersion; } }
/** * Check if field value is valid. * Value is valid if it is empty and optional or matches regular expression. * @return boolean */ function isValid() { return $this->isEmptyAndOptional() || String::regexp_match($this->regExp, $this->form->getData($this->field)); }
/** * Check the passed user agent for a bot. * @param $userAgent string * @param $botRegexpsFile string An alternative file with regular * expressions to find bots inside user agent strings. * @return boolean */ function isUserAgentBot($userAgent, $botRegexpsFile = USER_AGENTS_FILE) { static $botRegexps; Registry::set('currentUserAgentsFile', $botRegexpsFile); if (!isset($botRegexps[$botRegexpsFile])) { $botFileCacheId = md5($botRegexpsFile); $cacheManager =& CacheManager::getManager(); $cache =& $cacheManager->getCache('core', $botFileCacheId, array('Core', '_botFileListCacheMiss'), CACHE_TYPE_FILE); $botRegexps[$botRegexpsFile] = $cache->getContents(); } foreach ($botRegexps[$botRegexpsFile] as $regexp) { if (String::regexp_match($regexp, $userAgent)) { return true; } } return false; }
/** * This method pre-validates the service endpoint parts before * we try to convert them to a file/method name. This also * converts all parts to lower case. * @param $rpcServiceEndpointParts array * @return array the validated service endpoint parts or null if validation * does not succeed. */ function _validateServiceEndpointParts($rpcServiceEndpointParts) { // Do we have data at all? if (is_null($rpcServiceEndpointParts) || empty($rpcServiceEndpointParts) || !is_array($rpcServiceEndpointParts)) { return null; } // We require at least three parts: component directory, handler // and method name. if (count($rpcServiceEndpointParts) < 3) { return null; } // Check that the array dimensions remain within sane limits. if (count($rpcServiceEndpointParts) > COMPONENT_ROUTER_PARTS_MAXDEPTH) { return null; } // Validate the individual endpoint parts. foreach ($rpcServiceEndpointParts as $key => $rpcServiceEndpointPart) { // Make sure that none of the elements exceeds the length limit. $partLen = strlen($rpcServiceEndpointPart); if ($partLen > COMPONENT_ROUTER_PARTS_MAXLENGTH || $partLen < COMPONENT_ROUTER_PARTS_MINLENGTH) { return null; } // Service endpoint URLs are case insensitive. $rpcServiceEndpointParts[$key] = strtolower_codesafe($rpcServiceEndpointPart); // We only allow letters, numbers and the hyphen. if (!String::regexp_match('/^[a-z0-9-]*$/', $rpcServiceEndpointPart)) { return null; } } return $rpcServiceEndpointParts; }
/** * Insert an entry into metrics table. * * @param $record array * @param $errorMsg string */ function insertRecord($record) { $recordToStore = array(); // Required dimensions. $requiredDimensions = array('load_id', 'assoc_type', 'assoc_id', 'metric_type'); foreach ($requiredDimensions as $requiredDimension) { if (!isset($record[$requiredDimension])) { throw new Exception('Cannot load record: missing dimension "' . $requiredDimension . '".'); } $recordToStore[$requiredDimension] = $record[$requiredDimension]; } $assocType = $recordToStore['assoc_type'] = (int) $recordToStore['assoc_type']; $assocId = $recordToStore['assoc_id'] = (int) $recordToStore['assoc_id']; list($contextId, $pkpSectionId, $assocObjType, $assocObjId, $submissionId, $representationId) = $this->foreignKeyLookup($assocType, $assocId); $recordToStore['context_id'] = $contextId; $recordToStore['pkp_section_id'] = $pkpSectionId; $recordToStore['assoc_object_type'] = $assocObjType; $recordToStore['assoc_object_id'] = $assocObjId; $recordToStore['submission_id'] = $submissionId; $recordToStore['representation_id'] = $representationId; // File type is optional. if (isset($record['file_type']) && $record['file_type']) { $recordToStore['file_type'] = (int) $record['file_type']; } // We require either month or day in the time dimension. if (isset($record['day'])) { if (!String::regexp_match('/[0-9]{8}/', $record['day'])) { throw new Exception('Cannot load record: invalid date.'); } $recordToStore['day'] = $record['day']; $recordToStore['month'] = substr($record['day'], 0, 6); if (isset($record['month']) && $recordToStore['month'] != $record['month']) { throw new Exception('Cannot load record: invalid month.'); } } elseif (isset($record['month'])) { if (!String::regexp_match('/[0-9]{6}/', $record['month'])) { throw new Exception('Cannot load record: invalid month.'); } $recordToStore['month'] = $record['month']; } else { throw new Exception('Cannot load record: Missing time dimension.'); } // Geolocation is optional. if (isset($record['country_id'])) { $recordToStore['country_id'] = (string) $record['country_id']; } if (isset($record['region'])) { $recordToStore['region'] = (string) $record['region']; } if (isset($record['city'])) { $recordToStore['city'] = (string) $record['city']; } // The metric must be set. If it is 0 we ignore the record. if (!isset($record['metric'])) { throw new Exception('Cannot load record: metric is missing.'); } if (!is_numeric($record['metric'])) { throw new Exception('Cannot load record: invalid metric.'); } $recordToStore['metric'] = (int) $record['metric']; // Save the record to the database. $fields = implode(', ', array_keys($recordToStore)); $placeholders = implode(', ', array_pad(array(), count($recordToStore), '?')); $params = array_values($recordToStore); return $this->update("INSERT INTO metrics ({$fields}) VALUES ({$placeholders})", $params); }
/** * Check the passed user agent for a bot. * @param $userAgent string * @param $botRegexpsFile string An alternative file with regular * expressions to find bots inside user agent strings. * @return boolean */ static function isUserAgentBot($userAgent, $botRegexpsFile = USER_AGENTS_FILE) { static $botRegexps; if (!isset($botRegexps[$botRegexpsFile])) { $botRegexps[$botRegexpsFile] = array_filter(file($botRegexpsFile), array('Core', '_filterBotRegexps')); } foreach ($botRegexps[$botRegexpsFile] as $regexp) { if (String::regexp_match($regexp, $userAgent)) { return true; } } return false; }
function encodeDisplayName($displayName) { if (String::regexp_match('!^[-A-Za-z0-9\\!#\\$%&\'\\*\\+\\/=\\?\\^_\\`\\{\\|\\}~]+$!', $displayName)) { return $displayName; } return '"' . str_replace(array('"', '\\'), '', $displayName) . '"'; }
/** * Encode a display name for proper inclusion with an email address. * @param $displayName string * @param $send boolean True to encode the results for sending * @return string */ function encodeDisplayName($displayName, $send = false) { if (String::regexp_match('!^[-A-Za-z0-9\\!#\\$%&\'\\*\\+\\/=\\?\\^_\\`\\{\\|\\}~]+$!', $displayName)) { return $displayName; } return '"' . ($send ? String::encode_mime_header(str_replace(array('"', '\\'), '', $displayName)) : str_replace(array('"', '\\'), '', $displayName)) . '"'; }
/** * Converts a string with multiple persons * to an array of NLM name descriptions. * * @param $personsString string * @param $title boolean true to parse for title * @param $degrees boolean true to parse for degrees * @return array an array of NLM name descriptions or null * if the string could not be converted plus optionally a * single 'et-al' string. */ function &_parsePersonsString($personsString, $title, $degrees) { // Check for 'et al'. $personsStringBeforeEtal = String::strlen($personsString); $personsString = String::regexp_replace('/et ?al$/', '', $personsString); $etAl = $personsStringBeforeEtal == String::strlen($personsString) ? false : true; // Remove punctuation. $personsString = trim($personsString, ':;, '); // Cut the authors string into pieces. $personStrings = String::iterativeExplode(array(':', ';'), $personsString); // If we did not have success with simple patterns then try more complex // patterns to tokenize multiple-person strings. if (count($personStrings) == 1) { // The first pattern must match the whole string, the second is used // to extract names. $complexPersonsPatterns = array(array('/^((([^ \\t\\n\\r\\f\\v,.&]{2,}\\s*)+,\\s*([A-Z]\\.\\s*)+),\\s*)+(\\&|\\.\\s\\.\\s\\.)\\s*([^ \\t\\n\\r\\f\\v,.&]{2,}\\s*,\\s*([A-Z]\\.\\s*)+)$/i', '/(?:[^ \\t\\n\\r\\f\\v,.&]{2,}\\s*)+,\\s*(?:[A-Z]\\.\\s*)+/i'), array('/^((([^ \\t\\n\\r\\f\\v,&]+\\s+)+[^ \\t\\n\\r\\f\\v,&]+\\s*)[,&]\\s*)+(([^ \\t\\n\\r\\f\\v,&]+\\s+)+[^ \\t\\n\\r\\f\\v,&]+)/i', '/(?:(?:[^ \\t\\n\\r\\f\\v,&.]+|[^ \\t\\n\\r\\f\\v,&]{2,})\\s+)+(?:[^ \\t\\n\\r\\f\\v,&.]+|[^ \\t\\n\\r\\f\\v,&]{2,})/i')); $matched = false; foreach ($complexPersonsPatterns as $complexPersonsPattern) { // Break at the first pattern that matches. if ($matched = String::regexp_match($complexPersonsPattern[0], $personsString)) { // Retrieve names. $success = String::regexp_match_all($complexPersonsPattern[1], $personsString, $personStrings); assert($success && count($personStrings) == 1); $personStrings = $personStrings[0]; break; } } if (!$matched) { // If nothing matches then try to parse as a single person. $personStrings = array($personsString); } } // Parse persons. $persons = array(); foreach ($personStrings as $personString) { $persons[] =& $this->_parsePersonString($personString, $title, $degrees); } // Add et-al string. if ($etAl) { $persons[] = PERSON_STRING_FILTER_ETAL; } return $persons; }
/** * Instantiates an object for a given fully qualified * class name after executing several checks on the class. * * The checks prevent certain vulnerabilities when * instantiating classes generically. * * NB: We currently only support one constructor * argument. If we need arbitrary arguments later * we can do that via func_get_args() which allows us * to handle an arbitrary number of optional * constructor arguments. The $constructorArg * parameter needs to be last in the parameter list * to be forward compatible with this potential use * case. * * @param $fullyQualifiedClassName string * @param $expectedTypes string|array the class * must conform to at least one of the given types. * @param $expectedPackages string|array the class * must be part of at least one of the given packages. * @param $expectedMethods string|array names of methods * that must all be present for the requested class. * @param $constructorArg mixed constructor argument * * @return object|boolean the instantiated object or false * if the class instantiation didn't result in the expected * type. */ function &instantiate($fullyQualifiedClassName, $expectedTypes = null, $expectedPackages = null, $expectedMethods = null, $constructorArg = null) { $errorFlag = false; // Validate the class name if (!String::regexp_match('/^[a-zA-Z0-9.]+$/', $fullyQualifiedClassName)) { return $errorFlag; } // Validate the class package if (!is_null($expectedPackages)) { if (is_scalar($expectedPackages)) { $expectedPackages = array($expectedPackages); } $validPackage = false; foreach ($expectedPackages as $expectedPackage) { // No need to use String class here as class names are always US-ASCII if (substr($fullyQualifiedClassName, 0, strlen($expectedPackage) + 1) == $expectedPackage . '.') { $validPackage = true; break; } } // Raise a fatal error if the class does not belong // to any of the expected packages. This is to prevent // certain types of code inclusion attacks. if (!$validPackage) { // Construct meaningful error message. $expectedPackageCount = count($expectedPackages); $separator = ''; foreach ($expectedPackages as $expectedPackageIndex => $expectedPackage) { if ($expectedPackageIndex > 0) { $separator = $expectedPackageIndex == $expectedPackageCount - 1 ? ' or ' : ', '; } $expectedPackageString .= $separator . '"' . $expectedPackage . '"'; } fatalError('Trying to instantiate class "' . $fullyQualifiedClassName . '" which is not in any of the expected packages ' . $expectedPackageString . '.'); } } // Import the requested class import($fullyQualifiedClassName); // Identify the class name $fullyQualifiedClassNameParts = explode('.', $fullyQualifiedClassName); $className = array_pop($fullyQualifiedClassNameParts); // Type check I: The requested class should be declared by now. if (!class_exists($className)) { fatalError('Cannot instantiate class. Class "' . $className . '" is not declared in "' . $fullyQualifiedClassName . '".'); } // Check that the expected operation exists for the class. if (!is_null($expectedMethods)) { if (is_scalar($expectedMethods)) { $expectedMethods = array($expectedMethods); } // Lower case comparison for PHP4 compatibility. // We don't need the String class here as method names are // always US-ASCII. $declaredMethods = array_map('strtolower', get_class_methods($className)); foreach ($expectedMethods as $expectedMethod) { $requiredMethod = strtolower($expectedMethod); if (!in_array($requiredMethod, $declaredMethods)) { return $errorFlag; } } } // Instantiate the requested class if (is_null($constructorArg)) { $classInstance = new $className(); } else { $classInstance = new $className($constructorArg); } // Type check II: The object must conform to the given interface (if any). if (!is_null($expectedTypes)) { if (is_scalar($expectedTypes)) { $expectedTypes = array($expectedTypes); } $validType = false; foreach ($expectedTypes as $expectedType) { if (is_a($classInstance, $expectedType)) { $validType = true; break; } } if (!$validType) { return $errorFlag; } } return $classInstance; }
/** * Determine whether a user agent is a bot or not using an external * list of regular expressions. */ function isBot() { static $isBot; if (!isset($isBot)) { $userAgent = Request::getUserAgent(); $isBot = false; $userAgentsFile = Config::getVar('general', 'registry_dir') . DIRECTORY_SEPARATOR . 'botAgents.txt'; $regexps = array_filter(file($userAgentsFile), create_function('&$a', 'return ($a = trim($a)) && !empty($a) && $a[0] != \'#\';')); foreach ($regexps as $regexp) { if (String::regexp_match($regexp, $userAgent)) { $isBot = true; return $isBot; } } } return $isBot; }
/** * Determine whether a user agent is a bot or not using an external * list of regular expressions. */ function isBot() { $_this =& PKPRequest::_checkThis(); static $isBot; if (!isset($isBot)) { $userAgent = $_this->getUserAgent(); $isBot = false; $regexps = array_filter(file(USER_AGENTS_FILE), create_function('&$a', 'return ($a = trim($a)) && !empty($a) && $a[0] != \'#\';')); foreach ($regexps as $regexp) { if (String::regexp_match($regexp, $userAgent)) { $isBot = true; return $isBot; } } } return $isBot; }