drg_elfinder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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