Merge "jquery.makeCollapsible: fix jQuery memory leak"
[lhc/web/wiklou.git] / includes / Preferences.php
index 848cd32..6b5b5eb 100644 (file)
@@ -56,6 +56,12 @@ class Preferences {
                        'searchlimit' => array( 'Preferences', 'filterIntval' ),
        );
 
+       // Stuff that shouldn't be saved as a preference.
+       private static $saveBlacklist = array(
+               'realname',
+               'emailaddress',
+       );
+
        /**
         * @throws MWException
         * @param $user User
@@ -93,9 +99,14 @@ class Preferences {
                ## Make sure that form fields have their parent set. See bug 41337.
                $dummyForm = new HTMLForm( array(), $context );
 
+               $disable = !$user->isAllowed( 'editmyoptions' );
+
                ## Prod in defaults from the user
                foreach ( $defaultPreferences as $name => &$info ) {
                        $prefFromUser = self::getOptionFromUser( $name, $info, $user );
+                       if ( $disable && !in_array( $name, self::$saveBlacklist ) ) {
+                               $info['disabled'] = 'disabled';
+                       }
                        $field = HTMLForm::loadInputFromParameters( $name, $info ); // For validation
                        $field->mParent = $dummyForm;
                        $defaultOptions = User::getDefaultOptions();
@@ -256,9 +267,13 @@ class Preferences {
                        );
                }
 
+               $canViewPrivateInfo = $user->isAllowed( 'viewmyprivateinfo' );
+               $canEditPrivateInfo = $user->isAllowed( 'editmyprivateinfo' );
+
                // Actually changeable stuff
                $defaultPreferences['realname'] = array(
-                       'type' => $wgAuth->allowPropChange( 'realname' ) ? 'text' : 'info',
+                       // (not really "private", but still shouldn't be edited without permission)
+                       'type' => $canEditPrivateInfo && $wgAuth->allowPropChange( 'realname' ) ? 'text' : 'info',
                        'default' => $user->getRealName(),
                        'section' => 'personal/info',
                        'label-message' => 'yourrealname',
@@ -277,7 +292,7 @@ class Preferences {
                        'help-message' => 'prefs-help-gender',
                );
 
-               if ( $wgAuth->allowPasswordChange() ) {
+               if ( $canEditPrivateInfo && $wgAuth->allowPasswordChange() ) {
                        $link = Linker::link( SpecialPage::getTitleFor( 'ChangePassword' ),
                                $context->msg( 'prefs-resetpass' )->escaped(), array(),
                                array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ) );
@@ -398,22 +413,24 @@ class Preferences {
                                array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ) );
 
                        $emailAddress = $user->getEmail() ? htmlspecialchars( $user->getEmail() ) : '';
-                       if ( $wgAuth->allowPropChange( 'emailaddress' ) ) {
+                       if ( $canEditPrivateInfo && $wgAuth->allowPropChange( 'emailaddress' ) ) {
                                $emailAddress .= $emailAddress == '' ? $link : (
                                        $context->msg( 'word-separator' )->plain()
                                        . $context->msg( 'parentheses' )->rawParams( $link )->plain()
                                );
                        }
 
-                       $defaultPreferences['emailaddress'] = array(
-                               'type' => 'info',
-                               'raw' => true,
-                               'default' => $emailAddress,
-                               'label-message' => 'youremail',
-                               'section' => 'personal/email',
-                               'help-messages' => $helpMessages,
-                               # 'cssclass' chosen below
-                       );
+                       if ( $canViewPrivateInfo ) {
+                               $defaultPreferences['emailaddress'] = array(
+                                       'type' => 'info',
+                                       'raw' => true,
+                                       'default' => $emailAddress,
+                                       'label-message' => 'youremail',
+                                       'section' => 'personal/email',
+                                       'help-messages' => $helpMessages,
+                                       # 'cssclass' chosen below
+                               );
+                       }
 
                        $disableEmailPrefs = false;
 
@@ -448,16 +465,18 @@ class Preferences {
                                        $emailauthenticationclass = 'mw-email-none';
                                }
 
-                               $defaultPreferences['emailauthentication'] = array(
-                                       'type' => 'info',
-                                       'raw' => true,
-                                       'section' => 'personal/email',
-                                       'label-message' => 'prefs-emailconfirm-label',
-                                       'default' => $emailauthenticated,
-                                       # Apply the same CSS class used on the input to the message:
-                                       'cssclass' => $emailauthenticationclass,
-                               );
-                               $defaultPreferences['emailaddress']['cssclass'] = $emailauthenticationclass;
+                               if ( $canViewPrivateInfo ) {
+                                       $defaultPreferences['emailauthentication'] = array(
+                                               'type' => 'info',
+                                               'raw' => true,
+                                               'section' => 'personal/email',
+                                               'label-message' => 'prefs-emailconfirm-label',
+                                               'default' => $emailauthenticated,
+                                               # Apply the same CSS class used on the input to the message:
+                                               'cssclass' => $emailauthenticationclass,
+                                       );
+                                       $defaultPreferences['emailaddress']['cssclass'] = $emailauthenticationclass;
+                               }
                        }
 
                        if ( $wgEnableUserEmail && $user->isAllowed( 'sendemail' ) ) {
@@ -732,25 +751,28 @@ class Preferences {
                global $wgAllowUserCssPrefs;
 
                ## Editing #####################################
-               $defaultPreferences['cols'] = array(
-                       'type' => 'int',
-                       'label-message' => 'columns',
-                       'section' => 'editing/textboxsize',
-                       'min' => 4,
-                       'max' => 1000,
+               if ( $wgAllowUserCssPrefs ) {
+                       $defaultPreferences['editsection'] = array(
+                               'type' => 'toggle',
+                               'section' => 'editing/advancedediting',
+                               'label-message' => 'tog-editsection',
+                       );
+               }
+               $defaultPreferences['editsectiononrightclick'] = array(
+                       'type' => 'toggle',
+                       'section' => 'editing/advancedediting',
+                       'label-message' => 'tog-editsectiononrightclick',
                );
-               $defaultPreferences['rows'] = array(
-                       'type' => 'int',
-                       'label-message' => 'rows',
-                       'section' => 'editing/textboxsize',
-                       'min' => 4,
-                       'max' => 1000,
+               $defaultPreferences['editondblclick'] = array(
+                       'type' => 'toggle',
+                       'section' => 'editing/advancedediting',
+                       'label-message' => 'tog-editondblclick',
                );
 
                if ( $wgAllowUserCssPrefs ) {
                        $defaultPreferences['editfont'] = array(
                                'type' => 'select',
-                               'section' => 'editing/advancedediting',
+                               'section' => 'editing/editor',
                                'label-message' => 'editfont-style',
                                'options' => array(
                                        $context->msg( 'editfont-default' )->text() => 'default',
@@ -760,64 +782,57 @@ class Preferences {
                                )
                        );
                }
-               $defaultPreferences['previewontop'] = array(
-                       'type' => 'toggle',
-                       'section' => 'editing/advancedediting',
-                       'label-message' => 'tog-previewontop',
+               $defaultPreferences['cols'] = array(
+                       'type' => 'int',
+                       'label-message' => 'columns',
+                       'section' => 'editing/editor',
+                       'min' => 4,
+                       'max' => 1000,
                );
-               $defaultPreferences['previewonfirst'] = array(
-                       'type' => 'toggle',
-                       'section' => 'editing/advancedediting',
-                       'label-message' => 'tog-previewonfirst',
+               $defaultPreferences['rows'] = array(
+                       'type' => 'int',
+                       'label-message' => 'rows',
+                       'section' => 'editing/editor',
+                       'min' => 4,
+                       'max' => 1000,
                );
-
-               if ( $wgAllowUserCssPrefs ) {
-                       $defaultPreferences['editsection'] = array(
+               if ( $user->isAllowed( 'minoredit' ) ) {
+                       $defaultPreferences['minordefault'] = array(
                                'type' => 'toggle',
-                               'section' => 'editing/advancedediting',
-                               'label-message' => 'tog-editsection',
+                               'section' => 'editing/editor',
+                               'label-message' => 'tog-minordefault',
                        );
                }
-               $defaultPreferences['editsectiononrightclick'] = array(
+               $defaultPreferences['forceeditsummary'] = array(
                        'type' => 'toggle',
-                       'section' => 'editing/advancedediting',
-                       'label-message' => 'tog-editsectiononrightclick',
+                       'section' => 'editing/editor',
+                       'label-message' => 'tog-forceeditsummary',
                );
-               $defaultPreferences['editondblclick'] = array(
+               $defaultPreferences['useeditwarning'] = array(
                        'type' => 'toggle',
-                       'section' => 'editing/advancedediting',
-                       'label-message' => 'tog-editondblclick',
+                       'section' => 'editing/editor',
+                       'label-message' => 'tog-useeditwarning',
                );
                $defaultPreferences['showtoolbar'] = array(
                        'type' => 'toggle',
-                       'section' => 'editing/advancedediting',
+                       'section' => 'editing/editor',
                        'label-message' => 'tog-showtoolbar',
                );
 
-               if ( $user->isAllowed( 'minoredit' ) ) {
-                       $defaultPreferences['minordefault'] = array(
-                               'type' => 'toggle',
-                               'section' => 'editing/advancedediting',
-                               'label-message' => 'tog-minordefault',
-                       );
-               }
-
-               $defaultPreferences['forceeditsummary'] = array(
+               $defaultPreferences['previewonfirst'] = array(
                        'type' => 'toggle',
-                       'section' => 'editing/advancedediting',
-                       'label-message' => 'tog-forceeditsummary',
+                       'section' => 'editing/preview',
+                       'label-message' => 'tog-previewonfirst',
                );
-
-               $defaultPreferences['uselivepreview'] = array(
+               $defaultPreferences['previewontop'] = array(
                        'type' => 'toggle',
-                       'section' => 'editing/advancedediting',
-                       'label-message' => 'tog-uselivepreview',
+                       'section' => 'editing/preview',
+                       'label-message' => 'tog-previewontop',
                );
-
-               $defaultPreferences['useeditwarning'] = array(
+               $defaultPreferences['uselivepreview'] = array(
                        'type' => 'toggle',
-                       'section' => 'editing/advancedediting',
-                       'label-message' => 'tog-useeditwarning',
+                       'section' => 'editing/preview',
+                       'label-message' => 'tog-uselivepreview',
                );
 
        }
@@ -1389,6 +1404,10 @@ class Preferences {
                $user = $form->getModifiedUser();
                $result = true;
 
+               if ( !$user->isAllowedAny( 'editmyprivateinfo', 'editmyoptions' ) ) {
+                       return Status::newFatal( 'mypreferencesprotected' );
+               }
+
                // Filter input
                foreach ( array_keys( $formData ) as $name ) {
                        if ( isset( self::$saveFilters[$name] ) ) {
@@ -1397,40 +1416,37 @@ class Preferences {
                        }
                }
 
-               // Stuff that shouldn't be saved as a preference.
-               $saveBlacklist = array(
-                       'realname',
-                       'emailaddress',
-               );
-
                // Fortunately, the realname field is MUCH simpler
-               if ( !in_array( 'realname', $wgHiddenPrefs ) ) {
+               // (not really "private", but still shouldn't be edited without permission)
+               if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->isAllowed( 'editmyprivateinfo' ) ) {
                        $realName = $formData['realname'];
                        $user->setRealName( $realName );
                }
 
-               foreach ( $saveBlacklist as $b ) {
-                       unset( $formData[$b] );
-               }
+               if ( $user->isAllowed( 'editmyoptions' ) ) {
+                       foreach ( self::$saveBlacklist as $b ) {
+                               unset( $formData[$b] );
+                       }
 
-               # If users have saved a value for a preference which has subsequently been disabled
-               # via $wgHiddenPrefs, we don't want to destroy that setting in case the preference
-               # is subsequently re-enabled
-               # TODO: maintenance script to actually delete these
-               foreach ( $wgHiddenPrefs as $pref ) {
-                       # If the user has not set a non-default value here, the default will be returned
-                       # and subsequently discarded
-                       $formData[$pref] = $user->getOption( $pref, null, true );
-               }
+                       # If users have saved a value for a preference which has subsequently been disabled
+                       # via $wgHiddenPrefs, we don't want to destroy that setting in case the preference
+                       # is subsequently re-enabled
+                       # TODO: maintenance script to actually delete these
+                       foreach ( $wgHiddenPrefs as $pref ) {
+                               # If the user has not set a non-default value here, the default will be returned
+                               # and subsequently discarded
+                               $formData[$pref] = $user->getOption( $pref, null, true );
+                       }
 
-               // Keep old preferences from interfering due to back-compat code, etc.
-               $user->resetOptions( 'unused', $form->getContext() );
+                       // Keep old preferences from interfering due to back-compat code, etc.
+                       $user->resetOptions( 'unused', $form->getContext() );
 
-               foreach ( $formData as $key => $value ) {
-                       $user->setOption( $key, $value );
-               }
+                       foreach ( $formData as $key => $value ) {
+                               $user->setOption( $key, $value );
+                       }
 
-               $user->saveSettings();
+                       $user->saveSettings();
+               }
 
                $wgAuth->updateExternalDB( $user );
 
@@ -1465,7 +1481,8 @@ class Preferences {
        /**
         * Try to set a user's email address.
         * This does *not* try to validate the address.
-        * Caller is responsible for checking $wgAuth.
+        * Caller is responsible for checking $wgAuth and 'editmyprivateinfo'
+        * right.
         *
         * @deprecated in 1.20; use User::setEmailWithConfirmation() instead.
         * @param $user User
@@ -1554,13 +1571,19 @@ class PreferencesForm extends HTMLForm {
         * @return String
         */
        function getButtons() {
+               if ( !$this->getModifiedUser()->isAllowedAny( 'editmyprivateinfo', 'editmyoptions' ) ) {
+                       return '';
+               }
+
                $html = parent::getButtons();
 
-               $t = SpecialPage::getTitleFor( 'Preferences', 'reset' );
+               if ( $this->getModifiedUser()->isAllowed( 'editmyoptions' ) ) {
+                       $t = SpecialPage::getTitleFor( 'Preferences', 'reset' );
 
-               $html .= "\n" . Linker::link( $t, $this->msg( 'restoreprefs' )->escaped() );
+                       $html .= "\n" . Linker::link( $t, $this->msg( 'restoreprefs' )->escaped() );
 
-               $html = Xml::tags( 'div', array( 'class' => 'mw-prefs-buttons' ), $html );
+                       $html = Xml::tags( 'div', array( 'class' => 'mw-prefs-buttons' ), $html );
+               }
 
                return $html;
        }