/** * * Sends all headers and cookies. * * @return void * * @throws Solar_Http_Response_Exception_HeadersSent if headers have * already been sent. * */ protected function _sendHeaders() { // build the full status header string. the values have already been // sanitized by setStatus() and setStatusText(). $status = "HTTP/{$this->_version} {$this->_status_code}"; if ($this->_status_text) { $status .= " {$this->_status_text}"; } // send the status header header($status, true, $this->_status_code); // send each of the remaining headers foreach ($this->getHeaders() as $key => $list) { // sanitize and skip empty keys $key = Solar_Mime::headerLabel($key); if (!$key) { continue; } // send each value for the header foreach ((array) $list as $val) { // we don't need full MIME escaping here, just sanitize the // value by stripping CR and LF chars $val = str_replace(array("\r", "\n"), '', $val); header("{$key}: {$val}"); } } // send each of the cookies foreach ($this->_cookies as $key => $val) { // was httponly set for this cookie? if not, // use the default. $httponly = $val['httponly'] === null ? $this->_cookies_httponly : (bool) $val['httponly']; // try to allow for times not in unix-timestamp format if (!is_numeric($val['expires'])) { $val['expires'] = strtotime($val['expires']); } // actually set the cookie setcookie($key, $val['value'], (int) $val['expires'], $val['path'], $val['domain'], (bool) $val['secure'], (bool) $httponly); } }
/** * * Returns the body content of this part with the proper encoding. * * @return string * */ public function fetchContent() { $content = Solar_Mime::encode($this->_encoding, $this->_content, $this->_crlf); return $content; }
/** * * Fetches all the headers of this message as a sequential array. * * Each element is itself sequential array, where element 0 is the * header label, and element 1 is the encoded header value. * * @return array * */ public function fetchHeaders() { // the array of headers to return $headers = array(); // Return-Path: (alternatively, the From: address) if ($this->_return_path) { $headers[] = array('Return-Path', "<{$this->_return_path}>"); } else { $headers[] = array('Return-Path', "<{$this->_from[0]}>"); } // Date: $headers[] = array('Date', date('r')); // From: $value = "<{$this->_from[0]}>"; if ($this->_from[1]) { $value = '"' . $this->_from[1] . '" ' . $value; } $headers[] = array("From", $value); // Reply-To: (optional) if ($this->_reply_to[0]) { $value = "<{$this->_reply_to[0]}>"; if ($this->_reply_to[1]) { $value = '"' . $this->_reply_to[1] . '" ' . $value; } $headers[] = array("Reply-To", $value); } // To:, Cc:, Bcc: foreach ($this->_rcpt as $label => $rcpt) { foreach ($rcpt as $addr => $name) { $value = "<{$addr}>"; if ($name) { $value = '"' . $name . '" ' . $value; } $headers[] = array($label, $value); } } // Subject: $headers[] = array('Subject', $this->_subject); // Mime-Version: $headers[] = array('Mime-Version', '1.0'); // Determine the content type and transfer encoding. // Default is no transfer encoding. $encoding = null; if ($this->_text && $this->_html && !$this->_atch) { // both text and html, but no attachments: multipart/alternative $value = 'multipart/alternative; ' . 'charset="' . $this->_charset . '"; ' . $this->_crlf . " " . 'boundary="' . $this->_boundary . '"'; } elseif ($this->_atch) { // has attachments, use multipart/mixed $value = 'multipart/mixed; ' . 'charset="' . $this->_charset . '"; ' . $this->_crlf . " " . 'boundary="' . $this->_boundary . '"'; } elseif ($this->_html) { // no attachments, html only $value = 'text/html; ' . 'charset="' . $this->_charset . '"'; // use the part's encoding $encoding = $this->_html->getEncoding(); } elseif ($this->_text) { // no attachments, text only $value = 'text/plain; ' . 'charset="' . $this->_charset . '"'; // use the part's encoding $encoding = $this->_text->getEncoding(); } else { // final fallback $value = 'text/plain; ' . 'charset="' . $this->_charset . '"'; } // Content-Type: $headers[] = array('Content-Type', $value); // Content-Transfer-Encoding: if ($encoding) { $headers[] = array('Content-Transfer-Encoding', $encoding); } // encode all the headers so far foreach ($headers as $key => $val) { // val[0] is the label, val[1] is the value $val[0] = Solar_Mime::headerLabel($val[0]); $headers[$key][1] = Solar_Mime::headerValue($val[0], $val[1], $this->_charset, $this->_crlf); } // add and encode custom headers foreach ($this->_headers as $label => $list) { $label = Solar_Mime::headerLabel($label); foreach ($list as $value) { $headers[] = array($label, Solar_Mime::headerValue($label, $value, $this->_charset, $this->_crlf)); } } // done! return $headers; }
/** * * Prepares $this->_headers, $this->_cookies, and $this->content for the * request. * * @return array A sequential array where element 0 is a URI object, * element 1 is string of headers (including cookies), and element 2 is a * string of content. * * @todo Only generate $content on POST and PUT? * */ protected function _prepareRequest() { // get the URI if (!$this->_uri) { throw $this->_exception('ERR_NO_URI'); } else { $uri = clone $this->_uri; } // what kind of request is this? $is_get = $this->_method == Solar_Http_Request::METHOD_GET; $is_post = $this->_method == Solar_Http_Request::METHOD_POST; $is_put = $this->_method == Solar_Http_Request::METHOD_PUT; // do we have any body content? if (is_array($this->content) && ($is_post || $is_put)) { // is a POST or PUT with a data array. // convert from array and force the content-type. $content = http_build_query($this->content); $content_type = 'application/x-www-form-urlencoded'; } elseif (is_array($this->content) && $is_get) { // is a GET with a data array. // merge the content array to the cloned uri query params. $uri->query = array_merge($uri->query, $this->content); // now clear out the content $content = null; $content_type = null; } elseif (is_string($this->content)) { // honor as set by the user $content = $this->content; $content_type = $this->_content_type; } else { // no recognizable content $content = null; $content_type = null; } // get a list of the headers as they are now $list = $this->_headers; // force the content-type header if needed if ($content_type) { if ($this->_charset) { $content_type .= "; charset={$this->_charset}"; } $list['Content-Type'] = $content_type; } // auto-set the content-length if ($this->_config['auto_set_length']) { if ($content) { $list['Content-Length'] = strlen($content); } else { unset($list['Content-Length']); } } // force the user-agent header if needed if ($this->_user_agent) { $list['User-Agent'] = $this->_user_agent; } // force the referer if needed if ($this->_referer) { $list['Referer'] = $this->_referer->get(true); } // convert the list of all header values to a sequential array $headers = array(); foreach ($list as $key => $set) { settype($set, 'array'); foreach ($set as $val) { $headers[] = Solar_Mime::headerLine($key, $val); } } // create additional cookies in the headers array if ($this->_cookies) { $val = array(); foreach ($this->_cookies as $name => $data) { $val[] = "{$name}=" . urlencode($data); } $headers[] = Solar_Mime::headerLine('Cookie', implode(';', $val)); } // done! return array($uri, $headers, $content); }