Improved exceptions to be more specific
authorAlexander Ebert <ebert@woltlab.com>
Thu, 3 May 2012 12:59:38 +0000 (14:59 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Thu, 3 May 2012 12:59:38 +0000 (14:59 +0200)
Depending on exception type, different error codes will be sent to distinguish between soft-errors (e.g. bad parameter) or those where something is pretty screwed up.

wcfsetup/install/files/lib/action/AJAXProxyAction.class.php
wcfsetup/install/files/lib/system/exception/AJAXException.class.php

index 140d90af34462a4e3d261eaedc2aaf50df82b3b2..e8ba240d337994bf36686645f1b4511dc872ea76 100644 (file)
@@ -1,7 +1,14 @@
 <?php
 namespace wcf\action;
+use wcf\system\exception\IllegalLinkException;
+
+use wcf\system\WCF;
+
+use wcf\system\exception\PermissionDeniedException;
+
 use wcf\system\exception\AJAXException;
 use wcf\system\exception\SystemException;
+use wcf\system\exception\UserInputException;
 use wcf\system\exception\ValidateActionException;
 use wcf\util\ArrayUtil;
 use wcf\util\ClassUtil;
@@ -113,6 +120,9 @@ class AJAXProxyAction extends AbstractSecureAction {
                try {
                        $this->objectAction->validateAction();
                }
+               catch (UserInputException $e) {
+                       $this->throwException($e);
+               }
                catch (ValidateActionException $e) {
                        $this->throwException($e);
                }
@@ -138,11 +148,20 @@ class AJAXProxyAction extends AbstractSecureAction {
         * @param       \Exception      $e
         */
        protected function throwException(\Exception $e) {
-               if ($e instanceof SystemException) {
-                       throw new AJAXException($e->getMessage(), $e->__getTraceAsString());
+               if ($e instanceof IllegalLinkException) {
+                       throw new AJAXException(WCF::getLanguage()->get('wcf.global.error.sessionExpired'), AJAXException::SESSION_EXPIRED);
+               }
+               else if ($e instanceof PermissionDeniedException) {
+                       throw new AJAXException(WCF::getLanguage()->get('wcf.global.error.permissionDenied'), AJAXException::INSUFFICIENT_PERMISSIONS);
+               }
+               else if ($e instanceof SystemException) {
+                       throw new AJAXException($e->getMessage(), AJAXException::INTERNAL_ERROR, $e->__getTraceAsString());
+               }
+               else if ($e instanceof UserInputException) {
+                       throw new AJAXException($e->getMessage(), AJAXException::BAD_PARAMETERS);
                }
                else {
-                       throw new AJAXException($e->getMessage(), $e->getTraceAsString());
+                       throw new AJAXException($e->getMessage(), AJAXException::INTERNAL_ERROR, $e->getTraceAsString());
                }
        }
 }
index c67afd64cc18e41e6c936caa2d5e58a2adc47247..6be6ad065b5c432be7be0cb7be055fe1594ee771 100644 (file)
@@ -14,13 +14,44 @@ use wcf\util\JSON;
  * @category   Community Framework
  */
 class AJAXException extends LoggedException {
+       /**
+        * missing parameters
+        * @var integer
+        */
+       const MISSING_PARAMETERS = 400;
+       
+       /**
+        * session expired
+        * @var integer
+        */
+       const SESSION_EXPIRED = 401;
+       
+       /**
+        * insufficient permissions
+        * @var integer
+        */
+       const INSUFFICIENT_PERMISSIONS = 403;
+       
+       /**
+        * bad parameters
+        * @var integer
+        */
+       const BAD_PARAMETERS = 412;
+       
+       /**
+        * internal server error
+        * @var integer
+        */
+       const INTERNAL_ERROR = 503;
+       
        /**
         * Throws a JSON-encoded error message
         * 
         * @param       string          $message
+        * @param       boolean         $isDoomsday
         * @param       string          $stacktrace
         */
-       public function __construct($message, $stacktrace = null) {
+       public function __construct($message, $errorType = self::INTERNAL_ERROR, $stacktrace = null) {
                if ($stacktrace === null) $stacktrace = $this->getTraceAsString();
                
                if (WCF::debugModeIsEnabled()) {
@@ -35,11 +66,39 @@ class AJAXException extends LoggedException {
                        );
                }
                
-               // log error
-               $this->logError();
+               $responseData['code'] = $errorType;
+               $statusHeader = '';
+               switch ($errorType) {
+                       case self::MISSING_PARAMETERS:
+                               $statusHeader = 'HTTP/1.0 400 Bad Request';
+                               
+                               $this->logError();
+                       break;
+                       
+                       case self::SESSION_EXPIRED:
+                               $statusHeader = 'HTTP/1.0 401 Unauthorized';
+                       break;
+                       
+                       case self::INSUFFICIENT_PERMISSIONS:
+                               $statusHeader = 'HTTP/1.0 403 Forbidden';
+                       break;
+                       
+                       case self::BAD_PARAMETERS:
+                               $statusHeader = 'HTTP/1.0 412 Precondition Failed';
+                       break;
+                       
+                       default:
+                       case self::INTERNAL_ERROR:
+                               //header('HTTP/1.0 418 I\'m a Teapot');
+                               header('HTTP/1.0 503 Service Unavailable');
+                               
+                               $responseData['code'] = self::INTERNAL_ERROR;
+                               
+                               $this->logError();
+                       break;
+               }
                
-               //header('HTTP/1.0 418 I\'m a Teapot');
-               header('HTTP/1.0 503 Service Unavailable');
+               header($statusHeader);
                header('Content-type: application/json');
                echo JSON::encode($responseData);
                exit;