]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Merge branch 'nightly' into file_urlhash
authorMikael Nordfeldth <mmn@hethane.se>
Thu, 19 Feb 2015 17:13:09 +0000 (18:13 +0100)
committerMikael Nordfeldth <mmn@hethane.se>
Thu, 19 Feb 2015 17:13:09 +0000 (18:13 +0100)
14 files changed:
INSTALL
actions/apitimelineuser.php
actions/emailsettings.php
classes/Managed_DataObject.php
lib/activityimporter.php
lib/default.php
lib/installer.php
lib/util.php
plugins/Blog/classes/Blog_entry.php
plugins/Directory/actions/groupdirectory.php
plugins/Directory/actions/userdirectory.php
plugins/OStatus/classes/Ostatus_profile.php
plugins/OStatus/lib/salmonaction.php
scripts/clean_profiles.php [new file with mode: 0755]

diff --git a/INSTALL b/INSTALL
index 0483320a78bc08795afbde082346043a583d37a9..fff63681becfecd7f64530dc2e709d876f4f373f 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -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.
index 26c960fa0429b9e1d176713cd4e65e60be43ddfa..abc7fd6a96a13d63c3fd2881dbda0103bbb7885f 100644 (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);
-    }
 }
index 0c2033d821d0587a0bcbf5aeb974d17ad3024ebd..47c6fe54e513a738cedf12a7275d6e8edcbbf19a 100644 (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.'));
             }
index a628b8bee3aa1834879ecae689e4c9ca40ce2940..dc4352270d7232960a0c4847ee1c164f0eed93cd 100644 (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
      *
index 4e13419ae7482ccd0aed3eac7ffad9e15e6ca789..5bef4cfb072475e66cdaf73d1b4b4267107f78ed 100644 (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);
-    }
 }
index 6ca61f191b2c6160802434bb60e4351ac78204dc..b1c6d5ea3375284a1b32d18a15a04d2308e02b81 100644 (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/',
index cea7d29ec7df621801ffaeb934fc5fd7462b65ed..1fcd0961c5ba9c9b365797caada18e241f496a01 100644 (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) {
index a32c35395eb91ba004f48d43b828110195d54159..9a70d8d44ebaf9f010675b0c88d5691b01258101 100644 (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)
index 1f585dce4ff854c15b5b1c5ac8d0f7cebbd89671..6b82a0fdd12751e0885a5045897b7caaf86d78de 100644 (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;
-    }
 }
index 5e532fc214202cd909717be1cae84d09aadde98b..32e5ce50b4cdeb483831da0d9c3b150f4d7cfad4 100644 (file)
  * @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;
         }
     }
 
index 77ffb5206b22ee24d33930cdd1050110e2ec43ed..f178408e8bf11596d067fb5501ad1ead7c843956 100644 (file)
  * @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';
         }
index 79098c64048ed31705b54ecfb94259619dad826d..4be4e5112f67f5a4e8464e425135b5bd6b744c05 100644 (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
index 365f2c829c9ea2845467f4842c41142998d2a603..2954d8038c9492b00a5db95bdc2abebf92fd08c9 100644 (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
diff --git a/scripts/clean_profiles.php b/scripts/clean_profiles.php
new file mode 100755 (executable)
index 0000000..470d6c1
--- /dev/null
@@ -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";