drg_elfinder 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/drg_elfinder_manifest.js +1 -0
  6. data/app/assets/javascripts/drg_elfinder.js +15 -0
  7. data/app/assets/javascripts/elfinder/Changelog +1283 -0
  8. data/app/assets/javascripts/elfinder/LICENSE.md +15 -0
  9. data/app/assets/javascripts/elfinder/README.md +216 -0
  10. data/app/assets/javascripts/elfinder/bower.json +28 -0
  11. data/app/assets/javascripts/elfinder/composer.json +39 -0
  12. data/app/assets/javascripts/elfinder/css/elfinder.full.css +5350 -0
  13. data/app/assets/javascripts/elfinder/css/elfinder.min.css +9 -0
  14. data/app/assets/javascripts/elfinder/css/theme.css +430 -0
  15. data/app/assets/javascripts/elfinder/elfinder.html +74 -0
  16. data/app/assets/javascripts/elfinder/elfinder.legacy.html +94 -0
  17. data/app/assets/javascripts/elfinder/img/arrows-active.png +0 -0
  18. data/app/assets/javascripts/elfinder/img/arrows-normal.png +0 -0
  19. data/app/assets/javascripts/elfinder/img/crop.gif +0 -0
  20. data/app/assets/javascripts/elfinder/img/dialogs.png +0 -0
  21. data/app/assets/javascripts/elfinder/img/edit_aceeditor.png +0 -0
  22. data/app/assets/javascripts/elfinder/img/edit_ckeditor.png +0 -0
  23. data/app/assets/javascripts/elfinder/img/edit_ckeditor5.png +0 -0
  24. data/app/assets/javascripts/elfinder/img/edit_codemirror.png +0 -0
  25. data/app/assets/javascripts/elfinder/img/edit_creativecloud.png +0 -0
  26. data/app/assets/javascripts/elfinder/img/edit_onlineconvert.png +0 -0
  27. data/app/assets/javascripts/elfinder/img/edit_pixlreditor.png +0 -0
  28. data/app/assets/javascripts/elfinder/img/edit_pixlrexpress.png +0 -0
  29. data/app/assets/javascripts/elfinder/img/edit_simplemde.png +0 -0
  30. data/app/assets/javascripts/elfinder/img/edit_tinymce.png +0 -0
  31. data/app/assets/javascripts/elfinder/img/edit_tuiimgedit.png +0 -0
  32. data/app/assets/javascripts/elfinder/img/edit_zohooffice.png +0 -0
  33. data/app/assets/javascripts/elfinder/img/editor-icons.png +0 -0
  34. data/app/assets/javascripts/elfinder/img/icons-big.png +0 -0
  35. data/app/assets/javascripts/elfinder/img/icons-big.svg +1 -0
  36. data/app/assets/javascripts/elfinder/img/icons-small.png +0 -0
  37. data/app/assets/javascripts/elfinder/img/logo.png +0 -0
  38. data/app/assets/javascripts/elfinder/img/progress.gif +0 -0
  39. data/app/assets/javascripts/elfinder/img/quicklook-bg.png +0 -0
  40. data/app/assets/javascripts/elfinder/img/quicklook-icons.png +0 -0
  41. data/app/assets/javascripts/elfinder/img/resize.png +0 -0
  42. data/app/assets/javascripts/elfinder/img/spinner-mini.gif +0 -0
  43. data/app/assets/javascripts/elfinder/img/toolbar.png +0 -0
  44. data/app/assets/javascripts/elfinder/img/trashmesh.png +0 -0
  45. data/app/assets/javascripts/elfinder/img/tui-icon-a.svg +235 -0
  46. data/app/assets/javascripts/elfinder/img/tui-icon-b.svg +224 -0
  47. data/app/assets/javascripts/elfinder/img/tui-icon-c.svg +224 -0
  48. data/app/assets/javascripts/elfinder/img/tui-icon-d.svg +224 -0
  49. data/app/assets/javascripts/elfinder/img/ui-icons_ffffff_256x240.png +0 -0
  50. data/app/assets/javascripts/elfinder/img/volume_icon_box.png +0 -0
  51. data/app/assets/javascripts/elfinder/img/volume_icon_box.svg +1 -0
  52. data/app/assets/javascripts/elfinder/img/volume_icon_dropbox.png +0 -0
  53. data/app/assets/javascripts/elfinder/img/volume_icon_dropbox.svg +1 -0
  54. data/app/assets/javascripts/elfinder/img/volume_icon_ftp.png +0 -0
  55. data/app/assets/javascripts/elfinder/img/volume_icon_ftp.svg +1 -0
  56. data/app/assets/javascripts/elfinder/img/volume_icon_googledrive.png +0 -0
  57. data/app/assets/javascripts/elfinder/img/volume_icon_googledrive.svg +1 -0
  58. data/app/assets/javascripts/elfinder/img/volume_icon_local.png +0 -0
  59. data/app/assets/javascripts/elfinder/img/volume_icon_local.svg +1 -0
  60. data/app/assets/javascripts/elfinder/img/volume_icon_network.png +0 -0
  61. data/app/assets/javascripts/elfinder/img/volume_icon_network.svg +1 -0
  62. data/app/assets/javascripts/elfinder/img/volume_icon_onedrive.png +0 -0
  63. data/app/assets/javascripts/elfinder/img/volume_icon_onedrive.svg +1 -0
  64. data/app/assets/javascripts/elfinder/img/volume_icon_sql.png +0 -0
  65. data/app/assets/javascripts/elfinder/img/volume_icon_sql.svg +1 -0
  66. data/app/assets/javascripts/elfinder/img/volume_icon_trash.png +0 -0
  67. data/app/assets/javascripts/elfinder/img/volume_icon_trash.svg +1 -0
  68. data/app/assets/javascripts/elfinder/img/volume_icon_zip.png +0 -0
  69. data/app/assets/javascripts/elfinder/img/volume_icon_zip.svg +1 -0
  70. data/app/assets/javascripts/elfinder/js/elfinder.full.js +36019 -0
  71. data/app/assets/javascripts/elfinder/js/elfinder.min.js +25 -0
  72. data/app/assets/javascripts/elfinder/js/extras/editors.default.js +2643 -0
  73. data/app/assets/javascripts/elfinder/js/extras/editors.default.min.js +2 -0
  74. data/app/assets/javascripts/elfinder/js/extras/quicklook.googledocs.js +75 -0
  75. data/app/assets/javascripts/elfinder/js/extras/quicklook.googledocs.min.js +1 -0
  76. data/app/assets/javascripts/elfinder/js/i18n/elfinder.LANG.js +587 -0
  77. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ar.js +580 -0
  78. data/app/assets/javascripts/elfinder/js/i18n/elfinder.bg.js +559 -0
  79. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ca.js +375 -0
  80. data/app/assets/javascripts/elfinder/js/i18n/elfinder.cs.js +581 -0
  81. data/app/assets/javascripts/elfinder/js/i18n/elfinder.da.js +580 -0
  82. data/app/assets/javascripts/elfinder/js/i18n/elfinder.de.js +582 -0
  83. data/app/assets/javascripts/elfinder/js/i18n/elfinder.el.js +374 -0
  84. data/app/assets/javascripts/elfinder/js/i18n/elfinder.es.js +546 -0
  85. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fa.js +580 -0
  86. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fallback.js +11 -0
  87. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fo.js +419 -0
  88. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fr.js +578 -0
  89. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fr_CA.js +580 -0
  90. data/app/assets/javascripts/elfinder/js/i18n/elfinder.he.js +375 -0
  91. data/app/assets/javascripts/elfinder/js/i18n/elfinder.hr.js +434 -0
  92. data/app/assets/javascripts/elfinder/js/i18n/elfinder.hu.js +580 -0
  93. data/app/assets/javascripts/elfinder/js/i18n/elfinder.id.js +498 -0
  94. data/app/assets/javascripts/elfinder/js/i18n/elfinder.it.js +552 -0
  95. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ja.js +581 -0
  96. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ko.js +582 -0
  97. data/app/assets/javascripts/elfinder/js/i18n/elfinder.nl.js +581 -0
  98. data/app/assets/javascripts/elfinder/js/i18n/elfinder.no.js +374 -0
  99. data/app/assets/javascripts/elfinder/js/i18n/elfinder.pl.js +580 -0
  100. data/app/assets/javascripts/elfinder/js/i18n/elfinder.pt_BR.js +580 -0
  101. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ro.js +417 -0
  102. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ru.js +582 -0
  103. data/app/assets/javascripts/elfinder/js/i18n/elfinder.si.js +537 -0
  104. data/app/assets/javascripts/elfinder/js/i18n/elfinder.sk.js +581 -0
  105. data/app/assets/javascripts/elfinder/js/i18n/elfinder.sl.js +374 -0
  106. data/app/assets/javascripts/elfinder/js/i18n/elfinder.sr.js +374 -0
  107. data/app/assets/javascripts/elfinder/js/i18n/elfinder.sv.js +375 -0
  108. data/app/assets/javascripts/elfinder/js/i18n/elfinder.tr.js +583 -0
  109. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ug_CN.js +374 -0
  110. data/app/assets/javascripts/elfinder/js/i18n/elfinder.uk.js +580 -0
  111. data/app/assets/javascripts/elfinder/js/i18n/elfinder.vi.js +579 -0
  112. data/app/assets/javascripts/elfinder/js/i18n/elfinder.zh_CN.js +585 -0
  113. data/app/assets/javascripts/elfinder/js/i18n/elfinder.zh_TW.js +582 -0
  114. data/app/assets/javascripts/elfinder/js/i18n/help/cs.html.js +10 -0
  115. data/app/assets/javascripts/elfinder/js/i18n/help/de.html.js +15 -0
  116. data/app/assets/javascripts/elfinder/js/i18n/help/en.html.js +10 -0
  117. data/app/assets/javascripts/elfinder/js/i18n/help/es.html.js +10 -0
  118. data/app/assets/javascripts/elfinder/js/i18n/help/ja.html.js +10 -0
  119. data/app/assets/javascripts/elfinder/js/i18n/help/ko.html.js +10 -0
  120. data/app/assets/javascripts/elfinder/js/i18n/help/pl.html.js +10 -0
  121. data/app/assets/javascripts/elfinder/js/i18n/help/ru.html.js +10 -0
  122. data/app/assets/javascripts/elfinder/js/i18n/help/sk.html.js +10 -0
  123. data/app/assets/javascripts/elfinder/js/i18n/help/tr.html.js +10 -0
  124. data/app/assets/javascripts/elfinder/js/proxy/elFinderSupportVer1.js +408 -0
  125. data/app/assets/javascripts/elfinder/js/worker/calcfilehash.js +20 -0
  126. data/app/assets/javascripts/elfinder/js/worker/quicklook.tiff.js +7 -0
  127. data/app/assets/javascripts/elfinder/js/worker/quicklook.unzip.js +55 -0
  128. data/app/assets/javascripts/elfinder/main.default.js +175 -0
  129. data/app/assets/javascripts/elfinder/package.json +13 -0
  130. data/app/assets/javascripts/elfinder/php/MySQLStorage.sql +47 -0
  131. data/app/assets/javascripts/elfinder/php/autoload.php +56 -0
  132. data/app/assets/javascripts/elfinder/php/connector.maximal.php-dist +449 -0
  133. data/app/assets/javascripts/elfinder/php/connector.minimal.php-dist +180 -0
  134. data/app/assets/javascripts/elfinder/php/editors/OnlineConvert/editor.php +113 -0
  135. data/app/assets/javascripts/elfinder/php/editors/ZipArchive/editor.php +12 -0
  136. data/app/assets/javascripts/elfinder/php/editors/ZohoOffice/editor.php +206 -0
  137. data/app/assets/javascripts/elfinder/php/editors/editor.php +79 -0
  138. data/app/assets/javascripts/elfinder/php/elFinder.class.php +5401 -0
  139. data/app/assets/javascripts/elfinder/php/elFinderConnector.class.php +380 -0
  140. data/app/assets/javascripts/elfinder/php/elFinderFlysystemGoogleDriveNetmount.php +380 -0
  141. data/app/assets/javascripts/elfinder/php/elFinderPlugin.php +113 -0
  142. data/app/assets/javascripts/elfinder/php/elFinderSession.php +335 -0
  143. data/app/assets/javascripts/elfinder/php/elFinderSessionInterface.php +57 -0
  144. data/app/assets/javascripts/elfinder/php/elFinderVolumeBox.class.php +1972 -0
  145. data/app/assets/javascripts/elfinder/php/elFinderVolumeDriver.class.php +7651 -0
  146. data/app/assets/javascripts/elfinder/php/elFinderVolumeDropbox.class.php +1464 -0
  147. data/app/assets/javascripts/elfinder/php/elFinderVolumeDropbox2.class.php +1516 -0
  148. data/app/assets/javascripts/elfinder/php/elFinderVolumeFTP.class.php +1810 -0
  149. data/app/assets/javascripts/elfinder/php/elFinderVolumeGoogleDrive.class.php +2163 -0
  150. data/app/assets/javascripts/elfinder/php/elFinderVolumeGroup.class.php +315 -0
  151. data/app/assets/javascripts/elfinder/php/elFinderVolumeLocalFileSystem.class.php +1477 -0
  152. data/app/assets/javascripts/elfinder/php/elFinderVolumeMySQL.class.php +1022 -0
  153. data/app/assets/javascripts/elfinder/php/elFinderVolumeOneDrive.class.php +2131 -0
  154. data/app/assets/javascripts/elfinder/php/elFinderVolumeSFTPphpseclib.class.php +838 -0
  155. data/app/assets/javascripts/elfinder/php/elFinderVolumeTrash.class.php +51 -0
  156. data/app/assets/javascripts/elfinder/php/elFinderVolumeTrashMySQL.class.php +51 -0
  157. data/app/assets/javascripts/elfinder/php/libs/GdBmp.php +473 -0
  158. data/app/assets/javascripts/elfinder/php/mime.types +781 -0
  159. data/app/assets/javascripts/elfinder/php/plugins/AutoResize/plugin.php +151 -0
  160. data/app/assets/javascripts/elfinder/php/plugins/AutoRotate/plugin.php +148 -0
  161. data/app/assets/javascripts/elfinder/php/plugins/Normalizer/plugin.php +204 -0
  162. data/app/assets/javascripts/elfinder/php/plugins/Sanitizer/plugin.php +157 -0
  163. data/app/assets/javascripts/elfinder/php/plugins/Watermark/logo.png +0 -0
  164. data/app/assets/javascripts/elfinder/php/plugins/Watermark/plugin.php +432 -0
  165. data/app/assets/javascripts/elfinder/php/plugins/WinRemoveTailDots/plugin.php +114 -0
  166. data/app/assets/javascripts/elfinder/php/resources/image.png +0 -0
  167. data/app/assets/javascripts/elfinder/php/resources/video.png +0 -0
  168. data/app/assets/javascripts/elfinder/sounds/rm.wav +0 -0
  169. data/app/controllers/dc_elfinder_controller.rb +63 -0
  170. data/app/models/drgcms_form_fields/elfinder.rb +85 -0
  171. data/changelog.md +0 -0
  172. data/lib/drg_elfinder/engine.rb +5 -0
  173. data/lib/drg_elfinder/version.rb +3 -0
  174. data/lib/drg_elfinder.rb +9 -0
  175. data/lib/el_finder/action.rb +19 -0
  176. data/lib/el_finder/base64.rb +24 -0
  177. data/lib/el_finder/connector.rb +625 -0
  178. data/lib/el_finder/image.rb +33 -0
  179. data/lib/el_finder/mime_type.rb +86 -0
  180. data/lib/el_finder/pathname.rb +185 -0
  181. data/lib/el_finder/version.rb +5 -0
  182. data/lib/el_finder.rb +8 -0
  183. data/lib/patches/patch_for_elfinder.rb +115 -0
  184. data/lib/tasks/drg_elfinder_tasks.rake +10 -0
  185. metadata +245 -0
@@ -0,0 +1,838 @@
1
+ <?php
2
+
3
+ /**
4
+ * Simple elFinder driver for SFTP using phpseclib 1
5
+ *
6
+ * @author Dmitry (dio) Levashov
7
+ * @author Cem (discofever), sitecode
8
+ * @reference http://phpseclib.sourceforge.net/sftp/2.0/examples.html
9
+ **/
10
+ class elFinderVolumeSFTPphpseclib extends elFinderVolumeFTP {
11
+
12
+ /**
13
+ * Constructor
14
+ * Extend options with required fields
15
+ *
16
+ * @author Dmitry (dio) Levashov
17
+ * @author Cem (DiscoFever)
18
+ */
19
+ public function __construct()
20
+ {
21
+ $opts = array(
22
+ 'host' => 'localhost',
23
+ 'user' => '',
24
+ 'pass' => '',
25
+ 'port' => 22,
26
+ 'path' => '/',
27
+ 'timeout' => 20,
28
+ 'owner' => true,
29
+ 'tmbPath' => '',
30
+ 'tmpPath' => '',
31
+ 'separator' => '/',
32
+ 'phpseclibDir' => '../phpseclib/',
33
+ 'connectCallback' => null, //provide your own already instantiated phpseclib $Sftp object returned by this callback
34
+ //'connectCallback'=> function($options) {
35
+ // //load and instantiate phpseclib $sftp
36
+ // return $sftp;
37
+ // },
38
+ 'checkSubfolders' => -1,
39
+ 'dirMode' => 0755,
40
+ 'fileMode' => 0644,
41
+ 'rootCssClass' => 'elfinder-navbar-root-ftp',
42
+ );
43
+ $this->options = array_merge($this->options, $opts);
44
+ $this->options['mimeDetect'] = 'internal';
45
+ }
46
+
47
+ /**
48
+ * Prepare
49
+ * Call from elFinder::netmout() before volume->mount()
50
+ *
51
+ * @param $options
52
+ *
53
+ * @return array volume root options
54
+ * @author Naoki Sawada
55
+ */
56
+ public function netmountPrepare($options)
57
+ {
58
+ $options['statOwner'] = true;
59
+ $options['allowChmodReadOnly'] = true;
60
+ $options['acceptedName'] = '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#';
61
+ return $options;
62
+ }
63
+
64
+ /*********************************************************************/
65
+ /* INIT AND CONFIGURE */
66
+ /*********************************************************************/
67
+
68
+ /**
69
+ * Prepare SFTP connection
70
+ * Connect to remote server and check if credentials are correct, if so, store the connection
71
+ *
72
+ * @return bool
73
+ * @author Dmitry (dio) Levashov
74
+ * @author Cem (DiscoFever)
75
+ **/
76
+ protected function init()
77
+ {
78
+ if (!$this->options['connectCallback']) {
79
+ if (!$this->options['host']
80
+ || !$this->options['port']) {
81
+ return $this->setError('Required options undefined.');
82
+ }
83
+
84
+ if (!$this->options['path']) {
85
+ $this->options['path'] = '/';
86
+ }
87
+
88
+ // make net mount key
89
+ $this->netMountKey = md5(join('-', array('sftpphpseclib', $this->options['host'], $this->options['port'], $this->options['path'], $this->options['user'])));
90
+
91
+ set_include_path(get_include_path() . PATH_SEPARATOR . getcwd().'/'.$this->options['phpseclibDir']);
92
+ include_once('Net/SFTP.php');
93
+
94
+ if (!class_exists('Net_SFTP')) {
95
+ return $this->setError('SFTP extension not loaded. Install phpseclib version 1: http://phpseclib.sourceforge.net/ Set option "phpseclibDir" accordingly.');
96
+ }
97
+
98
+ // remove protocol from host
99
+ $scheme = parse_url($this->options['host'], PHP_URL_SCHEME);
100
+
101
+ if ($scheme) {
102
+ $this->options['host'] = substr($this->options['host'], strlen($scheme) + 3);
103
+ }
104
+ } else {
105
+ // make net mount key
106
+ $this->netMountKey = md5(join('-', array('sftpphpseclib', $this->options['path'])));
107
+ }
108
+
109
+ // normalize root path
110
+ $this->root = $this->options['path'] = $this->_normpath($this->options['path']);
111
+
112
+ if (empty($this->options['alias'])) {
113
+ $this->options['alias'] = $this->options['user'] . '@' . $this->options['host'];
114
+ if (!empty($this->options['netkey'])) {
115
+ elFinder::$instance->updateNetVolumeOption($this->options['netkey'], 'alias', $this->options['alias']);
116
+ }
117
+ }
118
+
119
+ $this->rootName = $this->options['alias'];
120
+ $this->options['separator'] = '/';
121
+
122
+ if (is_null($this->options['syncChkAsTs'])) {
123
+ $this->options['syncChkAsTs'] = true;
124
+ }
125
+
126
+ return $this->needOnline? $this->connect() : true;
127
+
128
+ }
129
+
130
+
131
+ /**
132
+ * Configure after successfull mount.
133
+ *
134
+ * @return void
135
+ * @throws elFinderAbortException
136
+ * @author Dmitry (dio) Levashov
137
+ */
138
+ protected function configure()
139
+ {
140
+ parent::configure();
141
+
142
+ if (!$this->tmp) {
143
+ $this->disabled[] = 'mkfile';
144
+ $this->disabled[] = 'paste';
145
+ $this->disabled[] = 'upload';
146
+ $this->disabled[] = 'edit';
147
+ //$this->disabled[] = 'archive';
148
+ //$this->disabled[] = 'extract';
149
+ }
150
+
151
+ $this->disabled[] = 'archive';
152
+ $this->disabled[] = 'extract';
153
+ }
154
+
155
+ /**
156
+ * Connect to sftp server
157
+ *
158
+ * @return bool
159
+ * @author sitecode
160
+ **/
161
+ protected function connect()
162
+ {
163
+ //use ca
164
+ if ($this->options['connectCallback']) {
165
+ $this->connect = $this->options['connectCallback']($this->options);
166
+ if (!$this->connect || !$this->connect->isConnected()) {
167
+ return $this->setError('Unable to connect successfully');
168
+ }
169
+
170
+ return true;
171
+ }
172
+
173
+ try{
174
+ $host = $this->options['host'] . ($this->options['port'] != 22 ? ':' . $this->options['port'] : '');
175
+ $this->connect = new Net_SFTP($host);
176
+ //TODO check fingerprint before login, fail if no match to last time
177
+ if (!$this->connect->login($this->options['user'], $this->options['pass'])) {
178
+ return $this->setError('Unable to connect to SFTP server ' . $host);
179
+ }
180
+ } catch (Exception $e) {
181
+ return $this->setError('Error while connecting to SFTP server ' . $host . ': ' . $e->getMessage());
182
+ }
183
+
184
+ if (!$this->connect->chdir($this->root)
185
+ /*|| $this->root != $this->connect->pwd()*/) {
186
+ //$this->umount();
187
+ return $this->setError('Unable to open root folder.');
188
+ }
189
+
190
+ return true;
191
+ }
192
+
193
+ /**
194
+ * Call rawlist
195
+ *
196
+ * @param string $path
197
+ *
198
+ * @return array
199
+ */
200
+ protected function ftpRawList($path)
201
+ {
202
+ return $this->connect->rawlist($path ?: '.') ?: [];
203
+ /*
204
+ $raw = $this->connect->rawlist($path ?: '.') ?: [];
205
+ $raw = array_map(function($key, $value) {
206
+ $value['name'] = $key;
207
+ return $value;
208
+ }, array_keys($raw), $raw);
209
+ return $raw;
210
+ */
211
+ }
212
+
213
+ /*********************************************************************/
214
+ /* FS API */
215
+ /*********************************************************************/
216
+
217
+ /**
218
+ * Close opened connection
219
+ *
220
+ * @return void
221
+ * @author Dmitry (dio) Levashov
222
+ **/
223
+ public function umount()
224
+ {
225
+ $this->connect && $this->connect->disconnect();
226
+ }
227
+
228
+
229
+ /**
230
+ * Parse line from rawlist() output and return file stat (array)
231
+ *
232
+ * @param string $raw line from rawlist() output
233
+ * @param $base
234
+ * @param bool $nameOnly
235
+ *
236
+ * @return array
237
+ * @author Dmitry Levashov
238
+ */
239
+ protected function parseRaw($raw, $base, $nameOnly = false)
240
+ {
241
+ $info = $raw;
242
+ $stat = array();
243
+
244
+ if ($info['filename'] == '.' || $info['filename'] == '..') {
245
+ return false;
246
+ }
247
+
248
+ $name = $info['filename'];
249
+
250
+ if (preg_match('|(.+)\-\>(.+)|', $name, $m)) {
251
+ $name = trim($m[1]);
252
+ // check recursive processing
253
+ if ($this->cacheDirTarget && $this->_joinPath($base, $name) !== $this->cacheDirTarget) {
254
+ return array();
255
+ }
256
+ if (!$nameOnly) {
257
+ $target = trim($m[2]);
258
+ if (substr($target, 0, 1) !== $this->separator) {
259
+ $target = $this->getFullPath($target, $base);
260
+ }
261
+ $target = $this->_normpath($target);
262
+ $stat['name'] = $name;
263
+ $stat['target'] = $target;
264
+ return $stat;
265
+ }
266
+ }
267
+
268
+ if ($nameOnly) {
269
+ return array('name' => $name);
270
+ }
271
+
272
+ $stat['ts'] = $info['mtime'];
273
+
274
+ if ($this->options['statOwner']) {
275
+ $stat['owner'] = $info['uid'];
276
+ $stat['group'] = $info['gid'];
277
+ $stat['perm'] = $info['permissions'];
278
+ $stat['isowner'] = isset($stat['owner']) ? ($this->options['owner'] ? true : ($stat['owner'] == $this->options['user'])) : true;
279
+ }
280
+
281
+ $owner_computed = isset($stat['isowner']) ? $stat['isowner'] : $this->options['owner'];
282
+ $perm = $this->parsePermissions($info['permissions'], $owner_computed);
283
+ $stat['name'] = $name;
284
+ $stat['mime'] = $info['type'] == NET_SFTP_TYPE_DIRECTORY ? 'directory' : $this->mimetype($stat['name'], true);
285
+ $stat['size'] = $stat['mime'] == 'directory' ? 0 : $info['size'];
286
+ $stat['read'] = $perm['read'];
287
+ $stat['write'] = $perm['write'];
288
+
289
+ return $stat;
290
+ }
291
+
292
+ /**
293
+ * Parse permissions string. Return array(read => true/false, write => true/false)
294
+ *
295
+ * @param int $perm
296
+ * The isowner parameter is computed by the caller.
297
+ * If the owner parameter in the options is true, the user is the actual owner of all objects even if the user used in the ftp Login
298
+ * is different from the file owner id.
299
+ * If the owner parameter is false to understand if the user is the file owner we compare the ftp user with the file owner id.
300
+ * @param Boolean $isowner . Tell if the current user is the owner of the object.
301
+ *
302
+ * @return array
303
+ * @author Dmitry (dio) Levashov
304
+ * @author sitecode
305
+ */
306
+ protected function parsePermissions($permissions, $isowner = true)
307
+ {
308
+ $permissions = decoct($permissions);
309
+ $perm = $isowner ? decbin($permissions[-3]) : decbin($permissions[-1]);
310
+
311
+ return array(
312
+ 'read' => $perm[-3],
313
+ 'write' => $perm[-2]
314
+ );
315
+ }
316
+
317
+ /**
318
+ * Cache dir contents
319
+ *
320
+ * @param string $path dir path
321
+ *
322
+ * @return void
323
+ * @author Dmitry Levashov, sitecode
324
+ **/
325
+ protected function cacheDir($path)
326
+ {
327
+ $this->dirsCache[$path] = array();
328
+ $hasDir = false;
329
+
330
+ $list = array();
331
+ $encPath = $this->convEncIn($path);
332
+ foreach ($this->ftpRawList($encPath) as $raw) {
333
+ if (($stat = $this->parseRaw($raw, $encPath))) {
334
+ $list[] = $stat;
335
+ }
336
+ }
337
+ $list = $this->convEncOut($list);
338
+ $prefix = ($path === $this->separator) ? $this->separator : $path . $this->separator;
339
+ $targets = array();
340
+ foreach ($list as $stat) {
341
+ $p = $prefix . $stat['name'];
342
+ if (isset($stat['target'])) {
343
+ // stat later
344
+ $targets[$stat['name']] = $stat['target'];
345
+ } else {
346
+ $stat = $this->updateCache($p, $stat);
347
+ if (empty($stat['hidden'])) {
348
+ if (!$hasDir && $stat['mime'] === 'directory') {
349
+ $hasDir = true;
350
+ }
351
+ $this->dirsCache[$path][] = $p;
352
+ }
353
+ }
354
+ }
355
+ // stat link targets
356
+ foreach ($targets as $name => $target) {
357
+ $stat = array();
358
+ $stat['name'] = $name;
359
+ $p = $prefix . $name;
360
+ $cacheDirTarget = $this->cacheDirTarget;
361
+ $this->cacheDirTarget = $this->convEncIn($target, true);
362
+ if ($tstat = $this->stat($target)) {
363
+ $stat['size'] = $tstat['size'];
364
+ $stat['alias'] = $target;
365
+ $stat['thash'] = $tstat['hash'];
366
+ $stat['mime'] = $tstat['mime'];
367
+ $stat['read'] = $tstat['read'];
368
+ $stat['write'] = $tstat['write'];
369
+
370
+ if (isset($tstat['ts'])) {
371
+ $stat['ts'] = $tstat['ts'];
372
+ }
373
+ if (isset($tstat['owner'])) {
374
+ $stat['owner'] = $tstat['owner'];
375
+ }
376
+ if (isset($tstat['group'])) {
377
+ $stat['group'] = $tstat['group'];
378
+ }
379
+ if (isset($tstat['perm'])) {
380
+ $stat['perm'] = $tstat['perm'];
381
+ }
382
+ if (isset($tstat['isowner'])) {
383
+ $stat['isowner'] = $tstat['isowner'];
384
+ }
385
+ } else {
386
+
387
+ $stat['mime'] = 'symlink-broken';
388
+ $stat['read'] = false;
389
+ $stat['write'] = false;
390
+ $stat['size'] = 0;
391
+
392
+ }
393
+ $this->cacheDirTarget = $cacheDirTarget;
394
+ $stat = $this->updateCache($p, $stat);
395
+ if (empty($stat['hidden'])) {
396
+ if (!$hasDir && $stat['mime'] === 'directory') {
397
+ $hasDir = true;
398
+ }
399
+ $this->dirsCache[$path][] = $p;
400
+ }
401
+ }
402
+
403
+ if (isset($this->sessionCache['subdirs'])) {
404
+ $this->sessionCache['subdirs'][$path] = $hasDir;
405
+ }
406
+ }
407
+
408
+
409
+ /***************** file stat ********************/
410
+
411
+ /**
412
+ * Return stat for given path.
413
+ * Stat contains following fields:
414
+ * - (int) size file size in b. required
415
+ * - (int) ts file modification time in unix time. required
416
+ * - (string) mime mimetype. required for folders, others - optionally
417
+ * - (bool) read read permissions. required
418
+ * - (bool) write write permissions. required
419
+ * - (bool) locked is object locked. optionally
420
+ * - (bool) hidden is object hidden. optionally
421
+ * - (string) alias for symlinks - link target path relative to root path. optionally
422
+ * - (string) target for symlinks - link target path. optionally
423
+ * If file does not exists - returns empty array or false.
424
+ *
425
+ * @param string $path file path
426
+ *
427
+ * @return array|false
428
+ * @author Dmitry (dio) Levashov
429
+ **/
430
+ protected function _stat($path)
431
+ {
432
+ $outPath = $this->convEncOut($path);
433
+ if (isset($this->cache[$outPath])) {
434
+ return $this->convEncIn($this->cache[$outPath]);
435
+ } else {
436
+ $this->convEncIn();
437
+ }
438
+ if ($path === $this->root) {
439
+ $res = array(
440
+ 'name' => $this->root,
441
+ 'mime' => 'directory',
442
+ 'dirs' => -1
443
+ );
444
+ if ($this->needOnline && (($this->ARGS['cmd'] === 'open' && $this->ARGS['target'] === $this->encode($this->root)) || $this->isMyReload())) {
445
+ $check = array(
446
+ 'ts' => true,
447
+ 'dirs' => true,
448
+ );
449
+ $ts = 0;
450
+ foreach ($this->ftpRawList($path) as $str) {
451
+ $info = preg_split('/\s+/', $str, 9);
452
+ if ($info[8] === '.') {
453
+ $info[8] = 'root';
454
+ if ($stat = $this->parseRaw(join(' ', $info), $path)) {
455
+ unset($stat['name']);
456
+ $res = array_merge($res, $stat);
457
+ if ($res['ts']) {
458
+ $ts = 0;
459
+ unset($check['ts']);
460
+ }
461
+ }
462
+ }
463
+ if ($check && ($stat = $this->parseRaw($str, $path))) {
464
+ if (isset($stat['ts']) && !empty($stat['ts'])) {
465
+ $ts = max($ts, $stat['ts']);
466
+ }
467
+ if (isset($stat['dirs']) && $stat['mime'] === 'directory') {
468
+ $res['dirs'] = 1;
469
+ unset($stat['dirs']);
470
+ }
471
+ if (!$check) {
472
+ break;
473
+ }
474
+ }
475
+ }
476
+ if ($ts) {
477
+ $res['ts'] = $ts;
478
+ }
479
+ $this->cache[$outPath] = $res;
480
+ }
481
+ return $res;
482
+ }
483
+
484
+ $pPath = $this->_dirname($path);
485
+ if ($this->_inPath($pPath, $this->root)) {
486
+ $outPPpath = $this->convEncOut($pPath);
487
+ if (!isset($this->dirsCache[$outPPpath])) {
488
+ $parentSubdirs = null;
489
+ if (isset($this->sessionCache['subdirs']) && isset($this->sessionCache['subdirs'][$outPPpath])) {
490
+ $parentSubdirs = $this->sessionCache['subdirs'][$outPPpath];
491
+ }
492
+ $this->cacheDir($outPPpath);
493
+ if ($parentSubdirs) {
494
+ $this->sessionCache['subdirs'][$outPPpath] = $parentSubdirs;
495
+ }
496
+ }
497
+ }
498
+
499
+ $stat = $this->convEncIn(isset($this->cache[$outPath]) ? $this->cache[$outPath] : array());
500
+ if (!$this->mounted) {
501
+ // dispose incomplete cache made by calling `stat` by 'startPath' option
502
+ $this->cache = array();
503
+ }
504
+
505
+ return $stat;
506
+ }
507
+
508
+ /**
509
+ * Return true if path is dir and has at least one childs directory
510
+ *
511
+ * @param string $path dir path
512
+ *
513
+ * @return bool
514
+ * @author Dmitry (dio) Levashov, sitecode
515
+ **/
516
+ protected function _subdirs($path)
517
+ {
518
+ foreach ($this->ftpRawList($path) as $info) {
519
+ $name = $info['filename'];
520
+ if ($name && $name !== '.' && $name !== '..' && $info['type'] == NET_SFTP_TYPE_DIRECTORY) {
521
+ return true;
522
+ }
523
+ }
524
+
525
+ return false;
526
+ }
527
+
528
+
529
+ /******************** file/dir content *********************/
530
+
531
+ /**
532
+ * Open file and return file pointer
533
+ *
534
+ * @param string $path file path
535
+ * @param string $mode
536
+ *
537
+ * @return false|resource
538
+ * @throws elFinderAbortException
539
+ * @internal param bool $write open file for writing
540
+ * @author Dmitry (dio) Levashov
541
+ */
542
+ protected function _fopen($path, $mode = 'rb')
543
+ {
544
+ if ($this->tmp) {
545
+ $local = $this->getTempFile($path);
546
+ $this->connect->get($path, $local);
547
+ return @fopen($local, $mode);
548
+ }
549
+
550
+ return false;
551
+ }
552
+
553
+ /**
554
+ * Close opened file
555
+ *
556
+ * @param resource $fp file pointer
557
+ * @param string $path
558
+ *
559
+ * @return void
560
+ * @author Dmitry (dio) Levashov
561
+ */
562
+ protected function _fclose($fp, $path = '')
563
+ {
564
+ is_resource($fp) && fclose($fp);
565
+ if ($path) {
566
+ unlink($this->getTempFile($path));
567
+ }
568
+ }
569
+
570
+
571
+ /******************** file/dir manipulations *************************/
572
+
573
+ /**
574
+ * Create dir and return created dir path or false on failed
575
+ *
576
+ * @param string $path parent dir path
577
+ * @param string $name new directory name
578
+ *
579
+ * @return string|bool
580
+ * @author Dmitry (dio) Levashov
581
+ **/
582
+ protected function _mkdir($path, $name)
583
+ {
584
+ $path = $this->_joinPath($path, $this->_basename($name));
585
+ if ($this->connect->mkdir($path) === false) {
586
+ return false;
587
+ }
588
+
589
+ $this->options['dirMode'] && $this->connect->chmod($this->options['dirMode'], $path);
590
+ return $path;
591
+ }
592
+
593
+ /**
594
+ * Create file and return it's path or false on failed
595
+ *
596
+ * @param string $path parent dir path
597
+ * @param string $name new file name
598
+ *
599
+ * @return string|bool
600
+ * @author sitecode
601
+ **/
602
+ protected function _mkfile($path, $name)
603
+ {
604
+ $path = $this->_joinPath($path, $this->_basename($name));
605
+ return $this->connect->put($path, '') ? $path : false;
606
+ /*
607
+ if ($this->tmp) {
608
+ $path = $this->_joinPath($path, $name);
609
+ $local = $this->getTempFile();
610
+ $res = touch($local) && $this->connect->put($path, $local, NET_SFTP_LOCAL_FILE);
611
+ unlink($local);
612
+ return $res ? $path : false;
613
+ }
614
+
615
+ return false;
616
+ */
617
+ }
618
+
619
+ /**
620
+ * Copy file into another file
621
+ *
622
+ * @param string $source source file path
623
+ * @param string $targetDir target directory path
624
+ * @param string $name new file name
625
+ *
626
+ * @return bool
627
+ * @author Dmitry (dio) Levashov, sitecode
628
+ **/
629
+ protected function _copy($source, $targetDir, $name)
630
+ {
631
+ $res = false;
632
+
633
+ $target = $this->_joinPath($targetDir, $this->_basename($name));
634
+ if ($this->tmp) {
635
+ $local = $this->getTempFile();
636
+
637
+ if ($this->connect->get($source, $local)
638
+ && $this->connect->put($target, $local, NET_SFTP_LOCAL_FILE)) {
639
+ $res = true;
640
+ }
641
+ unlink($local);
642
+ } else {
643
+ //not memory efficient
644
+ $res = $this->_filePutContents($target, $this->_getContents($source));
645
+ }
646
+
647
+ return $res;
648
+ }
649
+
650
+ /**
651
+ * Move file into another parent dir.
652
+ * Return new file path or false.
653
+ *
654
+ * @param string $source source file path
655
+ * @param $targetDir
656
+ * @param string $name file name
657
+ *
658
+ * @return bool|string
659
+ * @internal param string $target target dir path
660
+ * @author Dmitry (dio) Levashov
661
+ */
662
+ protected function _move($source, $targetDir, $name)
663
+ {
664
+ $target = $this->_joinPath($targetDir, $this->_basename($name));
665
+ return $this->connect->rename($source, $target) ? $target : false;
666
+ }
667
+
668
+ /**
669
+ * Remove file
670
+ *
671
+ * @param string $path file path
672
+ *
673
+ * @return bool
674
+ * @author Dmitry (dio) Levashov
675
+ **/
676
+ protected function _unlink($path)
677
+ {
678
+ return $this->connect->delete($path, false);
679
+ }
680
+
681
+ /**
682
+ * Remove dir
683
+ *
684
+ * @param string $path dir path
685
+ *
686
+ * @return bool
687
+ * @author Dmitry (dio) Levashov
688
+ **/
689
+ protected function _rmdir($path)
690
+ {
691
+ return $this->connect->delete($path);
692
+ }
693
+
694
+ /**
695
+ * Create new file and write into it from file pointer.
696
+ * Return new file path or false on error.
697
+ *
698
+ * @param resource $fp file pointer
699
+ * @param string $dir target dir path
700
+ * @param string $name file name
701
+ * @param array $stat file stat (required by some virtual fs)
702
+ *
703
+ * @return bool|string
704
+ * @author Dmitry (dio) Levashov
705
+ **/
706
+ protected function _save($fp, $dir, $name, $stat)
707
+ {
708
+ //TODO optionally encrypt $fp before uploading if mime is not already encrypted type
709
+ $path = $this->_joinPath($dir, $this->_basename($name));
710
+ return $this->connect->put($path, $fp)
711
+ ? $path
712
+ : false;
713
+ }
714
+
715
+ /**
716
+ * Get file contents
717
+ *
718
+ * @param string $path file path
719
+ *
720
+ * @return string|false
721
+ * @throws elFinderAbortException
722
+ * @author Dmitry (dio) Levashov
723
+ */
724
+ protected function _getContents($path)
725
+ {
726
+ return $this->connect->get($path);
727
+ }
728
+
729
+ /**
730
+ * Write a string to a file
731
+ *
732
+ * @param string $path file path
733
+ * @param string $content new file content
734
+ *
735
+ * @return bool
736
+ * @author Dmitry (dio) Levashov
737
+ **/
738
+ protected function _filePutContents($path, $content)
739
+ {
740
+ return $this->connect->put($path, $content);
741
+ }
742
+
743
+ /**
744
+ * chmod availability
745
+ *
746
+ * @param string $path
747
+ * @param string $mode
748
+ *
749
+ * @return bool
750
+ */
751
+ protected function _chmod($path, $mode)
752
+ {
753
+ $modeOct = is_string($mode) ? octdec($mode) : octdec(sprintf("%04o", $mode));
754
+ return $this->connect->chmod($modeOct, $path);
755
+ }
756
+
757
+ /**
758
+ * Extract files from archive
759
+ *
760
+ * @param string $path archive path
761
+ * @param array $arc archiver command and arguments (same as in $this->archivers)
762
+ *
763
+ * @return true
764
+ * @throws elFinderAbortException
765
+ * @author Dmitry (dio) Levashov,
766
+ * @author Alexey Sukhotin
767
+ */
768
+ protected function _extract($path, $arc)
769
+ {
770
+ return false; //TODO
771
+ }
772
+
773
+ /**
774
+ * Create archive and return its path
775
+ *
776
+ * @param string $dir target dir
777
+ * @param array $files files names list
778
+ * @param string $name archive name
779
+ * @param array $arc archiver options
780
+ *
781
+ * @return string|bool
782
+ * @throws elFinderAbortException
783
+ * @author Dmitry (dio) Levashov,
784
+ * @author Alexey Sukhotin
785
+ */
786
+ protected function _archive($dir, $files, $name, $arc)
787
+ {
788
+ return false; //TODO
789
+ }
790
+
791
+ /**
792
+ * Gets an array of absolute remote SFTP paths of files and
793
+ * folders in $remote_directory omitting symbolic links.
794
+ *
795
+ * @param $remote_directory string remote SFTP path to scan for file and folders recursively
796
+ * @param $targets array Array of target item. `null` is to get all of items
797
+ *
798
+ * @return array of elements each of which is an array of two elements:
799
+ * <ul>
800
+ * <li>$item['path'] - absolute remote SFTP path</li>
801
+ * <li>$item['type'] - either 'f' for file or 'd' for directory</li>
802
+ * </ul>
803
+ */
804
+ protected function ftp_scan_dir($remote_directory, $targets = null)
805
+ {
806
+ $buff = $this->ftpRawList($remote_directory);
807
+ $items = array();
808
+ if ($targets && is_array($targets)) {
809
+ $targets = array_flip($targets);
810
+ } else {
811
+ $targets = false;
812
+ }
813
+ foreach ($buff as $info) {
814
+ $name = $info['filename'];
815
+ if ($name !== '.' && $name !== '..' && (!$targets || isset($targets[$name]))) {
816
+ switch ($info['type']) {
817
+ case NET_SFTP_TYPE_SYMLINK : //omit symbolic links
818
+ case NET_SFTP_TYPE_DIRECTORY :
819
+ $remote_file_path = $this->_joinPath($remote_directory, $name);
820
+ $item = array();
821
+ $item['path'] = $remote_file_path;
822
+ $item['type'] = 'd'; // normal file
823
+ $items[] = $item;
824
+ $items = array_merge($items, $this->ftp_scan_dir($remote_file_path));
825
+ break;
826
+ default:
827
+ $remote_file_path = $this->_joinPath($remote_directory, $name);
828
+ $item = array();
829
+ $item['path'] = $remote_file_path;
830
+ $item['type'] = 'f'; // normal file
831
+ $items[] = $item;
832
+ }
833
+ }
834
+ }
835
+ return $items;
836
+ }
837
+
838
+ } // END class