+ /**\r
+ * Adds or removes 'Expect: 100-continue' header from request headers\r
+ *\r
+ * Also sets the $expect100Continue property. Parsing of existing header\r
+ * is somewhat needed due to its complex structure and due to the\r
+ * requirement in section 8.2.3 of RFC 2616:\r
+ * > A client MUST NOT send an Expect request-header field (section\r
+ * > 14.20) with the "100-continue" expectation if it does not intend\r
+ * > to send a request body.\r
+ *\r
+ * @param array &$headers Array of headers prepared for the request\r
+ *\r
+ * @throws HTTP_Request2_LogicException\r
+ * @link http://pear.php.net/bugs/bug.php?id=19233\r
+ * @link http://tools.ietf.org/html/rfc2616#section-8.2.3\r
+ */\r
+ protected function updateExpectHeader(&$headers)\r
+ {\r
+ $this->expect100Continue = false;\r
+ $expectations = array();\r
+ if (isset($headers['expect'])) {\r
+ if ('' === $headers['expect']) {\r
+ // empty 'Expect' header is technically invalid, so just get rid of it\r
+ unset($headers['expect']);\r
+ return;\r
+ }\r
+ // build regexp to parse the value of existing Expect header\r
+ $expectParam = ';\s*' . self::REGEXP_TOKEN . '(?:\s*=\s*(?:'\r
+ . self::REGEXP_TOKEN . '|'\r
+ . self::REGEXP_QUOTED_STRING . '))?\s*';\r
+ $expectExtension = self::REGEXP_TOKEN . '(?:\s*=\s*(?:'\r
+ . self::REGEXP_TOKEN . '|'\r
+ . self::REGEXP_QUOTED_STRING . ')\s*(?:'\r
+ . $expectParam . ')*)?';\r
+ $expectItem = '!(100-continue|' . $expectExtension . ')!A';\r
+\r
+ $pos = 0;\r
+ $length = strlen($headers['expect']);\r
+\r
+ while ($pos < $length) {\r
+ $pos += strspn($headers['expect'], " \t", $pos);\r
+ if (',' === substr($headers['expect'], $pos, 1)) {\r
+ $pos++;\r
+ continue;\r
+\r
+ } elseif (!preg_match($expectItem, $headers['expect'], $m, 0, $pos)) {\r
+ throw new HTTP_Request2_LogicException(\r
+ "Cannot parse value '{$headers['expect']}' of Expect header",\r
+ HTTP_Request2_Exception::INVALID_ARGUMENT\r
+ );\r
+\r
+ } else {\r
+ $pos += strlen($m[0]);\r
+ if (strcasecmp('100-continue', $m[0])) {\r
+ $expectations[] = $m[0];\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (1024 < $this->contentLength) {\r
+ $expectations[] = '100-continue';\r
+ $this->expect100Continue = true;\r
+ }\r
+\r
+ if (empty($expectations)) {\r
+ unset($headers['expect']);\r
+ } else {\r
+ $headers['expect'] = implode(',', $expectations);\r
+ }\r
+ }\r
+\r