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,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