Browse Source

initial commit of ebsco php library files

d9
ppound 3 years ago
parent
commit
1b8f5e8180
  1. 818
      modules/roblib_search_eds/src/Lib/EBSCOAPI.php
  2. 577
      modules/roblib_search_eds/src/Lib/EBSCOConnector.php
  3. 1050
      modules/roblib_search_eds/src/Lib/EBSCODocument.php
  4. 528
      modules/roblib_search_eds/src/Lib/EBSCORecord.php
  5. 1036
      modules/roblib_search_eds/src/Lib/EBSCOResponse.php
  6. 14
      modules/roblib_search_eds/src/Lib/RoblibEBSCOAPI.php
  7. 446
      modules/roblib_search_eds/src/Lib/sanitizer.class.php

818
modules/roblib_search_eds/src/Lib/EBSCOAPI.php

@ -0,0 +1,818 @@
<?php
namespace Drupal\roblib_search_eds\Lib;
/**
* @file
* The EBSCO EDS API class.
*
* PHP version 5
*
*
* Copyright [2017] [EBSCO Information Services]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use Drupal\roblib_search_eds\Lib\EBSCOConnector;
use Drupal\roblib_search_eds\Lib\EBSCOResponse;
/**
* EBSCO API class.
*/
class EBSCOAPI {
/**
* The authentication token used for API transactions.
*
* @global string
*/
private $authenticationToken;
/**
* The session token for API transactions.
*
* @global string
*/
private $sessionToken;
/**
* The EBSCOConnector object used for API transactions.
*
* @global object EBSCOConnector
*/
private $connector;
/**
* Configuration options.
*/
protected $config;
/**
* VuFind search types mapped to EBSCO search types
* used for urls in search results / detailed result.
*
* @global array
*/
private static $search_tags = array(
'' => '',
'AllFields' => '',
'Abstract' => 'AB',
'Author' => 'AU',
'Source' => 'SO',
'Subject' => 'SU',
'Title' => 'TI',
'ISBN' => 'IB',
'ISSN' => 'IS',
);
/**
* EBSCO sort options .
*
* @global array
*/
private static $sort_options = array(
'relevance',
'date',
'date2',
'source',
);
/**
* VuFind sort types mapped to EBSCO sort types
* used for urls in Search results / Detailed view.
*
* @global array
*/
private static $mapped_sort_options = array(
'' => 'relevance',
'relevance' => 'relevance',
'subject' => 'date',
'date' => 'date2',
'date_asc' => 'date2',
'date_desc' => 'date',
'callnumber' => 'date',
'author' => 'author',
'title' => 'date',
);
/**
* Constructor.
*
* @param array config
*
* @access public
*/
public function __construct($config) {
$this->config = $config;
}
/**
* Setter / Getter for authentication token.
*
* @param string The authentication token
*
* @return string or none
*
* @access public
*/
public function authenticationToken(){
$autocompleteTokenTimeOut = time();
$authenticationTimeout = 0;
//$authenticationTimeout;
// $autocompleteUrl = '';
// $token = '';
// $timeout = '';
// $autoToken = '';
// //$autocompleteTokenTimeOut = '';
// //$autocompleteTokenTimeOut;
// $autocompleteTokenTimeOut = 0;
// $autocompleteCustId ='';
if (isset($_SESSION["authenticationToken"])){
$token = $_SESSION["authenticationToken"];
$authenticationTimeout = $_SESSION["authenticationTimeout"]-600;
$timeout = $_SESSION["authenticationTimeout"];
$autocompleteUrl = $_SESSION["autocompleteUrl"];
$autoToken = $_SESSION["autocompleteToken"];
$autocompleteTokenTimeOut = $_SESSION["autocompleteTokenTimeOut"];
$autocompleteCustId = $_SESSION["autocompleteCustId"];
}else{
$result = $this->apiAuthenticationToken();
$_SESSION["authenticationToken"]= $result['authenticationToken'];
$_SESSION["authenticationTimeout"]= $result['authenticationTimeout'];
$_SESSION['autocompleteUrl'] = $result['autocompleteUrl'];
$_SESSION['autocompleteToken'] = $result['autocompleteToken'];
$_SESSION["autocompleteTokenTimeOut"]= $result['autocompleteTokenTimeOut'];
$_SESSION['autocompleteCustId'] = $result['autocompleteCustId'];
}
if(time()-$autocompleteTokenTimeOut >= $authenticationTimeout){
$result = $this->apiAuthenticationToken();
$_SESSION["authenticationToken"]= $result['authenticationToken'];
$_SESSION["authenticationTimeout"]= $result['authenticationTimeout'];
$_SESSION['autocompleteUrl'] = $result['autocompleteUrl'];
$_SESSION['autocompleteToken'] = $result['autocompleteToken'];
$_SESSION["autocompleteTokenTimeOut"]= $result['autocompleteTokenTimeOut'];
$_SESSION['autocompleteCustId'] = $result['autocompleteCustId'];
$result = array(
'authenticationToken' => $token,
'authenticationTimeout' => $timeout,
'autocompleteUrl' => $autocompleteUrl,
'autocompleteToken' => $autoToken,
'autocompleteTokenTimeOut' => $autocompleteTokenTimeOut,
'autocompleteCustId' => $autocompleteCustId
);
return $result['authenticationToken'];
}else{
return $this->token;
}
}
/**
* Setter / Getter for session token.
*
* @param string The session token
*
* @return string or none
*
* @access public
*/
public function sessionToken($token = NULL) {
if (empty($token)) {
$token = $this->readSession('sessionToken');
return !empty($token) ? $token : $this->sessionToken;
}
else {
$this->sessionToken = $token;
$this->writeSession('sessionToken', $token);
}
}
/**
* Getter for isGuest.
*
* @param string 'y' or 'n'
*
* @return string or none
*
* @access public
*/
public function isGuest($boolean = NULL) {
if (empty($boolean)) {
return $this->readSession('isGuest');
}
else {
$this->writeSession('isGuest', $boolean);
}
}
/**
* Create a new EBSCOConnector object or reuse an existing one.
*
* @param none
*
* @return EBSCOConnector object
*
* @access public
*/
public function connector() {
if (empty($this->connector)) {
$this->connector = new EBSCOConnector($this->config);
}
return $this->connector;
}
/**
* Create a new EBSCOResponse object.
*
* @param object $response
*
* @return EBSCOResponse object
*
* @access public
*/
public function response($response) {
$responseObj = new EBSCOResponse($response);
return $responseObj;
}
/**
* Request authentication and session tokens, then send the API request.
* Retry the request if authentication errors occur.
*
* @param string $action
* The EBSCOConnector method name.
* @param array $params
* The parameters of the HTTP request.
* @param int $attempts
* The number of retries.
*
* @return object SimpleXml DOM or PEAR Error
*
* @access protected
*/
protected function request($action, $params = NULL, $attempts = 5) {
$authenticationToken = $this->authenticationToken();
$sessionToken = $this->sessionToken();
// If authentication token is missing then the session token is missing too, so get both tokens
// If session token is missing then the authentication token may be invalid, so get both tokens.
if (empty($authenticationToken) || empty($sessionToken)) {
$result = $this->apiAuthenticationAndSessionToken();
if ($this->isError($result)) {
// Any error should terminate the request immediately
// in order to prevent infinite recursion.
return $result;
}
}
// Any change of the isGuest should request a new session
// (and don't terminate the current request if there was an error during the session request
// since it's not that important)
if ($this->isGuest() != $this->connector()->isGuest()) {
$this->apiSessionToken();
}
$headers = array(
'x-authenticationToken: '.$this->authenticationToken(),
'x-sessionToken: '.$this->sessionToken(),
);
$response = call_user_func_array(array($this->connector(), "request{$action}"), array($params, $headers));
if ($this->isError($response)) {
// Retry the request if there were authentication errors.
$code = $response->getCode();
switch ($code) {
// If authentication token is invalid then the session token is invalid too, so get both tokens
// If session token is invalid then the authentication token may be invalid too, so get both tokens.
case EBSCOConnector::EDS_AUTH_TOKEN_INVALID:
$result = $this->apiAuthenticationToken();
if ($this->isError($result)) {
// Any error should terminate the request immediately
// in order to prevent infinite recursion.
return $result;
}
if ($attempts > 0) {
$result = $this->request($action, $params, --$attempts);
}
break;
case EBSCOConnector::EDS_SESSION_TOKEN_INVALID:
$result = $this->apiAuthenticationAndSessionToken();
if ($this->isError($result)) {
// Any error should terminate the request immediately
// in order to prevent infinite recursion.
return $result;
}
if ($attempts > 0) {
$result = $this->request($action, $params, --$attempts);
}
break;
default:
$result = $this->handleError($response);
break;
}
}
else {
$result = $this->response($response)->result();
}
return $result;
}
/**
* Wrapper for authentication API call.
*
* @param none
*
* @access public
*/
public function apiAuthenticationToken() {
$response = $this->connector()->requestAuthenticationToken();
$result = $this->response($response)->result();
return $result;
}
/**
* Wrapper for session API call.
*
* @param none
*
* @access public
*/
public function apiSessionToken() {
// Add authentication tokens to headers.
$headers = array(
'x-authenticationToken: '.$this->authenticationToken(),
);
$response = $this->connector()->requestSessionToken($headers);
// Raise the exception so that any code running this method should exit immediately.
if ($this->isError($response)) {
return $response;
}
else {
$result = $this->response($response)->result();
if (is_string($result)) {
$this->sessionToken($result);
return $result;
}
else {
return new EBSCOException("No session token was found in the response.");
}
}
}
/**
* Initialize the authentication and session tokens.
*
* @param none
*
* @access public
*/
public function apiAuthenticationAndSessionToken() {
$authenticationToken = $this->apiAuthenticationToken();
if ($this->isError($authenticationToken)) {
// An authentication error should terminate the request immediately.
return $authenticationToken;
}
$sessionToken = $this->apiSessionToken();
if ($this->isError($sessionToken)) {
// A session error should terminate the request immediately.
return $sessionToken;
}
// We don't have to return anything, both tokens can be accessed using the getters.
return TRUE;
}
/**
* Wrapper for search API call.
*
* @param array $search
* The search terms.
* @param array $filters
* The facet filters.
* @param string $start
* The page to start with.
* @param string $limit
* The number of records to return.
* @param string $sortBy
* The value to be used by for sorting.
* @param string $amount
* The amount of data to be returned.
* @param string $mode
* The search mode.
*
* @throws object PEAR Error
*
* @return array An array of query results
*
* @access public
*/
public function apiSearch($search,
$filters,
$start = 1,
$limit = 10,
$sortBy = 'relevance',
$amount = 'detailed',
$mode = 'all',
$rs = FALSE,
$emp = FALSE,
$autosuggest = FALSE,
$includeimagequickview = FALSE,
$styles = '',
$IllustrationInfo = FALSE,
$autoComplete = FALSE
) {
$query = array();
// Basic search.
if (!empty($search['lookfor'])) {
$lookfor = $search['lookfor'];
$type = isset($search['index']) && !empty($search['index']) ? $search['index'] : 'AllFields';
// Escape some characters from lookfor term.
$term = str_replace(array(',', ':', '(', ')'), array('\,', '\:', '\(', '\)'), $lookfor);
// Replace multiple consecutive empty spaces with one empty space.
$term = preg_replace("/\s+/", ' ', $term);
// Search terms
// Complex search term.
if (preg_match('/(.*) (AND|OR) (.*)/i', $term)) {
$query['query'] = $term;
}
else {
$tag = self::$search_tags[$type];
$op = 'AND';
$query_str = implode(',', array($op, $tag));
$query_str = implode(($tag ? ':' : ''), array($query_str, $term));
$query['query-1'] = $query_str;
}
// Advanced search.
}
elseif (!empty($search['group'])) {
$counter = 1;
foreach ($search['group'] as $group) {
$type = $group['type'];
if (isset($group['lookfor'])) {
$term = $group['lookfor'];
$op = isset($group['bool'])?$group['bool']:"AND";
$tag = $type && isset(self::$search_tags[$type]) ? self::$search_tags[$type] : '';
// Escape some characters from lookfor term.
$term = str_replace(array(',', ':', '(', ')'), array('\,', '\:', '\(', '\)'), $term);
// Replace multiple consecutive empty spaces with one empty space.
$term = preg_replace("/\s+/", ' ', $term);
if (!empty($term)) {
$query_str = implode(',', array($op, $tag));
$query_str = implode(($tag ? ':' : ''), array($query_str, $term));
$query["query-$counter"] = $query_str;
$counter++;
}
}
}
// No search term, return an empty array.
}
else {
$results = array(
'recordCount' => 0,
'numFound' => 0,
'start' => 0,
'documents' => array(),
'facets' => array(),
);
return $results;
}
// Add filters.
$limiters = array(); $expanders = array(); $facets = array();
foreach ($filters as $filter) {
if (preg_match('/addlimiter/', $filter)) {
list($action, $str) = explode('(', $filter, 2);
// e.g. FT:y or GZ:Student Research, Projects and Publications.
$field_and_value = substr($str, 0, -1);
list($field, $value) = explode(':', $field_and_value, 2);
$limiters[$field][] = $value;
}
elseif (preg_match('/addexpander/', $filter)) {
list($action, $str) = explode('(', $filter, 2);
// Expanders don't have value.
$field = substr($str, 0, -1);
$expanders[] = $field;
}
elseif (preg_match('/addfacetfilter/', $filter)) {
list($action, $str) = explode('(', $filter, 2);
// e.g. ZG:FRANCE.
$field_and_value = substr($str, 0, -1);
list($field, $value) = explode(':', $field_and_value, 2);
$facets[$field][] = $field_and_value;
}
}
if (!empty($limiters)) {
$query['limiter']='';
foreach ($limiters as $field => $limiter) {
// e.g. LA99:English,French,German.
$query['limiter'].= $field . ':' . implode(',', $limiter);
}
}
if (!empty($expanders)) {
// e.g. fulltext, thesaurus.
$query['expander'] = implode(',', $expanders);
}
if (!empty($facets)) {
$groupId = 1;
foreach ($facets as $field => $facet) {
// e.g. 1,DE:Math,DE:History.
$query['facetfilter'] = $groupId . ',' . implode(',', $facet);
$groupId += 1;
}
}
// 2014-03-26 - new action to jump to page.
if ($start > 1) {
$query['action'] = "GoToPage(" . $start . ")";
}
// Add the sort option.
$sortBy = in_array($sortBy, self::$sort_options) ? $sortBy : self::$mapped_sort_options[$sortBy];
// Add the HTTP query params.
$params = array(
// Specifies the sort. Valid options are:
// relevance, date, date2
// date = Date descending
// date2 = Date ascending.
'sort' => $sortBy,
// Specifies the search mode. Valid options are:
// bool, any, all, smart.
'searchmode' => $mode,
// Specifies the amount of data to return with the response
// Valid options are:
// title: Title only
// brief: Title + Source, Subjects
// detailed: Brief + full abstract.
'view' => $amount,
// Specifies whether or not to include facets.
'includefacets' => 'y',
'resultsperpage' => $limit,
// 2014-03-26 RF.
'pagenumber' => $start,
// 'pagenumber' => 1,
// Specifies whether or not to include highlighting in the search results.
'highlight' => 'y',
'includeimagequickview' => $includeimagequickview,
'format' => 'ris',
'styles' => $styles,
);
if ($autosuggest == TRUE) {
$params["autosuggest"] = "y";
}
if ($rs == TRUE) {
$params["relatedcontent"] = "rs";
}
if ($emp == TRUE) {
if (isset($params["relatedcontent"])) {
$params["relatedcontent"] .= ",emp";
}
else {
$params["relatedcontent"] = "emp";
}
}
if ($includeimagequickview == TRUE) {
$params["includeimagequickview"] = "y";
}
if ($styles == 'all') {
$params["styles"] = "all";
}
if ($autoComplete == TRUE) {
$params["autocomplete"] = "y";
}
$params = array_merge($params, $query);
$result = $this->request('Search', $params);
return $result;
}
/**
* Wrapper for retrieve API call.
*
* @param array $an
* The accession number.
* @param string $start
* The short database name.
*
* @throws object PEAR Error
*
* @return array An associative array of data
*
* @access public
*/
public function apiRetrieve($an, $db) {
// Add the HTTP query params.
//$includeimagequickviewDetail = FALSE;
$params = array(
'an' => $an,
'dbid' => $db,
'highlight' => 'y',
//'includeimagequickview' => $includeimagequickviewDetail,
//'IllustrationInfo' => 'y',
'IllustrationInfo' => $IllustrationInfo,
'format' => 'ris',
'styles' => $styles,
);
$result = $this->request('Retrieve', $params);
return $result;
}
public function apiExport($an, $db) {
$params = array(
'an' => $an,
'dbid' => $db,
'format' => 'ris'
);
$result = $this->request('Export', $params);
return $result;
}
public function apiCitationStyles($an, $db, $styles) {
$params = array(
'an' => $an,
'dbid' => $db,
'styles' => $styles
);
$result = $this->request('CitationStyles', $params);
return $result;
}
/**
* Wrapper for info API call.
*
* @throws object PEAR Error
*
* @return array An associative array of data
*
* @access public
*/
public function apiInfo() {
if ($result = $this->readSession('info')) {
return $result;
}
$result = $this->request('Info');
if (!$this->isError($result)) {
$this->writeSession('info', $result);
}
return $result;
}
public function apiAutoComplete(){
if(self::$autocomplete == 'y'){
// var_dump($autocomplete);
// die();
return true;
}
else{
return false;
}
}
/**
* Handle a PEAR_Error. Return :
* - if the error is critical : an associative array with the current error message
* - if the error is not critical : the error message .
*
* @param Pear_Error $exception
*
* @return array or the Pear_Error exception
*
* @access protected
*/
private function handleError($error) {
$errorCode = $error->getCode();
switch ($errorCode) {
// This kind of error was generated by user , so display it to user.
case EBSCOConnector::EDS_INVALID_ARGUMENT_VALUE:
// Any other errors are system errors, don't display them to user.
default:
$errorMessage = 'An error occurred when getting the data.';
break;
}
$result = array(
'errors' => $errorMessage,
'recordCount' => 0,
'numFound' => 0,
'start' => 0,
'documents' => array(),
'facets' => array(),
);
return $result;
}
/**
* Store the given object into session.
*
* @param string $key
* The key used for reading the value.
* @param object $value
* The object stored in session.
*
* @return none
*
* @access protected
*/
protected function writeSession($key, $value) {
if (!empty($key) && !empty($value)) {
$_SESSION['EBSCO'][$key] = $value;
}
}
/**
* Read from session the object having the given key.
*
* @param string $key
* The key used for reading the object.
*
* @return object
*
* @access protected
*/
protected function readSession($key) {
$value = isset($_SESSION['EBSCO'][$key]) ? $_SESSION['EBSCO'][$key] : '';
return $value;
}
/**
* Check if given object is an EBSCOException object.
*
* @param object $object
*
* @return bool
*
* @access protected
*/
protected function isError($object) {
return is_a($object, 'EBSCOException');
}
}

577
modules/roblib_search_eds/src/Lib/EBSCOConnector.php

@ -0,0 +1,577 @@
<?php
namespace Drupal\roblib_search_eds\Lib;
/**
* @file
* The EBSCO Connector and Exception classes.
*
* Used when EBSCO API calls return error messages.
*
* Copyright [2017] [EBSCO Information Services]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* EBSCOException class.
*/
class EBSCOException extends \Exception {
const CRITICAL_ERROR = 1;
/**
* Make message argument mandatory.
*/
public function __construct($message, $code = self::CRITICAL_ERROR, Exception $previous = NULL) {
parent::__construct($message, $code, $previous);
}
}
/**
* EBSCOConnector class.
*/
class EBSCOConnector {
/**
* Error codes defined by EDS API.
*/
const EDS_UNKNOWN_PARAMETER = 100;
const EDS_INCORRECT_PARAMETER_FORMAT = 101;
const EDS_INVALID_PARAMETER_INDEX = 102;
const EDS_MISSING_PARAMETER = 103;
const EDS_AUTH_TOKEN_INVALID = 104;
const EDS_INCORRECT_ARGUMENTS_NUMBER = 105;
const EDS_UNKNOWN_ERROR = 106;
const EDS_AUTH_TOKEN_MISSING = 107;
const EDS_SESSION_TOKEN_MISSING = 108;
const EDS_SESSION_TOKEN_INVALID = 109;
const EDS_INVALID_RECORD_FORMAT = 110;
const EDS_UNKNOWN_ACTION = 111;
const EDS_INVALID_ARGUMENT_VALUE = 112;
const EDS_CREATE_SESSION_ERROR = 113;
const EDS_REQUIRED_DATA_MISSING = 114;
const EDS_TRANSACTION_LOGGING_ERROR = 115;
const EDS_DUPLICATE_PARAMETER = 116;
const EDS_UNABLE_TO_AUTHENTICATE = 117;
const EDS_SEARCH_ERROR = 118;
const EDS_INVALID_PAGE_SIZE = 119;
const EDS_SESSION_SAVE_ERROR = 120;
const EDS_SESSION_ENDING_ERROR = 121;
const EDS_CACHING_RESULTSET_ERROR = 122;
const EDS_INVALID_EXPANDER_ERROR = 123;
const EDS_INVALID_SEARCH_MODE_ERROR = 124;
const EDS_INVALID_LIMITER_ERROR = 125;
const EDS_INVALID_LIMITER_VALUE_ERROR = 126;
const EDS_UNSUPPORTED_PROFILE_ERROR = 127;
const EDS_PROFILE_NOT_SUPPORTED_ERROR = 128;
const EDS_INVALID_CONTENT_PROVIDER_ERROR = 129;
const EDS_INVALID_SOURCE_TYPE_ERROR = 130;
const EDS_XSLT_ERROR = 131;
const EDS_RECORD_NOT_FOUND_ERROR = 132;
const EDS_SIMULTANEOUS_USER_LIMIT_ERROR = 133;
const EDS_NO_GUEST_ACCESS_ERROR = 134;
const EDS_DBID_NOT_IN_PROFILE_ERROR = 135;
const EDS_INVALID_SEARCH_VIEW_ERROR = 136;
const EDS_RETRIEVING_FULL_TEXT_ERROR = 137;
/**
* HTTP status codes constants
* https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html.
*
* @global integer HTTP_OK The request has succeeded
* @global integer HTTP_NOT_FOUND The server has not found anything matching the Request-URI
*/
const HTTP_OK = 200;
const HTTP_BAD_REQUEST = 400;
const HTTP_NOT_FOUND = 404;
const HTTP_INTERNAL_SERVER_ERROR = 500;
/**
* The HTTP_Request object used for API transactions.
*
* @global object HTTP_Request
*/
private $client;
/**
* The URL of the EBSCO API server.
*
* @global string
*/
private static $end_point = 'https://eds-api.ebscohost.com/EDSAPI/rest';
/**
* The URL of the EBSCO API server.
*
* @global string
*/
private static $authentication_end_point = 'https://eds-api.ebscohost.com/AuthService/rest';
/**
* The password used for API transactions.
*
* @global string
*/
private $password;
/**
* The user id used for API transactions.
*
* @global string
*/
private $userId;
/**
* The profile ID used for API transactions.
*
* @global string
*/
private $profileId;
/**
* The interface ID used for API transactions.
*
* @global string
*/
private $interfaceId;
/**
* The customer ID used for API transactions.
*
* @global string
*/
private $orgId;
/**
* The isGuest used for API transactions.
*
* @global string 'y' or 'n'
*/
private $isGuest;
/**
* Contains the list of ip addresses.
*
* @global string
*/
private $local_ip_address;
/**
* You can log HTTP_Request requests using this option.
*
* @global bool logAPIRequests
*/
private $logAPIRequests;
/**
* Autocomplete
* @global string
*/
private $autoComplete;
/**
* The logger object.
*
* @global object Logger
*/
//private $logger;
/**
* Constructor.
*
* Sets up the EBSCO API settings.
*
* @param none
*
* @access public
*/
public function __construct($config) {
$this->password = $config['password'];
$this->userId = $config['user'];
$this->interfaceId = $config['interface'];
$this->profileId = $config['profile'];
$this->autoComplete = $config['autocomplete'];
$this->orgId = $config['organization'];
$this->local_ip_address = $config['local_ip_address'];
$this->isGuest = (\Drupal::currentUser()->isAuthenticated() || $this->isGuestIPAddress($_SERVER["REMOTE_ADDR"])) ? 'n' : 'y';
$this->logAPIRequests = ($config['log'] == 1);
}
/**
* Detects if the user is authorized based on the IP address.
*
* @return string
*/
public function isGuestIPAddress($ipUser) {
$s = $this->local_ip_address;
if (trim($s) == "") {
return FALSE;
}
// Break records.
$m = explode(",", $s);
foreach ($m as $ip) {
if (strcmp(substr($ipUser, 0, strlen(trim($ip))), trim($ip)) == 0) {
// Inside of ip address range of customer.
return TRUE;
}
}
return FALSE;
}
/**
* Public getter for private isGuest .
*
* @param none
*
* @return string isGuest
*
* @access public
*/
public function isGuest() {
return $this->isGuest;
}
/**
* Request the authentication token.
*
* @param none
*
* @return object SimpleXml or PEAR_Error
*
* @access public
*/
public function requestAuthenticationToken() {
$url = self::$authentication_end_point . '/uidauth';
// Add the body of the request.
$params = '<UIDAuthRequestMessage xmlns="https://www.ebscohost.com/services/public/AuthService/Response/2012/06/01">'
.'<UserId>'.$this->userId.'</UserId>'
.'<Password>'.$this->password.'</Password>'
.'<InterfaceId>wsapi</InterfaceId>'
.'<Options>
<Option>'.$this->autoComplete.'</Option>
</Options>'
.'</UIDAuthRequestMessage>';
$response = $this->request($url,$params, array(), 'POST');
return $response;
}
/**
* Request the session token.
*
* @param array $headers
* Authentication token.
*
* @return object SimpleXml or PEAR_Error
*
* @access public
*/
public function requestSessionToken($headers) {
$url = self::$end_point . '/CreateSession';
// Add the HTTP query params.
$params = array(
'profile' => $this->profileId,
'org' => $this->orgId,
'guest' => $this->isGuest
);
$response = $this->request($url, $params, $headers);
return $response;
}
/**
* Request the search records.
*
* @param array $params
* Search specific parameters.
* @param array $headers
* Authentication and session tokens.
*
* @return object SimpleXml or PEAR_Error
*
* @access public
*/
public function requestSearch($params, $headers) {
$url = self::$end_point . '/Search';
$response = $this->request($url, $params, $headers);
return $response;
}
/**
* Request a specific record.
*
* @param array $params
* Retrieve specific parameters.
* @param array $headers
* Authentication and session tokens.
*
* @return object SimpleXml or PEAR_Error
*
* @access public
*/
public function requestRetrieve($params, $headers) {
$url = self::$end_point . '/Retrieve';
$response = $this->request($url, $params, $headers);
return $response;
}
/**
* Export a specific record.
*
* @param array $params
* Export specific parameters.
* @param array $headers
* Authentication and session tokens.
*
* @return object SimpleXml or PEAR_Error
*
* @access public
*/
public function requestExport($params, $headers) {
$url = self::$end_point . '/ExportFormat';
$response = $this->request($url, $params, $headers);
return $response;
}
/**
* CitationStyles a specific record.
*
* @param array $params
* CitationStyles specific parameters.
* @param array $headers
* Authentication and session tokens.
*
* @return object SimpleXml or PEAR_Error
*
* @access public
*/
public function requestCitationStyles($params, $headers) {
$url = self::$end_point . '/CitationStyles';
$responseCitation = $this->request($url, $params, $headers);
$response = $responseCitation->Citations;
return $response;
}
/**
* Request the info data.
*
* @param null $params
* Not used.
* @param array $headers
* Authentication and session tokens.
*
* @return object SimpleXml or PEAR_Error
*
* @access public
*/
public function requestInfo($params, $headers) {
$url = self::$end_point . '/Info';
$response = $this->request($url, $params, $headers);
return $response;
}
/**
* Send an HTTP request and inspect the response.
*
* @param string $url
* The url of the HTTP request.
* @param array $params
* The parameters of the HTTP request.
* @param array $headers
* The headers of the HTTP request.
* @param array $body
* The body of the HTTP request.
* @param string $method
* The HTTP method, default is 'GET'.
*
* @return object SimpleXml or PEAR_Error
*
* @access protected
*/
protected function request($url, $params, $headers = array(), $method = 'GET') {
$xml = FALSE;
$return = FALSE;
$data = NULL;
// Add compression in case its not there.
array_push($headers, 'Content-Type: text/xml');
$data=$params;
// Send the request.
$response=null;
try {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_MAXREDIRS, 10 );
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
switch ($method)
{
case 'GET':
if ($data) { $url = sprintf('%s?%s', $url, http_build_query($data)); }
curl_setopt($curl, CURLOPT_URL, $url);
break;
case 'POST':
if ($data) {
curl_setopt($curl,CURLOPT_POST, 1);
curl_setopt($curl,CURLOPT_POSTFIELDS, $data);
}
break;
case 'DELETE':
if ($data) {
if (count($headers)>0) {
curl_setopt($curl,CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
}
break;
}
$response = curl_exec($curl);
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
switch ($code) {
case self::HTTP_OK:
$xml_str = $response;
try {
// Clean EMP namespace.
$xml_str = str_replace(array("<a:", "</a:"), array("<", "</"), $xml_str);
$xml = simplexml_load_string($xml_str);
$return = $xml;
}
catch (Exception $e) {
$return = new EBSCOException($xml);
}
break;
case self::HTTP_BAD_REQUEST:
$xml_str = $response;
try {
$xml = simplexml_load_string($xml_str);
// If the response is an API error.
$isError = isset($xml->ErrorNumber) || isset($xml->ErrorCode);
if ($isError) {
$error = ''; $code = 0;
if (isset($xml->DetailedErrorDescription) && !empty($xml->DetailedErrorDescription)) {
$error = (string) $xml->DetailedErrorDescription;
}
elseif (isset($xml->ErrorDescription)) {
$error = (string) $xml->ErrorDescription;
}
elseif (isset($xml->Reason)) {
$error = (string) $xml->Reason;
}
if (isset($xml->ErrorNumber)) {
$code = (integer) $xml->ErrorNumber;
}
elseif (isset($xml->ErrorCode)) {
$code = (integer) $xml->ErrorCode;
}
$return = new EBSCOException($error, $code);
}
else {
$return = new EBSCOException("HTTP {$code} : The request could not be understood by the server due to malformed syntax. Modify your search before retrying.");
}
}
catch (Exception $e) {
$return = new EBSCOException($xml);
}
break;
case self::HTTP_NOT_FOUND:
$return = new EBSCOException("HTTP {$code} : The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable.");
break;
case self::HTTP_INTERNAL_SERVER_ERROR:
$return = new EBSCOException("HTTP {$code} : The server encountered an unexpected condition which prevented it from fulfilling the request.");
break;
default:
$return = new EBSCOException("HTTP {$code} : Unexpected HTTP error.");
break;
}
}
catch (Exception $e) {
// Or $this->toString($response)
$message = $this->toString($e);
\Drupal::logger('ebsco')->error($message);
$return = new EBSCOException($response);
}
// Log any error
if ($this->logAPIRequests) {
// $client = both the HTTP request and response
// $response = only the HTTP response
$message = $this->toString($client); // or $this->toString($response)
\Drupal::logger('ebsco')->error($client);
}
return $return;
}
/**
* Capture the output of print_r into a string.
*
* @param object Any object
*
* @access private
*/
private function toString($object) {
ob_start();
print_r($object);
return ob_get_clean();
}
}

1050
modules/roblib_search_eds/src/Lib/EBSCODocument.php

File diff suppressed because it is too large Load Diff

528
modules/roblib_search_eds/src/Lib/EBSCORecord.php

@ -0,0 +1,528 @@
<?php
namespace Drupal\roblib_search_eds\Lib;
/**
* @file
* The EBSCO record object.
*
* PHP version 5
*
* Copyright [2017] [EBSCO Information Services]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* EBSCORecord class.
*/
class EBSCORecord {
/**
* The array of data.
*
* @global array
*/
private $data = array();
/**
* The result id (the EBSCO counter) of the record.
*
* @global integer
*/
public $result_id = NULL;
/**
* The id of the record.
*
* @global integer
*/
public $record_id = NULL;
/**
* The summary of the record.
*
* @global string
*/
public $summary = NULL;
/**
* The authors of the record.
*
* @global string
*/
public $authors = NULL;
/**
* The subjects of the record.
*
* @global string
*/
public $subjects = NULL;
/**
* The custom links provided for the record.
*
* @global array
*/
public $custom_links = array();
/**
* The database label of the record.
*
* @global string
*/
public $db_label = NULL;
/**
* The full-text availability of the record.
*
* @global boolean
*/
public $full_text_availability = NULL;
/**
* The full text of the record.
*
* @global string
*/
public $full_text = NULL;
/**
* The PDF availability of the record.
*
* @global boolean
*/
public $pdf_availability = NULL;
/**
* The items of the record.
*
* @global array
*/
public $items = array();
/**
* The external link of the record.
*
* @global string
*/
public $p_link = NULL;
/**
* The external link to the PDF version of the record.
*
* @global string
*/
public $pdf_link = NULL;
/**
* The publication type link of the record.
*
* @global string
*/
public $publication_type = NULL;
/**
* The external thumbnails links of the record.
*
* @global string
*/
public $small_thumb_link = NULL;
public $medium_thumb_link = NULL;
/**
* The title of the record.
*
* @global string
*/
public $title = NULL;
/**
* The source of the record.
*
* @global string
*/
public $source = NULL;
/**
* The access level of the record.
*
* @global string
*/
public $access_level = NULL;
/**image quick view
* ImageQuickViewItems
*/
/**
* * @global string
*/
//public $image_quick_view_type = NULL;
public $image_quick_view = array();
public $image_quick_view_type_2 = array();
/**image quick view
* ImageQuickViewItems
*/
/**
* * @global string
*/
public $image_quick_url = NULL;
/* IllustrationInfo
*/
/**
* * @global string
*/
public $illustrationinfo = array();
/**
* Type to IQV
* * @global string
*/
public $type = NULL;
/**
* Cite to IQV
* * @global string
*/
public $cite = NULL;
/**
* Permission to IQV
* * @global string
*/
public $permission = NULL;
/**
* imgTitle to IQV
* * @global string
*/
public $imgtitle = NULL;
/**
*Citations styles
* * @global string
*/
public $citationStylesRecord = NULL;
/**
* Constructor.
*
* @param array $data
* Raw data from the EBSCO search representing the record.
*/
public function __construct($data = array()) {
$this->data = $data;
$this->record_id = $this->record_id();
$this->result_id = $this->result_id();
$this->title = $this->title();
$this->summary = $this->summary();
$this->authors = $this->authors();
$this->subjects = $this->subjects();
$this->custom_links = $this->custom_links();
$this->db_label = $this->db_label();
$this->full_text_availability = $this->full_text_availability();
$this->full_text = $this->full_text();
$this->items = $this->items();
$this->p_link = $this->p_link();
$this->publication_type = $this->publication_type();
$this->pdf_availability = $this->pdf_availability();
$this->pdf_link = $this->pdf_link();
$this->small_thumb_link = $this->thumb_link();
$this->medium_thumb_link = $this->thumb_link('medium');
$this->source = $this->source();
$this->access_level = $this->access_level();
$this->image_quick_view = $this->image_quick_view();
$this->image_quick_view_type_2 = $this->image_quick_view_type_2();
$this->image_quick_url = $this->image_quick_url();
$this->illustrationinfo = $this->illustrationinfo();
$this->type = $this->type();
$this->cite = $this->cite();
$this->permission = $this->permission();
$this->imgtitle = $this->imgtitle();
$this->citationStylesRecord = $this->citationStylesRecord();
}
/********************************************************
*
* Getters
*
********************************************************/
/**
* Get the summary of the record.
*
* @return string
*/
public function access_level() {
return isset($this->data['AccessLevel']) ?
$this->data['AccessLevel'] : '';
}
/**
* Get the summary of the record.
*
* @return string
*/
public function summary() {
return isset($this->data['Items']['Abstract']) ?
$this->data['Items']['Abstract']['Data'] : '';
}
/**
* Get the authors of the record.
*
* @return string
*/
public function authors() {
return isset($this->data['Items']['Author']) ?
$this->data['Items']['Author']['Data'] : '';
}
/**
* Get the custom links of the record.
*
* @return array
*/
public function custom_links() {
return isset($this->data['CustomLinks']) ?
$this->data['CustomLinks'] : array();
}
/**
* Get the database label of the record.
*
* @return string
*/
public function db_label() {
return isset($this->data['DbLabel']) ?
$this->data['DbLabel'] : '';
}
/**
* Get the full text availability of the record.
*
* @return bool
*/
public function full_text() {
return isset($this->data['FullText']) &&
isset($this->data['FullText']['Value']) ? $this->data['FullText']['Value'] : '';
}
/**
* Get the full text availability of the record.
*
* @return bool
*/
public function full_text_availability() {
return isset($this->data['FullText']) &&
$this->data['FullText']['Availability'];
}
/**
* Get the items of the record.
*
* @return array
*/
public function items() {
return isset($this->data['Items']) ? $this->data['Items'] : array();
}
/**
* Get the external url of the record.
*
* @return string
*/
public function p_link() {
return isset($this->data['PLink']) ? $this->data['PLink'] : '';
}
/**
* Get the publication type of the record.
*
* @return string
*/
public function publication_type() {
return isset($this->data['PubType']) ? $this->data['PubType'] : '';
}
/**
* Get the PDF availability of the record.
*
* @return bool
*/
public function pdf_availability() {
return isset($this->data['FullText']) &&
isset($this->data['FullText']['Links']) &&
isset($this->data['FullText']['Links']['pdflink']) &&
$this->data['FullText']['Links']['pdflink'];
}
/**
* Get the PDF url of the record.
*
* @return string
*/
public function pdf_link() {
return isset($this->data['FullText']) &&
isset($this->data['FullText']['Links']) &&
isset($this->data['FullText']['Links']['pdflink']) ?
$this->data['FullText']['Links']['pdflink'] :
'';
}
/**
* Get the result id of the record.
*
* @return int
*/
public function result_id() {
return isset($this->data['ResultId']) ?
$this->data['ResultId'] : '';
}
/**
* Get the subject data of the record.
*
* @return string
*/
public function subjects() {
return isset($this->data['Items']['Subject']) ?
$this->data['Items']['Subject']['Data'] : '';
}
/**
* Return a URL to a thumbnail preview of the record, if available; false
* otherwise.
*
* @param string $size
* Size of thumbnail (small, medium or large -- small is
* default).
*
* @return string
*/
public function thumb_link($size = 'small') {
$imageInfo = isset($this->data['ImageInfo']) ? $this->data['ImageInfo'] : '';
if ($imageInfo && isset($imageInfo['thumb'])) {
switch ($size) {
case 'large':
case 'medium':
return $imageInfo['medium'];
break;
case 'small':
default:
return $imageInfo['thumb'];
break;
}
}
return FALSE;
}
/**
* Get the title of the record.
*
* @return string
*/
public function title() {
return isset($this->data['Items']['Title']) ?
$this->data['Items']['Title']['Data'] : '';
}
/**
* Get the source of the record.
*
* @return string
*/
public function source() {
return isset($this->data['Items']['TitleSource']) ?
$this->data['Items']['TitleSource']['Data'] : '';
}
/**
* Return the identifier of this record within the EBSCO databases.
*
* @return string Unique identifier.
*/
public function record_id() {
return isset($this->data['id']) ?
$this->data['id'] : '';
}
/**
* Get the image quick view of the record.
*
* @return string
*/
public function image_quick_view() {
return isset($this->data['iqv']) ? $this->data['iqv'] : array();
}
public function image_quick_url() {
return isset($this->data['iqv']) ? $this->data['iqv'] : array();
}
public function image_quick_view_type_2() {
return isset($this->data['ImageQuickViewItems']) &&
isset($this->data['ImageQuickViewItems']['iqv']) &&
isset($this->data['ImageQuickViewItems']['iqv']['DbId']) &&
isset($this->data['ImageQuickViewItems']['iqv']['An']) &&
isset($this->data['ImageQuickViewItems']['iqv']['Type']) &&
isset($this->data['ImageQuickViewItems']['iqv']['Url']) ?
$this->data['ImageQuickViewItems']['iqv']['DbId']['An']['Type']['Url'] : '';
}
public function illustrationinfo() {
return isset($this->data['IllustrationInfo'][0]) ? $this->data['IllustrationInfo'][0] : array();
}
public function type() {
return isset($this->data['Items']['type']) ?
$this->data['Items']['type'] : '';
}
public function cite() {
return isset($this->data['Items']['Cite']) ?
$this->data['Items']['Cite'] : '';
}
public function permission() {
return isset($this->data['Items']['Permission']) ?
$this->data['Items']['Permission'] : '';
}
public function imgtitle() {
return isset($this->data['Items']['imgTitle']) ?
$this->data['Items']['imgTitle'] : '';
}
public function citationStylesRecord() {
return isset($this->data['Citation']) ? $this->data['Citation'] : array();
}
}

1036
modules/roblib_search_eds/src/Lib/EBSCOResponse.php

File diff suppressed because it is too large Load Diff

14
modules/roblib_search_eds/src/Lib/RoblibEBSCOAPI.php

@ -0,0 +1,14 @@
<?php
namespace Drupal\roblib_search_eds\Lib;
use Drupal\roblib_search_eds\Lib\EBSCOAPI;
/**
* Wrapper for the EBSCOAPI class that allows config to be set.
*
* @author ppound
*/
class RoblibEBSCOAPI extends EBSCOAPI{
public function setConfig($config) {
$this->config = $config;
}
}

446
modules/roblib_search_eds/src/Lib/sanitizer.class.php

@ -0,0 +1,446 @@
<?php
namespace Drupal\roblib_search_eds\Lib;
/**
* @file
* $Id$.
*/
// vim: expandtab sw=4 ts=4 sts=4:
// ***** BEGIN LICENSE BLOCK *****
// This file is part of HTML Sanitizer.
// Copyright (c) 2005-2011 Frederic Minne <zefredz@gmail.com>.
// All rights reserved.
//
// HTML Sanitizer is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// HTML Sanitizer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with HTML Sanitizer; if not, see <https://www.gnu.org/licenses/>.
//
// ***** END LICENSE BLOCK *****.
/**
* Sanitize HTML contents :
* Remove dangerous tags and attributes that can lead to security issues like
* XSS or HTTP response splitting.
*
* @author Frederic Minne <zefredz@gmail.com>
* @copyright Copyright &copy; 2005-2011, Frederic Minne
* @license https://www.gnu.org/licenses/lgpl.txt GNU Lesser General Public License version 3 or later
* @version 1.1
*/
class HTML_Sanitizer {
/**
* Private fields.
*/
private $_allowedTags;
private $_allowJavascriptEvents;
private $_allowJavascriptInUrls;
private $_allowObjects;
private $_allowScript;
private $_allowStyle;
private $_additionalTags;
/**
* Constructor.
*/
public function __construct() {
$this->resetAll();
}
/**
* (re)set all options to default value.
*/
public function resetAll() {
$this->_allowDOMEvents = FALSE;
$this->_allowJavascriptInUrls = FALSE;
$this->_allowStyle = FALSE;
$this->_allowScript = FALSE;
$this->_allowObjects = FALSE;
$this->_allowStyle = FALSE;
$this->_allowedTags = '<a><br><b><h1><h2><h3><h4><h5><h6>'
. '<img><li><ol><p><strong><table><tr><td><th><u><ul><thead>'
. '<tbody><tfoot><em><dd><dt><dl><span><div><del><add><i><hr>'
. '<pre><br><blockquote><address><code><caption><abbr><acronym>'
. '<cite><dfn><q><ins><sup><sub><kbd><samp><var><tt><small><big>';
$this->_additionalTags = '';
}
/**
* Add additional tags to allowed tags.
*
* @param string
*
* @access public
*/
public function addAdditionalTags($tags) {
$this->_additionalTags .= $tags;
}
/**
* Allow iframes.
*
* @access public
*/
public function allowIframes() {
$this->addAdditionalTags('<iframe>');
}
/**
* Allow HTML5 media tags.
*
* @access public
*/
public function allowHtml5Media() {
$this->addAdditionalTags('<canvas><video><audio>');
}
/**
* Allow object, embed, applet and param tags in html.
*
* @access public
*/
public function allowObjects() {
$this->_allowObjects = TRUE;
}
/**
* Allow DOM event on DOM elements.
*
* @access public
*/
public function allowDOMEvents() {
$this->_allowDOMEvents = TRUE;
}
/**
* Allow script tags.
*
* @access public
*/
public function allowScript() {
$this->_allowScript = TRUE;
}
/**
* Allow the use of javascript: in urls.
*
* @access public
*/
public function allowJavascriptInUrls() {
$this->_allowJavascriptInUrls = TRUE;
}
/**
* Allow style tags and attributes.
*
* @access public
*/
public function allowStyle() {
$this->_allowStyle = TRUE;
}
/**
* Helper to allow all javascript related tags and attributes.
*
* @access public
*/
public function allowAllJavascript() {
$this->allowDOMEvents();
$this->allowScript();
$this->allowJavascriptInUrls();
}
/**
* Allow all tags and attributes.
*
* @access public
*/
public function allowAll() {
$this->allowAllJavascript();
$this->allowObjects();
$this->allowStyle();
$this->allowIframes();
$this->allowHtml5Media();
}
/**
* Filter URLs to avoid HTTP response splitting attacks.
*
* @access public
* @param string url
*
* @return string filtered url
*/
public function filterHTTPResponseSplitting($url) {
$dangerousCharactersPattern = '~(\r\n|\r|\n|%0a|%0d|%0D|%0A)~';
return preg_replace($dangerousCharactersPattern, '', $url);
}
/**
* Remove potential javascript in urls.
*
* @access public
* @param string url
*
* @return string filtered url
*/
public function removeJavascriptURL($str) {
$HTML_Sanitizer_stripJavascriptURL = 'javascript:[^"]+';
$str = preg_replace("/$HTML_Sanitizer_stripJavascriptURL/i", '__forbidden__', $str);
return $str;
}
/**
* Remove potential flaws in urls.
*
* @access private
* @param string url
*
* @return string filtered url
*/
private function sanitizeURL($url) {
if (!$this->_allowJavascriptInUrls) {
$url = $this->removeJavascriptURL($url);
}
$url = $this->filterHTTPResponseSplitting($url);
return $url;
}
/**
* Callback for PCRE.
*
* @access private
* @param matches array
*
* @return string
*
* @see sanitizeURL
*/
private function _sanitizeURLCallback($matches) {
return 'href="' . $this->sanitizeURL($matches[1]) . '"';
}
/**
* Remove potential flaws in href attributes.
*
* @access private
* @param string html tag
*
* @return string filtered html tag
*/
private function sanitizeHref($str) {
$HTML_Sanitizer_URL = 'href="([^"]+)"';
return preg_replace_callback("/$HTML_Sanitizer_URL/i", array(&$this, '_sanitizeURLCallback'), $str);
}
/**
* Callback for PCRE.
*
* @access private
* @param matches array
*
* @return string
*
* @see sanitizeURL
*/
private function _sanitizeSrcCallback($matches) {
return 'src="' . $this->sanitizeURL($matches[1]) . '"';
}
/**
* Remove potential flaws in href attributes.
*
* @access private
* @param string html tag
*
* @return string filtered html tag
*/
private function sanitizeSrc($str) {
$HTML_Sanitizer_URL = 'src="([^"]+)"';
return preg_replace_callback("/$HTML_Sanitizer_URL/i", array(&$this, '_sanitizeSrcCallback'), $str);
}
/**
* Remove dangerous attributes from html tags.
*
* @access private
* @param string html tag
*
* @return string filtered html tag
*/
private function removeEvilAttributes($str) {
if (!$this->_allowDOMEvents) {
$str = preg_replace_callback('/<(.*?)>/i', array(&$this, '_removeDOMEventsCallback'), $str);
}
if (!$this->_allowStyle) {
$str = preg_replace_callback('/<(.*?)>/i', array(&$this, '_removeStyleCallback'), $str);
}
return $str;
}
/**
* Remove DOM events attributes from html tags.
*
* @access private
* @param string html tag
*
* @return string filtered html tag
*/
private function removeDOMEvents($str) {
$str = preg_replace('/\s*=\s*/', '=', $str);
$HTML_Sanitizer_stripAttrib = '(onclick|ondblclick|onmousedown|'
. 'onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|'
. 'onkeyup|onfocus|onblur|onabort|onerror|onload)';
$str = stripslashes(preg_replace("/$HTML_Sanitizer_stripAttrib/i", 'forbidden', $str));
return $str;
}
/**
* Callback for PCRE.
*
* @access private
* @param matches array
*
* @return string
*
* @see removeDOMEvents
*/
private function _removeDOMEventsCallback($matches) {
return '<' . $this->removeDOMEvents($matches[1]) . '>';
}
/**
* Remove style attributes from html tags.
*
* @access private
* @param string html tag
*
* @return string filtered html tag
*/
private function removeStyle($str) {
$str = preg_replace('/\s*=\s*/', '=', $str);
$HTML_Sanitizer_stripAttrib = '(style)';
$str = stripslashes(preg_replace("/$HTML_Sanitizer_stripAttrib/i", 'forbidden', $str));
return $str;
}
/**
* Callback for PCRE.
*
* @access private
* @param matches array
*
* @return string
*
* @see removeStyle
*/
private function _removeStyleCallback($matches) {
return '<' . $this->removeStyle($matches[1]) . '>';
}
/**
* Remove dangerous HTML tags.
*
* @access private
* @param string html code
*
* @return string filtered url
*/
private function removeEvilTags($str) {
$allowedTags = $this->_allowedTags;
if ($this->_allowScript) {
$allowedTags .= '<script>';
}
if ($this->_allowStyle) {
$allowedTags .= '<style>';
}
if ($this->_allowObjects) {
$allowedTags .= '<object><embed><applet><param>';
}
$allowedTags .= $this->_additionalTags;
$str = strip_tags($str, $allowedTags);
return $str;
}
/**
* Sanitize HTML
* remove dangerous tags and attributes
* clean urls.
*
* @access public
* @param string html code
*
* @return string sanitized html code
*/
public function sanitize($html) {
$html = $this->removeEvilTags($html);
$html = $this->removeEvilAttributes($html);
$html = $this->sanitizeHref($html);
$html = $this->sanitizeSrc($html);
return $html;
}
}
/**
*
*/
function html_sanitize($str) {
static $san = NULL;
if (empty($san)) {
$san = new HTML_Sanitizer();
}
return $san->sanitize($str);
}
/**
*
*/
function html_loose_sanitize($str) {
static $san = NULL;
if (empty($san)) {
$san = new HTML_Sanitizer();
$san->allowAll();
}
return $san->sanitize($str);
}
Loading…
Cancel
Save