]> git.mxchange.org Git - friendica-addons.git/blob - js_upload/js_upload.php
22948b1c7bda68f28093039bf38356fc95a526ec
[friendica-addons.git] / js_upload / js_upload.php
1 <?php
2 /**
3  * Name: JS Uploader
4  * Description: JavaScript photo/image uploader. Uses Valum 'qq' Uploader.
5  * Version: 1.0
6  * Author: Chris Case <http://friendika.openmindspace.org/profile/chris_case>
7  */
8
9 /**
10  *
11  * JavaScript Photo/Image Uploader
12  *
13  * Uses Valum 'qq' Uploader.
14  * Module Author: Chris Case
15  *
16  */
17
18 use Friendica\Core\Config;
19 use Friendica\Core\Hook;
20 use Friendica\Core\L10n;
21 use Friendica\Core\Logger;
22
23 function js_upload_install() {
24         Hook::register('photo_upload_form', 'addon/js_upload/js_upload.php', 'js_upload_form');
25         Hook::register('photo_post_init',   'addon/js_upload/js_upload.php', 'js_upload_post_init');
26         Hook::register('photo_post_file',   'addon/js_upload/js_upload.php', 'js_upload_post_file');
27         Hook::register('photo_post_end',    'addon/js_upload/js_upload.php', 'js_upload_post_end');
28 }
29
30
31 function js_upload_uninstall() {
32         Hook::unregister('photo_upload_form', 'addon/js_upload/js_upload.php', 'js_upload_form');
33         Hook::unregister('photo_post_init',   'addon/js_upload/js_upload.php', 'js_upload_post_init');
34         Hook::unregister('photo_post_file',   'addon/js_upload/js_upload.php', 'js_upload_post_file');
35         Hook::unregister('photo_post_end',    'addon/js_upload/js_upload.php', 'js_upload_post_end');
36 }
37
38
39 function js_upload_form(&$a,&$b) {
40
41         $b['default_upload'] = false;
42
43         $b['addon_text'] .= '<link href="' . $a->getBaseURL() . '/addon/js_upload/file-uploader/client/fileuploader.css" rel="stylesheet" type="text/css">';
44         $b['addon_text'] .= '<script src="' . $a->getBaseURL() . '/addon/js_upload/file-uploader/client/fileuploader.js" type="text/javascript"></script>';
45
46         $upload_msg = L10n::t('Select files for upload');
47         $drop_msg = L10n::t('Drop files here to upload');
48         $cancel = L10n::t('Cancel');
49         $failed = L10n::t('Failed');
50
51         $maximagesize = intval(Config::get('system','maximagesize'));
52
53         $b['addon_text'] .= <<< EOT
54
55  <div id="file-uploader-demo1">
56   <noscript>
57    <p>Please enable JavaScript to use file uploader.</p>
58    <!-- or put a simple form for upload here -->
59   </noscript>
60  </div>
61
62 <script type="text/javascript">
63 var uploader = null;
64 function getSelected(opt) {
65             var selected = new Array();
66             var index = 0;
67             for (var intLoop = 0; intLoop < opt.length; intLoop++) {
68                if ((opt[intLoop].selected) ||
69                    (opt[intLoop].checked)) {
70                   index = selected.length;
71                   //selected[index] = new Object;
72                   selected[index] = opt[intLoop].value;
73                   //selected[index] = intLoop;
74                }
75             }
76             return selected;
77          }
78 function createUploader() {
79         uploader = new qq.FileUploader({
80                 element: document.getElementById('file-uploader-demo1'),
81                 action: '{$b['post_url']}',
82
83         template: '<div class="qq-uploader">' +
84                 '<div class="qq-upload-drop-area"><span>$drop_msg</span></div>' +
85                 '<div class="qq-upload-button">$upload_msg</div>' +
86                 '<ul class="qq-upload-list"></ul>' +
87              '</div>',
88
89         // template for one item in file list
90         fileTemplate: '<li>' +
91                 '<span class="qq-upload-file"></span>' +
92                 '<span class="qq-upload-spinner"></span>' +
93                 '<span class="qq-upload-size"></span>' +
94                 '<a class="qq-upload-cancel" href="#">$cancel</a>' +
95                 '<span class="qq-upload-failed-text">$failed</span>' +
96             '</li>',
97
98                 debug: true,
99                 sizeLimit: $maximagesize,
100                 onSubmit: function(id,filename) {
101                         var newalbumElm = document.getElementById('photos-upload-newalbum');
102                         var albumElm = document.getElementById('photos-upload-album-select');
103
104                         var newalbum = newalbumElm ? newalbumElm.value : "";
105                         var album = albumElm ? albumElm.value : "";
106
107                         if (typeof acl != "undefined"){
108                                 uploader.setParams( {
109                                         newalbum      : newalbum,
110                                         album         : album,
111                                         not_visible   : document.getElementById('photos-upload-noshare').checked,
112                                         group_allow   : acl.allow_gid.join(','),
113                                         contact_allow : acl.allow_cid.join(','),
114                                         group_deny    : acl.deny_gid.join(','),
115                                         contact_deny  : acl.deny_cid.join(',')
116                                 });
117                         } else {
118                                 uploader.setParams( {
119                                         newalbum      : newalbum,
120                                         album         : album,
121                                         not_visible   : document.getElementById('photos-upload-noshare').checked,
122                                         group_allow   : getSelected(document.getElementById('group_allow')).join(','),
123                                         contact_allow : getSelected(document.getElementById('contact_allow')).join(','),
124                                         group_deny    : getSelected(document.getElementById('group_deny')).join(','),
125                                         contact_deny  : getSelected(document.getElementById('contact_deny')).join(',')
126                                 });
127                         }
128                 }
129         });
130 }
131
132
133 // in your app create uploader as soon as the DOM is ready
134 // don't wait for the window to load
135 window.onload = createUploader;
136
137
138 </script>
139
140 EOT;
141
142
143 }
144
145 function js_upload_post_init(&$a,&$b) {
146
147         // list of valid extensions, ex. array("jpeg", "xml", "bmp")
148
149         $allowedExtensions = ["jpeg","gif","png","jpg"];
150
151         // max file size in bytes
152
153         $sizeLimit = Config::get('system','maximagesize'); //6 * 1024 * 1024;
154
155         $uploader = new qqFileUploader($allowedExtensions, $sizeLimit);
156
157         $result = $uploader->handleUpload();
158
159
160         // to pass data through iframe you will need to encode all html tags
161         $a->data['upload_jsonresponse'] =  htmlspecialchars(json_encode($result), ENT_NOQUOTES);
162
163         if(isset($result['error'])) {
164                 Logger::log('mod/photos.php: photos_post(): error uploading photo: ' . $result['error'] , Logger::DEBUG);
165                 echo json_encode($result);
166                 exit();
167         }
168
169         $a->data['upload_result'] = $result;
170
171 }
172
173 function js_upload_post_file(&$a,&$b) {
174
175         $result = $a->data['upload_result'];
176
177         $b['src']               = $result['path'];
178         $b['filename']  = $result['filename'];
179         $b['filesize']  = filesize($b['src']);
180
181 }
182
183
184 function js_upload_post_end(&$a,&$b) {
185
186 Logger::log('upload_post_end');
187         if(!empty($a->data['upload_jsonresponse'])) {
188                 echo $a->data['upload_jsonresponse'];
189                 exit();
190         }
191
192 }
193
194
195 /**
196  * Handle file uploads via XMLHttpRequest
197  */
198 class qqUploadedFileXhr {
199
200         private $pathnm = '';
201
202     /**
203      * Save the file in the temp dir.
204      * @return boolean TRUE on success
205      */
206     function save() {
207         $input = fopen("php://input", "r");
208
209                 $upload_dir = Config::get('system','tempdir');
210                 if(! $upload_dir)
211                         $upload_dir = sys_get_temp_dir();
212
213         $this->pathnm = tempnam($upload_dir,'frn');
214
215                 $temp = fopen($this->pathnm,"w");
216         $realSize = stream_copy_to_stream($input, $temp);
217
218         fclose($input);
219                 fclose($temp);
220
221         if ($realSize != $this->getSize()){
222             return false;
223         }
224         return true;
225     }
226
227         function getPath() {
228                 return $this->pathnm;
229         }
230
231     function getName() {
232         return $_GET['qqfile'];
233     }
234
235     function getSize() {
236         if (isset($_SERVER["CONTENT_LENGTH"])){
237             return (int)$_SERVER["CONTENT_LENGTH"];
238         } else {
239             throw new Exception('Getting content length is not supported.');
240         }
241     }
242 }
243
244 /**
245  * Handle file uploads via regular form post (uses the $_FILES array)
246  */
247
248 class qqUploadedFileForm {
249
250
251     /**
252      * Save the file to the specified path
253      * @return boolean TRUE on success
254      */
255
256
257     function save() {
258         return true;
259     }
260
261         function getPath() {
262                 return $_FILES['qqfile']['tmp_name'];
263         }
264
265     function getName() {
266         return $_FILES['qqfile']['name'];
267     }
268     function getSize() {
269         return $_FILES['qqfile']['size'];
270     }
271 }
272
273 class qqFileUploader {
274     private $allowedExtensions = [];
275     private $sizeLimit = 10485760;
276     private $file;
277
278     function __construct(array $allowedExtensions = [], $sizeLimit = 10485760){
279         $allowedExtensions = array_map("strtolower", $allowedExtensions);
280
281         $this->allowedExtensions = $allowedExtensions;
282         $this->sizeLimit = $sizeLimit;
283
284         if (isset($_GET['qqfile'])) {
285             $this->file = new qqUploadedFileXhr();
286         } elseif (isset($_FILES['qqfile'])) {
287             $this->file = new qqUploadedFileForm();
288         } else {
289             $this->file = false;
290         }
291
292     }
293
294
295     private function toBytes($str){
296         $val = trim($str);
297         $last = strtolower($str[strlen($str)-1]);
298         switch($last) {
299             case 'g': $val *= 1024;
300             case 'm': $val *= 1024;
301             case 'k': $val *= 1024;
302         }
303         return $val;
304     }
305
306     /**
307      * Returns array('success'=>true) or array('error'=>'error message')
308      */
309     function handleUpload(){
310
311         if (!$this->file){
312             return ['error' => L10n::t('No files were uploaded.')];
313         }
314
315         $size = $this->file->getSize();
316
317         if ($size == 0) {
318             return ['error' => L10n::t('Uploaded file is empty')];
319         }
320
321 //        if ($size > $this->sizeLimit) {
322
323 //            return array('error' => L10n::t('Uploaded file is too large'));
324 //        }
325
326
327                 $maximagesize = Config::get('system','maximagesize');
328
329                 if(($maximagesize) && ($size > $maximagesize)) {
330                         return ['error' => L10n::t('Image exceeds size limit of ') . $maximagesize ];
331
332                 }
333
334         $pathinfo = pathinfo($this->file->getName());
335         $filename = $pathinfo['filename'];
336
337         if (!isset($pathinfo['extension'])) {
338                 Logger::warning('extension isn\'t set.', ['filename' => $filename]);
339                 }
340         $ext = defaults($pathinfo, 'extension', '');
341
342         if($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions)){
343             $these = implode(', ', $this->allowedExtensions);
344             return ['error' => L10n::t('File has an invalid extension, it should be one of ') . $these . '.'];
345         }
346
347         if ($this->file->save()){
348             return [
349                                 'success'=>true,
350                                 'path' => $this->file->getPath(),
351                                 'filename' => $filename . '.' . $ext
352                         ];
353         } else {
354             return [
355                                 'error'=> L10n::t('Upload was cancelled, or server error encountered'),
356                                 'path' => $this->file->getPath(),
357                                 'filename' => $filename . '.' . $ext
358                         ];
359         }
360
361     }
362 }