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

/vendor/patchwork/utf8/src/Patchwork/Utf8/WindowsStreamWrapper.php

https://gitlab.com/xolotsoft/pumasruiz
PHP | 404 lines | 326 code | 61 blank | 17 comment | 37 complexity | bd7baf3e6fc0d8f75feddc2984f81529 MD5 | raw file
  1. <?php
  2. /*
  3. * Copyright (C) 2014 Nicolas Grekas - p@tchwork.com
  4. *
  5. * This library is free software; you can redistribute it and/or modify it
  6. * under the terms of the (at your option):
  7. * Apache License v2.0 (http://apache.org/licenses/LICENSE-2.0.txt), or
  8. * GNU General Public License v2.0 (http://gnu.org/licenses/gpl-2.0.txt).
  9. */
  10. namespace Patchwork\Utf8;
  11. /**
  12. * Unicode UTF-8 aware stream based filesystem access on MS-Windows.
  13. *
  14. * Based on COM Scripting.FileSystemObject object and short paths.
  15. * See Patchwork\Utf8::wrapPath()
  16. *
  17. * See also https://code.google.com/p/php-wfio/ for a PHP extension
  18. * and comments on http://www.rooftopsolutions.nl/blog/filesystem-encoding-and-php
  19. */
  20. class WindowsStreamWrapper
  21. {
  22. public $context;
  23. protected $handle;
  24. public static function hide($path)
  25. {
  26. list($fs, $path) = self::fs($path);
  27. if ($fs->FileExists($path)) {
  28. $fs->GetFile($path)->Attributes |= 2;
  29. } elseif ($fs->FolderExists($path)) {
  30. $fs->GetFolder($path)->Attributes |= 2;
  31. } else {
  32. return false;
  33. }
  34. return true;
  35. }
  36. public static function fs($path, $is_utf8 = true)
  37. {
  38. static $fs;
  39. if (!class_exists('COM', false)) {
  40. throw new \RuntimeException('The `wfio` or `com_dotnet` extension is required to handle UTF-8 filesystem access on Windows');
  41. }
  42. isset($fs) or $fs = new \COM('Scripting.FileSystemObject', null, CP_UTF8);
  43. $path = explode('://', $path, 2);
  44. $path = $path[(int) isset($path[1])];
  45. $path = strtr($path, '/', '\\');
  46. $pre = '';
  47. if (!isset($path[0]) || ('/' !== $path[0] && '\\' !== $path[0] && false === strpos($path, ':'))) {
  48. $pre = getcwd().'\\';
  49. }
  50. $pre = new \VARIANT($pre);
  51. if ($is_utf8) {
  52. $path = new \VARIANT($path, VT_BSTR, CP_UTF8);
  53. } else {
  54. $path = new \VARIANT($path);
  55. }
  56. return array($fs, $fs->getAbsolutePathName(variant_cat($pre, $path)));
  57. }
  58. public function dir_closedir()
  59. {
  60. $this->handle = null;
  61. return true;
  62. }
  63. public function dir_opendir($path, $options)
  64. {
  65. list($fs, $path) = self::fs($path);
  66. if (!$fs->FolderExists($path)) {
  67. return false;
  68. }
  69. $dir = $fs->GetFolder($path);
  70. try {
  71. $f = array('.', '..');
  72. foreach ($dir->SubFolders() as $v) {
  73. $f[] = $v->Name;
  74. }
  75. foreach ($dir->Files as $v) {
  76. $f[] = $v->Name;
  77. }
  78. } catch (\Exception $f) {
  79. $f = array();
  80. }
  81. $this->handle = $f;
  82. return true;
  83. }
  84. public function dir_readdir()
  85. {
  86. if (list(, $c) = each($this->handle)) {
  87. return $c;
  88. }
  89. return false;
  90. }
  91. public function dir_rewinddir()
  92. {
  93. reset($this->handle);
  94. return true;
  95. }
  96. public function mkdir($path, $mode, $options)
  97. {
  98. list($fs, $path) = self::fs($path);
  99. try {
  100. if ($options & STREAM_MKDIR_RECURSIVE) {
  101. $path = $fs->GetAbsolutePathName($path);
  102. $path = explode('\\', $path);
  103. if (isset($path[3]) && '' === $path[0].$path[1]) {
  104. $pre = '\\\\'.$path[2].'\\'.$path[3].'\\';
  105. $i = 4;
  106. } elseif (isset($path[1])) {
  107. $pre = $path[0].'\\';
  108. $i = 1;
  109. } else {
  110. $pre = '';
  111. $i = 0;
  112. }
  113. while (isset($path[$i]) && $fs->FolderExists($pre.$path[$i])) {
  114. $pre .= $path[$i++].'\\';
  115. }
  116. if (!isset($path[$i])) {
  117. return false;
  118. }
  119. while (isset($path[$i])) {
  120. $fs->CreateFolder($pre .= $path[$i++].'\\');
  121. }
  122. return true;
  123. } else {
  124. $fs->CreateFolder($path);
  125. }
  126. return true;
  127. } catch (\Exception $e) {
  128. return false;
  129. }
  130. }
  131. public function rename($from, $to)
  132. {
  133. list($fs, $to) = self::fs($to);
  134. if ($fs->FileExists($to) || $fs->FolderExists($to)) {
  135. return false;
  136. }
  137. list(, $from) = self::fs($from);
  138. try {
  139. if ($fs->FileExists($from)) {
  140. $fs->MoveFile($from, $to);
  141. return true;
  142. }
  143. if ($fs->FolderExists($from)) {
  144. $fs->MoveFolder($from, $to);
  145. return true;
  146. }
  147. } catch (\Exception $e) {
  148. }
  149. return false;
  150. }
  151. public function rmdir($path, $options)
  152. {
  153. list($fs, $path) = self::fs($path);
  154. if ($fs->FolderExists($path)) {
  155. return rmdir($fs->GetFolder($path)->ShortPath);
  156. }
  157. return false;
  158. }
  159. public function stream_close()
  160. {
  161. fclose($this->handle);
  162. $this->handle = null;
  163. }
  164. public function stream_eof()
  165. {
  166. return feof($this->handle);
  167. }
  168. public function stream_flush()
  169. {
  170. return fflush($this->handle);
  171. }
  172. public function stream_lock($operation)
  173. {
  174. return flock($this->handle, $operation);
  175. }
  176. public function stream_metadata($path, $option, $value)
  177. {
  178. list($fs, $path) = self::fs($path);
  179. if ($fs->FileExists($path)) {
  180. $f = $fs->GetFile($path);
  181. } elseif ($fs->FileExists($path)) {
  182. $f = $fs->GetFolder($path);
  183. } else {
  184. $f = false;
  185. }
  186. if (STREAM_META_TOUCH === $option) {
  187. if ($f) {
  188. return touch($f->ShortPath);
  189. }
  190. try {
  191. $fs->OpenTextFile($path, 8, true, 0)->Close();
  192. return true;
  193. } catch (\Exception $e) {
  194. }
  195. }
  196. if (!$f) {
  197. return false;
  198. }
  199. switch ($option) {
  200. case STREAM_META_ACCESS: return chmod($f->ShortPath, $value);
  201. case STREAM_META_OWNER:
  202. case STREAM_META_OWNER_NAME: return chown($f->ShortPath, $value);
  203. case STREAM_META_GROUP:
  204. case STREAM_META_GROUP_NAME: return chgrp($f->ShortPath, $value);
  205. default: return false;
  206. }
  207. }
  208. public function stream_open($path, $mode, $options, &$opened_path)
  209. {
  210. $mode .= '';
  211. list($fs, $path) = self::fs($path);
  212. if ($fs->FolderExists($path)) {
  213. return false;
  214. }
  215. try {
  216. if ('x' === $m = substr($mode, 0, 1)) {
  217. $fs->CreateTextFile($path, false)->Close();
  218. $f = $fs->GetFile($path);
  219. $mode[0] = 'w';
  220. } else {
  221. $f = $fs->GetFile($path);
  222. }
  223. } catch (\Exception $f) {
  224. try {
  225. switch ($m) {
  226. case 'w':
  227. case 'c':
  228. case 'a':
  229. $h = $fs->CreateTextFile($path, true);
  230. $f = $fs->GetFile($path);
  231. $h->Close();
  232. break;
  233. default: return false;
  234. }
  235. } catch (\Exception $e) {
  236. return false;
  237. }
  238. }
  239. if (!(STREAM_REPORT_ERRORS & $options)) {
  240. set_error_handler('var_dump', 0);
  241. $e = error_reporting(0);
  242. }
  243. $this->handle = fopen($f->ShortPath, $mode);
  244. if (!(STREAM_REPORT_ERRORS & $options)) {
  245. error_reporting($e);
  246. restore_error_handler();
  247. }
  248. if ($this->handle) {
  249. return true;
  250. }
  251. if (isset($h)) {
  252. $f->Delete(true);
  253. }
  254. return false;
  255. }
  256. public function stream_read($count)
  257. {
  258. return fread($this->handle, $count);
  259. }
  260. public function stream_seek($offset, $whence = SEEK_SET)
  261. {
  262. return fseek($this->handle, $offset, $whence);
  263. }
  264. public function stream_set_option($option, $arg1, $arg2)
  265. {
  266. switch ($option) {
  267. case STREAM_OPTION_BLOCKING: return stream_set_blocking($this->handle, $arg1);
  268. case STREAM_OPTION_READ_TIMEOUT: return stream_set_timeout($this->handle, $arg1, $arg2);
  269. case STREAM_OPTION_WRITE_BUFFER: return stream_set_write_buffer($this->handle, $arg1, $arg2);
  270. default: return false;
  271. }
  272. }
  273. public function stream_stat()
  274. {
  275. return fstat($this->handle);
  276. }
  277. public function stream_tell()
  278. {
  279. return ftell($this->handle);
  280. }
  281. public function stream_truncate($new_size)
  282. {
  283. return ftruncate($this->handle, $new_size);
  284. }
  285. public function stream_write($data)
  286. {
  287. return fwrite($this->handle, $data, strlen($data));
  288. }
  289. public function unlink($path)
  290. {
  291. list($fs, $path) = self::fs($path);
  292. if ($fs->FileExists($path)) {
  293. return unlink($fs->GetFile($path)->ShortPath);
  294. }
  295. return false;
  296. }
  297. public function url_stat($path, $flags)
  298. {
  299. list($fs, $path) = self::fs($path);
  300. if ($fs->FileExists($path)) {
  301. $f = $fs->GetFile($path);
  302. } elseif ($fs->FolderExists($path)) {
  303. $f = $fs->GetFolder($path);
  304. } else {
  305. return false;
  306. }
  307. if (STREAM_URL_STAT_QUIET & $flags) {
  308. set_error_handler('var_dump', 0);
  309. $e = error_reporting(0);
  310. }
  311. if (STREAM_URL_STAT_LINK & $flags) {
  312. $f = @lstat($f->ShortPath) ?: stat($f->ShortPath);
  313. } else {
  314. $f = stat($f->ShortPath);
  315. }
  316. if (STREAM_URL_STAT_QUIET & $flags) {
  317. error_reporting($e);
  318. restore_error_handler();
  319. }
  320. return $f;
  321. }
  322. }