/**
  * Called when the request notifies us of an event.
  *
  * @param SplSubject $request The HTTP_Request2 instance
  *
  * @return void
  * @throws HTTP_Request2_MessageException
  */
 public function update(SplSubject $request)
 {
     /* @var $request HTTP_Request2 */
     $event = $request->getLastEvent();
     $encoded = false;
     /* @var $event['data'] HTTP_Request2_Response */
     switch ($event['name']) {
         case 'receivedHeaders':
             $this->_processingHeader = true;
             $this->_redirect = $event['data']->isRedirect();
             $this->_encoding = strtolower($event['data']->getHeader('content-encoding'));
             $this->_possibleHeader = '';
             break;
         case 'receivedEncodedBodyPart':
             if (!$this->_streamFilter && ($this->_encoding === 'deflate' || $this->_encoding === 'gzip')) {
                 $this->_streamFilter = stream_filter_append($this->_stream, 'zlib.inflate', STREAM_FILTER_WRITE);
             }
             $encoded = true;
             // fall-through is intentional
         // fall-through is intentional
         case 'receivedBodyPart':
             if ($this->_redirect) {
                 break;
             }
             if (!$encoded || !$this->_processingHeader) {
                 $bytes = fwrite($this->_stream, $event['data']);
             } else {
                 $offset = 0;
                 $this->_possibleHeader .= $event['data'];
                 if ('deflate' === $this->_encoding) {
                     if (2 > strlen($this->_possibleHeader)) {
                         break;
                     }
                     $header = unpack('n', substr($this->_possibleHeader, 0, 2));
                     if (0 == $header[1] % 31) {
                         $offset = 2;
                     }
                 } elseif ('gzip' === $this->_encoding) {
                     if (10 > strlen($this->_possibleHeader)) {
                         break;
                     }
                     try {
                         $offset = HTTP_Request2_Response::parseGzipHeader($this->_possibleHeader, false);
                     } catch (HTTP_Request2_MessageException $e) {
                         // need more data?
                         if (false !== strpos($e->getMessage(), 'data too short')) {
                             break;
                         }
                         throw $e;
                     }
                 }
                 $this->_processingHeader = false;
                 $bytes = fwrite($this->_stream, substr($this->_possibleHeader, $offset));
             }
             if (false === $bytes) {
                 throw new HTTP_Request2_MessageException('fwrite failed.');
             }
             if ($this->_maxDownloadSize && ftell($this->_stream) - $this->_startPosition > $this->_maxDownloadSize) {
                 throw new HTTP_Request2_MessageException(sprintf('Body length limit (%d bytes) reached', $this->_maxDownloadSize));
             }
             break;
         case 'receivedBody':
             if ($this->_streamFilter) {
                 stream_filter_remove($this->_streamFilter);
                 $this->_streamFilter = null;
             }
             break;
     }
 }