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,1464 @@
1
+ <?php
2
+
3
+ elFinder::$netDrivers['dropbox'] = 'Dropbox';
4
+
5
+ /**
6
+ * Simple elFinder driver for FTP
7
+ *
8
+ * @author Dmitry (dio) Levashov
9
+ * @author Cem (discofever)
10
+ **/
11
+ class elFinderVolumeDropbox extends elFinderVolumeDriver {
12
+
13
+ /**
14
+ * Driver id
15
+ * Must be started from letter and contains [a-z0-9]
16
+ * Used as part of volume id
17
+ *
18
+ * @var string
19
+ **/
20
+ protected $driverId = 'd';
21
+
22
+ /**
23
+ * OAuth object
24
+ *
25
+ * @var oauth
26
+ **/
27
+ protected $oauth = null;
28
+
29
+ /**
30
+ * Dropbox object
31
+ *
32
+ * @var dropbox
33
+ **/
34
+ protected $dropbox = null;
35
+
36
+ /**
37
+ * Directory for meta data caches
38
+ * If not set driver not cache meta data
39
+ *
40
+ * @var string
41
+ **/
42
+ protected $metaCache = '';
43
+
44
+ /**
45
+ * Last API error message
46
+ *
47
+ * @var string
48
+ **/
49
+ protected $apiError = '';
50
+
51
+ /**
52
+ * Directory for tmp files
53
+ * If not set driver will try to use tmbDir as tmpDir
54
+ *
55
+ * @var string
56
+ **/
57
+ protected $tmp = '';
58
+
59
+ /**
60
+ * Dropbox.com uid
61
+ *
62
+ * @var string
63
+ **/
64
+ protected $dropboxUid = '';
65
+
66
+ /**
67
+ * Dropbox download host, replaces 'www.dropbox.com' of shares URL
68
+ *
69
+ * @var string
70
+ */
71
+ private $dropbox_dlhost = 'dl.dropboxusercontent.com';
72
+
73
+ private $dropbox_phpFound = false;
74
+
75
+ private $DB_TableName = '';
76
+
77
+ private $tmbPrefix = '';
78
+
79
+ /**
80
+ * Constructor
81
+ * Extend options with required fields
82
+ *
83
+ * @author Dmitry (dio) Levashov
84
+ * @author Cem (DiscoFever)
85
+ */
86
+ public function __construct() {
87
+
88
+ // check with composer
89
+ $this->dropbox_phpFound = class_exists('Dropbox_API');
90
+
91
+ if (! $this->dropbox_phpFound) {
92
+ // check with pear
93
+ if (include_once 'Dropbox/autoload.php') {
94
+ $this->dropbox_phpFound = in_array('Dropbox_autoload', spl_autoload_functions());
95
+ }
96
+ }
97
+
98
+ $opts = array(
99
+ 'consumerKey' => '',
100
+ 'consumerSecret' => '',
101
+ 'accessToken' => '',
102
+ 'accessTokenSecret' => '',
103
+ 'dropboxUid' => '',
104
+ 'root' => 'dropbox',
105
+ 'path' => '/',
106
+ 'separator' => '/',
107
+ 'PDO_DSN' => '', // if empty use 'sqlite:(metaCachePath|tmbPath)/elFinder_dropbox_db_(hash:dropboxUid+consumerSecret)'
108
+ 'PDO_User' => '',
109
+ 'PDO_Pass' => '',
110
+ 'PDO_Options' => array(),
111
+ 'PDO_DBName' => 'dropbox',
112
+ 'treeDeep' => 0,
113
+ 'tmbPath' => '',
114
+ 'tmbURL' => '',
115
+ 'tmpPath' => '',
116
+ 'getTmbSize' => 'large', // small: 32x32, medium or s: 64x64, large or m: 128x128, l: 640x480, xl: 1024x768
117
+ 'metaCachePath' => '',
118
+ 'metaCacheTime' => '600', // 10m
119
+ 'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#',
120
+ 'rootCssClass' => 'elfinder-navbar-root-dropbox'
121
+ );
122
+ $this->options = array_merge($this->options, $opts);
123
+ $this->options['mimeDetect'] = 'internal';
124
+ }
125
+
126
+ /**
127
+ * Prepare
128
+ * Call from elFinder::netmout() before volume->mount()
129
+ *
130
+ * @param $options
131
+ * @return Array
132
+ * @author Naoki Sawada
133
+ */
134
+ public function netmountPrepare($options) {
135
+ if (empty($options['consumerKey']) && defined('ELFINDER_DROPBOX_CONSUMERKEY')) $options['consumerKey'] = ELFINDER_DROPBOX_CONSUMERKEY;
136
+ if (empty($options['consumerSecret']) && defined('ELFINDER_DROPBOX_CONSUMERSECRET')) $options['consumerSecret'] = ELFINDER_DROPBOX_CONSUMERSECRET;
137
+
138
+ if ($options['user'] === 'init') {
139
+
140
+ if (! $this->dropbox_phpFound || empty($options['consumerKey']) || empty($options['consumerSecret']) || !class_exists('PDO', false)) {
141
+ return array('exit' => true, 'body' => '{msg:errNetMountNoDriver}');
142
+ }
143
+
144
+ if (defined('ELFINDER_DROPBOX_USE_CURL_PUT')) {
145
+ $this->oauth = new Dropbox_OAuth_Curl($options['consumerKey'], $options['consumerSecret']);
146
+ } else {
147
+ if (class_exists('OAuth', false)) {
148
+ $this->oauth = new Dropbox_OAuth_PHP($options['consumerKey'], $options['consumerSecret']);
149
+ } else {
150
+ if (! class_exists('HTTP_OAuth_Consumer')) {
151
+ // We're going to try to load in manually
152
+ include 'HTTP/OAuth/Consumer.php';
153
+ }
154
+ if (class_exists('HTTP_OAuth_Consumer', false)) {
155
+ $this->oauth = new Dropbox_OAuth_PEAR($options['consumerKey'], $options['consumerSecret']);
156
+ }
157
+ }
158
+ }
159
+
160
+ if (! $this->oauth) {
161
+ return array('exit' => true, 'body' => '{msg:errNetMountNoDriver}');
162
+ }
163
+
164
+ if ($options['pass'] === 'init') {
165
+ $html = '';
166
+ if ($sessionToken = $this->session->get('DropboxTokens')) {
167
+ // token check
168
+ try {
169
+ list(, $accessToken, $accessTokenSecret) = $sessionToken;
170
+ $this->oauth->setToken($accessToken, $accessTokenSecret);
171
+ $this->dropbox = new Dropbox_API($this->oauth, $this->options['root']);
172
+ $this->dropbox->getAccountInfo();
173
+ $script = '<script>
174
+ $("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "dropbox", mode: "done"});
175
+ </script>';
176
+ $html = $script;
177
+ } catch (Dropbox_Exception $e) {
178
+ $this->session->remove('DropboxTokens');
179
+ }
180
+ }
181
+ if (! $html) {
182
+ // get customdata
183
+ $cdata = '';
184
+ $innerKeys = array('cmd', 'host', 'options', 'pass', 'protocol', 'user');
185
+ $this->ARGS = $_SERVER['REQUEST_METHOD'] === 'POST'? $_POST : $_GET;
186
+ foreach($this->ARGS as $k => $v) {
187
+ if (! in_array($k, $innerKeys)) {
188
+ $cdata .= '&' . $k . '=' . rawurlencode($v);
189
+ }
190
+ }
191
+ if (strpos($options['url'], 'http') !== 0 ) {
192
+ $options['url'] = elFinder::getConnectorUrl();
193
+ }
194
+ $callback = $options['url']
195
+ . '?cmd=netmount&protocol=dropbox&host=dropbox.com&user=init&pass=return&node='.$options['id'].$cdata;
196
+
197
+ try {
198
+ $tokens = $this->oauth->getRequestToken();
199
+ $url= $this->oauth->getAuthorizeUrl(rawurlencode($callback));
200
+ } catch (Dropbox_Exception $e) {
201
+ return array('exit' => true, 'body' => '{msg:errAccess}');
202
+ }
203
+
204
+ $this->session->set('DropboxAuthTokens', $tokens);
205
+ $html = '<input id="elf-volumedriver-dropbox-host-btn" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" value="{msg:btnApprove}" type="button" onclick="window.open(\''.$url.'\')">';
206
+ $html .= '<script>
207
+ $("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "dropbox", mode: "makebtn"});
208
+ </script>';
209
+ }
210
+ return array('exit' => true, 'body' => $html);
211
+ } else {
212
+ $this->oauth->setToken($this->session->get('DropboxAuthTokens'));
213
+ $this->session->remove('DropboxAuthTokens');
214
+ $tokens = $this->oauth->getAccessToken();
215
+ $this->session->set('DropboxTokens', array($_GET['uid'], $tokens['token'], $tokens['token_secret']));
216
+
217
+ $out = array(
218
+ 'node' => $_GET['node'],
219
+ 'json' => '{"protocol": "dropbox", "mode": "done"}',
220
+ 'bind' => 'netmount'
221
+ );
222
+
223
+ return array('exit' => 'callback', 'out' => $out);
224
+ }
225
+ }
226
+ if ($sessionToken = $this->session->get('DropboxTokens')) {
227
+ list($options['dropboxUid'], $options['accessToken'], $options['accessTokenSecret']) = $sessionToken;
228
+ }
229
+ unset($options['user'], $options['pass']);
230
+ return $options;
231
+ }
232
+
233
+ /**
234
+ * process of on netunmount
235
+ * Drop table `dropbox` & rm thumbs
236
+ *
237
+ * @param $netVolumes
238
+ * @param $key
239
+ * @return bool
240
+ * @internal param array $options
241
+ */
242
+ public function netunmount($netVolumes, $key) {
243
+ $count = 0;
244
+ $dropboxUid = '';
245
+ if (isset($netVolumes[$key])) {
246
+ $dropboxUid = $netVolumes[$key]['dropboxUid'];
247
+ }
248
+ foreach($netVolumes as $volume) {
249
+ if ($volume['host'] === 'dropbox' && $volume['dropboxUid'] === $dropboxUid) {
250
+ $count++;
251
+ }
252
+ }
253
+ if ($count === 1) {
254
+ $this->DB->exec('drop table '.$this->DB_TableName);
255
+ foreach(glob(rtrim($this->options['tmbPath'], '\\/').DIRECTORY_SEPARATOR.$this->tmbPrefix.'*.png') as $tmb) {
256
+ unlink($tmb);
257
+ }
258
+ }
259
+ return true;
260
+ }
261
+
262
+ /*********************************************************************/
263
+ /* INIT AND CONFIGURE */
264
+ /*********************************************************************/
265
+
266
+ /**
267
+ * Prepare FTP connection
268
+ * Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn
269
+ *
270
+ * @return bool
271
+ * @author Dmitry (dio) Levashov
272
+ * @author Cem (DiscoFever)
273
+ **/
274
+ protected function init() {
275
+ if (!class_exists('PDO', false)) {
276
+ return $this->setError('PHP PDO class is require.');
277
+ }
278
+
279
+ if (!$this->options['consumerKey']
280
+ || !$this->options['consumerSecret']
281
+ || !$this->options['accessToken']
282
+ || !$this->options['accessTokenSecret']) {
283
+ return $this->setError('Required options undefined.');
284
+ }
285
+
286
+ if (empty($this->options['metaCachePath']) && defined('ELFINDER_DROPBOX_META_CACHE_PATH')) {
287
+ $this->options['metaCachePath'] = ELFINDER_DROPBOX_META_CACHE_PATH;
288
+ }
289
+
290
+ // make net mount key
291
+ $this->netMountKey = md5(join('-', array('dropbox', $this->options['path'])));
292
+
293
+ if (! $this->oauth) {
294
+ if (defined('ELFINDER_DROPBOX_USE_CURL_PUT')) {
295
+ $this->oauth = new Dropbox_OAuth_Curl($this->options['consumerKey'], $this->options['consumerSecret']);
296
+ } else {
297
+ if (class_exists('OAuth', false)) {
298
+ $this->oauth = new Dropbox_OAuth_PHP($this->options['consumerKey'], $this->options['consumerSecret']);
299
+ } else {
300
+ if (! class_exists('HTTP_OAuth_Consumer')) {
301
+ // We're going to try to load in manually
302
+ include 'HTTP/OAuth/Consumer.php';
303
+ }
304
+ if (class_exists('HTTP_OAuth_Consumer', false)) {
305
+ $this->oauth = new Dropbox_OAuth_PEAR($this->options['consumerKey'], $this->options['consumerSecret']);
306
+ }
307
+ }
308
+ }
309
+ }
310
+
311
+ if (! $this->oauth) {
312
+ return $this->setError('OAuth extension not loaded.');
313
+ }
314
+
315
+ // normalize root path
316
+ $this->root = $this->options['path'] = $this->_normpath($this->options['path']);
317
+
318
+ if (empty($this->options['alias'])) {
319
+ $this->options['alias'] = ($this->options['path'] === '/')? 'Dropbox.com' : 'Dropbox'.$this->options['path'];
320
+ }
321
+
322
+ $this->rootName = $this->options['alias'];
323
+
324
+ try {
325
+ $this->oauth->setToken($this->options['accessToken'], $this->options['accessTokenSecret']);
326
+ $this->dropbox = new Dropbox_API($this->oauth, $this->options['root']);
327
+ } catch (Dropbox_Exception $e) {
328
+ $this->session->remove('DropboxTokens');
329
+ return $this->setError('Dropbox error: '.$e->getMessage());
330
+ }
331
+
332
+ // user
333
+ if (empty($this->options['dropboxUid'])) {
334
+ try {
335
+ $res = $this->dropbox->getAccountInfo();
336
+ $this->options['dropboxUid'] = $res['uid'];
337
+ } catch (Dropbox_Exception $e) {
338
+ $this->session->remove('DropboxTokens');
339
+ return $this->setError('Dropbox error: '.$e->getMessage());
340
+ }
341
+ }
342
+
343
+ $this->dropboxUid = $this->options['dropboxUid'];
344
+ $this->tmbPrefix = 'dropbox'.base_convert($this->dropboxUid, 10, 32);
345
+
346
+ if (!empty($this->options['tmpPath'])) {
347
+ if ((is_dir($this->options['tmpPath']) || mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) {
348
+ $this->tmp = $this->options['tmpPath'];
349
+ }
350
+ }
351
+ if (!$this->tmp && is_writable($this->options['tmbPath'])) {
352
+ $this->tmp = $this->options['tmbPath'];
353
+ }
354
+ if (!$this->tmp && ($tmp = elFinder::getStaticVar('commonTempPath'))) {
355
+ $this->tmp = $tmp;
356
+ }
357
+
358
+ if (!empty($this->options['metaCachePath'])) {
359
+ if ((is_dir($this->options['metaCachePath']) || mkdir($this->options['metaCachePath'])) && is_writable($this->options['metaCachePath'])) {
360
+ $this->metaCache = $this->options['metaCachePath'];
361
+ }
362
+ }
363
+ if (!$this->metaCache && $this->tmp) {
364
+ $this->metaCache = $this->tmp;
365
+ }
366
+
367
+ if (!$this->metaCache) {
368
+ return $this->setError('Cache dirctory (metaCachePath or tmp) is require.');
369
+ }
370
+
371
+ // setup PDO
372
+ if (! $this->options['PDO_DSN']) {
373
+ $this->options['PDO_DSN'] = 'sqlite:'.$this->metaCache.DIRECTORY_SEPARATOR.'.elFinder_dropbox_db_'.md5($this->dropboxUid.$this->options['consumerSecret']);
374
+ }
375
+ // DataBase table name
376
+ $this->DB_TableName = $this->options['PDO_DBName'];
377
+ // DataBase check or make table
378
+ try {
379
+ $this->DB = new PDO($this->options['PDO_DSN'], $this->options['PDO_User'], $this->options['PDO_Pass'], $this->options['PDO_Options']);
380
+ if (! $this->checkDB()) {
381
+ return $this->setError('Can not make DB table');
382
+ }
383
+ } catch (PDOException $e) {
384
+ return $this->setError('PDO connection failed: '.$e->getMessage());
385
+ }
386
+
387
+ $res = $this->deltaCheck($this->isMyReload());
388
+ if ($res !== true) {
389
+ if (is_string($res)) {
390
+ return $this->setError($res);
391
+ } else {
392
+ return $this->setError('Could not check API "delta"');
393
+ }
394
+ }
395
+
396
+ if (is_null($this->options['syncChkAsTs'])) {
397
+ $this->options['syncChkAsTs'] = true;
398
+ }
399
+ if ($this->options['syncChkAsTs']) {
400
+ // 'tsPlSleep' minmum 5 sec
401
+ $this->options['tsPlSleep'] = max(5, $this->options['tsPlSleep']);
402
+ } else {
403
+ // 'lsPlSleep' minmum 10 sec
404
+ $this->options['lsPlSleep'] = max(10, $this->options['lsPlSleep']);
405
+ }
406
+
407
+ return true;
408
+ }
409
+
410
+
411
+ /**
412
+ * Configure after successful mount.
413
+ *
414
+ * @return string
415
+ * @author Dmitry (dio) Levashov
416
+ **/
417
+ protected function configure() {
418
+ parent::configure();
419
+
420
+ $this->disabled[] = 'archive';
421
+ $this->disabled[] = 'extract';
422
+ }
423
+
424
+ /**
425
+ * Check DB for delta cache
426
+ *
427
+ * @return bool
428
+ */
429
+ private function checkDB() {
430
+ $res = $this->query('SELECT * FROM sqlite_master WHERE type=\'table\' AND name=\''.$this->DB_TableName.'\'');
431
+ if ($res && isset($_REQUEST['init'])) {
432
+ // check is index(nameidx) UNIQUE?
433
+ $chk = $this->query('SELECT sql FROM sqlite_master WHERE type=\'index\' and name=\'nameidx\'');
434
+ if (!$chk || strpos(strtoupper($chk[0]), 'UNIQUE') === false) {
435
+ // remake
436
+ $this->DB->exec('DROP TABLE '.$this->DB_TableName);
437
+ $res = false;
438
+ }
439
+ }
440
+ if (! $res) {
441
+ try {
442
+ $this->DB->exec('CREATE TABLE '.$this->DB_TableName.'(path text, fname text, dat blob, isdir integer);');
443
+ $this->DB->exec('CREATE UNIQUE INDEX nameidx ON '.$this->DB_TableName.'(path, fname)');
444
+ $this->DB->exec('CREATE INDEX isdiridx ON '.$this->DB_TableName.'(isdir)');
445
+ } catch (PDOException $e) {
446
+ return $this->setError($e->getMessage());
447
+ }
448
+ }
449
+ return true;
450
+ }
451
+
452
+ /**
453
+ * DB query and fetchAll
454
+ *
455
+ * @param string $sql
456
+ * @return boolean|array
457
+ */
458
+ private function query($sql) {
459
+ if ($sth = $this->DB->query($sql)) {
460
+ $res = $sth->fetchAll(PDO::FETCH_COLUMN);
461
+ } else {
462
+ $res = false;
463
+ }
464
+ return $res;
465
+ }
466
+
467
+ /**
468
+ * Get dat(dropbox metadata) from DB
469
+ *
470
+ * @param string $path
471
+ * @return array dropbox metadata
472
+ */
473
+ private function getDBdat($path) {
474
+ if ($res = $this->query('select dat from '.$this->DB_TableName.' where path='.$this->DB->quote(strtolower($this->_dirname($path))).' and fname='.$this->DB->quote(strtolower($this->_basename($path))).' limit 1')) {
475
+ return unserialize($res[0]);
476
+ } else {
477
+ return array();
478
+ }
479
+ }
480
+
481
+ /**
482
+ * Update DB dat(dropbox metadata)
483
+ *
484
+ * @param string $path
485
+ * @param array $dat
486
+ * @return bool|array
487
+ */
488
+ private function updateDBdat($path, $dat) {
489
+ return $this->query('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($dat))
490
+ . ', isdir=' . ($dat['is_dir']? 1 : 0)
491
+ . ' where path='.$this->DB->quote(strtolower($this->_dirname($path))).' and fname='.$this->DB->quote(strtolower($this->_basename($path))));
492
+ }
493
+ /*********************************************************************/
494
+ /* FS API */
495
+ /*********************************************************************/
496
+
497
+ /**
498
+ * Close opened connection
499
+ *
500
+ * @return void
501
+ * @author Dmitry (dio) Levashov
502
+ **/
503
+ public function umount() {
504
+
505
+ }
506
+
507
+ /**
508
+ * Get delta data and DB update
509
+ *
510
+ * @param boolean $refresh force refresh
511
+ * @return true|string error message
512
+ */
513
+ protected function deltaCheck($refresh = true) {
514
+ $chk = false;
515
+ if (! $refresh && $chk = $this->query('select dat from '.$this->DB_TableName.' where path=\'\' and fname=\'\' limit 1')) {
516
+ $chk = unserialize($chk[0]);
517
+ }
518
+ if ($chk && ($chk['mtime'] + $this->options['metaCacheTime']) > $_SERVER['REQUEST_TIME']) {
519
+ return true;
520
+ }
521
+
522
+ try {
523
+ $more = true;
524
+ $this->DB->beginTransaction();
525
+
526
+ if ($res = $this->query('select dat from '.$this->DB_TableName.' where path=\'\' and fname=\'\' limit 1')) {
527
+ $res = unserialize($res[0]);
528
+ $cursor = $res['cursor'];
529
+ } else {
530
+ $cursor = '';
531
+ }
532
+ $delete = false;
533
+ $reset = false;
534
+ $ptimes = array();
535
+ $now = time();
536
+ do {
537
+ ini_set('max_execution_time', 120);
538
+ $_info = $this->dropbox->delta($cursor);
539
+ if (! empty($_info['reset'])) {
540
+ $this->DB->exec('TRUNCATE table '.$this->DB_TableName);
541
+ $this->DB->exec('insert into '.$this->DB_TableName.' values(\'\', \'\', \''.serialize(array('cursor' => '', 'mtime' => 0)).'\', 0);');
542
+ $this->DB->exec('insert into '.$this->DB_TableName.' values(\'/\', \'\', \''.serialize(array(
543
+ 'path' => '/',
544
+ 'is_dir' => 1,
545
+ 'mime_type' => '',
546
+ 'bytes' => 0
547
+ )).'\', 0);');
548
+ $reset = true;
549
+ }
550
+ $cursor = $_info['cursor'];
551
+
552
+ foreach($_info['entries'] as $entry) {
553
+ $key = strtolower($entry[0]);
554
+ $pkey = strtolower($this->_dirname($key));
555
+
556
+ $path = $this->DB->quote($pkey);
557
+ $fname = $this->DB->quote(strtolower($this->_basename($key)));
558
+ $where = 'where path='.$path.' and fname='.$fname;
559
+
560
+ if (empty($entry[1])) {
561
+ $ptimes[$pkey] = isset($ptimes[$pkey])? max(array($now, $ptimes[$pkey])) : $now;
562
+ $this->DB->exec('delete from '.$this->DB_TableName.' '.$where);
563
+ ! $delete && $delete = true;
564
+ continue;
565
+ }
566
+
567
+ $_itemTime = strtotime(isset($entry[1]['client_mtime'])? $entry[1]['client_mtime'] : $entry[1]['modified']);
568
+ $ptimes[$pkey] = isset($ptimes[$pkey])? max(array($_itemTime, $ptimes[$pkey])) : $_itemTime;
569
+ $sql = 'select path from '.$this->DB_TableName.' '.$where.' limit 1';
570
+ if (! $reset && $this->query($sql)) {
571
+ $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($entry[1])).', isdir='.($entry[1]['is_dir']? 1 : 0).' ' .$where);
572
+ } else {
573
+ $this->DB->exec('insert into '.$this->DB_TableName.' values ('.$path.', '.$fname.', '.$this->DB->quote(serialize($entry[1])).', '.(int)$entry[1]['is_dir'].')');
574
+ }
575
+ }
576
+ } while (! empty($_info['has_more']));
577
+
578
+ // update time stamp of parent holder
579
+ foreach ($ptimes as $_p => $_t) {
580
+ if ($praw = $this->getDBdat($_p)) {
581
+ $_update = false;
582
+ if (isset($praw['client_mtime']) && $_t > strtotime($praw['client_mtime'])) {
583
+ $praw['client_mtime'] = date('r', $_t);
584
+ $_update = true;
585
+ }
586
+ if (isset($praw['modified']) && $_t > strtotime($praw['modified'])) {
587
+ $praw['modified'] = date('r', $_t);
588
+ $_update = true;
589
+ }
590
+ if ($_update) {
591
+ $pwhere = 'where path='.$this->DB->quote(strtolower($this->_dirname($_p))).' and fname='.$this->DB->quote(strtolower($this->_basename($_p)));
592
+ $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($praw)).' '.$pwhere);
593
+ }
594
+ }
595
+ }
596
+
597
+ $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize(array('cursor'=>$cursor, 'mtime'=>$_SERVER['REQUEST_TIME']))).' where path=\'\' and fname=\'\'');
598
+ if (! $this->DB->commit()) {
599
+ $e = $this->DB->errorInfo();
600
+ return $e[2];
601
+ }
602
+ if ($delete) {
603
+ $this->DB->exec('vacuum');
604
+ }
605
+ } catch(Dropbox_Exception $e) {
606
+ return $e->getMessage();
607
+ }
608
+ return true;
609
+ }
610
+
611
+ /**
612
+ * Parse line from dropbox metadata output and return file stat (array)
613
+ *
614
+ * @param string $raw line from ftp_rawlist() output
615
+ * @return array
616
+ * @author Dmitry Levashov
617
+ **/
618
+ protected function parseRaw($raw) {
619
+ $stat = array();
620
+
621
+ $stat['rev'] = isset($raw['rev'])? $raw['rev'] : 'root';
622
+ $stat['name'] = $this->_basename($raw['path']);
623
+ $stat['mime'] = $raw['is_dir']? 'directory' : $raw['mime_type'];
624
+ $stat['size'] = $stat['mime'] == 'directory' ? 0 : $raw['bytes'];
625
+ $stat['ts'] = isset($raw['client_mtime'])? strtotime($raw['client_mtime']) :
626
+ (isset($raw['modified'])? strtotime($raw['modified']) : $_SERVER['REQUEST_TIME']);
627
+ $stat['dirs'] = 0;
628
+ if ($raw['is_dir']) {
629
+ $stat['dirs'] = (int)(bool)$this->query('select path from '.$this->DB_TableName.' where isdir=1 and path='.$this->DB->quote(strtolower($raw['path'])));
630
+ }
631
+
632
+ if (!empty($raw['url'])) {
633
+ $stat['url'] = $raw['url'];
634
+ } else if (! $this->disabledGetUrl) {
635
+ $stat['url'] = '1';
636
+ }
637
+ if (isset($raw['width'])) $stat['width'] = $raw['width'];
638
+ if (isset($raw['height'])) $stat['height'] = $raw['height'];
639
+
640
+ return $stat;
641
+ }
642
+
643
+ /**
644
+ * Cache dir contents
645
+ *
646
+ * @param string $path dir path
647
+ * @return string
648
+ * @author Dmitry Levashov
649
+ **/
650
+ protected function cacheDir($path) {
651
+ $this->dirsCache[$path] = array();
652
+ $hasDir = false;
653
+
654
+ $res = $this->query('select dat from '.$this->DB_TableName.' where path='.$this->DB->quote(strtolower($path)));
655
+
656
+ if ($res) {
657
+ foreach($res as $raw) {
658
+ $raw = unserialize($raw);
659
+ if ($stat = $this->parseRaw($raw)) {
660
+ $stat = $this->updateCache($raw['path'], $stat);
661
+ if (empty($stat['hidden']) && $path !== $raw['path']) {
662
+ if (! $hasDir && $stat['mime'] === 'directory') {
663
+ $hasDir = true;
664
+ }
665
+ $this->dirsCache[$path][] = $raw['path'];
666
+ }
667
+ }
668
+ }
669
+ }
670
+
671
+ if (isset($this->sessionCache['subdirs'])) {
672
+ $this->sessionCache['subdirs'][$path] = $hasDir;
673
+ }
674
+
675
+ return $this->dirsCache[$path];
676
+ }
677
+
678
+ /**
679
+ * Recursive files search
680
+ *
681
+ * @param string $path dir path
682
+ * @param string $q search string
683
+ * @param array $mimes
684
+ * @return array
685
+ * @author Naoki Sawada
686
+ **/
687
+ protected function doSearch($path, $q, $mimes) {
688
+ $result = array();
689
+ $sth = $this->DB->prepare('select dat from '.$this->DB_TableName.' WHERE path LIKE ? AND fname LIKE ?');
690
+ $sth->execute(array((($path === '/')? '' : strtolower($path)).'%', '%'.strtolower($q).'%'));
691
+ $res = $sth->fetchAll(PDO::FETCH_COLUMN);
692
+ $timeout = $this->options['searchTimeout']? $this->searchStart + $this->options['searchTimeout'] : 0;
693
+
694
+ if ($res) {
695
+ foreach($res as $raw) {
696
+ if ($timeout && $timeout < time()) {
697
+ $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($path)));
698
+ break;
699
+ }
700
+
701
+ $raw = unserialize($raw);
702
+ if ($stat = $this->parseRaw($raw)) {
703
+ if (!isset($this->cache[$raw['path']])) {
704
+ $stat = $this->updateCache($raw['path'], $stat);
705
+ }
706
+ if (!empty($stat['hidden']) || ($mimes && $stat['mime'] === 'directory') || !$this->mimeAccepted($stat['mime'], $mimes)) {
707
+ continue;
708
+ }
709
+ $stat = $this->stat($raw['path']);
710
+ $stat['path'] = $this->path($stat['hash']);
711
+ $result[] = $stat;
712
+ }
713
+ }
714
+ }
715
+ return $result;
716
+ }
717
+
718
+ /**
719
+ * Copy file/recursive copy dir only in current volume.
720
+ * Return new file path or false.
721
+ *
722
+ * @param string $src source path
723
+ * @param string $dst destination dir path
724
+ * @param string $name new file name (optionaly)
725
+ * @return string|false
726
+ * @author Dmitry (dio) Levashov
727
+ * @author Naoki Sawada
728
+ **/
729
+ protected function copy($src, $dst, $name) {
730
+
731
+ $this->clearcache();
732
+
733
+ return $this->_copy($src, $dst, $name)
734
+ ? $this->_joinPath($dst, $name)
735
+ : $this->setError(elFinder::ERROR_COPY, $this->_path($src));
736
+ }
737
+
738
+ /**
739
+ * Remove file/ recursive remove dir
740
+ *
741
+ * @param string $path file path
742
+ * @param bool $force try to remove even if file locked
743
+ * @param bool $recursive
744
+ * @return bool
745
+ * @author Dmitry (dio) Levashov
746
+ * @author Naoki Sawada
747
+ */
748
+ protected function remove($path, $force = false, $recursive = false) {
749
+ $stat = $this->stat($path);
750
+ $stat['realpath'] = $path;
751
+ $this->rmTmb($stat);
752
+ $this->clearcache();
753
+
754
+ if (empty($stat)) {
755
+ return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND);
756
+ }
757
+
758
+ if (!$force && !empty($stat['locked'])) {
759
+ return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path));
760
+ }
761
+
762
+ if ($stat['mime'] == 'directory') {
763
+ if (!$recursive && !$this->_rmdir($path)) {
764
+ return $this->setError(elFinder::ERROR_RM, $this->_path($path));
765
+ }
766
+ } else {
767
+ if (!$recursive && !$this->_unlink($path)) {
768
+ return $this->setError(elFinder::ERROR_RM, $this->_path($path));
769
+ }
770
+ }
771
+
772
+ $this->removed[] = $stat;
773
+ return true;
774
+ }
775
+
776
+ /**
777
+ * Create thumnbnail and return it's URL on success
778
+ *
779
+ * @param string $path file path
780
+ * @param $stat
781
+ * @return false|string
782
+ * @internal param string $mime file mime type
783
+ * @author Dmitry (dio) Levashov
784
+ * @author Naoki Sawada
785
+ */
786
+ protected function createTmb($path, $stat) {
787
+ if (!$stat || !$this->canCreateTmb($path, $stat)) {
788
+ return false;
789
+ }
790
+
791
+ $name = $this->tmbname($stat);
792
+ $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name;
793
+
794
+ // copy image into tmbPath so some drivers does not store files on local fs
795
+ if (! $data = $this->getThumbnail($path, $this->options['getTmbSize'])) {
796
+ return false;
797
+ }
798
+ if (! file_put_contents($tmb, $data)) {
799
+ return false;
800
+ }
801
+
802
+ $result = false;
803
+
804
+ $tmbSize = $this->tmbSize;
805
+
806
+ if (($s = getimagesize($tmb)) == false) {
807
+ return false;
808
+ }
809
+
810
+ /* If image smaller or equal thumbnail size - just fitting to thumbnail square */
811
+ if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) {
812
+ $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png' );
813
+
814
+ } else {
815
+
816
+ if ($this->options['tmbCrop']) {
817
+
818
+ /* Resize and crop if image bigger than thumbnail */
819
+ if (!(($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize) ) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) {
820
+ $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, false, 'png');
821
+ }
822
+
823
+ if (($s = getimagesize($tmb)) != false) {
824
+ $x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize)/2) : 0;
825
+ $y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize)/2) : 0;
826
+ $result = $this->imgCrop($tmb, $tmbSize, $tmbSize, $x, $y, 'png');
827
+ }
828
+
829
+ } else {
830
+ $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, true, 'png');
831
+ }
832
+
833
+ $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png' );
834
+ }
835
+
836
+ if (!$result) {
837
+ unlink($tmb);
838
+ return false;
839
+ }
840
+
841
+ return $name;
842
+ }
843
+
844
+ /**
845
+ * Return thumbnail file name for required file
846
+ *
847
+ * @param array $stat file stat
848
+ * @return string
849
+ * @author Dmitry (dio) Levashov
850
+ **/
851
+ protected function tmbname($stat) {
852
+ return $this->tmbPrefix.$stat['rev'].'.png';
853
+ }
854
+
855
+ /**
856
+ * Get thumbnail from dropbox.com
857
+ * @param string $path
858
+ * @param string $size
859
+ * @return string | boolean
860
+ */
861
+ protected function getThumbnail($path, $size = 'small') {
862
+ try {
863
+ return $this->dropbox->getThumbnail($path, $size);
864
+ } catch (Dropbox_Exception $e) {
865
+ return false;
866
+ }
867
+ }
868
+
869
+ /**
870
+ * Return content URL
871
+ *
872
+ * @param string $hash file hash
873
+ * @param array $options options
874
+ * @return array
875
+ * @author Naoki Sawada
876
+ **/
877
+ public function getContentUrl($hash, $options = array()) {
878
+ if (($file = $this->file($hash)) == false || !$file['url'] || $file['url'] == 1) {
879
+ $path = $this->decode($hash);
880
+ $cache = $this->getDBdat($path);
881
+ $url = '';
882
+ if (isset($cache['share']) && strpos($cache['share'], $this->dropbox_dlhost) !== false) {
883
+ $res = $this->getHttpResponseHeader($cache['share']);
884
+ if (preg_match("/^HTTP\/[01\.]+ ([0-9]{3})/", $res, $match)) {
885
+ if ($match[1] < 400) {
886
+ $url = $cache['share'];
887
+ }
888
+ }
889
+ }
890
+ if (! $url) {
891
+ try {
892
+ $res = $this->dropbox->share($path, null, false);
893
+ $url = $res['url'];
894
+ if (strpos($url, 'www.dropbox.com') === false) {
895
+ $res = $this->getHttpResponseHeader($url);
896
+ if (preg_match('/^location:\s*(http[^\s]+)/im', $res, $match)) {
897
+ $url = $match[1];
898
+ }
899
+ }
900
+ list($url) = explode('?', $url);
901
+ $url = str_replace('www.dropbox.com', $this->dropbox_dlhost, $url);
902
+ if (! isset($cache['share']) || $cache['share'] !== $url) {
903
+ $cache['share'] = $url;
904
+ $this->updateDBdat($path, $cache);
905
+ }
906
+ } catch (Dropbox_Exception $e) {
907
+ return false;
908
+ }
909
+ }
910
+ return $url;
911
+ }
912
+ return $file['url'];
913
+ }
914
+
915
+ /**
916
+ * Get HTTP request response header string
917
+ *
918
+ * @param string $url target URL
919
+ * @return string
920
+ * @author Naoki Sawada
921
+ */
922
+ private function getHttpResponseHeader($url) {
923
+ if (function_exists('curl_exec')) {
924
+
925
+ $c = curl_init();
926
+ curl_setopt( $c, CURLOPT_RETURNTRANSFER, true );
927
+ curl_setopt( $c, CURLOPT_CUSTOMREQUEST, 'HEAD' );
928
+ curl_setopt( $c, CURLOPT_HEADER, 1 );
929
+ curl_setopt( $c, CURLOPT_NOBODY, true );
930
+ curl_setopt( $c, CURLOPT_URL, $url );
931
+ $res = curl_exec( $c );
932
+
933
+ } else {
934
+
935
+ require_once 'HTTP/Request2.php';
936
+ try {
937
+ $request2 = new HTTP_Request2();
938
+ $request2->setConfig(array(
939
+ 'ssl_verify_peer' => false,
940
+ 'ssl_verify_host' => false
941
+ ));
942
+ $request2->setUrl($url);
943
+ $request2->setMethod(HTTP_Request2::METHOD_HEAD);
944
+ $result = $request2->send();
945
+ $res = array();
946
+ $res[] = 'HTTP/'.$result->getVersion().' '.$result->getStatus().' '.$result->getReasonPhrase();
947
+ foreach($result->getHeader() as $key => $val) {
948
+ $res[] = $key . ': ' . $val;
949
+ }
950
+ $res = join("\r\n", $res);
951
+ } catch( HTTP_Request2_Exception $e ){
952
+ $res = '';
953
+ } catch (Exception $e){
954
+ $res = '';
955
+ }
956
+
957
+ }
958
+ return $res;
959
+ }
960
+
961
+ /*********************** paths/urls *************************/
962
+
963
+ /**
964
+ * Return parent directory path
965
+ *
966
+ * @param string $path file path
967
+ * @return string
968
+ * @author Dmitry (dio) Levashov
969
+ **/
970
+ protected function _dirname($path) {
971
+ return $this->_normpath(substr($path, 0, strrpos($path, '/')));
972
+ }
973
+
974
+ /**
975
+ * Return file name
976
+ *
977
+ * @param string $path file path
978
+ * @return string
979
+ * @author Dmitry (dio) Levashov
980
+ **/
981
+ protected function _basename($path) {
982
+ return substr($path, strrpos($path, '/') + 1);
983
+ }
984
+
985
+ /**
986
+ * Join dir name and file name and retur full path
987
+ *
988
+ * @param string $dir
989
+ * @param string $name
990
+ * @return string
991
+ * @author Dmitry (dio) Levashov
992
+ **/
993
+ protected function _joinPath($dir, $name) {
994
+ return $this->_normpath($dir.'/'.$name);
995
+ }
996
+
997
+ /**
998
+ * Return normalized path, this works the same as os.path.normpath() in Python
999
+ *
1000
+ * @param string $path path
1001
+ * @return string
1002
+ * @author Troex Nevelin
1003
+ **/
1004
+ protected function _normpath($path) {
1005
+ $path = '/' . ltrim($path, '/');
1006
+ return $path;
1007
+ }
1008
+
1009
+ /**
1010
+ * Return file path related to root dir
1011
+ *
1012
+ * @param string $path file path
1013
+ * @return string
1014
+ * @author Dmitry (dio) Levashov
1015
+ **/
1016
+ protected function _relpath($path) {
1017
+ return $path;
1018
+ }
1019
+
1020
+ /**
1021
+ * Convert path related to root dir into real path
1022
+ *
1023
+ * @param string $path file path
1024
+ * @return string
1025
+ * @author Dmitry (dio) Levashov
1026
+ **/
1027
+ protected function _abspath($path) {
1028
+ return $path;
1029
+ }
1030
+
1031
+ /**
1032
+ * Return fake path started from root dir
1033
+ *
1034
+ * @param string $path file path
1035
+ * @return string
1036
+ * @author Dmitry (dio) Levashov
1037
+ **/
1038
+ protected function _path($path) {
1039
+ return $this->rootName . $this->_normpath(substr($path, strlen($this->root)));
1040
+ }
1041
+
1042
+ /**
1043
+ * Return true if $path is children of $parent
1044
+ *
1045
+ * @param string $path path to check
1046
+ * @param string $parent parent path
1047
+ * @return bool
1048
+ * @author Dmitry (dio) Levashov
1049
+ **/
1050
+ protected function _inpath($path, $parent) {
1051
+ return $path == $parent || strpos($path, $parent.'/') === 0;
1052
+ }
1053
+
1054
+ /***************** file stat ********************/
1055
+ /**
1056
+ * Return stat for given path.
1057
+ * Stat contains following fields:
1058
+ * - (int) size file size in b. required
1059
+ * - (int) ts file modification time in unix time. required
1060
+ * - (string) mime mimetype. required for folders, others - optionally
1061
+ * - (bool) read read permissions. required
1062
+ * - (bool) write write permissions. required
1063
+ * - (bool) locked is object locked. optionally
1064
+ * - (bool) hidden is object hidden. optionally
1065
+ * - (string) alias for symlinks - link target path relative to root path. optionally
1066
+ * - (string) target for symlinks - link target path. optionally
1067
+ *
1068
+ * If file does not exists - returns empty array or false.
1069
+ *
1070
+ * @param string $path file path
1071
+ * @return array|false
1072
+ * @author Dmitry (dio) Levashov
1073
+ **/
1074
+ protected function _stat($path) {
1075
+ //if (!empty($this->ARGS['reload']) && isset($this->ARGS['target']) && strpos($this->ARGS['target'], $this->id) === 0) {
1076
+ if ($this->isMyReload()) {
1077
+ $this->deltaCheck();
1078
+ }
1079
+ if ($raw = $this->getDBdat($path)) {
1080
+ return $this->parseRaw($raw);
1081
+ }
1082
+ return false;
1083
+ }
1084
+
1085
+ /**
1086
+ * Return true if path is dir and has at least one childs directory
1087
+ *
1088
+ * @param string $path dir path
1089
+ * @return bool
1090
+ * @author Dmitry (dio) Levashov
1091
+ **/
1092
+ protected function _subdirs($path) {
1093
+ return ($stat = $this->stat($path)) && isset($stat['dirs']) ? $stat['dirs'] : false;
1094
+ }
1095
+
1096
+ /**
1097
+ * Return object width and height
1098
+ * Ususaly used for images, but can be realize for video etc...
1099
+ *
1100
+ * @param string $path file path
1101
+ * @param string $mime file mime type
1102
+ * @return string
1103
+ * @author Dmitry (dio) Levashov
1104
+ **/
1105
+ protected function _dimensions($path, $mime) {
1106
+ if (strpos($mime, 'image') !== 0) return '';
1107
+ $cache = $this->getDBdat($path);
1108
+ if (isset($cache['width']) && isset($cache['height'])) {
1109
+ return $cache['width'].'x'.$cache['height'];
1110
+ }
1111
+ $ret = '';
1112
+ if ($work = $this->getWorkFile($path)) {
1113
+ if ($size = getimagesize($work)) {
1114
+ $cache['width'] = $size[0];
1115
+ $cache['height'] = $size[1];
1116
+ $this->updateDBdat($path, $cache);
1117
+ $ret = $size[0].'x'.$size[1];
1118
+ }
1119
+ }
1120
+ is_file($work) && unlink($work);
1121
+ return $ret;
1122
+ }
1123
+
1124
+ /******************** file/dir content *********************/
1125
+
1126
+ /**
1127
+ * Return files list in directory.
1128
+ *
1129
+ * @param string $path dir path
1130
+ * @return array
1131
+ * @author Dmitry (dio) Levashov
1132
+ * @author Cem (DiscoFever)
1133
+ **/
1134
+ protected function _scandir($path) {
1135
+ return isset($this->dirsCache[$path])
1136
+ ? $this->dirsCache[$path]
1137
+ : $this->cacheDir($path);
1138
+ }
1139
+
1140
+ /**
1141
+ * Open file and return file pointer
1142
+ *
1143
+ * @param string $path file path
1144
+ * @param string $mode
1145
+ * @return false|resource
1146
+ * @internal param bool $write open file for writing
1147
+ * @author Dmitry (dio) Levashov
1148
+ */
1149
+ protected function _fopen($path, $mode='rb') {
1150
+
1151
+ if (($mode == 'rb' || $mode == 'r')) {
1152
+ try {
1153
+ $res = $this->dropbox->media($path);
1154
+ $url = parse_url($res['url']);
1155
+ $fp = stream_socket_client('ssl://'.$url['host'].':443');
1156
+ fputs($fp, "GET {$url['path']} HTTP/1.0\r\n");
1157
+ fputs($fp, "Host: {$url['host']}\r\n");
1158
+ fputs($fp, "\r\n");
1159
+ while(trim(fgets($fp)) !== ''){};
1160
+ return $fp;
1161
+ } catch (Dropbox_Exception $e) {
1162
+ return false;
1163
+ }
1164
+ }
1165
+
1166
+ if ($this->tmp) {
1167
+ $contents = $this->_getContents($path);
1168
+
1169
+ if ($contents === false) {
1170
+ return false;
1171
+ }
1172
+
1173
+ if ($local = $this->getTempFile($path)) {
1174
+ if (file_put_contents($local, $contents, LOCK_EX) !== false) {
1175
+ return fopen($local, $mode);
1176
+ }
1177
+ }
1178
+ }
1179
+
1180
+ return false;
1181
+ }
1182
+
1183
+ /**
1184
+ * Close opened file
1185
+ *
1186
+ * @param resource $fp file pointer
1187
+ * @param string $path
1188
+ * @return bool
1189
+ * @author Dmitry (dio) Levashov
1190
+ */
1191
+ protected function _fclose($fp, $path='') {
1192
+ fclose($fp);
1193
+ if ($path) {
1194
+ unlink($this->getTempFile($path));
1195
+ }
1196
+ }
1197
+
1198
+ /******************** file/dir manipulations *************************/
1199
+
1200
+ /**
1201
+ * Create dir and return created dir path or false on failed
1202
+ *
1203
+ * @param string $path parent dir path
1204
+ * @param string $name new directory name
1205
+ * @return string|bool
1206
+ * @author Dmitry (dio) Levashov
1207
+ **/
1208
+ protected function _mkdir($path, $name) {
1209
+ $path = $this->_normpath($path.'/'.$name);
1210
+ try {
1211
+ $this->dropbox->createFolder($path);
1212
+ } catch (Dropbox_Exception $e) {
1213
+ $this->deltaCheck();
1214
+ if ($this->dir($this->encode($path))) {
1215
+ return $path;
1216
+ }
1217
+ return $this->setError('Dropbox error: '.$e->getMessage());
1218
+ }
1219
+ $this->deltaCheck();
1220
+ return $path;
1221
+ }
1222
+
1223
+ /**
1224
+ * Create file and return it's path or false on failed
1225
+ *
1226
+ * @param string $path parent dir path
1227
+ * @param string $name new file name
1228
+ * @return string|bool
1229
+ * @author Dmitry (dio) Levashov
1230
+ **/
1231
+ protected function _mkfile($path, $name) {
1232
+ return $this->_filePutContents($path.'/'.$name, '');
1233
+ }
1234
+
1235
+ /**
1236
+ * Create symlink. FTP driver does not support symlinks.
1237
+ *
1238
+ * @param string $target link target
1239
+ * @param string $path symlink path
1240
+ * @param string $name
1241
+ * @return bool
1242
+ * @author Dmitry (dio) Levashov
1243
+ */
1244
+ protected function _symlink($target, $path, $name) {
1245
+ return false;
1246
+ }
1247
+
1248
+ /**
1249
+ * Copy file into another file
1250
+ *
1251
+ * @param string $source source file path
1252
+ * @param string $targetDir target directory path
1253
+ * @param string $name new file name
1254
+ * @return bool
1255
+ * @author Dmitry (dio) Levashov
1256
+ **/
1257
+ protected function _copy($source, $targetDir, $name) {
1258
+ $path = $this->_normpath($targetDir.'/'.$name);
1259
+ try {
1260
+ $this->dropbox->copy($source, $path);
1261
+ } catch (Dropbox_Exception $e) {
1262
+ return $this->setError('Dropbox error: '.$e->getMessage());
1263
+ }
1264
+ $this->deltaCheck();
1265
+ return true;
1266
+ }
1267
+
1268
+ /**
1269
+ * Move file into another parent dir.
1270
+ * Return new file path or false.
1271
+ *
1272
+ * @param string $source source file path
1273
+ * @param $targetDir
1274
+ * @param string $name file name
1275
+ * @return bool|string
1276
+ * @internal param string $target target dir path
1277
+ * @author Dmitry (dio) Levashov
1278
+ */
1279
+ protected function _move($source, $targetDir, $name) {
1280
+ $target = $this->_normpath($targetDir.'/'.$name);
1281
+ try {
1282
+ $this->dropbox->move($source, $target);
1283
+ } catch (Dropbox_Exception $e) {
1284
+ return $this->setError('Dropbox error: '.$e->getMessage());
1285
+ }
1286
+ $this->deltaCheck();
1287
+ return $target;
1288
+ }
1289
+
1290
+ /**
1291
+ * Remove file
1292
+ *
1293
+ * @param string $path file path
1294
+ * @return bool
1295
+ * @author Dmitry (dio) Levashov
1296
+ **/
1297
+ protected function _unlink($path) {
1298
+ try {
1299
+ $this->dropbox->delete($path);
1300
+ } catch (Dropbox_Exception $e) {
1301
+ return $this->setError('Dropbox error: '.$e->getMessage());
1302
+ }
1303
+ $this->deltaCheck();
1304
+ return true;
1305
+ }
1306
+
1307
+ /**
1308
+ * Remove dir
1309
+ *
1310
+ * @param string $path dir path
1311
+ * @return bool
1312
+ * @author Dmitry (dio) Levashov
1313
+ **/
1314
+ protected function _rmdir($path) {
1315
+ return $this->_unlink($path);
1316
+ }
1317
+
1318
+ /**
1319
+ * Create new file and write into it from file pointer.
1320
+ * Return new file path or false on error.
1321
+ *
1322
+ * @param resource $fp file pointer
1323
+ * @param string $path
1324
+ * @param string $name file name
1325
+ * @param array $stat file stat (required by some virtual fs)
1326
+ * @return bool|string
1327
+ * @internal param string $dir target dir path
1328
+ * @author Dmitry (dio) Levashov
1329
+ */
1330
+ protected function _save($fp, $path, $name, $stat) {
1331
+ if ($name) $path .= '/'.$name;
1332
+ $path = $this->_normpath($path);
1333
+ try {
1334
+ $this->dropbox->putFile($path, $fp);
1335
+ } catch (Dropbox_Exception $e) {
1336
+ return $this->setError('Dropbox error: '.$e->getMessage());
1337
+ }
1338
+ $this->deltaCheck();
1339
+ if (is_array($stat)) {
1340
+ $raw = $this->getDBdat($path);
1341
+ if (isset($stat['width'])) $raw['width'] = $stat['width'];
1342
+ if (isset($stat['height'])) $raw['height'] = $stat['height'];
1343
+ $this->updateDBdat($path, $raw);
1344
+ }
1345
+ return $path;
1346
+ }
1347
+
1348
+ /**
1349
+ * Get file contents
1350
+ *
1351
+ * @param string $path file path
1352
+ * @return string|false
1353
+ * @author Dmitry (dio) Levashov
1354
+ **/
1355
+ protected function _getContents($path) {
1356
+ $contents = '';
1357
+ try {
1358
+ $contents = $this->dropbox->getFile($path);
1359
+ } catch (Dropbox_Exception $e) {
1360
+ return $this->setError('Dropbox error: '.$e->getMessage());
1361
+ }
1362
+ return $contents;
1363
+ }
1364
+
1365
+ /**
1366
+ * Write a string to a file
1367
+ *
1368
+ * @param string $path file path
1369
+ * @param string $content new file content
1370
+ * @return bool
1371
+ * @author Dmitry (dio) Levashov
1372
+ **/
1373
+ protected function _filePutContents($path, $content) {
1374
+ $res = false;
1375
+
1376
+ if ($local = $this->getTempFile($path)) {
1377
+ if (file_put_contents($local, $content, LOCK_EX) !== false
1378
+ && ($fp = fopen($local, 'rb'))) {
1379
+ clearstatcache();
1380
+ $res = $this->_save($fp, $path, '', array());
1381
+ fclose($fp);
1382
+ }
1383
+ file_exists($local) && unlink($local);
1384
+ }
1385
+
1386
+ return $res;
1387
+ }
1388
+
1389
+ /**
1390
+ * Detect available archivers
1391
+ *
1392
+ * @return array
1393
+ **/
1394
+ protected function _checkArchivers() {
1395
+ // die('Not yet implemented. (_checkArchivers)');
1396
+ return array();
1397
+ }
1398
+
1399
+ /**
1400
+ * chmod implementation
1401
+ *
1402
+ * @param string $path
1403
+ * @param string $mode
1404
+ * @return bool
1405
+ */
1406
+ protected function _chmod($path, $mode) {
1407
+ return false;
1408
+ }
1409
+
1410
+ /**
1411
+ * Unpack archive
1412
+ *
1413
+ * @param string $path archive path
1414
+ * @param array $arc archiver command and arguments (same as in $this->archivers)
1415
+ * @return true
1416
+ * @return void
1417
+ * @author Dmitry (dio) Levashov
1418
+ * @author Alexey Sukhotin
1419
+ **/
1420
+ protected function _unpack($path, $arc) {
1421
+ die('Not yet implemented. (_unpack)');
1422
+ }
1423
+
1424
+ /**
1425
+ * Recursive symlinks search
1426
+ *
1427
+ * @param string $path file/dir path
1428
+ * @return bool
1429
+ * @author Dmitry (dio) Levashov
1430
+ **/
1431
+ protected function _findSymlinks($path) {
1432
+ die('Not yet implemented. (_findSymlinks)');
1433
+ }
1434
+
1435
+ /**
1436
+ * Extract files from archive
1437
+ *
1438
+ * @param string $path archive path
1439
+ * @param array $arc archiver command and arguments (same as in $this->archivers)
1440
+ * @return true
1441
+ * @author Dmitry (dio) Levashov,
1442
+ * @author Alexey Sukhotin
1443
+ **/
1444
+ protected function _extract($path, $arc) {
1445
+ die('Not yet implemented. (_extract)');
1446
+
1447
+ }
1448
+
1449
+ /**
1450
+ * Create archive and return its path
1451
+ *
1452
+ * @param string $dir target dir
1453
+ * @param array $files files names list
1454
+ * @param string $name archive name
1455
+ * @param array $arc archiver options
1456
+ * @return string|bool
1457
+ * @author Dmitry (dio) Levashov,
1458
+ * @author Alexey Sukhotin
1459
+ **/
1460
+ protected function _archive($dir, $files, $name, $arc) {
1461
+ die('Not yet implemented. (_archive)');
1462
+ }
1463
+
1464
+ } // END class