308 lines
9.5 KiB
PHP
308 lines
9.5 KiB
PHP
<?php
|
|
/**
|
|
* \file
|
|
* \brief Utilities for the OAI Data Provider
|
|
*
|
|
* A collection of functions used.
|
|
*/
|
|
|
|
/** Dump information of a varible for debugging,
|
|
* only works when SHOW_QUERY_ERROR is true.
|
|
* \param $var_name Type: string Name of variable is being debugded
|
|
* \param $var Type: mix Any type of varibles used in PHP
|
|
* \see SHOW_QUERY_ERROR in oaidp-config.php
|
|
*/
|
|
function debug_var_dump($var_name, $var) {
|
|
if (SHOW_QUERY_ERROR) {
|
|
echo "Dumping \${$var_name}: \n";
|
|
var_dump($var)."\n";
|
|
}
|
|
}
|
|
|
|
/** Prints human-readable information about a variable for debugging,
|
|
* only works when SHOW_QUERY_ERROR is true.
|
|
* \param $var_name Type: string Name of variable is being debugded
|
|
* \param $var Type: mix Any type of varibles used in PHP
|
|
* \see SHOW_QUERY_ERROR in oaidp-config.php
|
|
*/
|
|
function debug_print_r($var_name, $var) {
|
|
if (SHOW_QUERY_ERROR) {
|
|
echo "Printing \${$var_name}: \n";
|
|
print_r($var)."\n";
|
|
}
|
|
}
|
|
|
|
/** Prints a message for debugging,
|
|
* only works when SHOW_QUERY_ERROR is true.
|
|
* PHP function print_r can be used to construct message with <i>return</i> parameter sets to true.
|
|
* \param $msg Type: string Message needs to be shown
|
|
* \see SHOW_QUERY_ERROR in oaidp-config.php
|
|
*/
|
|
function debug_message($msg) {
|
|
if (SHOW_QUERY_ERROR) {
|
|
echo $msg,"\n";
|
|
}
|
|
}
|
|
|
|
/** Check if provided correct arguments for a request.
|
|
*
|
|
* Only number of parameters is checked.
|
|
* metadataPrefix has to be checked before it is used.
|
|
* set has to be checked before it is used.
|
|
* resumptionToken has to be checked before it is used.
|
|
* from and until can easily checked here because no extra information
|
|
* is needed.
|
|
*/
|
|
function checkArgs($args, $checkList) {
|
|
global $errors, $METADATAFORMATS;
|
|
|
|
// "verb" has been checked before, no further check is needed
|
|
unset($args["verb"]);
|
|
|
|
if(isset($checkList['required'])) {
|
|
for($i = 0; $i < count($checkList["required"]); $i++) {
|
|
|
|
if(isset($args[$checkList['required'][$i]])==false) {
|
|
$errors[] = oai_error('missingArgument', $checkList["required"][$i]);
|
|
} else {
|
|
// if metadataPrefix is set, it is in required section
|
|
if(isset($args['metadataPrefix'])) {
|
|
$metadataPrefix = $args['metadataPrefix'];
|
|
// Check if the format is supported, it has enough infor (an array), last if a handle has been defined.
|
|
if (!array_key_exists($metadataPrefix, $METADATAFORMATS) ||
|
|
!(is_array($METADATAFORMATS[$metadataPrefix]) ||
|
|
!isset($METADATAFORMATS[$metadataPrefix]['myhandler']))) {
|
|
$errors[] = oai_error('cannotDisseminateFormat', 'metadataPrefix', $metadataPrefix);
|
|
}
|
|
}
|
|
unset($args[$checkList["required"][$i]]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($errors)) return;
|
|
|
|
// check to see if there is unwanted
|
|
foreach($args as $key => $val) {
|
|
|
|
if(!in_array($key, $checkList["ops"])) {
|
|
$errors[] = oai_error('badArgument', $key, $val);
|
|
}
|
|
switch ($key) {
|
|
case 'from':
|
|
case 'until':
|
|
if(!checkDateFormat($val)) {
|
|
$errors[] = oai_error('badGranularity', $key, $val);
|
|
}
|
|
break;
|
|
|
|
case 'resumptionToken':
|
|
// only check for expairation
|
|
if((int)$val+TOKEN_VALID < time())
|
|
$errors[] = oai_error('badResumptionToken');
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Validates an identifier. The pattern is: '/^[-a-z\.0-9]+$/i' which means
|
|
* it accepts -, letters and numbers.
|
|
* Used only by function <B>oai_error</B> code idDoesNotExist.
|
|
* \param $url Type: string
|
|
*/
|
|
function is_valid_uri($url) {
|
|
return((bool)preg_match('/^[-a-z\.0-9]+$/i', $url));
|
|
}
|
|
|
|
/** Validates attributes come with the query.
|
|
* It accepts letters, numbers, ':', '_', '.' and -.
|
|
* Here there are few more match patterns than is_valid_uri(): ':_'.
|
|
* \param $attrb Type: string
|
|
*/
|
|
function is_valid_attrb($attrb) {
|
|
return preg_match("/^[_a-zA-Z0-9\-\:\.]+$/",$attrb);
|
|
}
|
|
|
|
/** All datestamps used in this system are GMT even
|
|
* return value from database has no TZ information
|
|
*/
|
|
function formatDatestamp($datestamp) {
|
|
return date("Y-m-d\TH:i:s\Z",strtotime($datestamp));
|
|
}
|
|
|
|
/** The database uses datastamp without time-zone information.
|
|
* It needs to clean all time-zone informaion from time string and reformat it
|
|
*/
|
|
function checkDateFormat($date) {
|
|
$date = str_replace(array("T","Z")," ",$date);
|
|
$time_val = strtotime($date);
|
|
if (SHOW_QUERY_ERROR) { echo "timeval: $time_val\n"; }
|
|
if(!$time_val) return false;
|
|
if(strstr($date,":")) {
|
|
return date("Y-m-d H:i:s",$time_val);
|
|
} else {
|
|
return date("Y-m-d",$time_val);
|
|
}
|
|
}
|
|
|
|
/** Retrieve all defined 'setSpec' from configuraiton of $SETS.
|
|
* It is used by ANDS_TPA::create_obj_node();
|
|
*/
|
|
function prepare_set_names() {
|
|
global $SETS;
|
|
$n = count($SETS);
|
|
$a = array_fill(0,$n,'');
|
|
for ($i = 0; $i <$n; $i++) {
|
|
$a[$i] = $SETS[$i]['setSpec'];
|
|
}
|
|
return $a;
|
|
}
|
|
|
|
/** Finish a request when there is an error: send back errors. */
|
|
function oai_exit() {
|
|
|
|
// global $CONTENT_TYPE;
|
|
header(CONTENT_TYPE);
|
|
global $args,$errors,$compress;
|
|
$e = new ANDS_Error_XML($args,$errors);
|
|
if ($compress) {
|
|
ob_start('ob_gzhandler');
|
|
}
|
|
|
|
$e->display();
|
|
|
|
if ($compress) {
|
|
ob_end_flush();
|
|
}
|
|
exit();
|
|
}
|
|
|
|
// ResumToken section
|
|
/** Generate a string based on the current Unix timestamp in microseconds for creating resumToken file name. */
|
|
function get_token() {
|
|
list($usec, $sec) = explode(" ", microtime());
|
|
return ((int)($usec*1000) + (int)($sec*1000));
|
|
}
|
|
|
|
/** Create a token file.
|
|
* It has three parts which is separated by '#': cursor, extension of query, metadataPrefix.
|
|
* Called by listrecords.php.
|
|
*/
|
|
function createResumToken($cursor, $extquery, $metadataPrefix) {
|
|
$token = get_token();
|
|
$fp = fopen (TOKEN_PREFIX.$token, 'w');
|
|
if($fp==false) {
|
|
exit("Cannot write. Writer permission needs to be changed.");
|
|
}
|
|
fputs($fp, "$cursor#");
|
|
fputs($fp, "$extquery#");
|
|
fputs($fp, "$metadataPrefix#");
|
|
fclose($fp);
|
|
return $token;
|
|
}
|
|
|
|
/** Read a saved ResumToken */
|
|
function readResumToken($resumptionToken) {
|
|
$rtVal = false;
|
|
$fp = fopen($resumptionToken, 'r');
|
|
if ($fp!=false) {
|
|
$filetext = fgets($fp, 255);
|
|
$textparts = explode('#', $filetext);
|
|
fclose($fp);
|
|
unlink ($resumptionToken);
|
|
$rtVal = array((int)$textparts[0], $textparts[1], $textparts[2]);
|
|
}
|
|
return $rtVal;
|
|
}
|
|
|
|
// Here are a couple of queries which might need to be adjusted to
|
|
// your needs. Normally, if you have correctly named the columns above,
|
|
// this does not need to be done.
|
|
|
|
/** this function should generate a query which will return
|
|
* all records
|
|
* the useless condition id_column = id_column is just there to ease
|
|
* further extensions to the query, please leave it as it is.
|
|
*/
|
|
function selectallQuery($metadPrefix = "rif", $id = ''){
|
|
global $SQL;
|
|
$query = "SELECT * FROM ".$SQL['table'] . " WHERE ".$SQL['metadataPrefix']." LIKE '%$metadPrefix%'";
|
|
if ($id != '') {
|
|
$query .= " AND ".$SQL['identifier']." ='$id'";
|
|
}
|
|
return $query;
|
|
}
|
|
|
|
/** this function will return identifier and datestamp for all records
|
|
* not very useful
|
|
*/
|
|
function idQuery($metadPrefix = "rif", $id = '') {
|
|
global $SQL;
|
|
|
|
if ($SQL['set'] != '') {
|
|
$query = 'select '.$SQL['identifier'].','.$SQL['datestamp'].','.$SQL['set'].' FROM '.$SQL['table']. " WHERE ".$SQL['metadataPrefix']." LIKE '%$metadPrefix%'";
|
|
} else {
|
|
$query = 'select '.$SQL['identifier'].','.$SQL['datestamp'].' FROM '.$SQL['table']. " WHERE ".$SQL['metadataPrefix']." LIKE '%$metadPrefix%'";
|
|
}
|
|
|
|
if ($id != '') {
|
|
$query .= " AND ".$SQL['identifier']." = '$id'";
|
|
}
|
|
|
|
return $query;
|
|
}
|
|
|
|
/** filter for until, appends to the end of SQL query */
|
|
function untilQuery($until) {
|
|
global $SQL;
|
|
|
|
return ' AND '.$SQL['datestamp']." <= '$until'";
|
|
}
|
|
|
|
/** filter for from , appends to the end of SQL query */
|
|
function fromQuery($from) {
|
|
global $SQL;
|
|
|
|
return ' AND '.$SQL['datestamp']." >= '$from'";
|
|
}
|
|
|
|
/** filter for sets, appends to the end of SQL query */
|
|
function setQuery($set) {
|
|
global $SQL;
|
|
// strip off "class:" which is not saved in database
|
|
if(strstr($set,"class:")) $set = substr($set,6);
|
|
return ' AND '.$SQL['set']." LIKE '%$set%'";
|
|
}
|
|
|
|
/** for accurately to assess how many records satisfy conditions for all DBs */
|
|
function rowCount($metadataPrefix, $extQuery, $db) {
|
|
global $SQL;
|
|
$n = 0;
|
|
$sql = "SELECT COUNT(*) FROM ".$SQL['table'] . " WHERE ".$SQL['metadataPrefix']." LIKE '%$metadataPrefix%'" . $extQuery;
|
|
if ($res = $db->query($sql)) {
|
|
$n = $res->fetchColumn();
|
|
}
|
|
return $n;
|
|
}
|
|
|
|
/** A worker function for processing an error when a query was executed
|
|
* \param $query string, original query
|
|
* \param $e PDOException, the PDOException object
|
|
*/
|
|
function process_pdo_error($query, $e) {
|
|
echo $query.' was failed\n';
|
|
echo $e->getMessage();
|
|
}
|
|
|
|
/** When query return no result, throw an Exception of Not found.
|
|
* \param $db PDO
|
|
* \param $query string
|
|
* \return $res PDOStatement
|
|
*/
|
|
function exec_pdo_query($db, $query) {
|
|
$res = $db->query($query);
|
|
if ($res===false) {
|
|
throw new Exception($query.":\nIt found nothing.\n");
|
|
} else return $res;
|
|
}
|