PageRenderTime 48ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/app/code/core/Mage/Downloadable/Helper/Download.php

https://github.com/joebushi/magento-mirror
PHP | 297 lines | 175 code | 27 blank | 95 comment | 47 complexity | 9b1a4a49b1e60d554977a4233a8fd8b3 MD5 | raw file
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_Downloadable
  23. * @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * Downloadable Products Download Helper
  28. *
  29. * @category Mage
  30. * @package Mage_Downloadable
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_Downloadable_Helper_Download extends Mage_Core_Helper_Abstract
  34. {
  35. const LINK_TYPE_URL = 'url';
  36. const LINK_TYPE_FILE = 'file';
  37. const XML_PATH_CONTENT_DISPOSITION = 'catalog/downloadable/content_disposition';
  38. /**
  39. * Type of link
  40. *
  41. * @var string
  42. */
  43. protected $_linkType = self::LINK_TYPE_FILE;
  44. /**
  45. * Resource file
  46. *
  47. * @var string
  48. */
  49. protected $_resourceFile = null;
  50. /**
  51. * Resource open handle
  52. *
  53. * @var resource
  54. */
  55. protected $_handle = null;
  56. /**
  57. * Remote server headers
  58. *
  59. * @var array
  60. */
  61. protected $_urlHeaders = array();
  62. /**
  63. * MIME Content-type for a file
  64. *
  65. * @var string
  66. */
  67. protected $_contentType = 'application/octet-stream';
  68. /**
  69. * File name
  70. *
  71. * @var string
  72. */
  73. protected $_fileName = 'download';
  74. /**
  75. * Retrieve Resource file handle (socket, file pointer etc)
  76. *
  77. * @return resource
  78. */
  79. protected function _getHandle()
  80. {
  81. if (!$this->_resourceFile) {
  82. Mage::throwException(Mage::helper('downloadable')->__('Please set resource file and link type'));
  83. }
  84. if (is_null($this->_handle)) {
  85. if ($this->_linkType == self::LINK_TYPE_URL) {
  86. $port = 80;
  87. /**
  88. * Validate URL
  89. */
  90. $urlProp = parse_url($this->_resourceFile);
  91. if (!isset($urlProp['scheme']) || strtolower($urlProp['scheme'] != 'http')) {
  92. Mage::throwException(Mage::helper('downloadable')->__('Invalid download URL scheme'));
  93. }
  94. if (!isset($urlProp['host'])) {
  95. Mage::throwException(Mage::helper('downloadable')->__('Invalid download URL host'));
  96. }
  97. $hostname = $urlProp['host'];
  98. if (isset($urlProp['port'])) {
  99. $port = (int)$urlProp['port'];
  100. }
  101. $path = '/';
  102. if (isset($urlProp['path'])) {
  103. $path = $urlProp['path'];
  104. }
  105. $query = '';
  106. if (isset($urlProp['query'])) {
  107. $query = '?' . $urlProp['query'];
  108. }
  109. try {
  110. $this->_handle = fsockopen($hostname, $port, $errno, $errstr);
  111. }
  112. catch (Exception $e) {
  113. throw $e;
  114. }
  115. if ($this->_handle === false) {
  116. Mage::throwException(Mage::helper('downloadable')->__('Can\'t connect to remote host, error: %s', $errstr));
  117. }
  118. $headers = 'GET ' . $path . $query . ' HTTP/1.0' . "\r\n"
  119. . 'Host: ' . $hostname . "\r\n"
  120. . 'User-Agent: Magento ver/' . Mage::getVersion() . "\r\n"
  121. . 'Connection: close' . "\r\n"
  122. . "\r\n";
  123. fwrite($this->_handle, $headers);
  124. while (!feof($this->_handle)) {
  125. $str = fgets($this->_handle, 1024);
  126. if ($str == "\r\n") {
  127. break;
  128. }
  129. $match = array();
  130. if (preg_match('#^([^:]+): (.*)\s+$#', $str, $match)) {
  131. $k = strtolower($match[1]);
  132. if ($k == 'set-cookie') {
  133. continue;
  134. }
  135. else {
  136. $this->_urlHeaders[$k] = trim($match[2]);
  137. }
  138. }
  139. elseif (preg_match('#^HTTP/[0-9\.]+ (\d+) (.*)\s$#', $str, $match)) {
  140. $this->_urlHeaders['code'] = $match[1];
  141. $this->_urlHeaders['code-string'] = trim($match[2]);
  142. }
  143. }
  144. if (!isset($this->_urlHeaders['code']) || $this->_urlHeaders['code'] != 200) {
  145. Mage::throwException(Mage::helper('downloadable')->__('Sorry, the was an error getting requested content. Please contact store owner.'));
  146. }
  147. }
  148. elseif ($this->_linkType == self::LINK_TYPE_FILE) {
  149. $this->_handle = new Varien_Io_File();
  150. $this->_handle->open(array('path'=>Mage::getBaseDir('var')));
  151. if (!$this->_handle->fileExists($this->_resourceFile, true)) {
  152. Mage::throwException(Mage::helper('downloadable')->__('File does not exists'));
  153. }
  154. $this->_handle->streamOpen($this->_resourceFile, 'r');
  155. }
  156. else {
  157. Mage::throwException(Mage::helper('downloadable')->__('Invalid download link type'));
  158. }
  159. }
  160. return $this->_handle;
  161. }
  162. /**
  163. * Retrieve file size in bytes
  164. */
  165. public function getFilesize()
  166. {
  167. $handle = $this->_getHandle();
  168. if ($this->_linkType == self::LINK_TYPE_FILE) {
  169. return $handle->streamStat('size');
  170. }
  171. elseif ($this->_linkType == self::LINK_TYPE_URL) {
  172. if (isset($this->_urlHeaders['content-length'])) {
  173. return $this->_urlHeaders['content-length'];
  174. }
  175. }
  176. return null;
  177. }
  178. public function getContentType()
  179. {
  180. $handle = $this->_getHandle();
  181. if ($this->_linkType == self::LINK_TYPE_FILE) {
  182. if (function_exists('mime_content_type')) {
  183. return mime_content_type($this->_resourceFile);
  184. } else {
  185. return Mage::helper('downloadable/file')->getFileType($this->_resourceFile);
  186. }
  187. }
  188. elseif ($this->_linkType == self::LINK_TYPE_URL) {
  189. if (isset($this->_urlHeaders['content-type'])) {
  190. $contentType = explode('; ', $this->_urlHeaders['content-type']);
  191. return $contentType[0];
  192. }
  193. }
  194. return $this->_contentType;
  195. }
  196. public function getFilename()
  197. {
  198. $handle = $this->_getHandle();
  199. if ($this->_linkType == self::LINK_TYPE_FILE) {
  200. return pathinfo($this->_resourceFile, PATHINFO_BASENAME);
  201. }
  202. elseif ($this->_linkType == self::LINK_TYPE_URL) {
  203. if (isset($this->_urlHeaders['content-disposition'])) {
  204. $contentDisposition = explode('; ', $this->_urlHeaders['content-disposition']);
  205. if (!empty($contentDisposition[1]) && strpos($contentDisposition[1], 'filename=') !== false) {
  206. return substr($contentDisposition[1], 9);
  207. }
  208. }
  209. if ($fileName = @pathinfo($this->_resourceFile, PATHINFO_BASENAME)) {
  210. return $fileName;
  211. }
  212. }
  213. return $this->_fileName;
  214. }
  215. /**
  216. * Set resource file for download
  217. *
  218. * @param string $resourceFile
  219. * @param string $linkType
  220. * @return Mage_Downloadable_Helper_Download
  221. */
  222. public function setResource($resourceFile, $linkType = self::LINK_TYPE_FILE)
  223. {
  224. $this->_resourceFile = $resourceFile;
  225. $this->_linkType = $linkType;
  226. return $this;
  227. }
  228. /**
  229. * Retrieve Http Request Object
  230. *
  231. * @return Mage_Core_Controller_Request_Http
  232. */
  233. public function getHttpRequest()
  234. {
  235. return Mage::app()->getFrontController()->getRequest();
  236. }
  237. /**
  238. * Retrieve Http Response Object
  239. *
  240. * @return Mage_Core_Controller_Response_Http
  241. */
  242. public function getHttpResponse()
  243. {
  244. return Mage::app()->getFrontController()->getResponse();
  245. }
  246. public function output()
  247. {
  248. $handle = $this->_getHandle();
  249. if ($this->_linkType == self::LINK_TYPE_FILE) {
  250. while ($buffer = $handle->streamRead()) {
  251. print $buffer;
  252. }
  253. }
  254. elseif ($this->_linkType == self::LINK_TYPE_URL) {
  255. while (!feof($handle)) {
  256. print fgets($handle, 1024);
  257. }
  258. }
  259. }
  260. /**
  261. * Use Content-Disposition: attachment
  262. *
  263. * @param mixed $store
  264. * @return bool
  265. */
  266. public function getContentDisposition($store = null)
  267. {
  268. return Mage::getStoreConfig(self::XML_PATH_CONTENT_DISPOSITION, $store);
  269. }
  270. }