PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/sites/all/libraries/simpleajaxupload/uploader.php

https://bitbucket.org/jaayyy/country-lane-farms
PHP | 256 lines | 203 code | 40 blank | 13 comment | 30 complexity | 5b4d31e8e11df3ecd2ebfd43d3a4ff23 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0
  1. <?php
  2. /**
  3. * Simple Ajax Uploader
  4. * Version 2.0.1
  5. * https://github.com/LPology/Simple-Ajax-Uploader
  6. *
  7. * Copyright 2012-2015 LPology, LLC
  8. * Released under the MIT license
  9. *
  10. * View the documentation for an example of how to use this class.
  11. */
  12. class FileUpload {
  13. private $fileName; // Filename of the uploaded file
  14. private $fileSize; // Size of uploaded file in bytes
  15. private $fileExtension; // File extension of uploaded file
  16. private $fileNameWithoutExt;
  17. private $savedFile; // Path to newly uploaded file (after upload completed)
  18. private $errorMsg; // Error message if handleUpload() returns false (use getErrorMsg() to retrieve)
  19. private $isXhr;
  20. public $uploadDir; // File upload directory (include trailing slash)
  21. public $allowedExtensions; // Array of permitted file extensions
  22. public $sizeLimit = 10485760; // Max file upload size in bytes (default 10MB)
  23. public $newFileName; // Optionally save uploaded files with a new name by setting this
  24. public $corsInputName = 'XHR_CORS_TARGETORIGIN';
  25. public $uploadName = 'uploadfile';
  26. function __construct($uploadName = null) {
  27. if ($uploadName !== null) {
  28. $this->uploadName = $uploadName;
  29. }
  30. if (isset($_FILES[$this->uploadName])) {
  31. $this->isXhr = false;
  32. if ($_FILES[$this->uploadName]['error'] === UPLOAD_ERR_OK) {
  33. $this->fileName = $_FILES[$this->uploadName]['name'];
  34. $this->fileSize = $_FILES[$this->uploadName]['size'];
  35. } else {
  36. $this->setErrorMsg($this->errorCodeToMsg($_FILES[$this->uploadName]['error']));
  37. }
  38. } elseif (isset($_SERVER['HTTP_X_FILE_NAME']) || isset($_GET[$this->uploadName])) {
  39. $this->isXhr = true;
  40. $this->fileName = isset($_SERVER['HTTP_X_FILE_NAME']) ?
  41. $_SERVER['HTTP_X_FILE_NAME'] : $_GET[$this->uploadName];
  42. if (isset($_SERVER['CONTENT_LENGTH'])) {
  43. $this->fileSize = (int)$_SERVER['CONTENT_LENGTH'];
  44. } else {
  45. throw new Exception('Content length is empty.');
  46. }
  47. }
  48. if ($this->fileName) {
  49. $pathinfo = pathinfo($this->fileName);
  50. if (array_key_exists('extension', $pathinfo) &&
  51. array_key_exists('filename', $pathinfo))
  52. {
  53. $this->fileExtension = strtolower($pathinfo['extension']);
  54. $this->fileNameWithoutExt = $pathinfo['filename'];
  55. }
  56. $this->fileName = str_replace(array('/','\\'),'_',$this->fileName);
  57. }
  58. }
  59. public function getFileName() {
  60. return $this->fileName;
  61. }
  62. public function getFileSize() {
  63. return $this->fileSize;
  64. }
  65. public function getExtension() {
  66. return $this->fileExtension;
  67. }
  68. public function getErrorMsg() {
  69. return $this->errorMsg;
  70. }
  71. public function getSavedFile() {
  72. return $this->savedFile;
  73. }
  74. private function errorCodeToMsg($code) {
  75. switch($code) {
  76. case UPLOAD_ERR_INI_SIZE:
  77. $message = 'File size exceeds limit.';
  78. break;
  79. case UPLOAD_ERR_PARTIAL:
  80. $message = 'The uploaded file was only partially uploaded.';
  81. break;
  82. case UPLOAD_ERR_NO_FILE:
  83. $message = 'No file was uploaded.';
  84. break;
  85. case UPLOAD_ERR_NO_TMP_DIR:
  86. $message = 'Missing a temporary folder.';
  87. break;
  88. case UPLOAD_ERR_CANT_WRITE:
  89. $message = 'Failed to write file to disk.';
  90. break;
  91. case UPLOAD_ERR_EXTENSION:
  92. $message = 'File upload stopped by extension.';
  93. break;
  94. default:
  95. $message = 'Unknown upload error.';
  96. break;
  97. }
  98. return $message;
  99. }
  100. private function checkExtension($ext, $allowedExtensions) {
  101. if (!is_array($allowedExtensions))
  102. return false;
  103. if (!in_array(strtolower($ext), array_map('strtolower', $allowedExtensions)))
  104. return false;
  105. return true;
  106. }
  107. private function setErrorMsg($msg) {
  108. if (empty($this->errorMsg))
  109. $this->errorMsg = $msg;
  110. }
  111. private function fixDir($dir) {
  112. if (empty($dir))
  113. return $dir;
  114. $slash = DIRECTORY_SEPARATOR;
  115. $dir = str_replace('/', $slash, $dir);
  116. $dir = str_replace('\\', $slash, $dir);
  117. return substr($dir, -1) == $slash ? $dir : $dir . $slash;
  118. }
  119. // escapeJS and jsMatcher are adapted from the Escaper component of
  120. // Zend Framework, Copyright (c) 2005-2013, Zend Technologies USA, Inc.
  121. // https://github.com/zendframework/zf2/tree/master/library/Zend/Escaper
  122. private function escapeJS($string) {
  123. return preg_replace_callback('/[^a-z0-9,\._]/iSu', $this->jsMatcher, $string);
  124. }
  125. private function jsMatcher($matches) {
  126. $chr = $matches[0];
  127. if (strlen($chr) == 1)
  128. return sprintf('\\x%02X', ord($chr));
  129. if (function_exists('iconv'))
  130. $chr = iconv('UTF-16BE', 'UTF-8', $chr);
  131. elseif (function_exists('mb_convert_encoding'))
  132. $chr = mb_convert_encoding($chr, 'UTF-8', 'UTF-16BE');
  133. return sprintf('\\u%04s', strtoupper(bin2hex($chr)));
  134. }
  135. public function corsResponse($data) {
  136. if (isset($_REQUEST[$this->corsInputName])) {
  137. $targetOrigin = $this->escapeJS($_REQUEST[$this->corsInputName]);
  138. $targetOrigin = htmlspecialchars($targetOrigin, ENT_QUOTES, 'UTF-8');
  139. return "<script>window.parent.postMessage('$data','$targetOrigin');</script>";
  140. }
  141. return $data;
  142. }
  143. private function saveXhr($path) {
  144. if (false !== file_put_contents($path, fopen('php://input', 'r')))
  145. return true;
  146. return false;
  147. }
  148. private function saveForm($path) {
  149. if (move_uploaded_file($_FILES[$this->uploadName]['tmp_name'], $path))
  150. return true;
  151. return false;
  152. }
  153. private function save($path) {
  154. if (true === $this->isXhr)
  155. return $this->saveXhr($path);
  156. return $this->saveForm($path);
  157. }
  158. public function handleUpload($uploadDir = null, $allowedExtensions = null) {
  159. if (!$this->fileName) {
  160. $this->setErrorMsg('Incorrect upload name or no file uploaded');
  161. return false;
  162. }
  163. if ($this->fileSize == 0) {
  164. $this->setErrorMsg('File is empty');
  165. return false;
  166. }
  167. if ($this->fileSize > $this->sizeLimit) {
  168. $this->setErrorMsg('File size exceeds limit');
  169. return false;
  170. }
  171. if (!empty($uploadDir))
  172. $this->uploadDir = $uploadDir;
  173. $this->uploadDir = $this->fixDir($this->uploadDir);
  174. if (!is_writable($this->uploadDir)) {
  175. $this->setErrorMsg('Upload directory is not writable');
  176. return false;
  177. }
  178. if (is_array($allowedExtensions))
  179. $this->allowedExtensions = $allowedExtensions;
  180. if (!empty($this->allowedExtensions)) {
  181. if (!$this->checkExtension($this->fileExtension, $this->allowedExtensions)) {
  182. $this->setErrorMsg('Invalid file type');
  183. return false;
  184. }
  185. }
  186. $this->savedFile = $this->uploadDir . $this->fileName;
  187. if (!empty($this->newFileName)) {
  188. $this->fileName = $this->newFileName;
  189. $this->savedFile = $this->uploadDir . $this->fileName;
  190. $this->fileNameWithoutExt = null;
  191. $this->fileExtension = null;
  192. $pathinfo = pathinfo($this->fileName);
  193. if (array_key_exists('filename', $pathinfo))
  194. $this->fileNameWithoutExt = $pathinfo['filename'];
  195. if (array_key_exists('extension', $pathinfo))
  196. $this->fileExtension = strtolower($pathinfo['extension']);
  197. }
  198. if (!$this->save($this->savedFile)) {
  199. $this->setErrorMsg('File could not be saved');
  200. return false;
  201. }
  202. return true;
  203. }
  204. }