/** * * 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 all the headers as a string. * * @return string * */ public function fetchHeaders() { // start with all the "custom" headers. // we will apply header-value encoding at the end. $headers = $this->_headers; // Content-Type: $content_type = $this->_type; if ($this->_charset) { $content_type .= '; charset="' . $this->_charset . '"'; } if ($this->_boundary) { $content_type .= ';' . $this->_crlf . ' boundary="' . $this->_boundary . '"'; } $headers['Content-Type'] = $content_type; // Content-Disposition: if ($this->_disposition) { $disposition = $this->_disposition; if ($this->_filename) { $disposition .= '; filename="' . $this->_filename . '"'; } $headers['Content-Disposition'] = $disposition; } // Content-Transfer-Encoding: if ($this->_encoding) { $headers['Content-Transfer-Encoding'] = $this->_encoding; } // now loop through all the headers and build the header block, // using header-value encoding as we go. $output = ''; foreach ($headers as $label => $value) { $label = Solar_Mime::headerLabel($label); $value = Solar_Mime::headerValue($label, $value, $this->_charset, $this->_crlf); $output .= "{$label}: {$value}{$this->_crlf}"; } return $output; }
/** * * 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; }
/** * * Sets a header value in $this->_headers for sending at fetch() time. * * This method will not set cookie values; use setCookie() or setCookies() * instead. * * @param string $key The header label, such as "X-Foo-Bar". * * @param string $val The value for the header. When null or false, * deletes the header. * * @param bool $replace This header value should replace any previous * values of the same key. When false, the same header key is sent * multiple times with the different values. * * @return Solar_Http_Request_Adapter This adapter object. * * @see [[php::header() | ]] * */ public function setHeader($key, $val, $replace = true) { // normalize the header key and keep a lower-case version $key = Solar_Mime::headerLabel($key); $low = strtolower($key); // use special methods when available $special = array('content-type' => 'setContentType', 'http' => 'setVersion', 'referer' => 'setReferer', 'user-agent' => 'setUserAgent'); if (!empty($special[$low])) { $method = $special[$low]; return $this->{$method}($val); } // don't allow setting of cookies if ($low == 'cookie') { throw $this->_exception('ERR_USE_OTHER_METHOD', array('cookie' => 'setCookie() or setCookies()')); } // how to add the header? if ($val === null or $val === false) { // delete the key unset($this->_headers[$key]); } elseif ($replace || empty($this->_headers[$key])) { // replacement, or first instance of the key $this->_headers[$key] = $val; } else { // second or later instance of the key settype($this->_headers[$key], 'array'); $this->_headers[$key][] = $val; } // done return $this; }