MediaWiki  REL1_24
SpecialRunJobs.php
Go to the documentation of this file.
00001 <?php
00030 class SpecialRunJobs extends UnlistedSpecialPage {
00031     public function __construct() {
00032         parent::__construct( 'RunJobs' );
00033     }
00034 
00035     public function execute( $par = '' ) {
00036         $this->getOutput()->disable();
00037 
00038         if ( wfReadOnly() ) {
00039             header( "HTTP/1.0 423 Locked" );
00040             print 'Wiki is in read-only mode';
00041 
00042             return;
00043         } elseif ( !$this->getRequest()->wasPosted() ) {
00044             header( "HTTP/1.0 400 Bad Request" );
00045             print 'Request must be POSTed';
00046 
00047             return;
00048         }
00049 
00050         $optional = array( 'maxjobs' => 0, 'maxtime' => 30, 'type' => false, 'async' => true );
00051         $required = array_flip( array( 'title', 'tasks', 'signature', 'sigexpiry' ) );
00052 
00053         $params = array_intersect_key( $this->getRequest()->getValues(), $required + $optional );
00054         $missing = array_diff_key( $required, $params );
00055         if ( count( $missing ) ) {
00056             header( "HTTP/1.0 400 Bad Request" );
00057             print 'Missing parameters: ' . implode( ', ', array_keys( $missing ) );
00058 
00059             return;
00060         }
00061 
00062         $squery = $params;
00063         unset( $squery['signature'] );
00064         $cSig = self::getQuerySignature( $squery, $this->getConfig()->get( 'SecretKey' ) ); // correct signature
00065         $rSig = $params['signature']; // provided signature
00066 
00067         $verified = is_string( $rSig ) && hash_equals( $cSig, $rSig );
00068         if ( !$verified || $params['sigexpiry'] < time() ) {
00069             header( "HTTP/1.0 400 Bad Request" );
00070             print 'Invalid or stale signature provided';
00071 
00072             return;
00073         }
00074 
00075         // Apply any default parameter values
00076         $params += $optional;
00077 
00078         if ( $params['async'] ) {
00079             // Client will usually disconnect before checking the response,
00080             // but it needs to know when it is safe to disconnect. Until this
00081             // reaches ignore_user_abort(), it is not safe as the jobs won't run.
00082             ignore_user_abort( true ); // jobs may take a bit of time
00083             header( "HTTP/1.0 202 Accepted" );
00084             ob_flush();
00085             flush();
00086             // Once the client receives this response, it can disconnect
00087         }
00088 
00089         // Do all of the specified tasks...
00090         if ( in_array( 'jobs', explode( '|', $params['tasks'] ) ) ) {
00091             $runner = new JobRunner();
00092             $response = $runner->run( array(
00093                 'type'     => $params['type'],
00094                 'maxJobs'  => $params['maxjobs'] ? $params['maxjobs'] : 1,
00095                 'maxTime'  => $params['maxtime'] ? $params['maxjobs'] : 30
00096             ) );
00097             if ( !$params['async'] ) {
00098                 print FormatJson::encode( $response, true );
00099             }
00100         }
00101     }
00102 
00108     public static function getQuerySignature( array $query, $secretKey ) {
00109         ksort( $query ); // stable order
00110         return hash_hmac( 'sha1', wfArrayToCgi( $query ), $secretKey );
00111     }
00112 }