Merge branch 'nightly' into file_urlhash

This commit is contained in:
Mikael Nordfeldth 2015-02-19 18:13:09 +01:00
commit 176bde269f
14 changed files with 204 additions and 224 deletions

View File

@ -41,6 +41,7 @@ functional setup of GNU Social:
- php5-curl Fetching files by HTTP.
- php5-gd Image manipulation (scaling).
- php5-gmp For Salmon signatures (part of OStatus).
- php5-intl Internationalization support (transliteration et al).
- php5-json For WebFinger lookups and more.
- php5-mysqlnd The native driver for PHP5 MariaDB connections. If you
use MySQL, 'mysql' or 'mysqli' may work.

View File

@ -405,7 +405,7 @@ class ApiTimelineUserAction extends ApiBareAuthAction
// Get (safe!) HTML and text versions of the content
$rendered = $this->purify($sourceContent);
$rendered = common_purify($sourceContent);
$content = common_strip_html($rendered);
$shortened = $this->auth_user->shortenLinks($content);
@ -504,13 +504,4 @@ class ApiTimelineUserAction extends ApiBareAuthAction
return $saved;
}
function purify($content)
{
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
$config = array('safe' => 1,
'deny_attribute' => 'id,style,on*');
return htmLawed($content, $config);
}
}

View File

@ -313,7 +313,7 @@ class EmailsettingsAction extends SettingsAction
*/
function savePreferences()
{
$user = common_current_user();
$user = $this->scoped->getUser();
if (Event::handle('StartEmailSaveForm', array($this, $this->scoped))) {
$emailnotifysub = $this->boolean('emailnotifysub');
@ -323,8 +323,6 @@ class EmailsettingsAction extends SettingsAction
$emailmicroid = $this->boolean('emailmicroid');
$emailpost = $this->boolean('emailpost');
assert(!is_null($user)); // should already be checked
$user->query('BEGIN');
$original = clone($user);
@ -340,6 +338,7 @@ class EmailsettingsAction extends SettingsAction
if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__);
$user->query('ROLLBACK');
// TRANS: Server error thrown on database error updating e-mail preferences.
$this->serverError(_('Could not update user.'));
}

View File

@ -299,6 +299,11 @@ abstract class Managed_DataObject extends Memcached_DataObject
return $ckeys;
}
public function escapedTableName()
{
return common_database_tablename($this->tableName());
}
/**
* Returns an ID, checked that it is set and reasonably valid
*

View File

@ -213,7 +213,7 @@ class ActivityImporter extends QueueHandler
// Get (safe!) HTML and text versions of the content
$rendered = $this->purify($sourceContent);
$rendered = common_purify($sourceContent);
$content = common_strip_html($rendered);
$shortened = $user->shortenLinks($content);
@ -338,15 +338,4 @@ class ActivityImporter extends QueueHandler
return array($groups, $replies);
}
function purify($content)
{
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
$config = array('safe' => 1,
'deny_attribute' => 'id,style,on*');
return htmLawed($content, $config);
}
}

View File

@ -207,6 +207,9 @@ $default =
'newuser' =>
array('default' => null,
'welcome' => null),
'linkify' => array(
'bare_domains' => false, // convert domain.com to <a href="http://domain.com/" ...>domain.com</a> ?
),
'attachments' =>
array('server' => null,
'dir' => INSTALLDIR . '/file/',

View File

@ -101,7 +101,7 @@ abstract class Installer
$pass = false;
}
$reqs = array('gd', 'curl', 'json',
$reqs = array('gd', 'curl', 'intl', 'json',
'xmlwriter', 'mbstring', 'xml', 'dom', 'simplexml');
foreach ($reqs as $req) {

View File

@ -576,6 +576,25 @@ function common_canonical_email($email)
return $email;
}
function common_purify($html)
{
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
$config = array('safe' => 1,
'deny_attribute' => 'id,style,on*');
$html = common_remove_unicode_formatting($html);
return htmLawed($html, $config);
}
function common_remove_unicode_formatting($text)
{
// Strip Unicode text formatting/direction codes
// this is pretty dangerous for visualisation of text and can be used for mischief
return preg_replace('/[\\x{200b}-\\x{200f}\\x{202a}-\\x{202e}]/u', '', $text);
}
/**
* Partial notice markup rendering step: build links to !group references.
*
@ -585,9 +604,9 @@ function common_canonical_email($email)
*/
function common_render_content($text, Notice $notice)
{
$r = common_render_text($text);
$r = common_linkify_mentions($r, $notice);
return $r;
$text = common_render_text($text);
$text = common_linkify_mentions($text, $notice);
return $text;
}
/**
@ -829,14 +848,15 @@ function common_find_mentions_raw($text)
function common_render_text($text)
{
$r = nl2br(htmlspecialchars($text));
$text = common_remove_unicode_formatting($text);
$text = nl2br(htmlspecialchars($text));
$r = preg_replace('/[\x{0}-\x{8}\x{b}-\x{c}\x{e}-\x{19}]/', '', $r);
$r = common_replace_urls_callback($r, 'common_linkify');
$r = preg_replace_callback('/(^|\&quot\;|\'|\(|\[|\{|\s+)#([\pL\pN_\-\.]{1,64})/u',
function ($m) { return "{$m[1]}#".common_tag_link($m[2]); }, $r);
$text = preg_replace('/[\x{0}-\x{8}\x{b}-\x{c}\x{e}-\x{19}]/', '', $text);
$text = common_replace_urls_callback($text, 'common_linkify');
$text = preg_replace_callback('/(^|\&quot\;|\'|\(|\[|\{|\s+)#([\pL\pN_\-\.]{1,64})/u',
function ($m) { return "{$m[1]}#".common_tag_link($m[2]); }, $text);
// XXX: machine tags
return $r;
return $text;
}
/**
@ -870,12 +890,15 @@ function common_replace_urls_callback($text, $callback, $arg = null) {
'|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'. //IPv4
'|(?:'. //IPv6
'\[?(?:(?:(?:[0-9A-Fa-f]{1,4}:){7}(?:(?:[0-9A-Fa-f]{1,4})|:))|(?:(?:[0-9A-Fa-f]{1,4}:){6}(?::|(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})|(?::[0-9A-Fa-f]{1,4})))|(?:(?:[0-9A-Fa-f]{1,4}:){5}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:[0-9A-Fa-f]{1,4}:){4}(?::[0-9A-Fa-f]{1,4}){0,1}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:[0-9A-Fa-f]{1,4}:){3}(?::[0-9A-Fa-f]{1,4}){0,2}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:[0-9A-Fa-f]{1,4}:){2}(?::[0-9A-Fa-f]{1,4}){0,3}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:[0-9A-Fa-f]{1,4}:)(?::[0-9A-Fa-f]{1,4}){0,4}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?::(?::[0-9A-Fa-f]{1,4}){0,5}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))\]?(?<!:)'.
')|(?:'. //DNS
'(?:[\pN\pL\-\_\+\%\~]+(?:\:[\pN\pL\-\_\+\%\~]+)?\@)?'. //user:pass@
'[\pN\pL\-\_]+(?:\.[\pN\pL\-\_]+)*\.'.
//tld list from http://data.iana.org/TLD/tlds-alpha-by-domain.txt, also added local, loc, and onion
'(?:AC|AD|AE|AERO|AF|AG|AI|AL|AM|AN|AO|AQ|AR|ARPA|AS|ASIA|AT|AU|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BIZ|BJ|BM|BN|BO|BR|BS|BT|BV|BW|BY|BZ|CA|CAT|CC|CD|CF|CG|CH|CI|CK|CL|CM|CN|CO|COM|COOP|CR|CU|CV|CX|CY|CZ|DE|DJ|DK|DM|DO|DZ|EC|EDU|EE|EG|ER|ES|ET|EU|FI|FJ|FK|FM|FO|FR|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GOV|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|ID|IE|IL|IM|IN|INFO|INT|IO|IQ|IR|IS|IT|JE|JM|JO|JOBS|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MG|MH|MIL|MK|ML|MM|MN|MO|MOBI|MP|MQ|MR|MS|MT|MU|MUSEUM|MV|MW|MX|MY|MZ|NA|NAME|NC|NE|NET|NF|NG|NI|NL|NO|NP|NR|NU|NZ|OM|ORG|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PRO|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|ST|SU|SV|SY|SZ|TC|TD|TEL|TF|TG|TH|TJ|TK|TL|TM|TN|TO|TP|TR|TRAVEL|TT|TV|TW|TZ|UA|UG|UK|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|XN--0ZWM56D|测试|XN--11B5BS3A9AJ6G|परीक्षा|XN--80AKHBYKNJ4F|испытание|XN--9T4B11YI5A|테스트|XN--DEBA0AD|טעסט|XN--G6W251D|測試|XN--HGBK6AJ7F53BBA|آزمایشی|XN--HLCJ6AYA9ESC7A|பரிட்சை|XN--JXALPDLP|δοκιμή|XN--KGBECHTV|إختبار|XN--ZCKZAH|テスト|YE|YT|YU|ZA|ZM|ZONE|ZW|local|loc|onion)'.
')(?![\pN\pL\-\_])'.
')'.
(common_config('linkify', 'bare_domains')
? '|(?:'. //DNS
'(?:[\pN\pL\-\_\+\%\~]+(?:\:[\pN\pL\-\_\+\%\~]+)?\@)?'. //user:pass@
'[\pN\pL\-\_]+(?:\.[\pN\pL\-\_]+)*\.'.
//tld list from http://data.iana.org/TLD/tlds-alpha-by-domain.txt, also added local, loc, and onion
'(?:AC|AD|AE|AERO|AF|AG|AI|AL|AM|AN|AO|AQ|AR|ARPA|AS|ASIA|AT|AU|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BIZ|BJ|BM|BN|BO|BR|BS|BT|BV|BW|BY|BZ|CA|CAT|CC|CD|CF|CG|CH|CI|CK|CL|CM|CN|CO|COM|COOP|CR|CU|CV|CX|CY|CZ|DE|DJ|DK|DM|DO|DZ|EC|EDU|EE|EG|ER|ES|ET|EU|FI|FJ|FK|FM|FO|FR|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GOV|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|ID|IE|IL|IM|IN|INFO|INT|IO|IQ|IR|IS|IT|JE|JM|JO|JOBS|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MG|MH|MIL|MK|ML|MM|MN|MO|MOBI|MP|MQ|MR|MS|MT|MU|MUSEUM|MV|MW|MX|MY|MZ|NA|NAME|NC|NE|NET|NF|NG|NI|NL|NO|NP|NR|NU|NZ|OM|ORG|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PRO|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|ST|SU|SV|SY|SZ|TC|TD|TEL|TF|TG|TH|TJ|TK|TL|TM|TN|TO|TP|TR|TRAVEL|TT|TV|TW|TZ|UA|UG|UK|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|XN--0ZWM56D|测试|XN--11B5BS3A9AJ6G|परीक्षा|XN--80AKHBYKNJ4F|испытание|XN--9T4B11YI5A|테스트|XN--DEBA0AD|טעסט|XN--G6W251D|測試|XN--HGBK6AJ7F53BBA|آزمایشی|XN--HLCJ6AYA9ESC7A|பரிட்சை|XN--JXALPDLP|δοκιμή|XN--KGBECHTV|إختبار|XN--ZCKZAH|テスト|YE|YT|YU|ZA|ZM|ZONE|ZW|local|loc|onion)'.
')(?![\pN\pL\-\_])'
: '') . // if common_config('linkify', 'bare_domains') is false, don't add anything here
')'.
'(?:'.
'(?:\:\d+)?'. //:port
@ -1116,6 +1139,20 @@ function common_xml_safe_str($str)
return preg_replace('/[\p{Cc}\p{Cs}]/u', '*', $str);
}
function common_slugify($str)
{
$str = transliterator_transliterate(
'Any-Latin;' . // any charset to latin compatible
'NFD;' . // decompose
'[:Nonspacing Mark:] Remove;' . // remove nonspacing marks (accents etc.)
'NFC;' . // composite again
'[:Punctuation:] Remove;' . // remove punctuation (.,¿? etc.)
'Lower();' . // turn into lowercase
'Latin-ASCII;', // get ASCII equivalents (ð to d for example)
$str);
return preg_replace('/[^\pL\pN]/', '', $str);
}
function common_tag_link($tag)
{
$canonical = common_canonical_tag($tag);
@ -1139,11 +1176,9 @@ function common_tag_link($tag)
function common_canonical_tag($tag)
{
// only alphanum
$tag = preg_replace('/[^\pL\pN]/u', '', $tag);
$tag = mb_convert_case($tag, MB_CASE_LOWER, "UTF-8");
$tag = substr($tag, 0, 64);
return $tag;
$tag = common_slugify($tag);
$tag = substr($tag, 0, 64);
return $tag;
}
function common_valid_profile_tag($str)

View File

@ -117,10 +117,10 @@ class Blog_entry extends Managed_DataObject
$be->id = (string) new UUID();
$be->profile_id = $profile->id;
$be->title = $title; // Note: not HTML-protected
$be->content = self::purify($content);
$be->content = common_purify($content);
if (array_key_exists('summary', $options)) {
$be->summary = self::purify($options['summary']);
$be->summary = common_purify($options['summary']);
} else {
// Already purified
$be->summary = self::summarize($be->content);
@ -241,18 +241,4 @@ class Blog_entry extends Managed_DataObject
return $obj;
}
/**
* Clean up input HTML
*/
static function purify($html)
{
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
$config = array('safe' => 1,
'deny_attribute' => 'id,style,on*');
$pure = htmLawed($html, $config);
return $pure;
}
}

View File

@ -27,12 +27,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET'))
{
exit(1);
}
require_once INSTALLDIR . '/lib/publicgroupnav.php';
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Group directory
@ -40,10 +35,11 @@ require_once INSTALLDIR . '/lib/publicgroupnav.php';
* @category Directory
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @author Mikael Nordfeldth <mmn@hethane.se>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class GroupdirectoryAction extends Action
class GroupdirectoryAction extends ManagedAction
{
/**
* The page we're on
@ -138,17 +134,8 @@ class GroupdirectoryAction extends Action
return true;
}
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*/
function prepare($args)
protected function doPreparation()
{
parent::prepare($args);
$this->page = ($this->arg('page')) ? ($this->arg('page') + 0) : 1;
$this->filter = $this->arg('filter', 'all');
$this->reverse = $this->boolean('reverse');
@ -156,23 +143,6 @@ class GroupdirectoryAction extends Action
$this->sort = $this->arg('sort', 'nickname');
common_set_returnto($this->selfUrl());
return true;
}
/**
* Handle request
*
* Shows the page
*
* @param array $args $_REQUEST args; handled in prepare()
*
* @return void
*/
function handle($args)
{
parent::handle($args);
$this->showPage();
}
/**
@ -303,74 +273,61 @@ class GroupdirectoryAction extends Action
{
$group = new User_group();
$offset = ($this->page-1) * PROFILES_PER_PAGE;
$limit = PROFILES_PER_PAGE + 1;
// Disable this to get global group searches
$group->joinAdd(array('id', 'local_group:group_id'));
if (isset($this->q)) {
$order = false;
$order = 'user_group.created ASC';
if ($this->sort == 'nickname') {
if ($this->reverse) {
$order = 'user_group.nickname DESC';
} else {
$order = 'user_group.nickname ASC';
}
} else {
if ($this->reverse) {
$order = 'user_group.created DESC';
}
}
$sql = <<< GROUP_QUERY_END
SELECT user_group.*
FROM user_group
JOIN local_group ON user_group.id = local_group.group_id
ORDER BY %s
LIMIT %d, %d
GROUP_QUERY_END;
$cnt = 0;
$group->query(sprintf($sql, $order, $limit, $offset));
$group->find();
if (!empty($this->q)) {
$wheres = array('nickname', 'fullname', 'homepage', 'description', 'location');
foreach ($wheres as $where) {
// Double % because of sprintf
$group->whereAdd(sprintf('LOWER(%1$s.%2$s) LIKE LOWER("%%%3$s%%")',
$group->escapedTableName(), $where,
$group->escape($this->q)),
'OR');
}
$order = sprintf('%1$s.%2$s %3$s',
$group->escapedTableName(),
$this->getSortKey('created'),
$this->reverse ? 'DESC' : 'ASC');
} else {
// User is browsing via AlphaNav
$sort = $this->getSortKey();
$sql = <<< GROUP_QUERY_END
SELECT user_group.*
FROM user_group
JOIN local_group ON user_group.id = local_group.group_id
GROUP_QUERY_END;
switch($this->filter)
{
switch($this->filter) {
case 'all':
// NOOP
break;
case '0-9':
$sql .=
' AND LEFT(user_group.nickname, 1) BETWEEN \'0\' AND \'9\'';
$group->whereAdd(sprintf('LEFT(%1$s.%2$s, 1) BETWEEN %3$s AND %4$s',
$group->escapedTableName(),
'nickname',
$group->_quote("0"),
$group->_quote("9")));
break;
default:
$sql .= sprintf(
' AND LEFT(LOWER(user_group.nickname), 1) = \'%s\'',
$this->filter
);
$group->whereAdd(sprintf('LEFT(LOWER(%1$s.%2$s), 1) = %3$s',
$group->escapedTableName(),
'nickname',
$group->_quote($this->filter)));
}
$sql .= sprintf(
' ORDER BY user_group.%s %s, user_group.nickname ASC LIMIT %d, %d',
$sort,
$this->reverse ? 'DESC' : 'ASC',
$offset,
$limit
);
$group->query($sql);
$order = sprintf('%1$s.%2$s %3$s, %1$s.%4$s ASC',
$group->escapedTableName(),
$this->getSortKey('nickname'),
$this->reverse ? 'DESC' : 'ASC',
'nickname');
}
$offset = ($this->page-1) * PROFILES_PER_PAGE;
$limit = PROFILES_PER_PAGE + 1;
$group->orderBy($order);
$group->limit($offset, $limit);
$group->find();
return $group;
}
@ -379,17 +336,14 @@ GROUP_QUERY_END;
*
* @return string a column name for sorting
*/
function getSortKey()
function getSortKey($def='created')
{
switch ($this->sort) {
case 'nickname':
return $this->sort;
break;
case 'created':
return $this->sort;
break;
default:
return 'nickname';
return $def;
}
}

View File

@ -27,12 +27,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET'))
{
exit(1);
}
require_once INSTALLDIR . '/lib/publicgroupnav.php';
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* User directory
@ -43,7 +38,7 @@ require_once INSTALLDIR . '/lib/publicgroupnav.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class UserdirectoryAction extends Action
class UserdirectoryAction extends ManagedAction
{
/**
* The page we're on
@ -137,17 +132,8 @@ class UserdirectoryAction extends Action
return true;
}
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*/
function prepare($args)
protected function doPreparation()
{
parent::prepare($args);
$this->page = ($this->arg('page')) ? ($this->arg('page') + 0) : 1;
$this->filter = $this->arg('filter', 'all');
$this->reverse = $this->boolean('reverse');
@ -155,23 +141,6 @@ class UserdirectoryAction extends Action
$this->sort = $this->arg('sort', 'nickname');
common_set_returnto($this->selfUrl());
return true;
}
/**
* Handle request
*
* Shows the page
*
* @param array $args $_REQUEST args; handled in prepare()
*
* @return void
*/
function handle($args)
{
parent::handle($args);
$this->showPage();
}
/**
@ -291,10 +260,13 @@ class UserdirectoryAction extends Action
{
$profile = new Profile();
// Comment this out or disable to get global profile searches
$profile->joinAdd(array('id', 'user:id'));
$offset = ($this->page - 1) * PROFILES_PER_PAGE;
$limit = PROFILES_PER_PAGE + 1;
if (isset($this->q)) {
if (!empty($this->q)) {
// User is searching via query
$search_engine = $profile->getSearchEngine('profile');
@ -319,34 +291,34 @@ class UserdirectoryAction extends Action
$profile->find();
} else {
// User is browsing via AlphaNav
$sort = $this->getSortKey();
$sql = 'SELECT profile.* FROM profile, user WHERE profile.id = user.id';
switch($this->filter)
{
switch ($this->filter) {
case 'all':
// NOOP
break;
case '0-9':
$sql .=
' AND LEFT(profile.nickname, 1) BETWEEN \'0\' AND \'9\'';
$profile->whereAdd(sprintf('LEFT(%1$s.%2$s, 1) BETWEEN %3$s AND %4$s',
$profile->escapedTableName(),
'nickname',
$profile->_quote("0"),
$profile->_quote("9")));
break;
default:
$sql .= sprintf(
' AND LEFT(LOWER(profile.nickname), 1) = \'%s\'',
$this->filter
);
$profile->whereAdd(sprintf('LEFT(LOWER(%1$s.%2$s), 1) = %3$s',
$profile->escapedTableName(),
'nickname',
$profile->_quote($this->filter)));
}
$sql .= sprintf(
' ORDER BY profile.%s %s, profile.nickname ASC LIMIT %d, %d',
$sort,
$this->reverse ? 'DESC' : 'ASC',
$offset,
$limit
);
$order = sprintf('%1$s.%2$s %3$s, %1$s.%4$s ASC',
$profile->escapedTableName(),
$this->getSortKey('nickname'),
$this->reverse ? 'DESC' : 'ASC',
'nickname');
$profile->orderBy($order);
$profile->limit($offset, $limit);
$profile->query($sql);
$profile->find();
}
return $profile;
@ -357,15 +329,12 @@ class UserdirectoryAction extends Action
*
* @return string a column name for sorting
*/
function getSortKey()
function getSortKey($def='nickname')
{
switch ($this->sort) {
case 'nickname':
return $this->sort;
break;
case 'created':
return $this->sort;
break;
default:
return 'nickname';
}

View File

@ -621,7 +621,7 @@ class Ostatus_profile extends Managed_DataObject
// Get (safe!) HTML and text versions of the content
$rendered = $this->purify($sourceContent);
$rendered = common_purify($sourceContent);
$content = common_strip_html($rendered);
$shortened = common_shorten_links($content);
@ -788,7 +788,7 @@ class Ostatus_profile extends Managed_DataObject
// Get (safe!) HTML and text versions of the content
$rendered = $this->purify($sourceContent);
$rendered = common_purify($sourceContent);
$content = common_strip_html($rendered);
$shortened = common_shorten_links($content);
@ -914,17 +914,6 @@ class Ostatus_profile extends Managed_DataObject
return $saved;
}
/**
* Clean up HTML
*/
protected function purify($html)
{
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
$config = array('safe' => 1,
'deny_attribute' => 'id,style,on*');
return htmLawed($html, $config);
}
/**
* Filters a list of recipient ID URIs to just those for local delivery.
* @param Profile local profile of sender

View File

@ -249,7 +249,7 @@ class SalmonAction extends Action
$orig = clone($oprofile);
$oprofile->uri = $e->object_uri;
common_debug('URIFIX Updating Ostatus_profile URI for '.$aliased_uri.' to '.$oprofile->uri);
$oprofile->updateWithKeys($orig);
$oprofile->updateWithKeys($orig, 'uri'); // 'uri' is the primary key column
unset($orig);
$this->oprofile = $oprofile;
break; // don't iterate through aliases anymore

59
scripts/clean_profiles.php Executable file
View File

@ -0,0 +1,59 @@
#!/usr/bin/env php
<?php
/*
* StatusNet - a distributed open-source microblogging tool
* Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
$shortoptions = 'y';
$longoptions = array('yes');
$helptext = <<<END_OF_HELP
clean_profiles.php [options]
Deletes all profile table entries where the profile does not occur in the
notice table, is not a group and is not a local user. Very MySQL specific I think.
WARNING: This has not been tested thoroughly. Maybe we've missed a table to compare somewhere.
-y --yes do not wait for confirmation
END_OF_HELP;
require_once INSTALLDIR.'/scripts/commandline.inc';
if (!have_option('y', 'yes')) {
print "About to delete profiles that we think are useless to save. Are you sure? [y/N] ";
$response = fgets(STDIN);
if (strtolower(trim($response)) != 'y') {
print "Aborting.\n";
exit(0);
}
}
print "Deleting";
$profile = new Profile();
$profile->query('SELECT * FROM profile WHERE ' .
'NOT (SELECT COUNT(*) FROM notice WHERE profile_id=profile.id) ' .
'AND NOT (SELECT COUNT(*) FROM user WHERE user.id=profile.id) ' .
'AND NOT (SELECT COUNT(*) FROM user_group WHERE user_group.profile_id=profile.id) ' .
'AND NOT (SELECT COUNT(*) FROM subscription WHERE subscriber=profile.id OR subscribed=profile.id) ');
while ($profile->fetch()) {
echo ' '.$profile->getID().':'.$profile->getNickname();
$profile->delete();
}
print "\nDONE.\n";