WebInstallerName.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. <?php
  2. /**
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, write to the Free Software Foundation, Inc.,
  15. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. * http://www.gnu.org/copyleft/gpl.html
  17. *
  18. * @file
  19. * @ingroup Deployment
  20. */
  21. use MediaWiki\MediaWikiServices;
  22. class WebInstallerName extends WebInstallerPage {
  23. /**
  24. * @return string
  25. */
  26. public function execute() {
  27. $r = $this->parent->request;
  28. if ( $r->wasPosted() && $this->submit() ) {
  29. return 'continue';
  30. }
  31. $this->startForm();
  32. // Encourage people to not name their site 'MediaWiki' by blanking the
  33. // field. I think that was the intent with the original $GLOBALS['wgSitename']
  34. // but these two always were the same so had the effect of making the
  35. // installer forget $wgSitename when navigating back to this page.
  36. if ( $this->getVar( 'wgSitename' ) == 'MediaWiki' ) {
  37. $this->setVar( 'wgSitename', '' );
  38. }
  39. // Set wgMetaNamespace to something valid before we show the form.
  40. // $wgMetaNamespace defaults to $wgSiteName which is 'MediaWiki'
  41. $metaNS = $this->getVar( 'wgMetaNamespace' );
  42. $this->setVar(
  43. 'wgMetaNamespace',
  44. wfMessage( 'config-ns-other-default' )->inContentLanguage()->text()
  45. );
  46. $pingbackInfo = ( new Pingback() )->getSystemInfo();
  47. // Database isn't available in config yet, so take it
  48. // from the installer
  49. $pingbackInfo['database'] = $this->getVar( 'wgDBtype' );
  50. $this->addHTML(
  51. $this->parent->getTextBox( [
  52. 'var' => 'wgSitename',
  53. 'label' => 'config-site-name',
  54. 'help' => $this->parent->getHelpBox( 'config-site-name-help' )
  55. ] ) .
  56. // getRadioSet() builds a set of labeled radio buttons.
  57. // For grep: The following messages are used as the item labels:
  58. // config-ns-site-name, config-ns-generic, config-ns-other
  59. $this->parent->getRadioSet( [
  60. 'var' => '_NamespaceType',
  61. 'label' => 'config-project-namespace',
  62. 'itemLabelPrefix' => 'config-ns-',
  63. 'values' => [ 'site-name', 'generic', 'other' ],
  64. 'commonAttribs' => [ 'class' => 'enableForOther',
  65. 'rel' => 'config_wgMetaNamespace' ],
  66. 'help' => $this->parent->getHelpBox( 'config-project-namespace-help' )
  67. ] ) .
  68. $this->parent->getTextBox( [
  69. 'var' => 'wgMetaNamespace',
  70. 'label' => '', // @todo Needs a label?
  71. 'attribs' => [ 'class' => 'enabledByOther' ]
  72. ] ) .
  73. $this->getFieldsetStart( 'config-admin-box' ) .
  74. $this->parent->getTextBox( [
  75. 'var' => '_AdminName',
  76. 'label' => 'config-admin-name',
  77. 'help' => $this->parent->getHelpBox( 'config-admin-help' )
  78. ] ) .
  79. $this->parent->getPasswordBox( [
  80. 'var' => '_AdminPassword',
  81. 'label' => 'config-admin-password',
  82. ] ) .
  83. $this->parent->getPasswordBox( [
  84. 'var' => '_AdminPasswordConfirm',
  85. 'label' => 'config-admin-password-confirm'
  86. ] ) .
  87. $this->parent->getTextBox( [
  88. 'var' => '_AdminEmail',
  89. 'attribs' => [
  90. 'dir' => 'ltr',
  91. ],
  92. 'label' => 'config-admin-email',
  93. 'help' => $this->parent->getHelpBox( 'config-admin-email-help' )
  94. ] ) .
  95. $this->parent->getCheckBox( [
  96. 'var' => '_Subscribe',
  97. 'label' => 'config-subscribe',
  98. 'help' => $this->parent->getHelpBox( 'config-subscribe-help' )
  99. ] ) .
  100. $this->parent->getCheckBox( [
  101. 'var' => 'wgPingback',
  102. 'label' => 'config-pingback',
  103. 'help' => $this->parent->getHelpBox(
  104. 'config-pingback-help',
  105. FormatJson::encode( $pingbackInfo, true )
  106. ),
  107. 'value' => true,
  108. ] ) .
  109. $this->getFieldsetEnd() .
  110. $this->parent->getInfoBox( wfMessage( 'config-almost-done' )->plain() ) .
  111. // getRadioSet() builds a set of labeled radio buttons.
  112. // For grep: The following messages are used as the item labels:
  113. // config-optional-continue, config-optional-skip
  114. $this->parent->getRadioSet( [
  115. 'var' => '_SkipOptional',
  116. 'itemLabelPrefix' => 'config-optional-',
  117. 'values' => [ 'continue', 'skip' ]
  118. ] )
  119. );
  120. // Restore the default value
  121. $this->setVar( 'wgMetaNamespace', $metaNS );
  122. $this->endForm();
  123. return 'output';
  124. }
  125. /**
  126. * @return bool
  127. */
  128. public function submit() {
  129. global $wgPasswordPolicy;
  130. $retVal = true;
  131. $this->parent->setVarsFromRequest( [ 'wgSitename', '_NamespaceType',
  132. '_AdminName', '_AdminPassword', '_AdminPasswordConfirm', '_AdminEmail',
  133. '_Subscribe', '_SkipOptional', 'wgMetaNamespace', 'wgPingback' ] );
  134. // Validate site name
  135. if ( strval( $this->getVar( 'wgSitename' ) ) === '' ) {
  136. $this->parent->showError( 'config-site-name-blank' );
  137. $retVal = false;
  138. }
  139. // Fetch namespace
  140. $nsType = $this->getVar( '_NamespaceType' );
  141. if ( $nsType == 'site-name' ) {
  142. $name = $this->getVar( 'wgSitename' );
  143. // Sanitize for namespace
  144. // This algorithm should match the JS one in WebInstallerOutput.php
  145. $name = preg_replace( '/[\[\]\{\}|#<>%+? ]/', '_', $name );
  146. $name = str_replace( '&', '&amp;', $name );
  147. $name = preg_replace( '/__+/', '_', $name );
  148. $name = ucfirst( trim( $name, '_' ) );
  149. } elseif ( $nsType == 'generic' ) {
  150. $name = wfMessage( 'config-ns-generic' )->text();
  151. } else { // other
  152. $name = $this->getVar( 'wgMetaNamespace' );
  153. }
  154. // Validate namespace
  155. if ( strpos( $name, ':' ) !== false ) {
  156. $good = false;
  157. } else {
  158. // Title-style validation
  159. $title = Title::newFromText( $name );
  160. if ( !$title ) {
  161. $good = $nsType == 'site-name';
  162. } else {
  163. $name = $title->getDBkey();
  164. $good = true;
  165. }
  166. }
  167. if ( !$good ) {
  168. $this->parent->showError( 'config-ns-invalid', $name );
  169. $retVal = false;
  170. }
  171. // Make sure it won't conflict with any existing namespaces
  172. $nsIndex = MediaWikiServices::getInstance()->getContentLanguage()->getNsIndex( $name );
  173. if ( $nsIndex !== false && $nsIndex !== NS_PROJECT ) {
  174. $this->parent->showError( 'config-ns-conflict', $name );
  175. $retVal = false;
  176. }
  177. $this->setVar( 'wgMetaNamespace', $name );
  178. // Validate username for creation
  179. $name = $this->getVar( '_AdminName' );
  180. if ( strval( $name ) === '' ) {
  181. $this->parent->showError( 'config-admin-name-blank' );
  182. $cname = $name;
  183. $retVal = false;
  184. } else {
  185. $cname = User::getCanonicalName( $name, 'creatable' );
  186. if ( $cname === false ) {
  187. $this->parent->showError( 'config-admin-name-invalid', $name );
  188. $retVal = false;
  189. } else {
  190. $this->setVar( '_AdminName', $cname );
  191. }
  192. }
  193. // Validate password
  194. $msg = false;
  195. $pwd = $this->getVar( '_AdminPassword' );
  196. $user = User::newFromName( $cname );
  197. if ( $user ) {
  198. $upp = new UserPasswordPolicy(
  199. $wgPasswordPolicy['policies'],
  200. $wgPasswordPolicy['checks']
  201. );
  202. $status = $upp->checkUserPasswordForGroups(
  203. $user,
  204. $pwd,
  205. [ 'bureaucrat', 'sysop', 'interface-admin' ] // per Installer::createSysop()
  206. );
  207. $valid = $status->isGood() ? true : $status->getMessage();
  208. } else {
  209. $valid = 'config-admin-name-invalid';
  210. }
  211. if ( strval( $pwd ) === '' ) {
  212. // Provide a more specific and helpful message if password field is left blank
  213. $msg = 'config-admin-password-blank';
  214. } elseif ( $pwd !== $this->getVar( '_AdminPasswordConfirm' ) ) {
  215. $msg = 'config-admin-password-mismatch';
  216. } elseif ( $valid !== true ) {
  217. $msg = $valid;
  218. }
  219. if ( $msg !== false ) {
  220. call_user_func( [ $this->parent, 'showError' ], $msg );
  221. $this->setVar( '_AdminPassword', '' );
  222. $this->setVar( '_AdminPasswordConfirm', '' );
  223. $retVal = false;
  224. }
  225. // Validate e-mail if provided
  226. $email = $this->getVar( '_AdminEmail' );
  227. if ( $email && !Sanitizer::validateEmail( $email ) ) {
  228. $this->parent->showError( 'config-admin-error-bademail' );
  229. $retVal = false;
  230. }
  231. // If they asked to subscribe to mediawiki-announce but didn't give
  232. // an e-mail, show an error. T31332
  233. if ( !$email && $this->getVar( '_Subscribe' ) ) {
  234. $this->parent->showError( 'config-subscribe-noemail' );
  235. $retVal = false;
  236. }
  237. return $retVal;
  238. }
  239. }