static public regexp_match ( $pattern, $subject ) : integer | ||
$pattern | string Regular expression | |
$subject | string String to apply regular expression to | |
return | integer |
/** * @copydoc Filter::process() * @param $citationString string * @return MetadataDescription */ function &process(&$input) { $nullVar = null; $queryParams = array('demo' => '3', 'textlines' => $input); // 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 (!PKPString::regexp_match('/.*<algorithm[^>]+>.*<\\/algorithm>.*/s', $result)) { $translationParams = array('filterName' => $this->getDisplayName()); $this->addError(__('submission.citations.filter.webserviceResultTransformationError', $translationParams)); return $nullVar; } // Screen-scrape the tagged portion and turn it into XML. $xmlResult = PKPString::regexp_replace('/.*<algorithm[^>]+>(.*)<\\/algorithm>.*/s', '\\1', $result); $xmlResult = PKPString::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 (!PKPString::regexp_match('/^[a-z][a-zA-Z0-9]+$/', $typeNameParts[0])) { return false; } // Translate the validator name into a validator class name. $this->_validatorClassName = 'Validator' . PKPString::ucfirst($typeNameParts[0]); return true; }
/** * 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 (PKPString::regexp_match('#HTTP/.*100#', $header)); // Check whether we got a tar file. if (PKPString::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; PKPString::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; }
/** * @verbatim * Helper method that configures and optionally * installs a filter based on the given XML node * which represents a <filter> element. * @endverbatim * @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 (PKPString::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; }
/** * 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_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(); PKPString::regexp_match_get('#<faultstring>([^<]*)</faultstring>#', $response, $matches); if (empty($matches)) { if ($attachment) { assert(PKPString::regexp_match('#<returnCode>success</returnCode>#', $response)); } else { $parts = explode("\r\n\r\n", $response); $result = array_pop($parts); $result = PKPString::regexp_replace('/>[^>]*$/', '>', $result); } } else { $result = 'mEDRA: ' . $status . ' - ' . $matches[1]; } } else { $result = 'OJS-mEDRA: Expected string response.'; } return $result; }
/** * 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 = PKPString::strlen($personsString); $personsString = PKPString::regexp_replace('/et ?al$/', '', $personsString); $etAl = $personsStringBeforeEtal == PKPString::strlen($personsString) ? false : true; // Remove punctuation. $personsString = trim($personsString, ':;, '); // Cut the authors string into pieces. $personStrings = PKPString::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 = PKPString::regexp_match($complexPersonsPattern[0], $personsString)) { // Retrieve names. $success = PKPString::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; }
/** * 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 (PKPString::regexp_match('!^[-A-Za-z0-9\\!#\\$%&\'\\*\\+\\/=\\?\\^_\\`\\{\\|\\}~]+$!', $displayName)) { return $displayName; } return '"' . ($send ? PKPString::encode_mime_header(str_replace(array('"', '\\'), '', $displayName)) : str_replace(array('"', '\\'), '', $displayName)) . '"'; }
/** * 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 (!PKPString::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 (!PKPString::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; 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 (PKPString::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 (!PKPString::regexp_match('/^[a-z0-9-]*$/', $rpcServiceEndpointPart)) { return null; } } return $rpcServiceEndpointParts; }
/** * 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) { $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 (!PKPString::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 null; } } else { return $pluginVersion; } }