314c311a |
1 | <?php |
2 | /** |
3 | * Fichier OAI - script du dépot OAI |
4 | * |
5 | * Ce fichier reéoit les commande OAI et fait renvoit le XML associé |
6 | * |
7 | * Mostly taken and often adapted from OAI V2 Data-Provider, Heinrich Stamerjohanns, |
8 | * stamer@uni-oldenburg.de, http://physnet.uni-oldenburg.de/oai |
9 | * |
10 | * Code fortement repris/inspire de celui d''OAI V2 Data-Provider' par Heinrich Stamerjohanns : |
11 | * stamer@uni-oldenburg.de, http://physnet.uni-oldenburg.de/oai |
12 | * |
13 | * PHP versions 4 et 5 |
14 | * |
15 | * LODEL - Logiciel d'Edition ELectronique. |
16 | * |
17 | * Copyright (c) 2001-2002, Ghislain Picard, Marin Dacos |
18 | * Copyright (c) 2003, Ghislain Picard, Marin Dacos, Luc Santeramo, Nicolas Nutten, Anne Gentil-Beccot |
19 | * Copyright (c) 2004, Ghislain Picard, Marin Dacos, Luc Santeramo, Anne Gentil-Beccot, Bruno Cénou |
20 | * Copyright (c) 2005, Ghislain Picard, Marin Dacos, Luc Santeramo, Gautier Poupeau, Jean Lamy, Bruno Cénou |
21 | * Copyright (c) 2006, Marin Dacos, Luc Santeramo, Bruno Cénou, Jean Lamy, Mikaël Cixous, Sophie Malafosse |
22 | * Copyright (c) 2007, Marin Dacos, Bruno Cénou, Sophie Malafosse, Pierre-Alain Mignot |
23 | * Copyright (c) 2008, Marin Dacos, Bruno Cénou, Pierre-Alain Mignot, Inès Secondat de Montesquieu, Jean-François Rivière |
24 | * Copyright (c) 2009, Marin Dacos, Bruno Cénou, Pierre-Alain Mignot, Inès Secondat de Montesquieu, Jean-François Rivière |
25 | * |
26 | * Home page: http://www.lodel.org |
27 | * |
28 | * E-Mail: lodel@lodel.org |
29 | * |
30 | * All Rights Reserved |
31 | * |
32 | * This program is free software; you can redistribute it and/or modify |
33 | * it under the terms of the GNU General Public License as published by |
34 | * the Free Software Foundation; either version 2 of the License, or |
35 | * (at your option) any later version. |
36 | * |
37 | * This program is distributed in the hope that it will be useful, |
38 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
39 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
40 | * GNU General Public License for more details. |
41 | * |
42 | * You should have received a copy of the GNU General Public License |
43 | * along with this program; if not, write to the Free Software |
44 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
45 | * |
46 | * @author Ghislain Picard |
47 | * @author Jean Lamy |
48 | * @author Bruno Cénou |
49 | * @author Loéc Bontonou |
50 | * @copyright 2001-2002, Ghislain Picard, Marin Dacos |
51 | * @copyright 2003, Ghislain Picard, Marin Dacos, Luc Santeramo, Nicolas Nutten, Anne Gentil-Beccot |
52 | * @copyright 2004, Ghislain Picard, Marin Dacos, Luc Santeramo, Anne Gentil-Beccot, Bruno Cénou |
53 | * @copyright 2005, Ghislain Picard, Marin Dacos, Luc Santeramo, Gautier Poupeau, Jean Lamy, Bruno Cénou |
54 | * @copyright 2006, Marin Dacos, Luc Santeramo, Bruno Cénou, Jean Lamy, Mikaël Cixous, Sophie Malafosse |
55 | * @copyright 2007, Marin Dacos, Bruno Cénou, Sophie Malafosse, Pierre-Alain Mignot |
56 | * @copyright 2008, Marin Dacos, Bruno Cénou, Pierre-Alain Mignot, Inès Secondat de Montesquieu, Jean-François Rivière |
57 | * @copyright 2009, Marin Dacos, Bruno Cénou, Pierre-Alain Mignot, Inès Secondat de Montesquieu, Jean-François Rivière |
58 | * @licence http://www.gnu.org/copyleft/gpl.html |
59 | * @version CVS:$Id: |
60 | * @package lodel/source |
61 | */ |
62 | require 'siteconfig.php'; |
63 | |
64 | try |
65 | { |
66 | include 'auth.php'; |
67 | authenticate(); |
68 | |
69 | define('TOKENVALID', 24); // tokens lifetime in hours |
70 | define('MAXIDS', 10); // max delivered identifiers |
71 | define('MAXRECORDS', 10); // max delivered records |
72 | $metadataformats = array ('oai_dc'); // only Dublin Core at the moment |
73 | |
74 | $dateformat = ''; |
75 | |
76 | function getOut($hostname) |
77 | { |
78 | header ("http/1.0 403 Forbidden"); |
79 | echo "Host $hostname is not allowed"; |
80 | log_access($hostname, 1); |
81 | exit(); |
82 | } |
83 | |
84 | /*function log_access($hostname, $denied = 0){ |
85 | global $db; |
86 | $db->execute(lq("INSERT INTO #_TP_oailogs (host, date, denied) VALUES ('$hostname', ".date('YmdHis').", $denied)")); |
87 | }*/ |
88 | |
89 | function log_access($hostname, $denied = 0) |
90 | { |
91 | global $db; |
92 | $db->execute(lq("INSERT INTO #_TP_oailogs (host, denied) VALUES ('". $hostname. "','". $denied. "')")) or trigger_error("SQL ERROR :<br />".$GLOBALS['db']->ErrorMsg(), E_USER_ERROR); |
93 | } |
94 | |
95 | |
96 | |
97 | |
98 | /** |
99 | * Generates OAI error messages. |
100 | * |
101 | * Genere les messages d'erreur OAI. |
102 | * |
103 | * @param string $code le code d'erreur |
104 | * @param string $argument l'argument passé. Par défaut vide |
105 | * @param string $value la valeur de l'argument. Par défaut vide |
106 | * @return une chaine xml d'erreur <error code="">message</error> |
107 | */ |
108 | function oai_error ($code, $argument = '', $value = '') |
109 | { |
110 | global $request; |
111 | global $request_err; |
112 | |
113 | switch ($code) { |
114 | case 'badArgument' : |
115 | if($argument == 'granularity'){ |
116 | $text = 'mismatched granularities in from/until.'; |
117 | break; |
118 | } |
119 | $text = "The argument '$argument' (value='$value') included in the request is not valid."; |
120 | break; |
121 | case 'badGranularity' : |
122 | $text = "The value '$value' of the argument '$argument' is not valid."; |
123 | $code = 'badArgument'; |
124 | break; |
125 | case 'badResumptionToken' : |
126 | $text = "The resumptionToken '$value' does not exist or has already expired."; |
127 | break; |
128 | case 'badRequestMethod' : |
129 | $text = "The request method '$argument' is unknown."; |
130 | $code = 'badVerb'; |
131 | break; |
132 | case 'badVerb' : |
133 | $text = "The verb '$argument' provided in the request is illegal."; |
134 | break; |
135 | case 'cannotDisseminateFormat' : |
136 | $text = "The metadata format '$value' given by $argument is not supported by this repository."; |
137 | break; |
138 | case 'exclusiveArgument' : |
139 | $text = 'The usage of resumptionToken as an argument allows no other arguments.'; |
140 | $code = 'badArgument'; |
141 | break; |
142 | case 'idDoesNotExist' : |
143 | $text = "The value '$value' of the identifier is illegal for this repository."; |
144 | break; |
145 | case 'missingArgument' : |
146 | $text = "The required argument '$argument' is missing in the request."; |
147 | $code = 'badArgument'; |
148 | break; |
149 | case 'noRecordsMatch' : |
150 | $text = 'The combination of the given values results in an empty list.'; |
151 | break; |
152 | case 'noMetadataFormats' : |
153 | $text = 'There are no metadata formats available for the specified item.'; |
154 | break; |
155 | case 'noVerb' : |
156 | $text = 'The request does not provide any verb.'; |
157 | $code = 'badVerb'; |
158 | break; |
159 | case 'noSetHierarchy' : |
160 | $text = 'This repository does not support sets.'; |
161 | break; |
162 | case 'sameArgument' : |
163 | $text = 'Do not use them same argument more than once.'; |
164 | $code = 'badArgument'; |
165 | break; |
166 | case 'sameVerb' : |
167 | $text = 'Do not use verb more than once.'; |
168 | $code = 'badVerb'; |
169 | break; |
170 | default: |
171 | $text = "Unknown error: code: '$code', argument: '$argument', value: '$value'"; |
172 | $code = 'badArgument'; |
173 | } |
174 | |
175 | $error .= '<error code="'. xmlstr($code, 'utf-8', false). '">'. xmlstr($text, 'utf-8', false). '</error>'. "\n"; |
176 | return $error; |
177 | } |
178 | |
179 | /** |
180 | * Transforme une chaine pour l'inclure dans un fichier XML |
181 | * |
182 | * @param string $string la chaine de caractéres |
183 | * @param string $charset le jeu de caractére de la chaine (utf-8 par défaut). |
184 | * @param boolean $xmlescaped un boolean indiquant si le xml doit étre échappé ou non. Par défaut é false. |
185 | * @return la chaéne XML |
186 | */ |
187 | function xmlstr ($string, $charset = 'utf-8', $xmlescaped = false) |
188 | { |
189 | $string = stripslashes($string); |
190 | // just remove invalid characters |
191 | $pattern = "/[\x-\x8\xb-\xc\xe-\x1f]/"; |
192 | $string = preg_replace($pattern, '', $string); |
193 | |
194 | // escape only if string is not escaped |
195 | if (!$xmlescaped) { |
196 | $xmlstr = htmlspecialchars($string, ENT_QUOTES); |
197 | } |
198 | |
199 | if ($charset != 'utf-8') { |
200 | $xmlstr = utf8_encode($xmlstr); |
201 | } |
202 | return $xmlstr; |
203 | } |
204 | |
205 | /** |
206 | * Extracts a token's infos from the database. |
207 | * If the token doesn't exist, the error is handled in the 'verbs_processing' function. |
208 | * |
209 | * Extrait de la bd les infos concernant le token. |
210 | * Si le token n'existe pas, l'erreur est traitee par la suite dans la fonction "verbs_processing". |
211 | * |
212 | * @param string $token le token |
213 | * @return un resultset SQL |
214 | */ |
215 | function get_token_info($token) |
216 | { |
217 | global $db; |
218 | $result = $db->getrow(lq("SELECT * FROM #_TP_oaitokens WHERE token ='". $token. "'")); |
219 | if ($result === false) { |
220 | trigger_error("SQL ERROR :<br />".$GLOBALS['db']->ErrorMsg(), E_USER_ERROR); |
221 | } |
222 | return $result; |
223 | } |
224 | |
225 | /** |
226 | * Deletes a token from table oaitokens once it has been used. |
227 | * |
228 | * Une fois un token exploite, il est retire de la table oaitokens. |
229 | * @param string $token le token |
230 | * @return rien |
231 | */ |
232 | function del_token($token) |
233 | { |
234 | global $db; |
235 | $result = $db->execute(lq("DELETE FROM #_TP_oaitokens WHERE token ='". $token. "'")); |
236 | if ($result === false) { |
237 | trigger_error("SQL ERROR :<br />".$GLOBALS['db']->ErrorMsg(), E_USER_ERROR); |
238 | } |
239 | } |
240 | |
241 | /** |
242 | * Inserts new token in table oaitokens. |
243 | * |
244 | * Insere un nouveau token dans la table oaitokens. |
245 | * |
246 | * @param string $token le token |
247 | * @param string $where la clause where |
248 | * @param string $metadataprefix le format de métadonnées de la requéte |
249 | * @param integer $deliveredrecords le nombre d'enregistrements délivrés |
250 | * @param datetime $expirationdatetime le datetime d'expiration du token. |
251 | */ |
252 | function insert_token($token, $where, $metadataprefix, $deliveredrecords, $expirationdatetime) |
253 | { |
254 | global $db; |
255 | $q = "INSERT INTO #_TP_oaitokens (token, query, metadataprefix, deliveredrecords, expirationdatetime)"; |
256 | |
257 | $q .= " VALUES('".$token. "', '".addslashes($where). "', '". $metadataprefix. "', '". $deliveredrecords. "', '". $expirationdatetime. "')"; |
258 | |
259 | $result = $db->execute(lq($q)); |
260 | |
261 | if ($result === false) { |
262 | trigger_error("SQL ERROR :<br />".$GLOBALS['db']->ErrorMsg(), E_USER_ERROR); |
263 | } |
264 | } |
265 | |
266 | |
267 | |
268 | /** |
269 | * Deletes outdated tokens from table oaitokens. |
270 | * |
271 | * Supprime les tokens dont la date de validite est depassee. |
272 | */ |
273 | function clean_expired_tokens() |
274 | { |
275 | global $db; |
276 | $result = $db->execute(lq("DELETE FROM #_TP_oaitokens WHERE expirationdatetime < ". date('YmdHis', time() - (TOKENVALID*3600)))); |
277 | if ($result === false) { |
278 | trigger_error("SQL ERROR :<br />".$GLOBALS['db']->ErrorMsg(), E_USER_ERROR); |
279 | } |
280 | } |
281 | |
282 | /** |
283 | * Transforme une date SQL en timestamp unix |
284 | * @param string $date la date au format datetime de MySQL |
285 | * @return le timestamp unix |
286 | */ |
287 | function sql2TS($date) |
288 | { |
289 | $date = str_replace(array(' ', '-', ':'), '', $date); |
290 | return mktime(substr($date, 8, 2), substr($date, 10, 2), substr($date, 12, 2), substr($date, 4, 2), substr($date, 6, 2), substr($date, 0, 4)); |
291 | } |
292 | |
293 | /** |
294 | * dc types are defined in lodel's database using the template : "dc.name" |
295 | * to fit the OAI protocol, we have to rename them using the template "dc:name" |
296 | * |
297 | * les types dc sont definis dans la base de donnees en utilisant la forme "dc.nom", |
298 | * on les renomme en "dc:nom" pour coller au protocole OAI |
299 | * |
300 | * @param string $str la chaine é modifier |
301 | * @return la chaine modifiée |
302 | */ |
303 | function dc_rename($str) |
304 | { |
305 | return preg_replace("/dc./", "dc:", $str); |
306 | } |
307 | |
308 | |
309 | /** |
310 | * Only a limited set of characters is available for sets' names. |
311 | * This filter replaces the unapropriate characters by valid ones. |
312 | * |
313 | * Les noms de sets ne peuvent comporter qu'un ensemble limite de caracteres. |
314 | * Ce filtre remplace les caracteres inappropries. |
315 | * |
316 | * @param string $str la chaine é modifier |
317 | * @return la chaine modifiée |
318 | */ |
319 | function strip_set($str) |
320 | { |
321 | $str = makeSortKey($str); |
322 | return preg_replace("/[^a-zA-Z0-9_.!~*\'()]/", "_", $str); |
323 | } |
324 | |
325 | /** |
326 | * Uses $id_class_fields to get the name of an entity's dc.description field, |
327 | * extract its content from the database and return it. |
328 | * |
329 | * A partir de la table mettant en relation un id d'entite avec le nom de sa |
330 | * classe et celui du champ dc.description correspondant, on renvoit le contenu |
331 | * de ce champ dc.descrition. |
332 | * |
333 | * @param integer l'identifiant de l'entité |
334 | * @return un resultSet SQL |
335 | */ |
336 | function get_dc_description($id) |
337 | { |
338 | global $id_class_fields; |
339 | global $db; |
340 | if ($id_class_fields[$id]['dc.description']) { |
341 | $class_table = "#_TP_".$id_class_fields[$id]['class']; |
342 | $field = $id_class_fields[$id]['dc.description']; |
343 | $result =$db->getOne(lq("SELECT $field FROM $class_table WHERE identity = '$id'")); |
344 | if ($result===false) { |
345 | trigger_error("SQL ERROR :<br />".$GLOBALS['db']->ErrorMsg(), E_USER_ERROR); |
346 | } |
347 | } |
348 | return $result; |
349 | } |
350 | |
351 | |
352 | |
353 | /** |
354 | * Uses $id_class_fields to get the name of an entity's dc.language field, |
355 | * extract its content from the database and return it. |
356 | * |
357 | * A partir de la table mettant en relation un id d'entite avec le nom de sa |
358 | * classe et celui du champ dc.language correspondant, on renvoit le contenu |
359 | * de ce champ dc.language. |
360 | * |
361 | * @param integer l'identifiant de l'entité |
362 | * @return un resultSet SQL |
363 | */ |
364 | function get_dc_language($id) |
365 | { |
366 | global $id_class_fields; |
367 | global $db; |
368 | |
369 | if ($id_class_fields[$id]['dc.language']) { |
370 | $class_table = "#_TP_".$id_class_fields[$id]['class']; |
371 | $field = $id_class_fields[$id]['dc.language']; |
372 | $result = $db->getone(lq("SELECT $class_table.$field FROM $class_table WHERE $class_table.identity = $id")); |
373 | if ($result===false) { |
374 | trigger_error("SQL ERROR :<br />".$GLOBALS['db']->ErrorMsg(), E_USER_ERROR); |
375 | } |
376 | } |
377 | return $result; |
378 | } |
379 | |
380 | /** |
381 | * Tests the 'verb' argument. |
382 | */ |
383 | function verbs_processing() |
384 | { |
385 | global $args; |
386 | global $context; |
387 | global $errors; |
388 | global $db; |
389 | global $metadataformats; |
390 | global $format; |
391 | global $resumptionToken; |
392 | |
393 | if ($args['verb']) { |
394 | $format = strtolower($args['verb']); |
395 | switch ($args['verb']) { |
396 | case 'Identify': |
397 | unset($args['verb']); |
398 | illegal_parameters(); |
399 | break; |
400 | case 'ListMetadataFormats': |
401 | unset($args['verb']); |
402 | if ($args['identifier']) { |
403 | check_identifier($args['identifier']); |
404 | unset($args['identifier']); |
405 | } |
406 | illegal_parameters(); |
407 | break; |
408 | case 'ListSets': |
409 | unset($args['verb']); |
410 | if($args['resumptionToken']) { |
411 | $resumptionToken = $args['resumptionToken']; |
412 | unset($args['resumptionToken']); |
413 | } |
414 | illegal_parameters(); |
415 | break; |
416 | case 'GetRecord': |
417 | unset($args['verb']); |
418 | if (!$args['identifier']) { |
419 | $errors .= oai_error('missingArgument', 'identifier'); |
420 | } else { |
421 | check_identifier($args['identifier']); |
422 | unset($args['identifier']); |
423 | } |
424 | if (!$args['metadataPrefix']) { |
425 | $errors .= oai_error('missingArgument', 'metadataPrefix'); |
426 | } else { |
427 | check_mdp($args['metadataPrefix']); |
428 | unset($args['metadataPrefix']); |
429 | } |
430 | illegal_parameters(); |
431 | break; |
432 | case 'ListIdentifiers': |
433 | check_records(); |
434 | illegal_parameters(); |
435 | break; |
436 | case 'ListRecords': |
437 | check_records(); |
438 | illegal_parameters(); |
439 | break; |
440 | default: |
441 | $errors .= oai_error('badVerb', $args['verb']); |
442 | } /*switch */ |
443 | |
444 | if(!$errors){ |
445 | $context['oai_where'] .= "AND #_TP_entities.id ".sql_in_array($context['oai_ids'])." AND #_TP_types.oaireferenced >0 AND #_TP_entities.idtype = #_TP_types.id AND #_TP_entities.status >0 AND #_TP_types.status >0 AND #_TP_entities.creationdate<".date('Ymd'); |
446 | $context['oai_where'] = substr($context['oai_where'], 4); |
447 | |
448 | if($format == 'listidentifiers' || $format == 'listrecords') { |
449 | $MAX = $format == 'listidentifiers' ? $context['oai_maxids'] : $context['oai_maxrecords']; |
450 | |
451 | $query = "SELECT #_TP_entities.id FROM #_entitiestypesjoin_ WHERE ".$context[oai_where]; |
452 | $result =$db->execute(lq($query)); |
453 | if ($result === false) { |
454 | trigger_error("SQL ERROR :<br />".$GLOBALS['db']->ErrorMsg(), E_USER_ERROR); |
455 | } |
456 | $context['oai_nbtot'] = $result->RowCount(); |
457 | |
458 | $tokenValid = TOKENVALID*3600; |
459 | $exp_date = time()+$tokenValid; |
460 | $my_expirationdatetime = date('YmdHis', $exp_date); |
461 | $expirationdatetime = gmstrftime('%Y-%m-%dT%TZ', $exp_date); |
462 | |
463 | if (isset($resumptionToken)) { |
464 | $info = get_token_info($resumptionToken); |
465 | if (is_array($info) && sql2TS($info['expirationdatetime']) > (time() - $tokenValid)) { |
466 | $deliveredrecords = $info['deliveredrecords']; |
467 | $context['oai_where'] = $info['query']; |
468 | $metadataPrefix = $info['metadataprefix']; |
469 | unset($errors); |
470 | del_token($resumptionToken); |
471 | } else { |
472 | $errors = oai_error('badResumptionToken', '', $resumptionToken); |
473 | // echo $info['expirationdatetime']; |
474 | } |
475 | } |
476 | // Will we need a ResumptionToken? |
477 | $context['oai_offset'] = isset($deliveredrecords) ? $deliveredrecords : 0; |
478 | $query .= " LIMIT ". $context['oai_offset'].", $MAX"; |
479 | $result =$db->execute(lq($query)); |
480 | if ($result === false) { |
481 | trigger_error("SQL ERROR :<br />".$GLOBALS['db']->ErrorMsg(), E_USER_ERROR); |
482 | } |
483 | |
484 | $deliveredrecords += $result->RowCount(); |
485 | |
486 | if ($context['oai_nbtot'] - $deliveredrecords > 0) { |
487 | $token = uniqid(8); |
488 | insert_token($token, $context['oai_where'], $metadataPrefix, $deliveredrecords, $my_expirationdatetime); |
489 | $context['oai_restoken'] = |
490 | ' <resumptionToken expirationDate="'.$expirationdatetime.'" |
491 | completeListSize="'.$context['oai_nbtot'].'" |
492 | cursor="'.$deliveredrecords.'">'.$token."</resumptionToken>\n"; |
493 | } |
494 | // Last delivery, return empty ResumptionToken |
495 | |
496 | if($context['oai_nbtot'] == 0) { |
497 | $errors = oai_error('noRecordsMatch'); |
498 | } elseif ($context['oai_nbtot'] <= $deliveredrecords) { |
499 | del_token($token); |
500 | $context['oai_restoken'] = |
501 | ' <resumptionToken completeListSize="'.$context['oai_nbtot'].'" |
502 | cursor="'.$deliveredrecords.'"></resumptionToken>'."\n"; |
503 | } |
504 | } |
505 | } |
506 | } else { |
507 | $errors = oai_error('noVerb'); |
508 | } |
509 | } |
510 | |
511 | |
512 | |
513 | /** |
514 | * ListRecords and ListIdentifiers accept the same parameters, the shared |
515 | * tests are regrouped in this function. |
516 | * |
517 | * ListRecords et ListIdentifiers acceptent les meme parametres, les tests |
518 | * communs sont donc regroupes dans cette fonction. |
519 | */ |
520 | function check_records () |
521 | { |
522 | global $args; |
523 | global $context; |
524 | global $errors; |
525 | global $db; |
526 | global $metadataformats; |
527 | global $resumptionToken; |
528 | |
529 | unset($args['verb']); |
530 | if ((!$args['metadataPrefix']) && (!$args['resumptionToken'])) { |
531 | $errors .= oai_error('missingArgument', 'metadataPrefix'); |
532 | } elseif($args['resumptionToken'] && (count($args)>1)) { |
533 | $errors .= oai_error('exclusiveArgument'); |
534 | } else { |
535 | // patterns to test date granularity |
536 | $longdate = "/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/"; |
537 | $shortdate = "/^\\d{4}-\\d{2}-\\d{2}$/"; |
538 | |
539 | if ($args['from']) { |
540 | $from = $args['from']; |
541 | if (preg_match($longdate, $from)) { |
542 | $context['oai_where'] .= "AND (creationdate>= '". $from. "' || modificationdate >= '". $from. "')"; |
543 | } elseif (preg_match($shortdate, $from)) { |
544 | $context['oai_where'] .= "AND (creationdate>= '". $from. "' || modificationdate >= '". $from. "')"; |
545 | $context['short_date'] = true; |
546 | } else { |
547 | $errors .= oai_error('badArgument', 'from', $from); |
548 | unset($from); |
549 | } |
550 | unset($args['from']); |
551 | } |
552 | |
553 | if ($args['until']) { |
554 | $until = $args['until']; |
555 | if (preg_match($longdate, $until)) { |
556 | $context['oai_where'] .= "AND creationdate <= '".$until."'"; |
557 | } elseif (preg_match($shortdate, $until)) { |
558 | $context['oai_where'] .= "AND creationdate <= '".$until."'"; |
559 | $context['short_date'] = true; |
560 | } else { |
561 | $errors .= oai_error('badArgument', 'until', $until); |
562 | unset($until); |
563 | } |
564 | unset($args['until']); |
565 | } |
566 | |
567 | if ($args['metadataPrefix']) { |
568 | check_mdp($args['metadataPrefix']); |
569 | unset($args['metadataPrefix']); |
570 | } |
571 | |
572 | if($args['set']) { |
573 | $set = $args['set']; |
574 | $context['oai_ids'] = array(); |
575 | |
576 | $result =$db->execute(lq("SELECT id FROM #_TP_entities, #_TP_relations WHERE id2 = '".substr($args['set'], 4)."'")); |
577 | if ($result === false) { |
578 | trigger_error("SQL ERROR :<br />".$GLOBALS['db']->ErrorMsg(), E_USER_ERROR); |
579 | } |
580 | |
581 | while (!$result->EOF) { |
582 | $row = $result->fields; |
583 | $context['oai_ids'][] = $row['id']; |
584 | $result->MoveNext(); |
585 | } |
586 | unset($args['set']); |
587 | } |
588 | if($args['resumptionToken']) { |
589 | $resumptionToken = $args['resumptionToken']; |
590 | unset($args['resumptionToken']); |
591 | } |
592 | if(isset($from)&&isset($until)&&strlen($from)!=strlen($until)){ |
593 | $errors .= oai_error('badArgument', 'granularity', ''); |
594 | } |
595 | } |
596 | } |
597 | |
598 | /** |
599 | * Tests the 'metadataPrefix' argument. |
600 | * |
601 | * Verifie la validite de l'information liee a l'argument 'metadataPrefix'. |
602 | * |
603 | * @param string $val la valeur é vérifier |
604 | */ |
605 | function check_mdp ($val) |
606 | { |
607 | global $errors; |
608 | global $metadataformats; |
609 | |
610 | if (in_array($val, $metadataformats)) { |
611 | $metadataPrefix = $val; |
612 | } else { |
613 | $errors .= oai_error('cannotDisseminateFormat', 'metadataPrefix', $val); |
614 | } |
615 | } |
616 | |
617 | /** |
618 | * Tests the 'Identifier' argument. |
619 | * |
620 | * Verifie la validite de l'information liee a l'argument 'Identifier'. |
621 | * |
622 | * @param string $val la valeur de l'identifier OAI |
623 | */ |
624 | function check_identifier ($val) |
625 | { |
626 | global $context; |
627 | global $errors; |
628 | global $metadataformats; |
629 | |
630 | $identifier = $val; |
631 | // remove the OAI part to get the identifier |
632 | $id = str_replace($context['oai_prefix'], '', $identifier); |
633 | if (in_array($id, $context['oai_ids'])) { |
634 | $context['oai_ids'] = array(); |
635 | $context['oai_ids'][] = $id; |
636 | } else { |
637 | $errors .= oai_error('idDoesNotExist', '', $identifier); |
638 | } |
639 | } |
640 | |
641 | /** |
642 | * Tests for illegal parameters and generate the appropriate error messages. |
643 | * |
644 | * Traite la presence d'arguments illegaux en generant le message d'erreur approprie. |
645 | */ |
646 | function illegal_parameters() |
647 | { |
648 | global $args; |
649 | global $errors; |
650 | |
651 | if ($args) { |
652 | foreach ($args as $key=>$val) { |
653 | $errors .= oai_error('badArgument', $key, $val); |
654 | } |
655 | } |
656 | } |
657 | |
658 | //----------- DEBUT DU SCRIPT -----------// |
659 | |
660 | /** |
661 | * Check if the required options are defined (oai_identifier, oai_allow, |
662 | * oai_deny) and store their values. |
663 | * |
664 | * Verification de l'existence des options requises (oai_identifier, oai_allow, |
665 | * oai_deny) et recuperation de leur valeur. |
666 | * Le groupe d'option oai est aussi requis |
667 | */ |
668 | $result = getoption(array('oai.oai_identifier', 'oai.oai_allow', 'oai.oai_deny')); |
669 | |
670 | if($result['oai.oai_identifier']) { |
671 | $context['oai_identifier'] = $result['oai.oai_identifier']; |
672 | } |
673 | |
674 | if($result['oai.oai_allow']){ |
675 | $allowed = $result['oai.oai_allow']; |
676 | } |
677 | |
678 | if($result['oai.oai_deny']){ |
679 | $denied = $result['oai.oai_deny']; |
680 | } |
681 | |
682 | if(!isset($allowed) && !isset($denied)){ |
683 | echo "<code>Acces list of your OAI repository is not configured, please check site options.<br />"; |
684 | echo "In order to enable this you must configure an optiongroup called <em>oai</em> ". |
685 | "containing 2 options : <em>oai_allow</em> and <em>oai_deny</em>. By default,". |
686 | " <em>oai_allow</em> should be set to '*'</code>"; |
687 | exit; |
688 | } |
689 | |
690 | $oai_allowed = explode(',', $allowed); |
691 | $oai_denied = explode(',', $denied); |
692 | |
693 | if (!isset($_SERVER['REMOTE_HOST'])) { |
694 | $hostname = gethostbyaddr($_SERVER['REMOTE_ADDR']); |
695 | } |
696 | else { |
697 | $hostname = $_SERVER['REMOTE_HOST']; |
698 | } |
699 | |
700 | /** |
701 | * Identifies the request's emitter and check its rights. |
702 | * |
703 | * Identification de l'emetteur de la requete et verification de ses droits. |
704 | */ |
705 | if(in_array($_SERVER['REMOTE_ADDR'], $oai_denied) || in_array($hostname, $oai_denied) || (count($oai_denied) == 1 && $oai_denied[0] == '*' && !in_array($_SERVER['REMOTE_ADDR'], $oai_allowed) && !in_array($hostname, $oai_allowed))) { |
706 | getOut($hostname); |
707 | } |
708 | |
709 | if(!(in_array($_SERVER['REMOTE_ADDR'], $oai_allowed) || in_array($hostname, $oai_allowed) || (count($oai_allowed) == 1 && $oai_allowed[0] == '*'))){ |
710 | getOut($hostname); |
711 | } |
712 | |
713 | log_access($hostname); |
714 | $oai_open = "<?xml version=\"1.0\" encoding=\"utf-8\"?><OAI-PMH xmlns=\"http://www.openarchives.org/OAI/2.0/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd\"> |
715 | <responseDate>". gmstrftime('%Y-%m-%dT%TZ', time()). "</responseDate> |
716 | <request>". dirname($context['currenturl']). '/oai20.'. $context['extensionscripts']. "</request>"; |
717 | |
718 | $oai_close = "</OAI-PMH>\n"; |
719 | |
720 | /* A sortir dans les options du site ? *************************************************/ |
721 | $context['oai_prefix'] = isset($context['oai_identifier']) ? $context['oai_identifier'] : 'oai:'. str_replace(array('http://', '/'), array('', '.'), dirname($context['currenturl'])). ':'; |
722 | $context['oai_maxids'] = MAXIDS; |
723 | $context['oai_maxrecords'] = MAXRECORDS; |
724 | /***************************************************************************************/ |
725 | |
726 | /** |
727 | * List of OAI-referenced entities. |
728 | * |
729 | * Construit la liste des entites referencees par l'OAI. |
730 | */ |
731 | $result = $db->execute(lq("SELECT #_TP_entities.id FROM #_entitiestypesjoin_ WHERE #_TP_entities.idtype = #_TP_types.id AND #_TP_types.oaireferenced = 1")); |
732 | if ($result === false) { |
733 | trigger_error("SQL ERROR :<br />".$GLOBALS['db']->ErrorMsg(), E_USER_ERROR); |
734 | } |
735 | |
736 | while (!$result->EOF) { |
737 | $row = $result->fields; |
738 | $context['oai_ids'][] = $row['id']; |
739 | $result->MoveNext(); |
740 | } |
741 | |
742 | if(!$context['oai_ids']) { |
743 | $errors .= oai_error('noRecordsMatch'); |
744 | header("Content-type: application/xml"); |
745 | echo _indent($oai_open. $errors. $oai_close); |
746 | exit; |
747 | } |
748 | |
749 | /** |
750 | * Creates a table associating an entity's id with its class name and its associated |
751 | * fields which are equivalent to dc.description or dc.language. |
752 | * |
753 | * Creation de la table indiquant pour chaque entite referencee son nom de |
754 | * classe et les noms de champs equivalents a dc.description et dc.language. |
755 | */ |
756 | |
757 | $id_class_fields = array(); |
758 | $result = $db->execute(lq("SELECT #_TP_entities.id, #_TP_types.class, #_TP_tablefields.name, #_TP_tablefields.g_name |
759 | FROM #_entitiestypesjoin_, #_TP_tablefieldgroups, #_TP_tablefields |
760 | WHERE (#_TP_tablefields.g_name = 'dc.description' || #_TP_tablefields.g_name = 'dc.language') |
761 | AND #_TP_tablefields.class = #_TP_types.class |
762 | AND #_TP_types.oaireferenced = '1' |
763 | AND #_TP_entities.idtype = #_TP_types.id")); |
764 | if ($result === false) { |
765 | trigger_error("SQL ERROR :<br />".$GLOBALS['db']->ErrorMsg(), E_USER_ERROR); |
766 | } |
767 | |
768 | while (!$result->EOF) { |
769 | $row = $result->fields; |
770 | $id = $row['id']; |
771 | $id_class_fields[$id]['class'] = $row['class']; |
772 | $id_class_fields[$id][$row['g_name']] = $row['name']; |
773 | $result->MoveNext(); |
774 | } |
775 | |
776 | /** |
777 | * Stores the request's parameters. |
778 | * |
779 | * Recuperation des parametres de la requete. |
780 | */ |
781 | if ($_SERVER['REQUEST_METHOD'] == 'GET') { |
782 | $args = $_GET; |
783 | $getarr = explode('&', $_SERVER['QUERY_STRING']); |
784 | } elseif ($_SERVER['REQUEST_METHOD'] == 'POST') { |
785 | $args = $_POST; |
786 | } else { |
787 | $errors .= oai_error('badRequestMethod', $_SERVER['REQUEST_METHOD']); |
788 | } |
789 | |
790 | /** |
791 | * Detects duplicate arguments in GET request. |
792 | * |
793 | * Detecte les arguments dupliques dans une requete passee par GET. |
794 | */ |
795 | if (isset($getarr)) { |
796 | if (count($getarr) != count($args)) { |
797 | $errors .= oai_error('sameArgument'); |
798 | } |
799 | } |
800 | |
801 | /** |
802 | * Call to the 'clean_request_variable' function in func.php to remove potential |
803 | * risks of injection in the request's arguments. |
804 | * |
805 | * Utilisation de la fonction "clean_request_variable" de func.php pour supprimer |
806 | * tout risque d'injection dans les arguments de la requete. |
807 | */ |
808 | array_walk($args, 'clean_request_variable'); |
809 | $context['oai_args'] = ''; |
810 | if (is_array($args)) { |
811 | foreach ($args as $key => $val) { |
812 | $context['oai_args'] .= ' '.$key.'="'.htmlspecialchars(stripslashes($val)).'"'; |
813 | } |
814 | } |
815 | |
816 | /** |
817 | * Process the request. |
818 | * |
819 | * Traitement des arguments de la requete. |
820 | */ |
821 | verbs_processing(); |
822 | |
823 | /** |
824 | * If error messages were generated, they are displayed and the program ends. |
825 | * |
826 | * Si des messages d'erreur ont ete generes, ils sont affiches et l'execution du |
827 | * programme se termine. |
828 | */ |
829 | if(isset($errors)) { |
830 | header("Content-type: application/xml"); |
831 | echo _indent($oai_open.$errors.$oai_close); |
832 | exit; |
833 | } |
834 | |
835 | |
836 | |
837 | /** |
838 | * Generates response date, required by the protocol. |
839 | * |
840 | * Generation de la date de reponse, requise par le protocole. |
841 | */ |
842 | |
843 | $context['oai_responsedate'] = gmstrftime('%Y-%m-%dT%TZ', time()); |
844 | |
845 | |
846 | /** |
847 | * Displays the response. |
848 | * |
849 | * Affichage de la reponse. |
850 | */ |
851 | |
852 | $base = 'oai20'; |
853 | //$view->renderCached($context,$base); |
854 | View::getView()->render($base); |
855 | |
856 | |
857 | /** |
858 | * Suppress outdated tokens. |
859 | * |
860 | * Suppression des tokens dont la date limite de validite a ete atteinte. |
861 | */ |
862 | |
863 | clean_expired_tokens(); |
864 | } |
865 | catch(LodelException $e) |
866 | { |
867 | echo $e->getContent(); |
868 | exit(); |
869 | } |
870 | ?> |