add content negotiation for media type

darcs-hash:20080613144913-84dde-3e970b4e6f19ea1e0db09d7ab133a6c148be7a75.gz
This commit is contained in:
Evan Prodromou 2008-06-13 10:49:13 -04:00
parent ad7aa68a99
commit a86477aad3
2 changed files with 99 additions and 7 deletions

View File

@ -91,8 +91,8 @@ First public release (theoretically). Added distributed subscriptions,
+ log of consumers who ask for access + log of consumers who ask for access
+ receive remote notice + receive remote notice
+ send remote notice + send remote notice
- receive remote profile update + receive remote profile update
- send remote profile update + send remote profile update
+ subscribe form for not-logged-in users on showstream + subscribe form for not-logged-in users on showstream
+ pretty URLs + pretty URLs
+ doc action + doc action
@ -138,8 +138,8 @@ First public release (theoretically). Added distributed subscriptions,
- graphic refresh on remotesubscribe - graphic refresh on remotesubscribe
+ graphic refresh on shownotice + graphic refresh on shownotice
+ graphic refresh on showstream + graphic refresh on showstream
- graphic refresh on subscribed + graphic refresh on subscribed
- graphic refresh on subscriptions + graphic refresh on subscriptions
+ graphic refresh on userauthorization + graphic refresh on userauthorization
- update default theme to use new, more semantic, HTML - update default theme to use new, more semantic, HTML
- subscribe/unsubscribe on subscriptions page - 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 settings
+ correct use of views menu in streams + correct use of views menu in streams
- INSTALL file - INSTALL file
- content negotiation for content type
Release 0.4 Release 0.4
----------- -----------
- jQuery for as much as possible
- microid for profile page - microid for profile page
- format times per user - format times per user
- timezone preferences in Profile settings - timezone preferences in Profile settings
@ -164,8 +166,6 @@ Release 0.4
- email confirmation for registration - email confirmation for registration
- email options - email options
- change cookie handling for anon users to be more cache-friendly - 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 - content negotiation for encoding
- If-Modified-Since support - If-Modified-Since support
- Vary - Vary

View File

@ -123,10 +123,24 @@ function common_end_xml() {
$xw->flush(); $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) { function common_show_header($pagetitle, $callable=NULL, $data=NULL, $headercall=NULL) {
global $config, $xw; 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', common_start_xml('html',
'-//W3C//DTD XHTML 1.0 Strict//EN', '-//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'); 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;
}