protected function processCurlResponse ($ch, $errCode, $errMsg, $rawResp) {
    // check error codes
    $this->responseCurlErr = $errCode;
    $this->responseCurlErrMessage = $errMsg;

    if (CURLE_OK == $errCode) {
      $info = curl_getinfo($ch);
      $hdrSize = $info['header_size'];
      $respCode = (int) $info['http_code'];

      // parse the raw response
      $rawHeaders = mb_substr($rawResp, 0, $hdrSize, 'latin1');
      $respBody =  mb_substr(
          $rawResp, $hdrSize, mb_strlen($rawResp, 'latin1'), 'latin1');

      // parse response headers
      if ($info['redirect_count'] > 0) {
        // discard redirect headers
        // TODO: there may be useful info in here that we want to preserve
        $headerChunks = explode("\r\n\r\n", $rawHeaders);
        $rawHeaders = $headerChunks[$info['redirect_count']];
      }
      $respHeaderParts = explode("\r\n", $rawHeaders);
      $respHeaders = array();
      foreach ($respHeaderParts as $header) {
        if ($header) {
          $parts = explode(': ', $header, 2);
          $name = $parts[0];
          $value = '';
          if (count($parts) == 2) {
            $value = $parts[1];
          }
          if (isset($respHeaders[$name])) {
            if (!is_array($respHeaders[$name])) {
              // convert single value to collection
              $respHeaders[$name] = array($respHeaders[$name]);
            }
            $respHeaders[$name][] = $value;
          } else {
            $respHeaders[$name] = $value;
          }
        }
      } //end foreach $header

      // fill in request with response
      $this->setResponseCurlInfo($info);
      $this->setResponseHttpCode($respCode);
      $this->setResponseHeaders($respHeaders);
      $this->setResponseBody($respBody);
    } //end if CURLE_OK

    curl_close($ch);
    return $this;
  }