/**
  * Callback function called by cURL for saving the response headers
  *
  * @param    resource    cURL handle
  * @param    string      response header (with trailing CRLF)
  * @return   integer     number of bytes saved
  * @see      Diglin_HTTP_Request2_Response::parseHeaderLine()
  */
 protected function callbackWriteHeader($ch, $string)
 {
     // we may receive a second set of headers if doing e.g. digest auth
     if ($this->eventReceivedHeaders || !$this->eventSentHeaders) {
         // don't bother with 100-Continue responses (bug #15785)
         if (!$this->eventSentHeaders || $this->response->getStatus() >= 200) {
             $this->request->setLastEvent('sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT));
         }
         $upload = curl_getinfo($ch, CURLINFO_SIZE_UPLOAD);
         // if body wasn't read by a callback, send event with total body size
         if ($upload > $this->position) {
             $this->request->setLastEvent('sentBodyPart', $upload - $this->position);
             $this->position = $upload;
         }
         $this->eventSentHeaders = true;
         // we'll need a new response object
         if ($this->eventReceivedHeaders) {
             $this->eventReceivedHeaders = false;
             $this->response = null;
         }
     }
     if (empty($this->response)) {
         $this->response = new Diglin_HTTP_Request2_Response($string, false);
     } else {
         $this->response->parseHeaderLine($string);
         if ('' == trim($string)) {
             // don't bother with 100-Continue responses (bug #15785)
             if (200 <= $this->response->getStatus()) {
                 $this->request->setLastEvent('receivedHeaders', $this->response);
             }
             // for versions lower than 5.2.10, check the redirection URL protocol
             if ($this->request->getConfig('follow_redirects') && !defined('CURLOPT_REDIR_PROTOCOLS') && $this->response->isRedirect()) {
                 $redirectUrl = new Diglin_Net_URL2($this->response->getHeader('location'));
                 if ($redirectUrl->isAbsolute() && !in_array($redirectUrl->getScheme(), array('http', 'https'))) {
                     return -1;
                 }
             }
             $this->eventReceivedHeaders = true;
         }
     }
     return strlen($string);
 }
 /**
  * Checks whether another request should be performed with proxy digest auth
  *
  * Several conditions should be satisfied for it to return true:
  *   - response status should be 407
  *   - proxy auth credentials should be set in the request object
  *   - response should contain Proxy-Authenticate header with digest challenge
  *   - there is either no challenge stored for this proxy or new challenge
  *     contains stale=true parameter (in other case we probably just failed
  *     due to invalid username / password)
  *
  * The method stores challenge values in $challenges static property
  *
  * @param    Diglin_HTTP_Request2_Response  response to check
  * @return   boolean whether another request should be performed
  * @throws   Diglin_HTTP_Request2_Exception in case of unsupported challenge parameters
  */
 protected function shouldUseProxyDigestAuth(Diglin_HTTP_Request2_Response $response)
 {
     if (407 != $response->getStatus() || !$this->request->getConfig('proxy_user')) {
         return false;
     }
     if (!($challenge = $this->parseDigestChallenge($response->getHeader('proxy-authenticate')))) {
         return false;
     }
     $key = 'proxy://' . $this->request->getConfig('proxy_host') . ':' . $this->request->getConfig('proxy_port');
     if (!empty(self::$challenges[$key]) && (empty($challenge['stale']) || strcasecmp('true', $challenge['stale']))) {
         $ret = false;
     } else {
         $ret = true;
     }
     self::$challenges[$key] = $challenge;
     return $ret;
 }