Conneg.php
Go to the documentation of this file.
00001 <?php 00002 00005 00025 class Conneg 00026 { 00028 private $mime = "text/plain"; // http://www.iana.org/assignments/media-types/ 00029 00031 private $charset = "utf-8"; // http://www.iana.org/assignments/character-sets 00032 00034 private $encoding = "identity"; // http://www.iana.org/assignments/http-parameters (content-coding section) 00035 00037 private $lang = "en"; // http://www.iana.org/assignments/language-subtag-registry 00038 00040 private $status = 200; // Check the status of the interaction with the user. 00041 00043 private $statusMsg = "OK"; 00044 00046 private $statusMsgExt = ""; 00047 00049 private $supported_serializations = ""; 00050 00052 public $error; 00053 00070 function __construct($accept = "", $accept_charset = "", $accept_encoding = "", $accept_language = "", 00071 $supported_serializations) 00072 { 00073 $this->supported_serializations = $supported_serializations; 00074 00075 $this->accept($accept); 00076 00077 if($this->status == 200) 00078 { 00079 $this->accept_charset($accept_charset); 00080 } 00081 00082 if($this->status == 200) 00083 { 00084 $this->accept_encoding($accept_encoding); 00085 } 00086 00087 if($this->status == 200) 00088 { 00089 $this->accept_language($accept_language); 00090 } 00091 } 00092 00093 function __destruct() { } 00094 00103 public function respond() 00104 { 00105 header("HTTP/1.1 " . $this->status . " " . $this->statusMsg); 00106 header("Content-Type: " . $this->mime . "; charset=" . $this->charset); 00107 header("Content-Language: " . $this->lang); 00108 header("Content-Encoding: " . $this->encoding); 00109 00110 if(!isset($this->error)) 00111 { 00112 if($this->statusMsgExt != "") 00113 { 00114 echo $this->statusMsgExt . "\n"; 00115 } 00116 } 00117 else 00118 { 00119 echo $this->error->getError() . "\n"; 00120 } 00121 00122 $this->__destruct(); 00123 } 00124 00135 public function getAccept() { return $this->mime; } 00136 00147 public function getAcceptCharset() { return $this->charset; } 00148 00159 public function getAcceptEncoding() { return $this->encoding; } 00160 00171 public function getAcceptLanguage() { return $this->lang; } 00172 00183 public function setStatus($status) { return $this->status = $status; } 00184 00195 public function setStatusMsg($statusMsg) { return $this->statusMsg = $statusMsg; } 00196 00207 public function setStatusMsgExt($statusMsgExt) { return $this->statusMsgExt = $statusMsgExt; } 00208 00226 public function setError($id, $webservice, $name, $description, $debugInfo, $level) 00227 { 00228 include_once("Error.php"); 00229 $mime = "text/plain"; 00230 00231 switch($this->mime) 00232 { 00233 case "application/rdf+xml": 00234 case "application/xhtml+rdfa": 00235 case "text/rdf+n3": 00236 case "text/xml": 00237 case "text/html": 00238 case "application/sparql-results+xml": 00239 case "application/rdf+n3": 00240 $mime = "text/xml"; 00241 break; 00242 00243 case "application/sparql-results+json": 00244 case "application/json": 00245 case "application/iron+json": 00246 case "application/bib+json": 00247 case "application/rdf+json": 00248 $mime = "application/json"; 00249 break; 00250 00251 case "text/tsv": 00252 case "text/csv": 00253 case "application/x-bibtex": 00254 $mime = "text/plain"; 00255 break; 00256 } 00257 00258 $this->error = new Error($id, $webservice, $name, $description, $debugInfo, $mime, $level); 00259 } 00260 00271 public function getStatus() { return $this->status; } 00272 00283 public function getStatusMsg() { return $this->statusMsg; } 00284 00295 public function getStatusMsgExt() { return $this->statusMsgExt; } 00296 00306 public function getMime() { return $this->mime; } 00307 00318 public function accept($header) 00319 { 00320 $accepts = array(); 00321 $mimes = array(); 00322 00323 if(strlen($header) > 0) 00324 { 00325 // break up string into pieces (languages and q factors) 00326 preg_match_all('/([^,]+)/', $header, $accepts); 00327 00328 foreach($accepts[0] as $accept) 00329 { 00330 $foo = explode(";", str_replace(" ", "", $accept)); 00331 00332 if(isset($foo[1])) 00333 { 00334 if(stripos($foo[1], "q=") !== FALSE) 00335 { 00336 $foo[1] = str_replace("q=", "", $foo[1]); 00337 00338 /* 00339 This is to ensure that the "q=1" parameter will be prioritary on the "non-q" accept mimes. 00340 It is the reason why we set it to 1.1 00341 00342 This is particularly interesting in some usecases when a user agent "highjack" the accept header sent by 00343 another user agent. One good usecase is the one of a Flash Movie embedded in a FireFox Browser window. 00344 When using the HTTPService API, the FireFox browser will add its default accept mimes to the query 00345 sent by the embeded flash movie. By seting "q=1" for any flash movies that send a query, it ensures 00346 that that mime will be the one selected by the WS, and not the ones added by FireFox. 00347 */ 00348 if($foo[1] == "1") 00349 { 00350 $foo[1] = "1.1"; 00351 } 00352 } 00353 else 00354 { 00355 $foo[1] = "1"; 00356 } 00357 } 00358 else 00359 { 00360 array_push($foo, "1"); 00361 } 00362 00363 $mimes[$foo[0]] = $foo[1]; 00364 } 00365 00366 // In the case that there is a Accept: header, but that it is empty. We set it to: anything. 00367 if(count($mimes) <= 0) 00368 { 00369 $mimes["*/*"] = 1; 00370 } 00371 00372 arsort($mimes, SORT_NUMERIC); 00373 00374 $notAcceptable406 = TRUE; 00375 00376 foreach($mimes as $mime => $q) 00377 { 00378 $mime = strtolower($mime); 00379 00380 if($mime == "application/rdf+xml" 00381 && array_search("application/rdf+xml", $this->supported_serializations) !== FALSE) 00382 { 00383 $this->status = 200; 00384 $this->statusMsg = "OK"; 00385 $this->mime = "application/rdf+xml"; 00386 00387 $notAcceptable406 = FALSE; 00388 00389 break; 00390 } 00391 00392 if(($mime == "application/rdf+n3" 00393 && array_search("application/rdf+n3", $this->supported_serializations) !== FALSE) || 00394 ($mime == "text/rdf+n3" 00395 && array_search("text/rdf+n3", $this->supported_serializations) !== FALSE) 00396 || ($mime == "application/*" && array_search("application/*", $this->supported_serializations) !== FALSE)) 00397 { 00398 $this->status = 200; 00399 $this->statusMsg = "OK"; 00400 $this->mime = "application/rdf+n3"; 00401 00402 $notAcceptable406 = FALSE; 00403 00404 break; 00405 } 00406 00407 if(($mime == "text/plain" && array_search("text/plain", $this->supported_serializations) !== FALSE) 00408 || ($mime == "text/*" && array_search("text/*", $this->supported_serializations) !== FALSE) 00409 || ($mime == "application/*" && array_search("application/*", $this->supported_serializations) !== FALSE) 00410 || ($mime == "*/*" && array_search("*/*", $this->supported_serializations) !== FALSE)) 00411 { 00412 $this->status = 200; 00413 $this->statusMsg = "OK"; 00414 $this->mime = "text/xml"; 00415 00416 $notAcceptable406 = FALSE; 00417 00418 break; 00419 } 00420 00421 if($mime == "application/xhtml+xml" 00422 && array_search("application/xhtml+xml", $this->supported_serializations) !== FALSE) 00423 { 00424 $this->status = 200; 00425 $this->statusMsg = "OK"; 00426 $this->mime = "application/xhtml+rdfa"; 00427 00428 $notAcceptable406 = FALSE; 00429 00430 break; 00431 } 00432 00433 if($mime == "application/xhtml+rdfa" 00434 && array_search("application/xhtml+rdfa", $this->supported_serializations) !== FALSE) 00435 { 00436 $this->status = 200; 00437 $this->statusMsg = "OK"; 00438 $this->mime = "application/xhtml+rdfa"; 00439 00440 $notAcceptable406 = FALSE; 00441 00442 break; 00443 } 00444 00445 if($mime == "text/xml" && array_search("text/xml", $this->supported_serializations) !== FALSE) 00446 { 00447 $this->status = 200; 00448 $this->statusMsg = "OK"; 00449 $this->mime = "text/xml"; 00450 00451 $notAcceptable406 = FALSE; 00452 00453 break; 00454 } 00455 00456 if($mime == "application/xml" && array_search("application/xml", $this->supported_serializations) !== FALSE) 00457 { 00458 $this->status = 200; 00459 $this->statusMsg = "OK"; 00460 $this->mime = "application/xml"; 00461 00462 $notAcceptable406 = FALSE; 00463 00464 break; 00465 } 00466 00467 if($mime == "text/html" && array_search("text/html", $this->supported_serializations) !== FALSE) 00468 { 00469 $this->status = 200; 00470 $this->statusMsg = "OK"; 00471 $this->mime = "text/html"; 00472 00473 $notAcceptable406 = FALSE; 00474 00475 break; 00476 } 00477 00478 if($mime == "application/sparql-results+xml" 00479 && array_search("application/sparql-results+xml", $this->supported_serializations) !== FALSE) 00480 { 00481 $this->status = 200; 00482 $this->statusMsg = "OK"; 00483 $this->mime = "application/sparql-results+xml"; 00484 00485 $notAcceptable406 = FALSE; 00486 00487 break; 00488 } 00489 00490 if($mime == "application/sparql-results+json" 00491 && array_search("application/sparql-results+json", $this->supported_serializations) !== FALSE) 00492 { 00493 $this->status = 200; 00494 $this->statusMsg = "OK"; 00495 $this->mime = "application/sparql-results+json"; 00496 00497 $notAcceptable406 = FALSE; 00498 00499 break; 00500 } 00501 00502 if($mime == "application/rdf+json" 00503 && array_search("application/rdf+json", $this->supported_serializations) !== FALSE) 00504 { 00505 $this->status = 200; 00506 $this->statusMsg = "OK"; 00507 $this->mime = "application/rdf+json"; 00508 00509 $notAcceptable406 = FALSE; 00510 00511 break; 00512 } 00513 00514 if($mime == "text/tsv" && array_search("text/tsv", $this->supported_serializations) !== FALSE) 00515 { 00516 $this->status = 200; 00517 $this->statusMsg = "OK"; 00518 $this->mime = "text/tsv"; 00519 00520 $notAcceptable406 = FALSE; 00521 00522 break; 00523 } 00524 00525 if($mime == "text/csv" && array_search("text/csv", $this->supported_serializations) !== FALSE) 00526 { 00527 $this->status = 200; 00528 $this->statusMsg = "OK"; 00529 $this->mime = "text/csv"; 00530 00531 $notAcceptable406 = FALSE; 00532 00533 break; 00534 } 00535 00536 if($mime == "application/sparql-results+json" 00537 && array_search("application/sparql-results+json", $this->supported_serializations) !== FALSE) 00538 { 00539 $this->status = 200; 00540 $this->statusMsg = "OK"; 00541 $this->mime = "application/sparql-results+json"; 00542 00543 $notAcceptable406 = FALSE; 00544 00545 break; 00546 } 00547 00548 if($mime == "application/x-bibtex" 00549 && array_search("application/x-bibtex", $this->supported_serializations) !== FALSE) 00550 { 00551 $this->status = 200; 00552 $this->statusMsg = "OK"; 00553 $this->mime = "application/x-bibtex"; 00554 00555 $notAcceptable406 = FALSE; 00556 00557 break; 00558 } 00559 00560 if($mime == "application/json" && array_search("application/json", $this->supported_serializations) !== FALSE) 00561 { 00562 $this->status = 200; 00563 $this->statusMsg = "OK"; 00564 $this->mime = "application/json"; 00565 00566 $notAcceptable406 = FALSE; 00567 00568 break; 00569 } 00570 00571 if($mime == "application/iron+json" 00572 && array_search("application/iron+json", $this->supported_serializations) !== FALSE) 00573 { 00574 $this->status = 200; 00575 $this->statusMsg = "OK"; 00576 $this->mime = "application/iron+json"; 00577 00578 $notAcceptable406 = FALSE; 00579 00580 break; 00581 } 00582 00583 if($mime == "application/bib+json" 00584 && array_search("application/bib+json", $this->supported_serializations) !== FALSE) 00585 { 00586 $this->status = 200; 00587 $this->statusMsg = "OK"; 00588 $this->mime = "application/bib+json"; 00589 00590 $notAcceptable406 = FALSE; 00591 00592 break; 00593 } 00594 } 00595 00596 if($notAcceptable406) 00597 { 00598 $this->status = 406; 00599 $this->statusMsg = "Not Acceptable"; 00600 $this->statusMsgExt = "Unacceptable mime type requested"; 00601 } 00602 } 00603 else 00604 { 00605 // If no access header specified; it means that the client accept *anything* 00606 // In such a case we send back rdf+xml 00607 $this->status = 200; 00608 $this->statusMsg = "OK"; 00609 $this->mime = "application/rdf+xml"; 00610 } 00611 } 00612 00623 public function accept_charset($header) 00624 { 00625 $accepts = array(); 00626 $charsets = array(); 00627 00628 if(strlen($header) > 0) 00629 { 00630 // break up string into pieces (languages and q factors) 00631 preg_match_all('/([^,]+)/', $header, $accepts); 00632 00633 foreach($accepts[0] as $accept) 00634 { 00635 $foo = explode(";", str_replace(" ", "", $accept)); 00636 00637 if(isset($foo[1])) 00638 { 00639 if(stripos($foo[1], "q=") !== FALSE) 00640 { 00641 $foo[1] = str_replace("q=", "", $foo[1]); 00642 } 00643 else 00644 { 00645 $foo[1] = "1"; 00646 } 00647 } 00648 else 00649 { 00650 array_push($foo, "1"); 00651 } 00652 00653 $charsets[$foo[0]] = $foo[1]; 00654 } 00655 00656 // In the case that there is a Accept-Charset: header, but that it is empty. We set it to: anything. 00657 if(count($charsets) <= 0) 00658 { 00659 $charsets["*"] = 1; 00660 } 00661 00662 arsort($charsets, SORT_NUMERIC); 00663 00664 $notAcceptable406 = TRUE; 00665 00666 foreach($charsets as $charset => $q) 00667 { 00668 $charset = strtolower($charset); 00669 00670 if($charset == "utf-8" || $charset == "*") 00671 { 00672 $this->status = 200; 00673 $this->statusMsg = "OK"; 00674 $this->charset = "utf-8"; 00675 00676 $notAcceptable406 = FALSE; 00677 00678 break; 00679 } 00680 } 00681 00682 if($notAcceptable406) 00683 { 00684 $this->status = 406; 00685 $this->statusMsg = "Not Acceptable"; 00686 $this->statusMsgExt = "Unacceptable charset requested"; 00687 } 00688 } 00689 else 00690 { 00691 // If no access header specified; it means that the client accept *anything* 00692 // In such a case we send back utf-8 00693 $this->status = 200; 00694 $this->statusMsg = "OK"; 00695 $this->charset = "utf-8"; 00696 } 00697 } 00698 00711 public function accept_encoding($header) 00712 { 00713 $accepts = array(); 00714 $encodings = array(); 00715 00716 if(strlen($header) > 0) 00717 { 00718 // break up string into pieces (languages and q factors) 00719 preg_match_all('/([^,]+)/', $header, $accepts); 00720 00721 foreach($accepts[0] as $accept) 00722 { 00723 $foo = explode(";", str_replace(" ", "", $accept)); 00724 00725 if(isset($foo[1])) 00726 { 00727 if(stripos($foo[1], "q=") !== FALSE) 00728 { 00729 $foo[1] = str_replace("q=", "", $foo[1]); 00730 } 00731 else 00732 { 00733 $foo[1] = "1"; 00734 } 00735 } 00736 else 00737 { 00738 array_push($foo, "1"); 00739 } 00740 00741 $encodings[$foo[0]] = $foo[1]; 00742 } 00743 00744 // In the case that there is a Accept-Charset: header, but that it is empty. We set it to: anything. 00745 if(count($encodings) <= 0) 00746 { 00747 $encodings["*"] = 1; 00748 } 00749 00750 arsort($encodings, SORT_NUMERIC); 00751 00752 $notAcceptable406 = TRUE; 00753 00754 foreach($encodings as $encoding => $q) 00755 { 00756 $encoding = strtolower($encoding); 00757 00758 if($encoding == "identity" || $encoding == "*") 00759 { 00760 $this->status = 200; 00761 $this->statusMsg = "OK"; 00762 $this->encoding = "identity"; 00763 00764 $notAcceptable406 = FALSE; 00765 00766 break; 00767 } 00768 } 00769 00770 if($notAcceptable406) 00771 { 00772 /* $this->status = 406; 00773 $this->statusMsg = "Not Acceptable"; 00774 $this->statusMsgExt = "Unacceptable encoding requested";*/ 00775 } 00776 } 00777 else 00778 { 00779 // If no access header specified; it means that the client accept *anything* 00780 // In such a case we send back utf-8 00781 $this->status = 200; 00782 $this->statusMsg = "OK"; 00783 $this->encoding = "identity"; 00784 } 00785 } 00786 00800 public function accept_language($header) 00801 { 00802 $accepts = array(); 00803 $languages = array(); 00804 00805 if(strlen($header) > 0) 00806 { 00807 // break up string into pieces (languages and q factors) 00808 preg_match_all('/([^,]+)/', $header, $accepts); 00809 00810 foreach($accepts[0] as $accept) 00811 { 00812 $foo = explode(";", str_replace(" ", "", $accept)); 00813 00814 if(isset($foo[1])) 00815 { 00816 if(stripos($foo[1], "q=") !== FALSE) 00817 { 00818 $foo[1] = str_replace("q=", "", $foo[1]); 00819 } 00820 else 00821 { 00822 $foo[1] = "1"; 00823 } 00824 } 00825 else 00826 { 00827 array_push($foo, "1"); 00828 } 00829 00830 $languages[$foo[0]] = $foo[1]; 00831 } 00832 00833 // In the case that there is a Accept-Charset: header, but that it is empty. We set it to: anything. 00834 if(count($languages) <= 0) 00835 { 00836 $languages["*"] = 1; 00837 } 00838 00839 arsort($languages, SORT_NUMERIC); 00840 00841 $notAcceptable406 = TRUE; 00842 00843 foreach($languages as $language => $q) 00844 { 00845 $language = strtolower($language); 00846 00847 if($language == "en" || $language == "*") 00848 { 00849 $this->status = 200; 00850 $this->statusMsg = "OK"; 00851 $this->language = "en"; 00852 00853 $notAcceptable406 = FALSE; 00854 00855 break; 00856 } 00857 } 00858 00859 if($notAcceptable406) 00860 { 00861 /* $this->status = 406; 00862 $this->statusMsg = "Not Acceptable"; 00863 $this->statusMsgExt = "Unacceptable language requested";*/ 00864 } 00865 } 00866 else 00867 { 00868 // If no access header specified; it means that the client accept *anything* 00869 // In such a case we send back utf-8 00870 $this->status = 200; 00871 $this->statusMsg = "OK"; 00872 $this->language = "en"; 00873 } 00874 } 00875 } 00876 00878 00879 ?>
