* This is the list of preferred extensions for uploading files. Uploading files
* with extensions not in this list will trigger a warning.
*/
-$wgFileExtensions = array( 'png', 'gif', 'jpg', 'jpeg', 'ogg' );
+$wgFileExtensions = array( 'png', 'gif', 'jpg', 'jpeg' );
/** Files with these extensions will never be allowed as uploads. */
$wgFileBlacklist = array(
$wgSkinExtensionFunctions = array();
$wgExtensionFunctions = array();
-/** Allow user Javascript page? */
-$wgAllowUserJs = true;
+/**
+ * Allow user Javascript page?
+ * This enables a lot of neat customizations, but may
+ * increase security risk to users and server load.
+ */
+$wgAllowUserJs = false;
-/** Allow user Cascading Style Sheets (CSS)? */
-$wgAllowUserCss = true;
+/**
+ * Allow user Cascading Style Sheets (CSS)?
+ * This enables a lot of neat customizations, but may
+ * increase security risk to users and server load.
+ */
+$wgAllowUserCss = false;
/** Use the site's Javascript page? */
$wgUseSiteJs = true;
# If the form is incomplete, force to preview.
$this->preview = true;
} else {
- # Some browsers will not report any submit button
- # if the user hits enter in the comment box.
- # The unmarked state will be assumed to be a save,
- # if the form seems otherwise complete.
- $this->preview = $request->getCheck( 'wpPreview' );
+ if( $this->tokenOk( $request ) ) {
+ # Some browsers will not report any submit button
+ # if the user hits enter in the comment box.
+ # The unmarked state will be assumed to be a save,
+ # if the form seems otherwise complete.
+ $this->preview = $request->getCheck( 'wpPreview' );
+ } else {
+ # Page might be a hack attempt posted from
+ # an external site. Preview instead of saving.
+ $this->preview = true;
+ }
}
$this->save = !$this->preview;
if( !preg_match( '/^\d{14}$/', $this->edittime )) {
$this->live = $request->getCheck( 'live' );
}
+ /**
+ * Make sure the form isn't faking a user's credentials.
+ *
+ * @param WebRequest $request
+ * @return bool
+ * @access private
+ */
+ function tokenOk( &$request ) {
+ global $wgUser;
+ if( $wgUser->getId() == 0 ) {
+ # Anonymous users may not have a session
+ # open. Don't tokenize.
+ return true;
+ } else {
+ return $wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) );
+ }
+ }
+
function submit() {
$this->edit();
}
<input type='hidden' value=\"" . htmlspecialchars( $this->section ) . "\" name=\"wpSection\" />
<input type='hidden' value=\"{$this->edittime}\" name=\"wpEdittime\" />\n" );
+ if ( 0 != $wgUser->getID() ) {
+ /**
+ * To make it harder for someone to slip a user a page
+ * which submits an edit form to the wiki without their
+ * knowledge, a random token is associated with the login
+ * session. If it's not passed back with the submission,
+ * we won't save the page, or render user JavaScript and
+ * CSS previews.
+ */
+ $token = htmlspecialchars( $wgUser->editToken() );
+ $wgOut->addHTML( "
+<input type='hidden' value=\"$token\" name=\"wpEditToken\" />\n" );
+ }
+
+
if ( $isConflict ) {
require_once( "DifferenceEngine.php" );
$wgOut->addHTML( "<h2>" . wfMsg( "yourdiff" ) . "</h2>\n" );
return $r;
}
+ /**
+ * To make it harder for someone to slip a user a fake
+ * user-JavaScript or user-CSS preview, a random token
+ * is associated with the login session. If it's not
+ * passed back with the preview request, we won't render
+ * the code.
+ *
+ * @param string $action
+ * @return bool
+ * @access private
+ */
+ function userCanPreview( $action ) {
+ global $wgTitle, $wgRequest, $wgUser;
+
+ if( $action != 'submit' )
+ return false;
+ if( !$wgRequest->wasPosted() )
+ return false;
+ if( !$wgTitle->userCanEditCssJsSubpage() )
+ return false;
+ return $wgUser->matchEditToken(
+ $wgRequest->getVal( 'wpEditToken' ) );
+ }
+
# get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
function getUserStylesheet() {
global $wgOut, $wgStylePath, $wgContLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
$s = "@import \"$wgStylePath/$sheet\";\n";
if($wgContLang->isRTL()) $s .= "@import \"$wgStylePath/common/common_rtl.css\";\n";
if( $wgAllowUserCss && $wgUser->getID() != 0 ) { # logged in
- if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
+ if($wgTitle->isCssSubpage() && $this->userCanPreview( $action ) ) {
$s .= $wgRequest->getText('wpTextbox1');
} else {
$userpage = $wgContLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
$action = $wgRequest->getText('action');
# if we're previewing the CSS page, use it
- if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
+ if( $wgTitle->isCssSubpage() and $this->userCanPreview( $action ) ) {
$siteargs = "&smaxage=0&maxage=0";
$usercss = $wgRequest->getText('wpTextbox1');
} else {
$action = $wgRequest->getText('action');
if( $wgAllowUserJs && $this->loggedin ) {
- if($wgTitle->isJsSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
+ if( $wgTitle->isJsSubpage() and $this->userCanPreview( $action ) ) {
# XXX: additional security check/prompt?
$this->userjsprev = '/*<![CDATA[*/ ' . $wgRequest->getText('wpTextbox1') . ' /*]]>*/';
} else {
}
return false;
}
+
+ /**
+ * Initialize (if necessary) and return a session token value
+ * which can be used in edit forms to show that the user's
+ * login credentials aren't being hijacked with a foreign form
+ * submission.
+ *
+ * @return string
+ * @access public
+ */
+ function editToken() {
+ if( !isset( $_SESSION['wsEditToken'] ) ) {
+ $token = dechex( mt_rand() ) . dechex( mt_rand() );
+ $_SESSION['wsEditToken'] = $token;
+ }
+ return $_SESSION['wsEditToken'];
+ }
+
+ /**
+ * Check given value against the token value stored in the session.
+ * A match should confirm that the form was submitted from the
+ * user's own login session, not a form submission from a third-party
+ * site.
+ *
+ * @param string $val
+ * @return bool
+ * @access public
+ */
+ function matchEditToken( $val ) {
+ if( !isset( $_SESSION['wsEditToken'] ) )
+ return false;
+ return $_SESSION['wsEditToken'] == $val;
+ }
}
?>