Merge branch 'master' into 0.9.x
This commit is contained in:
commit
59a413cf5e
@ -59,7 +59,8 @@ class ApiStatusnetConfigAction extends ApiAction
|
|||||||
'notice' => array('contentlimit'),
|
'notice' => array('contentlimit'),
|
||||||
'throttle' => array('enabled', 'count', 'timespan'),
|
'throttle' => array('enabled', 'count', 'timespan'),
|
||||||
'xmpp' => array('enabled', 'server', 'port', 'user'),
|
'xmpp' => array('enabled', 'server', 'port', 'user'),
|
||||||
'integration' => array('source')
|
'integration' => array('source'),
|
||||||
|
'attachments' => array('uploads', 'file_quota')
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,7 +97,7 @@ class ApiStatusnetConfigAction extends ApiAction
|
|||||||
foreach ($this->keys as $section => $settings) {
|
foreach ($this->keys as $section => $settings) {
|
||||||
$this->elementStart($section);
|
$this->elementStart($section);
|
||||||
foreach ($settings as $setting) {
|
foreach ($settings as $setting) {
|
||||||
$value = common_config($section, $setting);
|
$value = $this->setting($section, $setting);
|
||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
$value = implode(',', $value);
|
$value = implode(',', $value);
|
||||||
} else if ($value === false || $value == '0') {
|
} else if ($value === false || $value == '0') {
|
||||||
@ -125,7 +126,7 @@ class ApiStatusnetConfigAction extends ApiAction
|
|||||||
$result[$section] = array();
|
$result[$section] = array();
|
||||||
foreach ($settings as $setting) {
|
foreach ($settings as $setting) {
|
||||||
$result[$section][$setting]
|
$result[$section][$setting]
|
||||||
= common_config($section, $setting);
|
= $this->setting($section, $setting);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->initDocument('json');
|
$this->initDocument('json');
|
||||||
@ -143,6 +144,20 @@ class ApiStatusnetConfigAction extends ApiAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setting($section, $key) {
|
||||||
|
$result = common_config($section, $key);
|
||||||
|
if ($key == 'file_quota') {
|
||||||
|
// hack: adjust for the live upload limit
|
||||||
|
if (common_config($section, 'uploads')) {
|
||||||
|
$max = ImageFile::maxFileSizeInt();
|
||||||
|
} else {
|
||||||
|
$max = 0;
|
||||||
|
}
|
||||||
|
return min($result, $max);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if read only.
|
* Return true if read only.
|
||||||
*
|
*
|
||||||
|
@ -202,13 +202,20 @@ class SearchNoticeListItem extends NoticeListItem {
|
|||||||
$options = implode('|', array_map('preg_quote', array_map('htmlspecialchars', $terms),
|
$options = implode('|', array_map('preg_quote', array_map('htmlspecialchars', $terms),
|
||||||
array_fill(0, sizeof($terms), '/')));
|
array_fill(0, sizeof($terms), '/')));
|
||||||
$pattern = "/($options)/i";
|
$pattern = "/($options)/i";
|
||||||
$result = preg_replace($pattern, '<strong>\\1</strong>', $text);
|
$result = '';
|
||||||
|
|
||||||
|
/* Divide up into text (highlight me) and tags (don't touch) */
|
||||||
|
$chunks = preg_split('/(<[^>]+>)/', $text, 0, PREG_SPLIT_DELIM_CAPTURE);
|
||||||
|
foreach ($chunks as $i => $chunk) {
|
||||||
|
if ($i % 2 == 1) {
|
||||||
|
// odd: delimiter (tag)
|
||||||
|
$result .= $chunk;
|
||||||
|
} else {
|
||||||
|
// even: freetext between tags
|
||||||
|
$result .= preg_replace($pattern, '<strong>\\1</strong>', $chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Remove highlighting from inside links, loop incase multiple highlights in links */
|
|
||||||
$pattern = '/(\w+="[^"]*)<strong>('.$options.')<\/strong>([^"]*")/iU';
|
|
||||||
do {
|
|
||||||
$result = preg_replace($pattern, '\\1\\2\\3', $result, -1, $count);
|
|
||||||
} while ($count);
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -854,8 +854,11 @@ class Action extends HTMLOutputter // lawsuit
|
|||||||
function showFooter()
|
function showFooter()
|
||||||
{
|
{
|
||||||
$this->elementStart('div', array('id' => 'footer'));
|
$this->elementStart('div', array('id' => 'footer'));
|
||||||
|
if (Event::handle('StartShowInsideFooter', array($this))) {
|
||||||
$this->showSecondaryNav();
|
$this->showSecondaryNav();
|
||||||
$this->showLicenses();
|
$this->showLicenses();
|
||||||
|
Event::handle('EndShowInsideFooter', array($this));
|
||||||
|
}
|
||||||
$this->elementEnd('div');
|
$this->elementEnd('div');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,9 @@ class MobileProfilePlugin extends WAP20Plugin
|
|||||||
$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'])) {
|
$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'])) {
|
||||||
|
|
||||||
$this->serveMobile = true;
|
$this->serveMobile = true;
|
||||||
|
} else if (isset($_COOKIE['MobileOverride'])) {
|
||||||
|
// Cookie override is controlled by link at bottom.
|
||||||
|
$this->serveMobile = (bool)$_COOKIE['MobileOverride'];
|
||||||
} else {
|
} else {
|
||||||
// If they like the WAP 2.0 mimetype, serve them MP
|
// If they like the WAP 2.0 mimetype, serve them MP
|
||||||
// @fixme $type is undefined, making this if case useless and spewing errors.
|
// @fixme $type is undefined, making this if case useless and spewing errors.
|
||||||
@ -381,9 +384,40 @@ class MobileProfilePlugin extends WAP20Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onStartShowScripts($action)
|
function onEndShowScripts($action)
|
||||||
{
|
{
|
||||||
|
$action->inlineScript('
|
||||||
|
$(function() {
|
||||||
|
$("#mobile-toggle-disable").click(function() {
|
||||||
|
$.cookie("MobileOverride", "0", {path: "/"});
|
||||||
|
window.location.reload();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$("#mobile-toggle-enable").click(function() {
|
||||||
|
$.cookie("MobileOverride", "1", {path: "/"});
|
||||||
|
window.location.reload();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function onEndShowInsideFooter($action)
|
||||||
|
{
|
||||||
|
if ($this->serveMobile) {
|
||||||
|
// TRANS: Link to switch site layout from mobile to desktop mode. Appears at very bottom of page.
|
||||||
|
$linkText = _m('Switch to desktop site layout.');
|
||||||
|
$key = 'mobile-toggle-disable';
|
||||||
|
} else {
|
||||||
|
// TRANS: Link to switch site layout from desktop to mobile mode. Appears at very bottom of page.
|
||||||
|
$linkText = _m('Switch to mobile site layout.');
|
||||||
|
$key = 'mobile-toggle-enable';
|
||||||
|
}
|
||||||
|
$action->elementStart('p');
|
||||||
|
$action->element('a', array('href' => '#', 'id' => $key), $linkText);
|
||||||
|
$action->elementEnd('p');
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _common_path($relative, $ssl=false)
|
function _common_path($relative, $ssl=false)
|
||||||
|
@ -554,8 +554,8 @@ class TwitterImport
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Move all the entities into order so we can
|
// Move all the entities into order so we can
|
||||||
// replace them in reverse order and thus
|
// replace them and escape surrounding plaintext
|
||||||
// not mess up their indices
|
// in order
|
||||||
|
|
||||||
$toReplace = array();
|
$toReplace = array();
|
||||||
|
|
||||||
@ -577,56 +577,85 @@ class TwitterImport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort in reverse order by key
|
// sort in forward order by key
|
||||||
|
|
||||||
krsort($toReplace);
|
ksort($toReplace);
|
||||||
|
|
||||||
|
$result = '';
|
||||||
|
$cursor = 0;
|
||||||
|
|
||||||
foreach ($toReplace as $part) {
|
foreach ($toReplace as $part) {
|
||||||
list($type, $object) = $part;
|
list($type, $object) = $part;
|
||||||
|
$start = $object->indices[0];
|
||||||
|
$end = $object->indices[1];
|
||||||
|
if ($cursor < $start) {
|
||||||
|
// Copy in the preceding plaintext
|
||||||
|
$result .= $this->twitEscape(mb_substr($text, $cursor, $start - $cursor));
|
||||||
|
$cursor = $start;
|
||||||
|
}
|
||||||
|
$orig = $this->twitEscape(mb_substr($text, $start, $end - $start));
|
||||||
switch($type) {
|
switch($type) {
|
||||||
case self::URL:
|
case self::URL:
|
||||||
$linkText = $this->makeUrlLink($object);
|
$linkText = $this->makeUrlLink($object, $orig);
|
||||||
break;
|
break;
|
||||||
case self::HASHTAG:
|
case self::HASHTAG:
|
||||||
$linkText = $this->makeHashtagLink($object);
|
$linkText = $this->makeHashtagLink($object, $orig);
|
||||||
break;
|
break;
|
||||||
case self::MENTION:
|
case self::MENTION:
|
||||||
$linkText = $this->makeMentionLink($object);
|
$linkText = $this->makeMentionLink($object, $orig);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
$linkText = $orig;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$text = mb_substr($text, 0, $object->indices[0]) . $linkText . mb_substr($text, $object->indices[1]);
|
$result .= $linkText;
|
||||||
|
$cursor = $end;
|
||||||
}
|
}
|
||||||
return $text;
|
$last = $this->twitEscape(mb_substr($text, $cursor));
|
||||||
|
$result .= $last;
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeUrlLink($object)
|
function twitEscape($str)
|
||||||
{
|
{
|
||||||
return "<a href='{$object->url}' class='extlink'>{$object->url}</a>";
|
// Twitter seems to preemptive turn < and > into < and >
|
||||||
|
// but doesn't for &, so while you may have some magic protection
|
||||||
|
// against XSS by not bothing to escape manually, you still get
|
||||||
|
// invalid XHTML. Thanks!
|
||||||
|
//
|
||||||
|
// Looks like their web interface pretty much sends anything
|
||||||
|
// through intact, so.... to do equivalent, decode all entities
|
||||||
|
// and then re-encode the special ones.
|
||||||
|
return htmlspecialchars(html_entity_decode($str, ENT_COMPAT, 'UTF-8'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeHashtagLink($object)
|
function makeUrlLink($object, $orig)
|
||||||
{
|
{
|
||||||
return "#" . self::tagLink($object->text);
|
return "<a href='{$object->url}' class='extlink'>{$orig}</a>";
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeMentionLink($object)
|
function makeHashtagLink($object, $orig)
|
||||||
{
|
{
|
||||||
return "@".self::atLink($object->screen_name, $object->name);
|
return "#" . self::tagLink($object->text, substr($orig, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static function tagLink($tag)
|
function makeMentionLink($object, $orig)
|
||||||
{
|
{
|
||||||
return "<a href='https://search.twitter.com/search?q=%23{$tag}' class='hashtag'>{$tag}</a>";
|
return "@".self::atLink($object->screen_name, $object->name, substr($orig, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static function atLink($screenName, $fullName=null)
|
static function tagLink($tag, $orig)
|
||||||
|
{
|
||||||
|
return "<a href='https://search.twitter.com/search?q=%23{$tag}' class='hashtag'>{$orig}</a>";
|
||||||
|
}
|
||||||
|
|
||||||
|
static function atLink($screenName, $fullName, $orig)
|
||||||
{
|
{
|
||||||
if (!empty($fullName)) {
|
if (!empty($fullName)) {
|
||||||
return "<a href='http://twitter.com/#!/{$screenName}' title='{$fullName}'>{$screenName}</a>";
|
return "<a href='http://twitter.com/#!/{$screenName}' title='{$fullName}'>{$orig}</a>";
|
||||||
} else {
|
} else {
|
||||||
return "<a href='http://twitter.com/#!/{$screenName}'>{$screenName}</a>";
|
return "<a href='http://twitter.com/#!/{$screenName}'>{$orig}</a>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user