getOutput()->disable(); if ( wfReadOnly() ) { header( "HTTP/1.0 423 Locked" ); print 'Wiki is in read-only mode'; return; } elseif ( !$this->getRequest()->wasPosted() ) { header( "HTTP/1.0 400 Bad Request" ); print 'Request must be POSTed'; return; } $optional = array( 'maxjobs' => 0, 'maxtime' => 30, 'type' => false, 'async' => true ); $required = array_flip( array( 'title', 'tasks', 'signature', 'sigexpiry' ) ); $params = array_intersect_key( $this->getRequest()->getValues(), $required + $optional ); $missing = array_diff_key( $required, $params ); if ( count( $missing ) ) { header( "HTTP/1.0 400 Bad Request" ); print 'Missing parameters: ' . implode( ', ', array_keys( $missing ) ); return; } $squery = $params; unset( $squery['signature'] ); $cSig = self::getQuerySignature( $squery, $this->getConfig()->get( 'SecretKey' ) ); // correct signature $rSig = $params['signature']; // provided signature $verified = is_string( $rSig ) && hash_equals( $cSig, $rSig ); if ( !$verified || $params['sigexpiry'] < time() ) { header( "HTTP/1.0 400 Bad Request" ); print 'Invalid or stale signature provided'; return; } // Apply any default parameter values $params += $optional; if ( $params['async'] ) { // Client will usually disconnect before checking the response, // but it needs to know when it is safe to disconnect. Until this // reaches ignore_user_abort(), it is not safe as the jobs won't run. ignore_user_abort( true ); // jobs may take a bit of time header( "HTTP/1.0 202 Accepted" ); ob_flush(); flush(); // Once the client receives this response, it can disconnect } // Do all of the specified tasks... if ( in_array( 'jobs', explode( '|', $params['tasks'] ) ) ) { $runner = new JobRunner(); $response = $runner->run( array( 'type' => $params['type'], 'maxJobs' => $params['maxjobs'] ? $params['maxjobs'] : 1, 'maxTime' => $params['maxtime'] ? $params['maxjobs'] : 30 ) ); if ( !$params['async'] ) { print FormatJson::encode( $response, true ); } } } /** * @param array $query * @param string $secretKey * @return string */ public static function getQuerySignature( array $query, $secretKey ) { ksort( $query ); // stable order return hash_hmac( 'sha1', wfArrayToCgi( $query ), $secretKey ); } }