From a86477aad3bab8ad519626c56e3e253faea50518 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 13 Jun 2008 10:49:13 -0400 Subject: add content negotiation for media type darcs-hash:20080613144913-84dde-3e970b4e6f19ea1e0db09d7ab133a6c148be7a75.gz --- doc/roadmap | 12 ++++---- lib/util.php | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 7 deletions(-) diff --git a/doc/roadmap b/doc/roadmap index a3e725833..4caeb4e61 100644 --- a/doc/roadmap +++ b/doc/roadmap @@ -91,8 +91,8 @@ First public release (theoretically). Added distributed subscriptions, + log of consumers who ask for access + receive remote notice + send remote notice -- receive remote profile update -- send remote profile update ++ receive remote profile update ++ send remote profile update + subscribe form for not-logged-in users on showstream + pretty URLs + doc action @@ -138,8 +138,8 @@ First public release (theoretically). Added distributed subscriptions, - graphic refresh on remotesubscribe + graphic refresh on shownotice + graphic refresh on showstream -- graphic refresh on subscribed -- graphic refresh on subscriptions ++ graphic refresh on subscribed ++ graphic refresh on subscriptions + graphic refresh on userauthorization - update default theme to use new, more semantic, HTML - subscribe/unsubscribe on subscriptions page @@ -147,10 +147,12 @@ First public release (theoretically). Added distributed subscriptions, + correct use of views menu in settings + correct use of views menu in streams - INSTALL file +- content negotiation for content type Release 0.4 ----------- +- jQuery for as much as possible - microid for profile page - format times per user - timezone preferences in Profile settings @@ -164,8 +166,6 @@ Release 0.4 - email confirmation for registration - email options - change cookie handling for anon users to be more cache-friendly -- jQuery for as much as possible -- content negotiation for content type - content negotiation for encoding - If-Modified-Since support - Vary diff --git a/lib/util.php b/lib/util.php index d6c1a9f8b..e1e508176 100644 --- a/lib/util.php +++ b/lib/util.php @@ -123,10 +123,24 @@ function common_end_xml() { $xw->flush(); } +define('PAGE_TYPE_PREFS', 'application/xhtml+xml,text/html;q=0.7,application/xml;q=0.3,text/xml;q=0.2'); + function common_show_header($pagetitle, $callable=NULL, $data=NULL, $headercall=NULL) { global $config, $xw; - header('Content-Type: application/xhtml+xml'); + $httpaccept = isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : NULL; + + # XXX: allow content negotiation for RDF, RSS, or XRDS + + $type = common_negotiate_type(common_accept_to_prefs($httpaccept), + common_accept_to_prefs(PAGE_TYPE_PREFS)); + + if (!$type) { + common_client_error(_t('This page is not available in a media type you accept'), 406); + exit(0); + } + + header('Content-Type: '.$type); common_start_xml('html', '-//W3C//DTD XHTML 1.0 Strict//EN', @@ -736,3 +750,81 @@ function common_pagination($have_before, $have_after, $page, $action, $args=NULL common_element_end('div'); } } + +/* Following functions are copied from MediaWiki GlobalFunctions.php + * and written by Evan Prodromou. */ + +function common_accept_to_prefs($accept, $def = '*/*') { + # No arg means accept anything (per HTTP spec) + if(!$accept) { + return array($def => 1); + } + + $prefs = array(); + + $parts = explode(',', $accept); + + foreach($parts as $part) { + # FIXME: doesn't deal with params like 'text/html; level=1' + @list($value, $qpart) = explode(';', $part); + $match = array(); + if(!isset($qpart)) { + $prefs[$value] = 1; + } elseif(preg_match('/q\s*=\s*(\d*\.\d+)/', $qpart, $match)) { + $prefs[$value] = $match[1]; + } + } + + return $prefs; +} + +function common_mime_type_match($type, $avail) { + if(array_key_exists($type, $avail)) { + return $type; + } else { + $parts = explode('/', $type); + if(array_key_exists($parts[0] . '/*', $avail)) { + return $parts[0] . '/*'; + } elseif(array_key_exists('*/*', $avail)) { + return '*/*'; + } else { + return NULL; + } + } +} + +function common_negotiate_type($cprefs, $sprefs) { + $combine = array(); + + foreach(array_keys($sprefs) as $type) { + $parts = explode('/', $type); + if($parts[1] != '*') { + $ckey = common_mime_type_match($type, $cprefs); + if($ckey) { + $combine[$type] = $sprefs[$type] * $cprefs[$ckey]; + } + } + } + + foreach(array_keys($cprefs) as $type) { + $parts = explode('/', $type); + if($parts[1] != '*' && !array_key_exists($type, $sprefs)) { + $skey = common_mime_type_match($type, $sprefs); + if($skey) { + $combine[$type] = $sprefs[$skey] * $cprefs[$type]; + } + } + } + + $bestq = 0; + $besttype = NULL; + + foreach(array_keys($combine) as $type) { + if($combine[$type] > $bestq) { + $besttype = $type; + $bestq = $combine[$type]; + } + } + + return $besttype; +} -- cgit v1.2.3-54-g00ecf