MediaWiki
REL1_22
|
00001 <?php 00028 class DBError extends MWException { 00029 00033 public $db; 00034 00040 function __construct( DatabaseBase $db = null, $error ) { 00041 $this->db = $db; 00042 parent::__construct( $error ); 00043 } 00044 00048 function getText() { 00049 global $wgShowDBErrorBacktrace; 00050 00051 $s = $this->getTextContent() . "\n"; 00052 00053 if ( $wgShowDBErrorBacktrace ) { 00054 $s .= "Backtrace:\n" . $this->getTraceAsString() . "\n"; 00055 } 00056 00057 return $s; 00058 } 00059 00063 function getHTML() { 00064 global $wgShowDBErrorBacktrace; 00065 00066 $s = $this->getHTMLContent(); 00067 00068 if ( $wgShowDBErrorBacktrace ) { 00069 $s .= '<p>Backtrace:</p><p>' . 00070 nl2br( htmlspecialchars( $this->getTraceAsString() ) ) . '</p>'; 00071 } 00072 00073 return $s; 00074 } 00075 00079 protected function getTextContent() { 00080 return $this->getMessage(); 00081 } 00082 00086 protected function getHTMLContent() { 00087 return '<p>' . nl2br( htmlspecialchars( $this->getMessage() ) ) . '</p>'; 00088 } 00089 } 00090 00094 class DBConnectionError extends DBError { 00095 public $error; 00096 00097 function __construct( DatabaseBase $db = null, $error = 'unknown error' ) { 00098 $msg = 'DB connection error'; 00099 00100 if ( trim( $error ) != '' ) { 00101 $msg .= ": $error"; 00102 } elseif ( $db ) { 00103 $error = $this->db->getServer(); 00104 } 00105 00106 parent::__construct( $db, $msg ); 00107 $this->error = $error; 00108 } 00109 00113 function useOutputPage() { 00114 // Not likely to work 00115 return false; 00116 } 00117 00123 function msg( $key, $fallback /*[, params...] */ ) { 00124 global $wgLang; 00125 00126 $args = array_slice( func_get_args(), 2 ); 00127 00128 if ( $this->useMessageCache() ) { 00129 $message = $wgLang->getMessage( $key ); 00130 } else { 00131 $message = $fallback; 00132 } 00133 return wfMsgReplaceArgs( $message, $args ); 00134 } 00135 00139 function isLoggable() { 00140 // Don't send to the exception log, already in dberror log 00141 return false; 00142 } 00143 00147 function getPageTitle() { 00148 return $this->msg( 'dberr-header', 'This wiki has a problem' ); 00149 } 00150 00154 function getHTML() { 00155 global $wgShowDBErrorBacktrace, $wgShowHostnames, $wgShowSQLErrors; 00156 00157 $sorry = htmlspecialchars( $this->msg( 'dberr-problems', "Sorry!\nThis site is experiencing technical difficulties." ) ); 00158 $again = htmlspecialchars( $this->msg( 'dberr-again', 'Try waiting a few minutes and reloading.' ) ); 00159 00160 if ( $wgShowHostnames || $wgShowSQLErrors ) { 00161 $info = str_replace( 00162 '$1', Html::element( 'span', array( 'dir' => 'ltr' ), $this->error ), 00163 htmlspecialchars( $this->msg( 'dberr-info', '(Cannot contact the database server: $1)' ) ) 00164 ); 00165 } else { 00166 $info = htmlspecialchars( $this->msg( 'dberr-info-hidden', '(Cannot contact the database server)' ) ); 00167 } 00168 00169 # No database access 00170 MessageCache::singleton()->disable(); 00171 00172 $text = "<h1>$sorry</h1><p>$again</p><p><small>$info</small></p>"; 00173 00174 if ( $wgShowDBErrorBacktrace ) { 00175 $text .= '<p>Backtrace:</p><p>' . 00176 nl2br( htmlspecialchars( $this->getTraceAsString() ) ) . '</p>'; 00177 } 00178 00179 $text .= '<hr />'; 00180 $text .= $this->searchForm(); 00181 00182 return $text; 00183 } 00184 00185 protected function getTextContent() { 00186 global $wgShowHostnames, $wgShowSQLErrors; 00187 00188 if ( $wgShowHostnames || $wgShowSQLErrors ) { 00189 return $this->getMessage(); 00190 } else { 00191 return 'DB connection error'; 00192 } 00193 } 00194 00195 public function reportHTML() { 00196 global $wgUseFileCache; 00197 00198 # Check whether we can serve a file-cached copy of the page with the error underneath 00199 if ( $wgUseFileCache ) { 00200 try { 00201 $cache = $this->fileCachedPage(); 00202 # Cached version on file system? 00203 if ( $cache !== null ) { 00204 # Hack: extend the body for error messages 00205 $cache = str_replace( array( '</html>', '</body>' ), '', $cache ); 00206 # Add cache notice... 00207 $cache .= '<div style="color:red;font-size:150%;font-weight:bold;">' . 00208 htmlspecialchars( $this->msg( 'dberr-cachederror', 00209 'This is a cached copy of the requested page, and may not be up to date. ' ) ) . 00210 '</div>'; 00211 00212 # Output cached page with notices on bottom and re-close body 00213 echo "{$cache}<hr />{$this->getHTML()}</body></html>"; 00214 return; 00215 } 00216 } catch ( MWException $e ) { 00217 // Do nothing, just use the default page 00218 } 00219 } 00220 00221 # We can't, cough and die in the usual fashion 00222 parent::reportHTML(); 00223 } 00224 00228 function searchForm() { 00229 global $wgSitename, $wgCanonicalServer, $wgRequest; 00230 00231 $usegoogle = htmlspecialchars( $this->msg( 'dberr-usegoogle', 'You can try searching via Google in the meantime.' ) ); 00232 $outofdate = htmlspecialchars( $this->msg( 'dberr-outofdate', 'Note that their indexes of our content may be out of date.' ) ); 00233 $googlesearch = htmlspecialchars( $this->msg( 'searchbutton', 'Search' ) ); 00234 00235 $search = htmlspecialchars( $wgRequest->getVal( 'search' ) ); 00236 00237 $server = htmlspecialchars( $wgCanonicalServer ); 00238 $sitename = htmlspecialchars( $wgSitename ); 00239 00240 $trygoogle = <<<EOT 00241 <div style="margin: 1.5em">$usegoogle<br /> 00242 <small>$outofdate</small></div> 00243 <!-- SiteSearch Google --> 00244 <form method="get" action="//www.google.com/search" id="googlesearch"> 00245 <input type="hidden" name="domains" value="$server" /> 00246 <input type="hidden" name="num" value="50" /> 00247 <input type="hidden" name="ie" value="UTF-8" /> 00248 <input type="hidden" name="oe" value="UTF-8" /> 00249 00250 <input type="text" name="q" size="31" maxlength="255" value="$search" /> 00251 <input type="submit" name="btnG" value="$googlesearch" /> 00252 <div> 00253 <input type="radio" name="sitesearch" id="gwiki" value="$server" checked="checked" /><label for="gwiki">$sitename</label> 00254 <input type="radio" name="sitesearch" id="gWWW" value="" /><label for="gWWW">WWW</label> 00255 </div> 00256 </form> 00257 <!-- SiteSearch Google --> 00258 EOT; 00259 return $trygoogle; 00260 } 00261 00265 private function fileCachedPage() { 00266 global $wgTitle, $wgOut, $wgRequest; 00267 00268 if ( $wgOut->isDisabled() ) { 00269 return ''; // Done already? 00270 } 00271 00272 if ( $wgTitle ) { // use $wgTitle if we managed to set it 00273 $t = $wgTitle->getPrefixedDBkey(); 00274 } else { 00275 # Fallback to the raw title URL param. We can't use the Title 00276 # class is it may hit the interwiki table and give a DB error. 00277 # We may get a cache miss due to not sanitizing the title though. 00278 $t = str_replace( ' ', '_', $wgRequest->getVal( 'title' ) ); 00279 if ( $t == '' ) { // fallback to main page 00280 $t = Title::newFromText( 00281 $this->msg( 'mainpage', 'Main Page' ) )->getPrefixedDBkey(); 00282 } 00283 } 00284 00285 $cache = HTMLFileCache::newFromTitle( $t, 'view' ); 00286 if ( $cache->isCached() ) { 00287 return $cache->fetchText(); 00288 } else { 00289 return ''; 00290 } 00291 } 00292 } 00293 00297 class DBQueryError extends DBError { 00298 public $error, $errno, $sql, $fname; 00299 00307 function __construct( DatabaseBase $db, $error, $errno, $sql, $fname ) { 00308 $message = "A database error has occurred. Did you forget to run maintenance/update.php after upgrading? See: https://www.mediawiki.org/wiki/Manual:Upgrading#Run_the_update_script\n" . 00309 "Query: $sql\n" . 00310 "Function: $fname\n" . 00311 "Error: $errno $error\n"; 00312 parent::__construct( $db, $message ); 00313 00314 $this->error = $error; 00315 $this->errno = $errno; 00316 $this->sql = $sql; 00317 $this->fname = $fname; 00318 } 00319 00323 function isLoggable() { 00324 // Don't send to the exception log, already in dberror log 00325 return false; 00326 } 00327 00331 function getPageTitle() { 00332 return $this->msg( 'databaseerror', 'Database error' ); 00333 } 00334 00338 protected function getHTMLContent() { 00339 $key = 'databaseerror-text'; 00340 $s = Html::element( 'p', array(), $this->msg( $key, $this->getFallbackMessage( $key ) ) ); 00341 00342 $details = $this->getTechnicalDetails(); 00343 if ( $details ) { 00344 $s .= '<ul>'; 00345 foreach ( $details as $key => $detail ) { 00346 $s .= str_replace( 00347 '$1', call_user_func_array( 'Html::element', $detail ), 00348 Html::element( 'li', array(), 00349 $this->msg( $key, $this->getFallbackMessage( $key ) ) 00350 ) 00351 ); 00352 } 00353 $s .= '</ul>'; 00354 } 00355 00356 return $s; 00357 } 00358 00362 protected function getTextContent() { 00363 $key = 'databaseerror-textcl'; 00364 $s = $this->msg( $key, $this->getFallbackMessage( $key ) ) . "\n"; 00365 00366 foreach ( $this->getTechnicalDetails() as $key => $detail ) { 00367 $s .= $this->msg( $key, $this->getFallbackMessage( $key ), $detail[2] ) . "\n"; 00368 } 00369 00370 return $s; 00371 } 00372 00386 protected function getTechnicalDetails() { 00387 global $wgShowHostnames, $wgShowSQLErrors; 00388 00389 $attribs = array( 'dir' => 'ltr' ); 00390 $details = array(); 00391 00392 if ( $wgShowSQLErrors ) { 00393 $details['databaseerror-query'] = array( 00394 'div', array( 'class' => 'mw-code' ) + $attribs, $this->sql ); 00395 } 00396 00397 if ( $wgShowHostnames || $wgShowSQLErrors ) { 00398 $errorMessage = $this->errno . ' ' . $this->error; 00399 $details['databaseerror-function'] = array( 'code', $attribs, $this->fname ); 00400 $details['databaseerror-error'] = array( 'samp', $attribs, $errorMessage ); 00401 } 00402 00403 return $details; 00404 } 00405 00410 private function getFallbackMessage( $key ) { 00411 $messages = array( 00412 'databaseerror-text' => 'A database query error has occurred. 00413 This may indicate a bug in the software.', 00414 'databaseerror-textcl' => 'A database query error has occurred.', 00415 'databaseerror-query' => 'Query: $1', 00416 'databaseerror-function' => 'Function: $1', 00417 'databaseerror-error' => 'Error: $1', 00418 ); 00419 return $messages[$key]; 00420 } 00421 00422 } 00423 00427 class DBUnexpectedError extends DBError {}