MediaWiki  1.23.16
ApiMain.php
Go to the documentation of this file.
1 <?php
41 class ApiMain extends ApiBase {
45  const API_DEFAULT_FORMAT = 'xmlfm';
46 
50  private static $Modules = array(
51  'login' => 'ApiLogin',
52  'logout' => 'ApiLogout',
53  'createaccount' => 'ApiCreateAccount',
54  'query' => 'ApiQuery',
55  'expandtemplates' => 'ApiExpandTemplates',
56  'parse' => 'ApiParse',
57  'opensearch' => 'ApiOpenSearch',
58  'feedcontributions' => 'ApiFeedContributions',
59  'feedrecentchanges' => 'ApiFeedRecentChanges',
60  'feedwatchlist' => 'ApiFeedWatchlist',
61  'help' => 'ApiHelp',
62  'paraminfo' => 'ApiParamInfo',
63  'rsd' => 'ApiRsd',
64  'compare' => 'ApiComparePages',
65  'tokens' => 'ApiTokens',
66 
67  // Write modules
68  'purge' => 'ApiPurge',
69  'setnotificationtimestamp' => 'ApiSetNotificationTimestamp',
70  'rollback' => 'ApiRollback',
71  'delete' => 'ApiDelete',
72  'undelete' => 'ApiUndelete',
73  'protect' => 'ApiProtect',
74  'block' => 'ApiBlock',
75  'unblock' => 'ApiUnblock',
76  'move' => 'ApiMove',
77  'edit' => 'ApiEditPage',
78  'upload' => 'ApiUpload',
79  'filerevert' => 'ApiFileRevert',
80  'emailuser' => 'ApiEmailUser',
81  'watch' => 'ApiWatch',
82  'patrol' => 'ApiPatrol',
83  'import' => 'ApiImport',
84  'userrights' => 'ApiUserrights',
85  'options' => 'ApiOptions',
86  'imagerotate' => 'ApiImageRotate',
87  'revisiondelete' => 'ApiRevisionDelete',
88  );
89 
93  private static $Formats = array(
94  'json' => 'ApiFormatJson',
95  'jsonfm' => 'ApiFormatJson',
96  'php' => 'ApiFormatPhp',
97  'phpfm' => 'ApiFormatPhp',
98  'wddx' => 'ApiFormatWddx',
99  'wddxfm' => 'ApiFormatWddx',
100  'xml' => 'ApiFormatXml',
101  'xmlfm' => 'ApiFormatXml',
102  'yaml' => 'ApiFormatYaml',
103  'yamlfm' => 'ApiFormatYaml',
104  'rawfm' => 'ApiFormatJson',
105  'txt' => 'ApiFormatTxt',
106  'txtfm' => 'ApiFormatTxt',
107  'dbg' => 'ApiFormatDbg',
108  'dbgfm' => 'ApiFormatDbg',
109  'dump' => 'ApiFormatDump',
110  'dumpfm' => 'ApiFormatDump',
111  'none' => 'ApiFormatNone',
112  );
113 
114  // @codingStandardsIgnoreStart String contenation on "msg" not allowed to break long line
121  private static $mRights = array(
122  'writeapi' => array(
123  'msg' => 'Use of the write API',
124  'params' => array()
125  ),
126  'apihighlimits' => array(
127  'msg' => 'Use higher limits in API queries (Slow queries: $1 results; Fast queries: $2 results). The limits for slow queries also apply to multivalue parameters.',
129  )
130  );
131  // @codingStandardsIgnoreEnd
132 
136  private $mPrinter;
137 
139  private $mAction;
140  private $mEnableWrite;
142 
143  private $mCacheMode = 'private';
144  private $mCacheControl = array();
145  private $mParamsUsed = array();
146  private $mParamsSensitive = [];
147 
149  private $lacksSameOriginSecurity = null;
150 
158  public function __construct( $context = null, $enableWrite = false ) {
159  if ( $context === null ) {
161  } elseif ( $context instanceof WebRequest ) {
162  // BC for pre-1.19
163  $request = $context;
165  }
166  // We set a derivative context so we can change stuff later
167  $this->setContext( new DerivativeContext( $context ) );
168 
169  if ( isset( $request ) ) {
170  $this->getContext()->setRequest( $request );
171  }
172 
173  $this->mInternalMode = ( $this->getRequest() instanceof FauxRequest );
174 
175  // Special handling for the main module: $parent === $this
176  parent::__construct( $this, $this->mInternalMode ? 'main_int' : 'main' );
177 
178  if ( !$this->mInternalMode ) {
179  // Impose module restrictions.
180  // If the current user cannot read,
181  // Remove all modules other than login
182  global $wgUser;
183 
184  if ( $this->getVal( 'callback' ) !== null ) {
185  // JSON callback allows cross-site reads.
186  // For safety, strip user credentials.
187  wfDebug( "API: stripping user credentials for JSON callback\n" );
188  $wgUser = new User();
189  $this->getContext()->setUser( $wgUser );
190  }
191  }
192 
193  global $wgAPIModules, $wgAPIFormatModules;
194  $this->mModuleMgr = new ApiModuleManager( $this );
195  $this->mModuleMgr->addModules( self::$Modules, 'action' );
196  $this->mModuleMgr->addModules( $wgAPIModules, 'action' );
197  $this->mModuleMgr->addModules( self::$Formats, 'format' );
198  $this->mModuleMgr->addModules( $wgAPIFormatModules, 'format' );
199 
200  $this->mResult = new ApiResult( $this );
201  $this->mEnableWrite = $enableWrite;
202 
203  $this->mSquidMaxage = -1; // flag for executeActionWithErrorHandling()
204  $this->mCommit = false;
205  }
206 
211  public function isInternalMode() {
212  return $this->mInternalMode;
213  }
214 
220  public function getResult() {
221  return $this->mResult;
222  }
223 
228  public function lacksSameOriginSecurity() {
229  if ( $this->lacksSameOriginSecurity !== null ) {
231  }
232 
233  $request = $this->getRequest();
234 
235  // JSONP mode
236  if ( $request->getVal( 'callback' ) !== null ) {
237  $this->lacksSameOriginSecurity = true;
238  return true;
239  }
240 
241  // Header to be used from XMLHTTPRequest when the request might
242  // otherwise be used for XSS.
243  if ( $request->getHeader( 'Treat-as-Untrusted' ) !== false ) {
244  $this->lacksSameOriginSecurity = true;
245  return true;
246  }
247 
248  // Allow extensions to override.
249  $this->lacksSameOriginSecurity = !Hooks::run( 'RequestHasSameOriginSecurity', array( $request ) );
251  }
252 
258  public function getModule() {
259  return $this->mModule;
260  }
261 
267  public function getPrinter() {
268  return $this->mPrinter;
269  }
270 
276  public function setCacheMaxAge( $maxage ) {
277  $this->setCacheControl( array(
278  'max-age' => $maxage,
279  's-maxage' => $maxage
280  ) );
281  }
282 
308  public function setCacheMode( $mode ) {
309  if ( !in_array( $mode, array( 'private', 'public', 'anon-public-user-private' ) ) ) {
310  wfDebug( __METHOD__ . ": unrecognised cache mode \"$mode\"\n" );
311 
312  // Ignore for forwards-compatibility
313  return;
314  }
315 
316  if ( !User::isEveryoneAllowed( 'read' ) ) {
317  // Private wiki, only private headers
318  if ( $mode !== 'private' ) {
319  wfDebug( __METHOD__ . ": ignoring request for $mode cache mode, private wiki\n" );
320 
321  return;
322  }
323  }
324 
325  wfDebug( __METHOD__ . ": setting cache mode $mode\n" );
326  $this->mCacheMode = $mode;
327  }
328 
339  public function setCacheControl( $directives ) {
340  $this->mCacheControl = $directives + $this->mCacheControl;
341  }
342 
350  public function createPrinterByName( $format ) {
351  $printer = $this->mModuleMgr->getModule( $format, 'format' );
352  if ( $printer === null ) {
353  $this->dieUsage( "Unrecognized format: {$format}", 'unknown_format' );
354  }
355 
356  return $printer;
357  }
358 
362  public function execute() {
363  $this->profileIn();
364  if ( $this->mInternalMode ) {
365  $this->executeAction();
366  } else {
368  }
369 
370  $this->profileOut();
371  }
372 
377  protected function executeActionWithErrorHandling() {
378  // Verify the CORS header before executing the action
379  if ( !$this->handleCORS() ) {
380  // handleCORS() has sent a 403, abort
381  return;
382  }
383 
384  // Exit here if the request method was OPTIONS
385  // (assume there will be a followup GET or POST)
386  if ( $this->getRequest()->getMethod() === 'OPTIONS' ) {
387  return;
388  }
389 
390  // In case an error occurs during data output,
391  // clear the output buffer and print just the error information
392  ob_start();
393 
394  $t = microtime( true );
395  try {
396  $this->executeAction();
397  } catch ( Exception $e ) {
398  $this->handleException( $e );
399  }
400 
401  // Log the request whether or not there was an error
402  $this->logRequest( microtime( true ) - $t );
403 
404  // Send cache headers after any code which might generate an error, to
405  // avoid sending public cache headers for errors.
406  $this->sendCacheHeaders();
407 
408  if ( $this->mPrinter->getIsHtml() && !$this->mPrinter->isDisabled() ) {
409  echo wfReportTime();
410  }
411 
412  ob_end_flush();
413  }
414 
421  protected function handleException( Exception $e ) {
422  // Bug 63145: Rollback any open database transactions
423  if ( !( $e instanceof UsageException ) ) {
424  // UsageExceptions are intentional, so don't rollback if that's the case
426  }
427 
428  // Allow extra cleanup and logging
429  wfRunHooks( 'ApiMain::onException', array( $this, $e ) );
430 
431  // Log it
432  if ( !( $e instanceof UsageException ) ) {
434  }
435 
436  // Handle any kind of exception by outputting properly formatted error message.
437  // If this fails, an unhandled exception should be thrown so that global error
438  // handler will process and log it.
439 
440  $errCode = $this->substituteResultWithError( $e );
441 
442  // Error results should not be cached
443  $this->setCacheMode( 'private' );
444 
445  $response = $this->getRequest()->response();
446  $headerStr = 'MediaWiki-API-Error: ' . $errCode;
447  if ( $e->getCode() === 0 ) {
448  $response->header( $headerStr );
449  } else {
450  $response->header( $headerStr, true, $e->getCode() );
451  }
452 
453  // Reset and print just the error message
454  ob_clean();
455 
456  // If the error occurred during printing, do a printer->profileOut()
457  $this->mPrinter->safeProfileOut();
458  $this->printResult( true );
459  }
460 
470  public static function handleApiBeforeMainException( Exception $e ) {
471  ob_start();
472 
473  try {
474  $main = new self( RequestContext::getMain(), false );
475  $main->handleException( $e );
476  } catch ( Exception $e2 ) {
477  // Nope, even that didn't work. Punt.
478  throw $e;
479  }
480 
481  // Log the request and reset cache headers
482  $main->logRequest( 0 );
483  $main->sendCacheHeaders();
484 
485  ob_end_flush();
486  }
487 
500  protected function handleCORS() {
501  global $wgCrossSiteAJAXdomains, $wgCrossSiteAJAXdomainExceptions;
502 
503  $originParam = $this->getParameter( 'origin' ); // defaults to null
504  if ( $originParam === null ) {
505  // No origin parameter, nothing to do
506  return true;
507  }
508 
509  $request = $this->getRequest();
510  $response = $request->response();
511  // Origin: header is a space-separated list of origins, check all of them
512  $originHeader = $request->getHeader( 'Origin' );
513  if ( $originHeader === false ) {
514  $origins = array();
515  } else {
516  $origins = explode( ' ', $originHeader );
517  }
518 
519  if ( !in_array( $originParam, $origins ) ) {
520  // origin parameter set but incorrect
521  // Send a 403 response
522  $message = HttpStatus::getMessage( 403 );
523  $response->header( "HTTP/1.1 403 $message", true, 403 );
524  $response->header( 'Cache-Control: no-cache' );
525  echo "'origin' parameter does not match Origin header\n";
526 
527  return false;
528  }
529 
530  $matchOrigin = self::matchOrigin(
531  $originParam,
532  $wgCrossSiteAJAXdomains,
533  $wgCrossSiteAJAXdomainExceptions
534  );
535 
536  if ( $matchOrigin ) {
537  $response->header( "Access-Control-Allow-Origin: $originParam" );
538  $response->header( 'Access-Control-Allow-Credentials: true' );
539  $this->getOutput()->addVaryHeader( 'Origin' );
540  }
541 
542  return true;
543  }
544 
553  protected static function matchOrigin( $value, $rules, $exceptions ) {
554  foreach ( $rules as $rule ) {
555  if ( preg_match( self::wildcardToRegex( $rule ), $value ) ) {
556  // Rule matches, check exceptions
557  foreach ( $exceptions as $exc ) {
558  if ( preg_match( self::wildcardToRegex( $exc ), $value ) ) {
559  return false;
560  }
561  }
562 
563  return true;
564  }
565  }
566 
567  return false;
568  }
569 
578  protected static function wildcardToRegex( $wildcard ) {
579  $wildcard = preg_quote( $wildcard, '/' );
580  $wildcard = str_replace(
581  array( '\*', '\?' ),
582  array( '.*?', '.' ),
583  $wildcard
584  );
585 
586  return "/^https?:\/\/$wildcard$/";
587  }
588 
589  protected function sendCacheHeaders() {
590  global $wgUseXVO, $wgVaryOnXFP;
591  $response = $this->getRequest()->response();
592  $out = $this->getOutput();
593 
594  $out->addVaryHeader( 'Treat-as-Untrusted' );
595 
596  if ( $wgVaryOnXFP ) {
597  $out->addVaryHeader( 'X-Forwarded-Proto' );
598  }
599 
600  if ( $this->mCacheMode == 'private' ) {
601  $response->header( 'Cache-Control: private' );
602 
603  return;
604  }
605 
606  if ( $this->mCacheMode == 'anon-public-user-private' ) {
607  $out->addVaryHeader( 'Cookie' );
608  $response->header( $out->getVaryHeader() );
609  if ( $wgUseXVO ) {
610  $response->header( $out->getXVO() );
611  if ( $out->haveCacheVaryCookies() ) {
612  // Logged in, mark this request private
613  $response->header( 'Cache-Control: private' );
614 
615  return;
616  }
617  // Logged out, send normal public headers below
618  } elseif ( session_id() != '' ) {
619  // Logged in or otherwise has session (e.g. anonymous users who have edited)
620  // Mark request private
621  $response->header( 'Cache-Control: private' );
622 
623  return;
624  } // else no XVO and anonymous, send public headers below
625  }
626 
627  // Send public headers
628  $response->header( $out->getVaryHeader() );
629  if ( $wgUseXVO ) {
630  $response->header( $out->getXVO() );
631  }
632 
633  // If nobody called setCacheMaxAge(), use the (s)maxage parameters
634  if ( !isset( $this->mCacheControl['s-maxage'] ) ) {
635  $this->mCacheControl['s-maxage'] = $this->getParameter( 'smaxage' );
636  }
637  if ( !isset( $this->mCacheControl['max-age'] ) ) {
638  $this->mCacheControl['max-age'] = $this->getParameter( 'maxage' );
639  }
640 
641  if ( !$this->mCacheControl['s-maxage'] && !$this->mCacheControl['max-age'] ) {
642  // Public cache not requested
643  // Sending a Vary header in this case is harmless, and protects us
644  // against conditional calls of setCacheMaxAge().
645  $response->header( 'Cache-Control: private' );
646 
647  return;
648  }
649 
650  $this->mCacheControl['public'] = true;
651 
652  // Send an Expires header
653  $maxAge = min( $this->mCacheControl['s-maxage'], $this->mCacheControl['max-age'] );
654  $expiryUnixTime = ( $maxAge == 0 ? 1 : time() + $maxAge );
655  $response->header( 'Expires: ' . wfTimestamp( TS_RFC2822, $expiryUnixTime ) );
656 
657  // Construct the Cache-Control header
658  $ccHeader = '';
659  $separator = '';
660  foreach ( $this->mCacheControl as $name => $value ) {
661  if ( is_bool( $value ) ) {
662  if ( $value ) {
663  $ccHeader .= $separator . $name;
664  $separator = ', ';
665  }
666  } else {
667  $ccHeader .= $separator . "$name=$value";
668  $separator = ', ';
669  }
670  }
671 
672  $response->header( "Cache-Control: $ccHeader" );
673  }
674 
681  protected function substituteResultWithError( $e ) {
682  global $wgShowHostnames;
683 
684  $result = $this->getResult();
685 
686  // Printer may not be initialized if the extractRequestParams() fails for the main module
687  if ( !isset( $this->mPrinter ) ) {
688  // The printer has not been created yet. Try to manually get formatter value.
689  $value = $this->getRequest()->getVal( 'format', self::API_DEFAULT_FORMAT );
690  if ( !$this->mModuleMgr->isDefined( $value, 'format' ) ) {
692  }
693 
694  $this->mPrinter = $this->createPrinterByName( $value );
695  }
696 
697  // Printer may not be able to handle errors. This is particularly
698  // likely if the module returns something for getCustomPrinter().
699  if ( !$this->mPrinter->canPrintErrors() ) {
700  $this->mPrinter->safeProfileOut();
701  $this->mPrinter = $this->createPrinterByName( self::API_DEFAULT_FORMAT );
702  }
703 
704  // Update raw mode flag for the selected printer.
705  $result->setRawMode( $this->mPrinter->getNeedsRawData() );
706 
707  if ( $e instanceof UsageException ) {
708  // User entered incorrect parameters - print usage screen
709  $errMessage = $e->getMessageArray();
710 
711  // Only print the help message when this is for the developer, not runtime
712  if ( $this->mPrinter->getWantsHelp() || $this->mAction == 'help' ) {
713  ApiResult::setContent( $errMessage, $this->makeHelpMsg() );
714  }
715  } else {
716  global $wgShowSQLErrors, $wgShowExceptionDetails;
717  // Something is seriously wrong
718  if ( ( $e instanceof DBQueryError ) && !$wgShowSQLErrors ) {
719  $info = 'Database query error';
720  } else {
721  $info = "Exception Caught: {$e->getMessage()}";
722  }
723 
724  $errMessage = array(
725  'code' => 'internal_api_error_' . get_class( $e ),
726  'info' => $info,
727  );
729  $errMessage,
730  $wgShowExceptionDetails ? "\n\n{$e->getTraceAsString()}\n\n" : ''
731  );
732  }
733 
734  // Remember all the warnings to re-add them later
735  $oldResult = $result->getData();
736  $warnings = isset( $oldResult['warnings'] ) ? $oldResult['warnings'] : null;
737 
738  $result->reset();
739  $result->disableSizeCheck();
740  // Re-add the id
741  $requestid = $this->getParameter( 'requestid' );
742  if ( !is_null( $requestid ) ) {
743  $result->addValue( null, 'requestid', $requestid );
744  }
745  if ( $wgShowHostnames ) {
746  // servedby is especially useful when debugging errors
747  $result->addValue( null, 'servedby', wfHostName() );
748  }
749  if ( $warnings !== null ) {
750  $result->addValue( null, 'warnings', $warnings );
751  }
752 
753  $result->addValue( null, 'error', $errMessage );
754 
755  return $errMessage['code'];
756  }
757 
762  protected function setupExecuteAction() {
763  global $wgShowHostnames;
764 
765  // First add the id to the top element
766  $result = $this->getResult();
767  $requestid = $this->getParameter( 'requestid' );
768  if ( !is_null( $requestid ) ) {
769  $result->addValue( null, 'requestid', $requestid );
770  }
771 
772  if ( $wgShowHostnames ) {
773  $servedby = $this->getParameter( 'servedby' );
774  if ( $servedby ) {
775  $result->addValue( null, 'servedby', wfHostName() );
776  }
777  }
778 
779  $params = $this->extractRequestParams();
780 
781  $this->mAction = $params['action'];
782 
783  if ( !is_string( $this->mAction ) ) {
784  $this->dieUsage( 'The API requires a valid action parameter', 'unknown_action' );
785  }
786 
787  return $params;
788  }
789 
794  protected function setupModule() {
795  // Instantiate the module requested by the user
796  $module = $this->mModuleMgr->getModule( $this->mAction, 'action' );
797  if ( $module === null ) {
798  $this->dieUsage( 'The API requires a valid action parameter', 'unknown_action' );
799  }
800  $moduleParams = $module->extractRequestParams();
801 
802  // Die if token required, but not provided
803  $salt = $module->getTokenSalt();
804  if ( $salt !== false ) {
805  if ( !isset( $moduleParams['token'] ) ) {
806  $this->dieUsageMsg( array( 'missingparam', 'token' ) );
807  }
808 
809  if ( !$this->getUser()->matchEditToken(
810  $moduleParams['token'],
811  $salt,
812  $this->getContext()->getRequest() )
813  ) {
814  $this->dieUsageMsg( 'sessionfailure' );
815  }
816  }
817 
818  return $module;
819  }
820 
827  protected function checkMaxLag( $module, $params ) {
828  if ( $module->shouldCheckMaxlag() && isset( $params['maxlag'] ) ) {
829  // Check for maxlag
830  global $wgShowHostnames;
831  $maxLag = $params['maxlag'];
832  list( $host, $lag ) = wfGetLB()->getMaxLag();
833  if ( $lag > $maxLag ) {
834  $response = $this->getRequest()->response();
835 
836  $response->header( 'Retry-After: ' . max( intval( $maxLag ), 5 ) );
837  $response->header( 'X-Database-Lag: ' . intval( $lag ) );
838 
839  if ( $wgShowHostnames ) {
840  $this->dieUsage( "Waiting for $host: $lag seconds lagged", 'maxlag' );
841  }
842 
843  $this->dieUsage( "Waiting for a database server: $lag seconds lagged", 'maxlag' );
844  }
845  }
846 
847  return true;
848  }
849 
854  protected function checkExecutePermissions( $module ) {
855  $user = $this->getUser();
856  if ( $module->isReadMode() && !User::isEveryoneAllowed( 'read' ) &&
857  !$user->isAllowed( 'read' )
858  ) {
859  $this->dieUsageMsg( 'readrequired' );
860  }
861  if ( $module->isWriteMode() ) {
862  if ( !$this->mEnableWrite ) {
863  $this->dieUsageMsg( 'writedisabled' );
864  }
865  if ( !$user->isAllowed( 'writeapi' ) ) {
866  $this->dieUsageMsg( 'writerequired' );
867  }
868  if ( wfReadOnly() ) {
869  $this->dieReadOnly();
870  }
871  }
872 
873  // Allow extensions to stop execution for arbitrary reasons.
874  $message = false;
875  if ( !wfRunHooks( 'ApiCheckCanExecute', array( $module, $user, &$message ) ) ) {
876  $this->dieUsageMsg( $message );
877  }
878  }
879 
884  protected function checkAsserts( $params ) {
885  if ( isset( $params['assert'] ) ) {
886  $user = $this->getUser();
887  switch ( $params['assert'] ) {
888  case 'user':
889  if ( $user->isAnon() ) {
890  $this->dieUsage( 'Assertion that the user is logged in failed', 'assertuserfailed' );
891  }
892  break;
893  case 'bot':
894  if ( !$user->isAllowed( 'bot' ) ) {
895  $this->dieUsage( 'Assertion that the user has the bot right failed', 'assertbotfailed' );
896  }
897  break;
898  }
899  }
900  }
901 
907  protected function setupExternalResponse( $module, $params ) {
908  if ( !$this->getRequest()->wasPosted() && $module->mustBePosted() ) {
909  // Module requires POST. GET request might still be allowed
910  // if $wgDebugApi is true, otherwise fail.
911  $this->dieUsageMsgOrDebug( array( 'mustbeposted', $this->mAction ) );
912  }
913 
914  // See if custom printer is used
915  $this->mPrinter = $module->getCustomPrinter();
916  if ( is_null( $this->mPrinter ) ) {
917  // Create an appropriate printer
918  $this->mPrinter = $this->createPrinterByName( $params['format'] );
919  }
920 
921  if ( $this->mPrinter->getNeedsRawData() ) {
922  $this->getResult()->setRawMode();
923  }
924  }
925 
929  protected function executeAction() {
930  $params = $this->setupExecuteAction();
931  $module = $this->setupModule();
932  $this->mModule = $module;
933 
934  $this->checkExecutePermissions( $module );
935 
936  if ( !$this->checkMaxLag( $module, $params ) ) {
937  return;
938  }
939 
940  if ( !$this->mInternalMode ) {
941  $this->setupExternalResponse( $module, $params );
942  }
943 
944  $this->checkAsserts( $params );
945 
946  // Execute
947  $module->profileIn();
948  $module->execute();
949  wfRunHooks( 'APIAfterExecute', array( &$module ) );
950  $module->profileOut();
951 
952  $this->reportUnusedParams();
953 
954  if ( !$this->mInternalMode ) {
955  //append Debug information
957 
958  // Print result data
959  $this->printResult( false );
960  }
961  }
962 
967  protected function logRequest( $time ) {
968  $request = $this->getRequest();
969  $milliseconds = $time === null ? '?' : round( $time * 1000 );
970  $s = 'API' .
971  ' ' . $request->getMethod() .
972  ' ' . wfUrlencode( str_replace( ' ', '_', $this->getUser()->getName() ) ) .
973  ' ' . $request->getIP() .
974  ' T=' . $milliseconds . 'ms';
975 
976  $sensitive = array_flip( $this->getSensitiveParams() );
977  foreach ( $this->getParamsUsed() as $name ) {
978  $value = $request->getVal( $name );
979  if ( $value === null ) {
980  continue;
981  }
982  $s .= ' ' . $name . '=';
983  if ( isset( $sensitive[$name] ) ) {
984  $value = '[redacted]';
985  $encValue = '[redacted]';
986  } elseif ( strlen( $value ) > 256 ) {
987  $encValue = $this->encodeRequestLogValue( substr( $value, 0, 256 ) );
988  $s .= $encValue . '[...]';
989  } else {
990  $s .= $this->encodeRequestLogValue( $value );
991  }
992  }
993  $s .= "\n";
994  wfDebugLog( 'api', $s, 'private' );
995  }
996 
1000  protected function encodeRequestLogValue( $s ) {
1001  static $table;
1002  if ( !$table ) {
1003  $chars = ';@$!*(),/:';
1004  $numChars = strlen( $chars );
1005  for ( $i = 0; $i < $numChars; $i++ ) {
1006  $table[rawurlencode( $chars[$i] )] = $chars[$i];
1007  }
1008  }
1009 
1010  return strtr( rawurlencode( $s ), $table );
1011  }
1012 
1016  protected function getParamsUsed() {
1017  return array_keys( $this->mParamsUsed );
1018  }
1019 
1025  protected function getSensitiveParams() {
1026  return array_keys( $this->mParamsSensitive );
1027  }
1028 
1034  public function markParamsSensitive( $params ) {
1035  $this->mParamsSensitive += array_fill_keys( (array)$params, true );
1036  }
1037 
1041  public function getVal( $name, $default = null ) {
1042  $this->mParamsUsed[$name] = true;
1043 
1044  return $this->getRequest()->getVal( $name, $default );
1045  }
1046 
1051  public function getCheck( $name ) {
1052  $this->mParamsUsed[$name] = true;
1053 
1054  return $this->getRequest()->getCheck( $name );
1055  }
1056 
1064  public function getUpload( $name ) {
1065  $this->mParamsUsed[$name] = true;
1066 
1067  return $this->getRequest()->getUpload( $name );
1068  }
1069 
1074  protected function reportUnusedParams() {
1075  $paramsUsed = $this->getParamsUsed();
1076  $allParams = $this->getRequest()->getValueNames();
1077 
1078  if ( !$this->mInternalMode ) {
1079  // Printer has not yet executed; don't warn that its parameters are unused
1080  $printerParams = array_map(
1081  array( $this->mPrinter, 'encodeParamName' ),
1082  array_keys( $this->mPrinter->getFinalParams() ?: array() )
1083  );
1084  $unusedParams = array_diff( $allParams, $paramsUsed, $printerParams );
1085  } else {
1086  $unusedParams = array_diff( $allParams, $paramsUsed );
1087  }
1088 
1089  if ( count( $unusedParams ) ) {
1090  $s = count( $unusedParams ) > 1 ? 's' : '';
1091  $this->setWarning( "Unrecognized parameter$s: '" . implode( $unusedParams, "', '" ) . "'" );
1092  }
1093  }
1094 
1100  protected function printResult( $isError ) {
1101  global $wgDebugAPI;
1102  if ( $wgDebugAPI !== false ) {
1103  $this->setWarning( 'SECURITY WARNING: $wgDebugAPI is enabled' );
1104  }
1105 
1106  $this->getResult()->cleanUpUTF8();
1107  $printer = $this->mPrinter;
1108  $printer->profileIn();
1109 
1115  $isHelp = $isError || $this->mAction == 'help';
1116  $printer->setUnescapeAmps( $isHelp && $printer->getFormat() == 'XML' && $printer->getIsHtml() );
1117 
1118  $printer->initPrinter( $isHelp );
1119 
1120  $printer->execute();
1121  $printer->closePrinter();
1122  $printer->profileOut();
1123  }
1124 
1128  public function isReadMode() {
1129  return false;
1130  }
1131 
1137  public function getAllowedParams() {
1138  return array(
1139  'format' => array(
1141  ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'format' )
1142  ),
1143  'action' => array(
1144  ApiBase::PARAM_DFLT => 'help',
1145  ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'action' )
1146  ),
1147  'maxlag' => array(
1148  ApiBase::PARAM_TYPE => 'integer'
1149  ),
1150  'smaxage' => array(
1151  ApiBase::PARAM_TYPE => 'integer',
1152  ApiBase::PARAM_DFLT => 0
1153  ),
1154  'maxage' => array(
1155  ApiBase::PARAM_TYPE => 'integer',
1156  ApiBase::PARAM_DFLT => 0
1157  ),
1158  'assert' => array(
1159  ApiBase::PARAM_TYPE => array( 'user', 'bot' )
1160  ),
1161  'requestid' => null,
1162  'servedby' => false,
1163  'origin' => null,
1164  );
1165  }
1166 
1172  public function getParamDescription() {
1173  return array(
1174  'format' => 'The format of the output',
1175  'action' => 'What action you would like to perform. See below for module help',
1176  'maxlag' => array(
1177  'Maximum lag can be used when MediaWiki is installed on a database replicated cluster.',
1178  'To save actions causing any more site replication lag, this parameter can make the client',
1179  'wait until the replication lag is less than the specified value.',
1180  'In case of a replag error, error code "maxlag" is returned, with the message like',
1181  '"Waiting for $host: $lag seconds lagged\n".',
1182  'See https://www.mediawiki.org/wiki/Manual:Maxlag_parameter for more information',
1183  ),
1184  'smaxage' => 'Set the s-maxage header to this many seconds. Errors are never cached',
1185  'maxage' => 'Set the max-age header to this many seconds. Errors are never cached',
1186  'assert' => 'Verify the user is logged in if set to "user", or has the bot userright if "bot"',
1187  'requestid' => 'Request ID to distinguish requests. This will just be output back to you',
1188  'servedby' => 'Include the hostname that served the request in the ' .
1189  'results. Unconditionally shown on error',
1190  'origin' => array(
1191  'When accessing the API using a cross-domain AJAX request (CORS), set this to the',
1192  'originating domain. This must be included in any pre-flight request, and',
1193  'therefore must be part of the request URI (not the POST body). This must match',
1194  'one of the origins in the Origin: header exactly, so it has to be set to ',
1195  'something like http://en.wikipedia.org or https://meta.wikimedia.org . If this',
1196  'parameter does not match the Origin: header, a 403 response will be returned. If',
1197  'this parameter matches the Origin: header and the origin is whitelisted, an',
1198  'Access-Control-Allow-Origin header will be set.',
1199  ),
1200  );
1201  }
1202 
1208  public function getDescription() {
1209  return array(
1210  '',
1211  '',
1212  '**********************************************************************************************',
1213  '** **',
1214  '** This is an auto-generated MediaWiki API documentation page **',
1215  '** **',
1216  '** Documentation and Examples: **',
1217  '** https://www.mediawiki.org/wiki/API **',
1218  '** **',
1219  '**********************************************************************************************',
1220  '',
1221  'Status: All features shown on this page should be working, but the API',
1222  ' is still in active development, and may change at any time.',
1223  ' Make sure to monitor our mailing list for any updates.',
1224  '',
1225  'Erroneous requests: When erroneous requests are sent to the API, a HTTP header will be sent',
1226  ' with the key "MediaWiki-API-Error" and then both the value of the',
1227  ' header and the error code sent back will be set to the same value.',
1228  '',
1229  ' In the case of an invalid action being passed, these will have a value',
1230  ' of "unknown_action".',
1231  '',
1232  ' For more information see https://www.mediawiki.org' .
1233  '/wiki/API:Errors_and_warnings',
1234  '',
1235  'Documentation: https://www.mediawiki.org/wiki/API:Main_page',
1236  'FAQ https://www.mediawiki.org/wiki/API:FAQ',
1237  'Mailing list: https://lists.wikimedia.org/mailman/listinfo/mediawiki-api',
1238  'Api Announcements: https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce',
1239  'Bugs & Requests: https://bugzilla.wikimedia.org/buglist.cgi?component=API&' .
1240  'bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=bugs.delta_ts',
1241  '',
1242  '',
1243  '',
1244  '',
1245  '',
1246  );
1247  }
1248 
1252  public function getPossibleErrors() {
1253  return array_merge( parent::getPossibleErrors(), array(
1254  array( 'readonlytext' ),
1255  array( 'code' => 'unknown_format', 'info' => 'Unrecognized format: format' ),
1256  array( 'code' => 'unknown_action', 'info' => 'The API requires a valid action parameter' ),
1257  array( 'code' => 'maxlag', 'info' => 'Waiting for host: x seconds lagged' ),
1258  array( 'code' => 'maxlag', 'info' => 'Waiting for a database server: x seconds lagged' ),
1259  array( 'code' => 'assertuserfailed', 'info' => 'Assertion that the user is logged in failed' ),
1260  array(
1261  'code' => 'assertbotfailed',
1262  'info' => 'Assertion that the user has the bot right failed'
1263  ),
1264  ) );
1265  }
1266 
1271  protected function getCredits() {
1272  return array(
1273  'API developers:',
1274  ' Roan Kattouw (lead developer Sep 2007-2009)',
1275  ' Victor Vasiliev',
1276  ' Bryan Tong Minh',
1277  ' Sam Reed',
1278  ' Yuri Astrakhan (creator, lead developer Sep 2006-Sep 2007, 2012-present)',
1279  '',
1280  'Please send your comments, suggestions and questions to mediawiki-api@lists.wikimedia.org',
1281  'or file a bug report at https://bugzilla.wikimedia.org/'
1282  );
1283  }
1284 
1290  public function setHelp( $help = true ) {
1291  $this->mPrinter->setHelp( $help );
1292  }
1293 
1299  public function makeHelpMsg() {
1300  global $wgMemc, $wgAPICacheHelpTimeout;
1301  $this->setHelp();
1302  // Get help text from cache if present
1303  $key = wfMemcKey( 'apihelp', $this->getModuleName(),
1304  str_replace( ' ', '_', SpecialVersion::getVersion( 'nodb' ) ) );
1305  if ( $wgAPICacheHelpTimeout > 0 ) {
1306  $cached = $wgMemc->get( $key );
1307  if ( $cached ) {
1308  return $cached;
1309  }
1310  }
1311  $retval = $this->reallyMakeHelpMsg();
1312  if ( $wgAPICacheHelpTimeout > 0 ) {
1313  $wgMemc->set( $key, $retval, $wgAPICacheHelpTimeout );
1314  }
1315 
1316  return $retval;
1317  }
1318 
1322  public function reallyMakeHelpMsg() {
1323  $this->setHelp();
1324 
1325  // Use parent to make default message for the main module
1326  $msg = parent::makeHelpMsg();
1327 
1328  $astriks = str_repeat( '*** ', 14 );
1329  $msg .= "\n\n$astriks Modules $astriks\n\n";
1330 
1331  foreach ( $this->mModuleMgr->getNames( 'action' ) as $name ) {
1332  $module = $this->mModuleMgr->getModule( $name );
1333  $msg .= self::makeHelpMsgHeader( $module, 'action' );
1334 
1335  $msg2 = $module->makeHelpMsg();
1336  if ( $msg2 !== false ) {
1337  $msg .= $msg2;
1338  }
1339  $msg .= "\n";
1340  }
1341 
1342  $msg .= "\n$astriks Permissions $astriks\n\n";
1343  foreach ( self::$mRights as $right => $rightMsg ) {
1345  $msg .= "* " . $right . " *\n " . wfMsgReplaceArgs( $rightMsg['msg'], $rightMsg['params'] ) .
1346  "\nGranted to:\n " . str_replace( '*', 'all', implode( ', ', $groups ) ) . "\n\n";
1347  }
1348 
1349  $msg .= "\n$astriks Formats $astriks\n\n";
1350  foreach ( $this->mModuleMgr->getNames( 'format' ) as $name ) {
1351  $module = $this->mModuleMgr->getModule( $name );
1352  $msg .= self::makeHelpMsgHeader( $module, 'format' );
1353  $msg2 = $module->makeHelpMsg();
1354  if ( $msg2 !== false ) {
1355  $msg .= $msg2;
1356  }
1357  $msg .= "\n";
1358  }
1359 
1360  $msg .= "\n*** Credits: ***\n " . implode( "\n ", $this->getCredits() ) . "\n";
1361 
1362  return $msg;
1363  }
1364 
1371  public static function makeHelpMsgHeader( $module, $paramName ) {
1372  $modulePrefix = $module->getModulePrefix();
1373  if ( strval( $modulePrefix ) !== '' ) {
1374  $modulePrefix = "($modulePrefix) ";
1375  }
1376 
1377  return "* $paramName={$module->getModuleName()} $modulePrefix*";
1378  }
1379 
1380  private $mCanApiHighLimits = null;
1381 
1386  public function canApiHighLimits() {
1387  if ( !isset( $this->mCanApiHighLimits ) ) {
1388  $this->mCanApiHighLimits = $this->getUser()->isAllowed( 'apihighlimits' );
1389  }
1390 
1391  return $this->mCanApiHighLimits;
1392  }
1393 
1399  public function getShowVersions() {
1400  wfDeprecated( __METHOD__, '1.21' );
1401 
1402  return false;
1403  }
1404 
1409  public function getModuleManager() {
1410  return $this->mModuleMgr;
1411  }
1412 
1422  protected function addModule( $name, $class ) {
1423  $this->getModuleManager()->addModule( $name, 'action', $class );
1424  }
1425 
1434  protected function addFormat( $name, $class ) {
1435  $this->getModuleManager()->addModule( $name, 'format', $class );
1436  }
1437 
1443  function getModules() {
1444  return $this->getModuleManager()->getNamesWithClasses( 'action' );
1445  }
1446 
1454  public function getFormats() {
1455  return $this->getModuleManager()->getNamesWithClasses( 'format' );
1456  }
1457 }
1458 
1465 class UsageException extends MWException {
1466 
1467  private $mCodestr;
1468 
1472  private $mExtraData;
1473 
1480  public function __construct( $message, $codestr, $code = 0, $extradata = null ) {
1481  parent::__construct( $message, $code );
1482  $this->mCodestr = $codestr;
1483  $this->mExtraData = $extradata;
1484  }
1485 
1489  public function getCodeString() {
1490  return $this->mCodestr;
1491  }
1492 
1496  public function getMessageArray() {
1497  $result = array(
1498  'code' => $this->mCodestr,
1499  'info' => $this->getMessage()
1500  );
1501  if ( is_array( $this->mExtraData ) ) {
1502  $result = array_merge( $result, $this->mExtraData );
1503  }
1504 
1505  return $result;
1506  }
1507 
1511  public function __toString() {
1512  return "{$this->getCodeString()}: {$this->getMessage()}";
1513  }
1514 }
ApiMain\getDescription
getDescription()
See ApiBase for description.
Definition: ApiMain.php:1206
ApiBase\dieUsageMsgOrDebug
dieUsageMsgOrDebug( $error)
Will only set a warning instead of failing if the global $wgDebugAPI is set to true.
Definition: ApiBase.php:2015
ApiMain\executeActionWithErrorHandling
executeActionWithErrorHandling()
Execute an action, and in case of an error, erase whatever partial results have been accumulated,...
Definition: ApiMain.php:375
ApiMain
This is the main API class, used for both external and internal processing.
Definition: ApiMain.php:41
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:33
$wgUser
$wgUser
Definition: Setup.php:572
$result
The index of the header message $result[1]=The index of the body text message $result[2 through n]=Parameters passed to body text message. Please note the header message cannot receive/use parameters. 'ImportHandleLogItemXMLTag':When parsing a XML tag in a log item. $reader:XMLReader object $logInfo:Array of information Return false to stop further processing of the tag 'ImportHandlePageXMLTag':When parsing a XML tag in a page. $reader:XMLReader object $pageInfo:Array of information Return false to stop further processing of the tag 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information Return false to stop further processing of the tag 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. $reader:XMLReader object Return false to stop further processing of the tag 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. $reader:XMLReader object $revisionInfo:Array of information Return false to stop further processing of the tag 'InfoAction':When building information to display on the action=info page. $context:IContextSource object & $pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect. $title:Title object for the current page $request:WebRequest $ignoreRedirect:boolean to skip redirect check $target:Title/string of redirect target $article:Article object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not. Return true without providing an interwiki to continue interwiki search. $prefix:interwiki prefix we are looking for. & $iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InternalParseBeforeSanitize':during Parser 's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings. Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InternalParseBeforeLinks':during Parser 's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InvalidateEmailComplete':Called after a user 's email has been invalidated successfully. $user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification. Callee may modify $url and $query, URL will be constructed as $url . $query & $url:URL to index.php & $query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) $article:article(object) being checked 'IsTrustedProxy':Override the result of wfIsTrustedProxy() $ip:IP being check $result:Change this value to override the result of wfIsTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from & $allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of User::isValidEmailAddr(), for instance to return false if the domain name doesn 't match your organization. $addr:The e-mail address entered by the user & $result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user & $result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we 're looking for a messages file for & $file:The messages file path, you can override this to change the location. 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces. Do not use this hook to add namespaces. Use CanonicalNamespaces for that. & $namespaces:Array of namespaces indexed by their numbers 'LanguageGetMagic':DEPRECATED, use $magicWords in a file listed in $wgExtensionMessagesFiles instead. Use this to define synonyms of magic words depending of the language $magicExtensions:associative array of magic words synonyms $lang:language code(string) 'LanguageGetSpecialPageAliases':DEPRECATED, use $specialPageAliases in a file listed in $wgExtensionMessagesFiles instead. Use to define aliases of special pages names depending of the language $specialPageAliases:associative array of magic words synonyms $lang:language code(string) 'LanguageGetTranslatedLanguageNames':Provide translated language names. & $names:array of language code=> language name $code language of the preferred translations 'LanguageLinks':Manipulate a page 's language links. This is called in various places to allow extensions to define the effective language links for a page. $title:The page 's Title. & $links:Associative array mapping language codes to prefixed links of the form "language:title". & $linkFlags:Associative array mapping prefixed links to arrays of flags. Currently unused, but planned to provide support for marking individual language links in the UI, e.g. for featured articles. 'LinkBegin':Used when generating internal and interwiki links in Linker::link(), before processing starts. Return false to skip default processing and return $ret. See documentation for Linker::link() for details on the expected meanings of parameters. $skin:the Skin object $target:the Title that the link is pointing to & $html:the contents that the< a > tag should have(raw HTML) $result
Definition: hooks.txt:1528
FauxRequest
WebRequest clone which takes values from a provided array.
Definition: WebRequest.php:1275
ContextSource\getContext
getContext()
Get the RequestContext object.
Definition: ContextSource.php:40
ApiMain\getCredits
getCredits()
Returns an array of strings with credits for the API.
Definition: ApiMain.php:1269
ApiMain\sendCacheHeaders
sendCacheHeaders()
Definition: ApiMain.php:587
$request
do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values my talk my contributions etc etc otherwise the built in rate limiting checks are if enabled also a ContextSource error or success you ll probably need to make sure the header is varied on WebRequest $request
Definition: hooks.txt:1961
ApiMain\$mParamsSensitive
$mParamsSensitive
Definition: ApiMain.php:145
ApiMain\$mAction
$mAction
Definition: ApiMain.php:138
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
ApiMain\getModules
getModules()
Get the array mapping module names to class names.
Definition: ApiMain.php:1441
ApiMain\$mSquidMaxage
$mSquidMaxage
Definition: ApiMain.php:140
$response
$response
Definition: opensearch_desc.php:32
ApiMain\getParamsUsed
getParamsUsed()
Get the request parameters used in the course of the preceding execute() request.
Definition: ApiMain.php:1014
ApiResult\setContent
static setContent(&$arr, $value, $subElemName=null)
Adds a content element to an array.
Definition: ApiResult.php:201
ApiMain\getVal
getVal( $name, $default=null)
Get a request value, and register the fact that it was used, for logging.
Definition: ApiMain.php:1039
$wgMemc
globals will be eliminated from MediaWiki replaced by an application object which would be passed to constructors Whether that would be an convenient solution remains to be but certainly PHP makes such object oriented programming models easier than they were in previous versions For the time being MediaWiki programmers will have to work in an environment with some global context At the time of globals were initialised on startup by MediaWiki of these were configuration which are documented in DefaultSettings php There is no comprehensive documentation for the remaining however some of the most important ones are listed below They are typically initialised either in index php or in Setup php For a description of the see design txt $wgTitle Title object created from the request URL $wgOut OutputPage object for HTTP response $wgUser User object for the user associated with the current request $wgLang Language object selected by user preferences $wgContLang Language object associated with the wiki being viewed $wgParser Parser object Parser extensions register their hooks here $wgRequest WebRequest to get request data $wgMemc
Definition: globals.txt:25
wfGetLB
wfGetLB( $wiki=false)
Get a load balancer object.
Definition: GlobalFunctions.php:3724
ApiBase\dieUsageMsg
dieUsageMsg( $error)
Output the error message related to a certain array.
Definition: ApiBase.php:1999
ApiMain\$Modules
static $Modules
List of available modules: action name => module class.
Definition: ApiMain.php:50
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:2530
ApiBase\PARAM_TYPE
const PARAM_TYPE
Definition: ApiBase.php:50
ApiFormatBase
This is the abstract base class for API formatters.
Definition: ApiFormatBase.php:32
wfDebugLog
wfDebugLog( $logGroup, $text, $dest='all')
Send a line to a supplementary debug log file, if configured, or main debug log if not.
Definition: GlobalFunctions.php:1087
wfUrlencode
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
Definition: GlobalFunctions.php:377
ApiMain\isReadMode
isReadMode()
Definition: ApiMain.php:1126
ApiMain\handleCORS
handleCORS()
Check the &origin= query parameter against the Origin: HTTP header and respond appropriately.
Definition: ApiMain.php:498
$time
see documentation in includes Linker php for Linker::makeImageLink & $time
Definition: hooks.txt:1358
ApiMain\handleApiBeforeMainException
static handleApiBeforeMainException(Exception $e)
Handle an exception from the ApiBeforeMain hook.
Definition: ApiMain.php:468
$right
return false if a UserGetRights hook might remove the named right $right
Definition: hooks.txt:2809
ApiMain\getShowVersions
getShowVersions()
Check whether the user wants us to show version information in the API help.
Definition: ApiMain.php:1397
$params
$params
Definition: styleTest.css.php:40
ApiMain\lacksSameOriginSecurity
lacksSameOriginSecurity()
Get the security flag for the current request.
Definition: ApiMain.php:226
UsageException\getMessageArray
getMessageArray()
Definition: ApiMain.php:1493
wfReadOnly
wfReadOnly()
Check whether the wiki is in read-only mode.
Definition: GlobalFunctions.php:1360
wfMsgReplaceArgs
wfMsgReplaceArgs( $message, $args)
Replace message parameter keys on the given formatted output.
Definition: GlobalFunctions.php:1637
$s
$s
Definition: mergeMessageFileList.php:156
ContextSource\getRequest
getRequest()
Get the WebRequest object.
Definition: ContextSource.php:77
ApiMain\encodeRequestLogValue
encodeRequestLogValue( $s)
Encode a value in a format suitable for a space-separated log line.
Definition: ApiMain.php:998
ContextSource\getUser
getUser()
Get the User object.
Definition: ContextSource.php:132
UsageException\$mExtraData
null array $mExtraData
Definition: ApiMain.php:1469
ApiMain\makeHelpMsg
makeHelpMsg()
Override the parent to generate help messages for all available modules.
Definition: ApiMain.php:1297
ApiMain\matchOrigin
static matchOrigin( $value, $rules, $exceptions)
Attempt to match an Origin header against a set of rules and a set of exceptions.
Definition: ApiMain.php:551
ApiMain\$mRights
static $mRights
List of user roles that are specifically relevant to the API.
Definition: ApiMain.php:121
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:42
ApiMain\getModule
getModule()
Get the API module object.
Definition: ApiMain.php:256
ApiBase\profileOut
profileOut()
End module profiling.
Definition: ApiBase.php:2283
DerivativeContext
An IContextSource implementation which will inherit context from another source but allow individual ...
Definition: DerivativeContext.php:32
MWException
MediaWiki exception.
Definition: MWException.php:26
wfMemcKey
wfMemcKey()
Get a cache key.
Definition: GlobalFunctions.php:3635
$out
$out
Definition: UtfNormalGenerate.php:167
ApiMain\getParamDescription
getParamDescription()
See ApiBase for description.
Definition: ApiMain.php:1170
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1174
DBQueryError
Definition: DatabaseError.php:306
ApiMain\setupExecuteAction
setupExecuteAction()
Set up for the execution.
Definition: ApiMain.php:760
ApiResult
This class represents the result of the API operations.
Definition: ApiResult.php:44
ApiMain\$mResult
$mResult
Definition: ApiMain.php:137
UsageException
This exception will be thrown when dieUsage is called to stop module execution.
Definition: ApiMain.php:1463
ApiMain\addFormat
addFormat( $name, $class)
Add or overwrite an output format for this ApiMain.
Definition: ApiMain.php:1432
ApiMain\$lacksSameOriginSecurity
bool null $lacksSameOriginSecurity
Cached return value from self::lacksSameOriginSecurity() *.
Definition: ApiMain.php:147
ContextSource\getOutput
getOutput()
Get the OutputPage object.
Definition: ContextSource.php:122
ApiMain\getResult
getResult()
Get the ApiResult object associated with current request.
Definition: ApiMain.php:218
ApiMain\getSensitiveParams
getSensitiveParams()
Get the request parameters that should be considered sensitive.
Definition: ApiMain.php:1023
UsageException\__toString
__toString()
Definition: ApiMain.php:1508
wfRunHooks
wfRunHooks( $event, array $args=array(), $deprecatedVersion=null)
Call hook functions defined in $wgHooks.
Definition: GlobalFunctions.php:4066
ApiMain\checkMaxLag
checkMaxLag( $module, $params)
Check the max lag if necessary.
Definition: ApiMain.php:825
ApiMain\setCacheControl
setCacheControl( $directives)
Set directives (key/value pairs) for the Cache-Control header.
Definition: ApiMain.php:337
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
ApiMain\getAllowedParams
getAllowedParams()
See ApiBase for description.
Definition: ApiMain.php:1135
ApiMain\setupExternalResponse
setupExternalResponse( $module, $params)
Check POST for external response and setup result printer.
Definition: ApiMain.php:905
ApiMain\createPrinterByName
createPrinterByName( $format)
Create an instance of an output formatter by its name.
Definition: ApiMain.php:348
ApiMain\getModuleManager
getModuleManager()
Overrides to return this instance's module manager.
Definition: ApiMain.php:1407
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
ApiMain\$mCanApiHighLimits
$mCanApiHighLimits
Definition: ApiMain.php:1378
ContextSource\setContext
setContext(IContextSource $context)
Set the IContextSource object.
Definition: ContextSource.php:57
ApiMain\canApiHighLimits
canApiHighLimits()
Check whether the current user is allowed to use high limits.
Definition: ApiMain.php:1384
list
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
false
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:188
ApiMain\$mPrinter
ApiFormatBase $mPrinter
Definition: ApiMain.php:135
ApiMain\$mModule
$mModule
Definition: ApiMain.php:140
ApiModuleManager
This class holds a list of modules and handles instantiation.
Definition: ApiModuleManager.php:34
wfDebug
wfDebug( $text, $dest='all')
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:980
ApiMain\checkAsserts
checkAsserts( $params)
Check asserts of the user's rights.
Definition: ApiMain.php:882
ApiBase\extractRequestParams
extractRequestParams( $parseLimit=true)
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:715
ApiMain\$mCacheMode
$mCacheMode
Definition: ApiMain.php:142
MWDebug\appendDebugInfoToApiResult
static appendDebugInfoToApiResult(IContextSource $context, ApiResult $result)
Append the debug info to given ApiResult.
Definition: Debug.php:491
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:336
UsageException\$mCodestr
$mCodestr
Definition: ApiMain.php:1465
ApiMain\$mInternalMode
$mInternalMode
Definition: ApiMain.php:140
$value
$value
Definition: styleTest.css.php:45
ApiMain\wildcardToRegex
static wildcardToRegex( $wildcard)
Helper function to convert wildcard string into a regex '*' => '.
Definition: ApiMain.php:576
ApiMain\checkExecutePermissions
checkExecutePermissions( $module)
Check for sufficient permissions to execute.
Definition: ApiMain.php:852
ApiMain\reallyMakeHelpMsg
reallyMakeHelpMsg()
Definition: ApiMain.php:1320
ApiBase\LIMIT_SML2
const LIMIT_SML2
Definition: ApiBase.php:88
ApiBase\dieUsage
dieUsage( $description, $errorCode, $httpRespCode=0, $extradata=null)
Throw a UsageException, which will (if uncaught) call the main module's error handler and die with an...
Definition: ApiBase.php:1429
ApiBase\dieReadOnly
dieReadOnly()
Helper function for readonly errors.
Definition: ApiBase.php:1989
ApiMain\__construct
__construct( $context=null, $enableWrite=false)
Constructs an instance of ApiMain that utilizes the module and format specified by $request.
Definition: ApiMain.php:156
ApiMain\reportUnusedParams
reportUnusedParams()
Report unused parameters, so the client gets a hint in case it gave us parameters we don't know,...
Definition: ApiMain.php:1072
ApiMain\execute
execute()
Execute api request.
Definition: ApiMain.php:360
ApiMain\logRequest
logRequest( $time)
Log the preceding request.
Definition: ApiMain.php:965
ApiMain\$Formats
static $Formats
List of available formats: format name => format class.
Definition: ApiMain.php:93
ApiMain\markParamsSensitive
markParamsSensitive( $params)
Mark parameters as sensitive.
Definition: ApiMain.php:1032
ApiMain\substituteResultWithError
substituteResultWithError( $e)
Replace the result data with the information about an exception.
Definition: ApiMain.php:679
RequestContext\getMain
static getMain()
Static methods.
Definition: RequestContext.php:420
HttpStatus\getMessage
static getMessage( $code)
Get the message associated with HTTP response code $code.
Definition: HttpStatus.php:37
$exceptions
$exceptions
Definition: Utf8Test.php:72
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:237
Hooks\run
static run( $event, array $args=array(), $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:136
ApiMain\getCheck
getCheck( $name)
Get a boolean request value, and register the fact that the parameter was used, for logging.
Definition: ApiMain.php:1049
UsageException\getCodeString
getCodeString()
Definition: ApiMain.php:1486
wfReportTime
wfReportTime()
Returns a script tag that stores the amount of time it took MediaWiki to handle the request in millis...
Definition: GlobalFunctions.php:1873
ApiBase\profileIn
profileIn()
Start module profiling.
Definition: ApiBase.php:2272
WebRequest
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form,...
Definition: WebRequest.php:38
ApiMain\makeHelpMsgHeader
static makeHelpMsgHeader( $module, $paramName)
Definition: ApiMain.php:1369
ApiMain\$mEnableWrite
$mEnableWrite
Definition: ApiMain.php:139
ApiBase\setWarning
setWarning( $warning)
Set warning section for this module.
Definition: ApiBase.php:252
User\isEveryoneAllowed
static isEveryoneAllowed( $right)
Check if all users have the given permission.
Definition: User.php:4179
UsageException\__construct
__construct( $message, $codestr, $code=0, $extradata=null)
Definition: ApiMain.php:1477
ApiBase\LIMIT_BIG2
const LIMIT_BIG2
Definition: ApiBase.php:86
ApiMain\API_DEFAULT_FORMAT
const API_DEFAULT_FORMAT
When no format parameter is given, this format will be used.
Definition: ApiMain.php:45
ApiMain\addModule
addModule( $name, $class)
Add or overwrite a module in this ApiMain instance.
Definition: ApiMain.php:1420
ApiMain\setHelp
setHelp( $help=true)
Sets whether the pretty-printer should format bold and $italics$.
Definition: ApiMain.php:1288
ApiMain\printResult
printResult( $isError)
Print results using the current printer.
Definition: ApiMain.php:1098
ApiMain\getUpload
getUpload( $name)
Get a request upload, and register the fact that it was used, for logging.
Definition: ApiMain.php:1062
MWExceptionHandler\rollbackMasterChangesAndLog
static rollbackMasterChangesAndLog(Exception $e)
If there are any open database transactions, roll them back and log the stack trace of the exception ...
Definition: MWExceptionHandler.php:111
ApiBase\PARAM_DFLT
const PARAM_DFLT
Definition: ApiBase.php:46
ApiBase\getParameter
getParameter( $paramName, $parseLimit=true)
Get a value for the given parameter.
Definition: ApiBase.php:739
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
ApiMain\getPossibleErrors
getPossibleErrors()
Definition: ApiMain.php:1250
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:155
User
User
Definition: All_system_messages.txt:425
ApiMain\executeAction
executeAction()
Execute the actual module, without any error handling.
Definition: ApiMain.php:927
ApiMain\setupModule
setupModule()
Set up the module for response.
Definition: ApiMain.php:792
$help
$help
Definition: mcc.php:31
MWExceptionHandler\logException
static logException(Exception $e)
Log an exception to the exception log (if enabled).
Definition: MWExceptionHandler.php:351
ApiMain\$mCacheControl
$mCacheControl
Definition: ApiMain.php:143
$t
$t
Definition: testCompression.php:65
ApiMain\handleException
handleException(Exception $e)
Handle an exception as an API response.
Definition: ApiMain.php:419
ApiMain\isInternalMode
isInternalMode()
Return true if the API was started by other PHP code using FauxRequest.
Definition: ApiMain.php:209
ApiMain\$mParamsUsed
$mParamsUsed
Definition: ApiMain.php:144
ApiMain\$mModuleMgr
$mModuleMgr
Definition: ApiMain.php:137
ApiMain\setCacheMaxAge
setCacheMaxAge( $maxage)
Set how long the response should be cached.
Definition: ApiMain.php:274
$retval
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account incomplete not yet checked for validity & $retval
Definition: hooks.txt:237
ApiMain\setCacheMode
setCacheMode( $mode)
Set the type of caching headers which will be sent.
Definition: ApiMain.php:306
TS_RFC2822
const TS_RFC2822
RFC 2822 format, for E-mail and HTTP headers.
Definition: GlobalFunctions.php:2488
ApiMain\getPrinter
getPrinter()
Get the result formatter object.
Definition: ApiMain.php:265
User\getGroupsWithPermission
static getGroupsWithPermission( $role)
Get all the groups who have a given permission.
Definition: User.php:4143
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:1632
SpecialVersion\getVersion
static getVersion( $flags='')
Return a string of the MediaWiki version with SVN revision if available.
Definition: SpecialVersion.php:246
ApiMain\getFormats
getFormats()
Returns the list of supported formats in form ( 'format' => 'ClassName' )
Definition: ApiMain.php:1452