├── .gitignore ├── changelog.md ├── composer.json ├── config └── elfinder.php ├── readme.md ├── resources ├── assets │ └── js │ │ ├── standalonepopup.js │ │ ├── standalonepopup.min.js │ │ └── tiny_mce_popup.js └── views │ ├── .gitkeep │ ├── ckeditor4.blade.php │ ├── ckeditor4.php │ ├── elfinder.blade.php │ ├── elfinder.php │ ├── filepicker.blade.php │ ├── filepicker.php │ ├── standalonepopup.blade.php │ ├── standalonepopup.php │ ├── tinymce.blade.php │ ├── tinymce.php │ ├── tinymce4.blade.php │ ├── tinymce4.php │ ├── tinymce5.blade.php │ └── tinymce5.php └── src ├── Connector.php ├── Console └── PublishCommand.php ├── Elfinder.php ├── ElfinderController.php ├── ElfinderServiceProvider.php └── Session └── LaravelSession.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.phar 3 | composer.lock 4 | .DS_Store -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | [Next release] 6 | -------------- 7 | 8 | 9 | 2023-07-20, 0.5.3 10 | ------------------ 11 | 12 | - Update elfinder to 2.1.62 because CVE-2023-35840 13 | 14 | | studio-42/elfinder | 15 | | CVE | CVE-2023-35840 | 16 | | Title | elFinder vulnerable to path traversal in LocalVolumeDriver connector | 17 | | URL | https://github.com/advisories/GHSA-wm5g-p99q-66g4 | 18 | | Affected versions | <2.1.62 | 19 | | Reported at | 2023-06-14T16:37:01+00:00 20 | 21 | 22 | 2023-02-05, 0.5.2 23 | ------------------ 24 | 25 | Allow Laravel 10 26 | Laravel 10.x Compatibility (#321) 27 | 28 | * Bump dependencies for Laravel 10 29 | 30 | * Relax constraints 31 | 32 | 33 | 2022-03-15, 0.5.0 34 | ------------------ 35 | 36 | ### Changed 37 | - Drop support for Laravel 8.x and older (because of Flysystem v3) 38 | - Fix accessControl for disks 39 | - Change default dir to 'storage' instead of 'files' 40 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "barryvdh/laravel-elfinder", 3 | "keywords": [ 4 | "laravel", 5 | "elfinder", 6 | "tinymce", 7 | "filebrowser" 8 | ], 9 | "description": "A Laravel Package to integrate elFinder 2", 10 | "license": "MIT", 11 | "authors": [ 12 | { 13 | "name": "Barry vd. Heuvel", 14 | "email": "barryvdh@gmail.com" 15 | } 16 | ], 17 | "require": { 18 | "php": "^8.1", 19 | "illuminate/support": "^9|^10|^11.0|^12.0", 20 | "studio-42/elfinder": "~2.1.62", 21 | "barryvdh/elfinder-flysystem-driver": "^0.4.2|^0.5" 22 | }, 23 | "autoload": { 24 | "psr-4": { 25 | "Barryvdh\\Elfinder\\": "src/" 26 | } 27 | }, 28 | "extra": { 29 | "branch-alias": { 30 | "dev-master": "0.5-dev" 31 | }, 32 | "laravel": { 33 | "providers": [ 34 | "Barryvdh\\Elfinder\\ElfinderServiceProvider" 35 | ] 36 | } 37 | }, 38 | "minimum-stability": "dev" 39 | } 40 | -------------------------------------------------------------------------------- /config/elfinder.php: -------------------------------------------------------------------------------- 1 | ['storage'], 14 | 15 | /* 16 | |-------------------------------------------------------------------------- 17 | | Filesystem disks (Flysytem) 18 | |-------------------------------------------------------------------------- 19 | | 20 | | Define an array of Filesystem disks, which use Flysystem. 21 | | You can set extra options, example: 22 | | 23 | | 'my-disk' => [ 24 | | 'URL' => url('to/disk'), 25 | | 'alias' => 'Local storage', 26 | | ] 27 | */ 28 | 'disks' => [ 29 | 30 | ], 31 | 32 | /* 33 | |-------------------------------------------------------------------------- 34 | | Routes group config 35 | |-------------------------------------------------------------------------- 36 | | 37 | | The default group settings for the elFinder routes. 38 | | 39 | */ 40 | 41 | 'route' => [ 42 | 'prefix' => 'elfinder', 43 | 'middleware' => array('web', 'auth'), //Set to null to disable middleware filter 44 | ], 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Access filter 49 | |-------------------------------------------------------------------------- 50 | | 51 | | Filter callback to check the files 52 | | 53 | */ 54 | 55 | 'access' => 'Barryvdh\Elfinder\Elfinder::checkAccess', 56 | 57 | /* 58 | |-------------------------------------------------------------------------- 59 | | Roots 60 | |-------------------------------------------------------------------------- 61 | | 62 | | By default, the roots file is LocalFileSystem, with the above public dir. 63 | | If you want custom options, you can set your own roots below. 64 | | 65 | */ 66 | 67 | 'roots' => null, 68 | 69 | /* 70 | |-------------------------------------------------------------------------- 71 | | Options 72 | |-------------------------------------------------------------------------- 73 | | 74 | | These options are merged, together with 'roots' and passed to the Connector. 75 | | See https://github.com/Studio-42/elFinder/wiki/Connector-configuration-options-2.1 76 | | 77 | */ 78 | 79 | 'options' => array(), 80 | 81 | /* 82 | |-------------------------------------------------------------------------- 83 | | Root Options 84 | |-------------------------------------------------------------------------- 85 | | 86 | | These options are merged, together with every root by default. 87 | | See https://github.com/Studio-42/elFinder/wiki/Connector-configuration-options-2.1#root-options 88 | | 89 | */ 90 | 'root_options' => array( 91 | 92 | ), 93 | 94 | ); 95 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## elFinder Package for Laravel 2 | 3 | ### For Laravel 8.x and older, please use the latest 0.4 version. 4 | 5 | [![Packagist License](https://poser.pugx.org/barryvdh/laravel-elfinder/license.png)](http://choosealicense.com/licenses/mit/) 6 | [![Latest Stable Version](https://poser.pugx.org/barryvdh/laravel-elfinder/version.png)](https://packagist.org/packages/barryvdh/laravel-elfinder) 7 | [![Total Downloads](https://poser.pugx.org/barryvdh/laravel-elfinder/d/total.png)](https://packagist.org/packages/barryvdh/laravel-elfinder) 8 | 9 | This packages integrates [elFinder](https://github.com/Studio-42/elFinder), 10 | by making the php files available with Composer (+autoloading) and the assets with a publish command. It also provides some example views for standalone, tinymce and ckeditor. 11 | Files are updated from the a seperate [build repository](https://github.com/barryvdh/elfinder-builds) 12 | 13 | > Note: Use `php artisan elfinder:publish` instead of the old publish command, for future changes! 14 | 15 | ![image](https://user-images.githubusercontent.com/973269/158461690-2e6431a1-3a36-43f2-8219-0a21cee85ffc.png) 16 | 17 | ### Installation 18 | 19 | Require this package with Composer 20 | 21 | composer require barryvdh/laravel-elfinder 22 | 23 | 24 | You need to copy the assets to the public folder, using the following artisan command: 25 | 26 | php artisan elfinder:publish 27 | 28 | Remember to publish the assets after each update (or add the command to your post-update-cmd in composer.json) 29 | 30 | Routes are added in the ElfinderServiceProvider. You can set the group parameters for the routes in the configuration. 31 | You can change the prefix or filter/middleware for the routes. If you want full customisation, you can extend the ServiceProvider and override the `map()` function. 32 | 33 | ### Configuration 34 | 35 | The default configuration requires a directory called 'files' in the public folder. You can change this by publishing the config file. 36 | 37 | php artisan vendor:publish --provider='Barryvdh\Elfinder\ElfinderServiceProvider' --tag=config 38 | 39 | In your config/elfinder.php, you can change the default folder, the access callback or define your own roots. 40 | 41 | ### Views 42 | 43 | You can override the default views by copying the resources/views folder. You can also do that with the `vendor:publish` command: 44 | 45 | php artisan vendor:publish --provider='Barryvdh\Elfinder\ElfinderServiceProvider' --tag=views 46 | 47 | ### Using Filesystem disks 48 | 49 | Laravel has the ability to use Flysystem adapters as local/cloud disks. You can add those disks to elFinder, using the `disks` config. 50 | 51 | This examples adds the `local` disk and `my-disk`: 52 | 53 | ```php 54 | 'disks' => [ 55 | 'local', 56 | 'my-disk' => [ 57 | 'URL' => url('to/disk'), 58 | 'alias' => 'Local storage', 59 | ] 60 | ], 61 | ``` 62 | 63 | You can add an array to provide extra options, like the URL, alias etc. [Look here](https://github.com/Studio-42/elFinder/wiki/Connector-configuration-options-2.1#root-options) for all options. If you do not provide an URL, the URL will be generated by the disk itself. 64 | 65 | ### Using Glide for images 66 | 67 | See [elfinder-flysystem-driver](https://github.com/barryvdh/elfinder-flysystem-driver) for [Glide](http://glide.thephpleague.com/) usage. A basic example with a custom Laravel disk and Glide would be: 68 | 69 | 1. Add the disk to your apps config/filesystems disks: 70 | 71 | ```php 72 | 'public' => [ 73 | 'driver' => 'local', 74 | 'root' => base_path().'/public', 75 | ], 76 | ``` 77 | 78 | > Tip: you can use the `extend` method to register your own driver, if you want to use non-default Flysystem disks 79 | 80 | 2. Create a Glide Server for your disk, eg. on the `glide/` route, using a cache path: 81 | 82 | ```php 83 | Route::get('glide/{path}', function($path){ 84 | $server = \League\Glide\ServerFactory::create([ 85 | 'source' => app('filesystem')->disk('public')->getDriver(), 86 | 'cache' => storage_path('glide'), 87 | ]); 88 | return $server->getImageResponse($path, Input::query()); 89 | })->where('path', '.+'); 90 | ``` 91 | 92 | 4. Add the disk to your elfinder config: 93 | 94 | ```php 95 | 'disks' => [ 96 | 'public' => [ 97 | 'glideURL' => '/glide', 98 | ], 99 | ], 100 | ``` 101 | 102 | 5. (Optional) Add the `glideKey` also to the config, and verify the key in your glide route using the Glide HttpSignature. 103 | 104 | You should now see a root 'public' in elFinder with the files in your public folder, with thumbnails generated by Glide. 105 | URLs will also point to the Glide server, for images. 106 | 107 | ### TinyMCE 5.x 108 | 109 | You can use tinyMCE 5 integration with the following route `/elfinder/tinymce5`: 110 | 111 | ```php 112 | route('elfinder.tinymce5'); 113 | ``` 114 | 115 | In the TinyMCE init code, add the following line: 116 | 117 | ```javascript 118 | file_picker_callback : elFinderBrowser 119 | ``` 120 | 121 | Then add the following function (change the `elfinder_url` to the correct path on your system): 122 | 123 | ```javascript 124 | function elFinderBrowser (callback, value, meta) { 125 | tinymce.activeEditor.windowManager.openUrl({ 126 | title: 'File Manager', 127 | url: elfinder_url, 128 | /** 129 | * On message will be triggered by the child window 130 | * 131 | * @param dialogApi 132 | * @param details 133 | * @see https://www.tiny.cloud/docs/ui-components/urldialog/#configurationoptions 134 | */ 135 | onMessage: function (dialogApi, details) { 136 | if (details.mceAction === 'fileSelected') { 137 | const file = details.data.file; 138 | 139 | // Make file info 140 | const info = file.name; 141 | 142 | // Provide file and text for the link dialog 143 | if (meta.filetype === 'file') { 144 | callback(file.url, {text: info, title: info}); 145 | } 146 | 147 | // Provide image and alt text for the image dialog 148 | if (meta.filetype === 'image') { 149 | callback(file.url, {alt: info}); 150 | } 151 | 152 | // Provide alternative source and posted for the media dialog 153 | if (meta.filetype === 'media') { 154 | callback(file.url); 155 | } 156 | 157 | dialogApi.close(); 158 | } 159 | } 160 | }); 161 | } 162 | ``` 163 | 164 | ### TinyMCE 4.x 165 | 166 | You can use tinyMCE integration with the following route, which by default is `/elfinder/tinymce4`: 167 | 168 | ```php 169 | route('elfinder.tinymce4'); 170 | ``` 171 | 172 | In the TinyMCE init code, add the following line: 173 | 174 | ```javascript 175 | file_browser_callback : elFinderBrowser 176 | ``` 177 | 178 | Then add the following function (change the `elfinder_url` to the correct path on your system): 179 | 180 | ```javascript 181 | function elFinderBrowser (field_name, url, type, win) { 182 | tinymce.activeEditor.windowManager.open({ 183 | file: '',// use an absolute path! 184 | title: 'elFinder 2.0', 185 | width: 900, 186 | height: 450, 187 | resizable: 'yes' 188 | }, { 189 | setUrl: function (url) { 190 | win.document.getElementById(field_name).value = url; 191 | } 192 | }); 193 | return false; 194 | } 195 | ``` 196 | 197 | ### TinyMCE 3.x 198 | 199 | You can add tinyMCE integration with the following route (default: `/elfinder/tinymce`): 200 | 201 | route('elfinder.tinymce'); 202 | 203 | In the TinyMCE init code, add the following line: 204 | 205 | ```javascript 206 | file_browser_callback : 'elFinderBrowser' 207 | ``` 208 | 209 | Then add the following function (change the `elfinder_url` to the correct path on your system): 210 | 211 | ```javascript 212 | function elFinderBrowser (field_name, url, type, win) { 213 | var elfinder_url = '/elfinder/tinymce'; // use an absolute path! 214 | tinyMCE.activeEditor.windowManager.open({ 215 | file: elfinder_url, 216 | title: 'elFinder 2.0', 217 | width: 900, 218 | height: 450, 219 | resizable: 'yes', 220 | inline: 'yes', // This parameter only has an effect if you use the inlinepopups plugin! 221 | popup_css: false, // Disable TinyMCE's default popup CSS 222 | close_previous: 'no' 223 | }, { 224 | window: win, 225 | input: field_name 226 | }); 227 | return false; 228 | } 229 | ``` 230 | 231 | ### CKeditor 4.x 232 | 233 | You can add CKeditor integration with the following route: 234 | 235 | 'elfinder.ckeditor' 236 | 237 | In the CKeditor config file: 238 | 239 | ```javascript 240 | config.filebrowserBrowseUrl = '/elfinder/ckeditor'; 241 | ``` 242 | 243 | ### Standalone Popup Selector 244 | 245 | To use elFinder by using a href, button or other element to trigger a popup window, you will need to do the following. 246 | 247 | Add support for a popup window, we have used [Jacklmoore's jQuery colorbox](http://www.jacklmoore.com/colorbox/), (Not included), but you could use any other, obviously adjusting the following instructions accordingly. 248 | 249 | #### Add required routes 250 | 251 | You can add the popup with the following action: 252 | 253 | 'Barryvdh\Elfinder\ElfinderController@showPopup' 254 | 255 | #### Add the required resources 256 | 257 | Be Sure that you have published this packages public assets as described above. Then within the \ section of your page include the required colorbox styles (we suggest example1' styles, but any will do) 258 | 259 | ```html 260 | 261 | ``` 262 | 263 | Colorbox depends on jQuery, so ensure that you have it included within your page, then somewhere after your jQuery file has been included, add the script for jQuery Colorbox, such as... 264 | 265 | ```html 266 | 267 | ``` 268 | 269 | Now add a link to the popup script, just before the close of your \ tag. A non-minified version is also provided, for if you wish to modify the colorbox config. Simply copy to your assets location, and adjust/minify as desired. 270 | 271 | ```html 272 | 273 | ``` 274 | 275 | #### Usage 276 | 277 | In order to use the finder to populate an input, simply add your input that you wish to be populated, ensuring to use an ID (This will be used to update the value once a file/image has been selected)...... 278 | 279 | ```html 280 | 281 | 282 | ``` 283 | 284 | Now just add the element that you wish to use to trigger the popup, ensuring to add the class ```popup_selector``` and the ```data-inputid``` atribute containing the value matching the id of your input you wish to be populated, as below. 285 | 286 | ```html 287 | Select Image 288 | ``` 289 | 290 | You can have as many elements as you wish on the page, just be sure to provide each with a unique ID, and set the data-updateid attribute on the selector accordingly. 291 | -------------------------------------------------------------------------------- /resources/assets/js/standalonepopup.js: -------------------------------------------------------------------------------- 1 | $(document).on('click','.popup_selector',function (event) { 2 | event.preventDefault(); 3 | var updateID = $(this).attr('data-inputid'); // Btn id clicked 4 | var elfinderUrl = '/elfinder/popup/'; 5 | 6 | // trigger the reveal modal with elfinder inside 7 | var triggerUrl = elfinderUrl + updateID; 8 | $.colorbox({ 9 | href: triggerUrl, 10 | fastIframe: true, 11 | iframe: true, 12 | width: '70%', 13 | height: '50%' 14 | }); 15 | 16 | }); 17 | // function to update the file selected by elfinder 18 | function processSelectedFile(filePath, requestingField) { 19 | $('#' + requestingField).val(filePath).trigger('change'); 20 | } 21 | -------------------------------------------------------------------------------- /resources/assets/js/standalonepopup.min.js: -------------------------------------------------------------------------------- 1 | function processSelectedFile(e,t){$("#"+t).val(e)}$(document).on("click",".popup_selector",function(e){e.preventDefault();var t=$(this).attr("data-inputid");var n="/elfinder/popup/";var r=n+t;$.colorbox({href:r,fastIframe:true,iframe:true,width:"70%",height:"50%"})}) 2 | -------------------------------------------------------------------------------- /resources/assets/js/tiny_mce_popup.js: -------------------------------------------------------------------------------- 1 | // Copy from https://github.com/tinymce/tinymce/blob/3.x/jscripts/tiny_mce/tiny_mce_popup.js 2 | // See the GNU LESSER GENERAL PUBLIC LICENSE here: https://github.com/tinymce/tinymce/blob/3.x/jscripts/tiny_mce/license.txt 3 | // Uncomment and change this document.domain value if you are loading the script cross subdomains 4 | // document.domain = 'moxiecode.com'; 5 | 6 | var tinymce=null,tinyMCEPopup,tinyMCE;tinyMCEPopup={init:function(){var b=this,a,c;a=b.getWin();tinymce=a.tinymce;tinyMCE=a.tinyMCE;b.editor=tinymce.EditorManager.activeEditor;b.params=b.editor.windowManager.params;b.features=b.editor.windowManager.features;b.dom=b.editor.windowManager.createInstance("tinymce.dom.DOMUtils",document,{ownEvents:true,proxy:tinyMCEPopup._eventProxy});b.dom.bind(window,"ready",b._onDOMLoaded,b);if(b.features.popup_css!==false){b.dom.loadCSS(b.features.popup_css||b.editor.settings.popup_css)}b.listeners=[];b.onInit={add:function(e,d){b.listeners.push({func:e,scope:d})}};b.isWindow=!b.getWindowArg("mce_inline");b.id=b.getWindowArg("mce_window_id");b.editor.windowManager.onOpen.dispatch(b.editor.windowManager,window)},getWin:function(){return(!window.frameElement&&window.dialogArguments)||opener||parent||top},getWindowArg:function(c,b){var a=this.params[c];return tinymce.is(a)?a:b},getParam:function(b,a){return this.editor.getParam(b,a)},getLang:function(b,a){return this.editor.getLang(b,a)},execCommand:function(d,c,e,b){b=b||{};b.skip_focus=1;this.restoreSelection();return this.editor.execCommand(d,c,e,b)},resizeToInnerSize:function(){var a=this;setTimeout(function(){var b=a.dom.getViewPort(window);a.editor.windowManager.resizeBy(a.getWindowArg("mce_width")-b.w,a.getWindowArg("mce_height")-b.h,a.id||window)},10)},executeOnLoad:function(s){this.onInit.add(function(){eval(s)})},storeSelection:function(){this.editor.windowManager.bookmark=tinyMCEPopup.editor.selection.getBookmark(1)},restoreSelection:function(){var a=tinyMCEPopup;if(!a.isWindow&&tinymce.isIE){a.editor.selection.moveToBookmark(a.editor.windowManager.bookmark)}},requireLangPack:function(){var b=this,a=b.getWindowArg("plugin_url")||b.getWindowArg("theme_url");if(a&&b.editor.settings.language&&b.features.translate_i18n!==false&&b.editor.settings.language_load!==false){a+="/langs/"+b.editor.settings.language+"_dlg.js";if(!tinymce.ScriptLoader.isDone(a)){document.write(' 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | @if($locale) 20 | 21 | 22 | @endif 23 | 24 | 25 | 54 | 55 | 56 | 57 | 58 |
59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /resources/views/ckeditor4.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 54 | 55 | 56 | 57 | 58 |
59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /resources/views/elfinder.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | @if($locale) 20 | 21 | 22 | @endif 23 | 24 | 25 | 42 | 43 | 44 | 45 | 46 |
47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /resources/views/elfinder.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 42 | 43 | 44 | 45 | 46 |
47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /resources/views/filepicker.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | @if($locale) 20 | 21 | 22 | @endif 23 | 24 | 25 | 75 | 76 | 77 | 78 | 79 |
80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /resources/views/filepicker.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 75 | 76 | 77 | 78 | 79 | 80 |
81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /resources/views/standalonepopup.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | @if($locale) 20 | 21 | 22 | @endif 23 | 24 | 25 | 51 | 52 | 53 | 54 | 55 | 56 |
57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /resources/views/standalonepopup.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 52 | 53 | 54 | 55 | 56 | 57 |
58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /resources/views/tinymce.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | @if($locale) 23 | 24 | 25 | @endif 26 | 27 | 28 | 75 | 76 | 77 | 78 | 79 | 80 |
81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /resources/views/tinymce.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 74 | 75 | 76 | 77 | 78 | 79 |
80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /resources/views/tinymce4.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | @if($locale) 20 | 21 | 22 | @endif 23 | 24 | 25 | 56 | 57 | 58 | 59 | 60 |
61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /resources/views/tinymce4.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 56 | 57 | 58 | 59 | 60 |
61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /resources/views/tinymce5.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | @if($locale) 20 | 21 | 22 | @endif 23 | 24 | 25 | 57 | 58 | 59 | 60 | 61 |
62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /resources/views/tinymce5.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 57 | 58 | 59 | 60 | 61 |
62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/Connector.php: -------------------------------------------------------------------------------- 1 | response; 22 | } 23 | 24 | /** 25 | * Output json 26 | * 27 | * @param array data to output 28 | * @return void 29 | * @author Dmitry (dio) Levashov 30 | **/ 31 | protected function output(array $data) { 32 | 33 | $header = isset($data['header']) ? $data['header'] : $this->header; 34 | unset($data['header']); 35 | 36 | $headers = array(); 37 | if($header){ 38 | foreach((array) $header as $headerString){ 39 | if(strpos($headerString, ':') !== false){ 40 | list($key, $value) = explode(':', $headerString, 2); 41 | $headers[$key] = $value; 42 | } 43 | } 44 | } 45 | 46 | if (isset($data['pointer'])) { 47 | $this->response = new StreamedResponse(function () use($data) { 48 | if (stream_get_meta_data($data['pointer'])['seekable']) { 49 | rewind($data['pointer']); 50 | } 51 | fpassthru($data['pointer']); 52 | if (!empty($data['volume'])) { 53 | $data['volume']->close($data['pointer'], $data['info']['hash']); 54 | } 55 | }, 200, $headers); 56 | } else { 57 | if (!empty($data['raw']) && !empty($data['error'])) { 58 | $this->response = new JsonResponse($data['error'], 500); 59 | } else { 60 | $this->response = new JsonResponse($data, 200, $headers); 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Console/PublishCommand.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class PublishCommand extends Command { 13 | 14 | /** 15 | * The console command name. 16 | * 17 | * @var string 18 | */ 19 | protected $name = 'elfinder:publish'; 20 | 21 | /** 22 | * The console command description. 23 | * 24 | * @var string 25 | */ 26 | protected $description = 'Publish the elFinder assets'; 27 | 28 | /** @var Filesystem $fs */ 29 | protected $files; 30 | 31 | protected $publishPath; 32 | 33 | /** 34 | * Create a new Publish command 35 | * 36 | * @param \Illuminate\Filesystem\Filesystem $files 37 | * @param string $publishPath 38 | */ 39 | public function __construct($files, $publishPath) 40 | { 41 | parent::__construct(); 42 | 43 | $this->files = $files; 44 | $this->publishPath = $publishPath; 45 | } 46 | 47 | /** 48 | * Execute the console command. 49 | * 50 | * @return void 51 | */ 52 | public function handle() 53 | { 54 | 55 | $package = 'barryvdh/elfinder'; 56 | $destination = $this->publishPath . "/packages/{$package}"; 57 | 58 | if ( ! is_null($path = $this->getElfinderPath())) { 59 | if ($this->files->exists($destination)) { 60 | $this->files->deleteDirectory($destination); 61 | $this->info('Old published Assets have been removed'); 62 | } 63 | $copyElfinder = $this->copyElfinderFiles($destination); 64 | } else { 65 | $copyElfinder = false; 66 | $this->error('Could not find elfinder path'); 67 | } 68 | 69 | if ( ! is_null($path = $this->getPath())) { 70 | $copyPublic = $this->files->copyDirectory($path, $destination); 71 | } else { 72 | $copyPublic = false; 73 | $this->error('Could not find public path'); 74 | } 75 | 76 | if ($copyElfinder && $copyPublic) { 77 | $this->info('Published assets to: '.$package); 78 | } else { 79 | $this->error('Could not publish alles assets for '.$package); 80 | } 81 | 82 | } 83 | 84 | /** 85 | * Copy specific directories from elFinder to their destination 86 | * 87 | * @param $destination 88 | * @return bool 89 | */ 90 | protected function copyElfinderFiles($destination) 91 | { 92 | $result = true; 93 | $directories = array('js', 'css', 'img', 'sounds'); 94 | $elfinderPath = $this->getElfinderPath(); 95 | foreach($directories as $dir){ 96 | $path = $elfinderPath.'/'.$dir; 97 | $success = $this->files->copyDirectory($path, $destination.'/'.$dir); 98 | $result = $success && $result; 99 | } 100 | return $result; 101 | } 102 | 103 | /** 104 | * Get the path of the public folder, to merge with the elFinder folders. 105 | */ 106 | protected function getPath(){ 107 | return __DIR__ .'/../../resources/assets'; 108 | } 109 | 110 | /** 111 | * Find the elFinder path from the vendor dir. 112 | * 113 | * @return string 114 | */ 115 | protected function getElfinderPath() 116 | { 117 | $reflector = new \ReflectionClass('elFinder'); 118 | return realpath(dirname($reflector->getFileName()) . '/..'); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/Elfinder.php: -------------------------------------------------------------------------------- 1 | app = $app; 26 | } 27 | 28 | public function showIndex() 29 | { 30 | return $this->app['view'] 31 | ->make($this->package . '::elfinder') 32 | ->with($this->getViewVars()); 33 | } 34 | 35 | public function showTinyMCE() 36 | { 37 | return $this->app['view'] 38 | ->make($this->package . '::tinymce') 39 | ->with($this->getViewVars()); 40 | } 41 | 42 | public function showTinyMCE4() 43 | { 44 | return $this->app['view'] 45 | ->make($this->package . '::tinymce4') 46 | ->with($this->getViewVars()); 47 | } 48 | 49 | public function showTinyMCE5() 50 | { 51 | return $this->app['view'] 52 | ->make($this->package . '::tinymce5') 53 | ->with($this->getViewVars()); 54 | } 55 | 56 | public function showCKeditor4() 57 | { 58 | return $this->app['view'] 59 | ->make($this->package . '::ckeditor4') 60 | ->with($this->getViewVars()); 61 | } 62 | 63 | public function showPopup($input_id) 64 | { 65 | return $this->app['view'] 66 | ->make($this->package . '::standalonepopup') 67 | ->with($this->getViewVars()) 68 | ->with(compact('input_id')); 69 | } 70 | 71 | public function showFilePicker($input_id) 72 | { 73 | $type = Request::input('type'); 74 | $mimeTypes = implode(',',array_map(function($t){return "'".$t."'";}, explode(',',$type))); 75 | return $this->app['view'] 76 | ->make($this->package . '::filepicker') 77 | ->with($this->getViewVars()) 78 | ->with(compact('input_id','type','mimeTypes')); 79 | } 80 | 81 | public function showConnector() 82 | { 83 | $roots = $this->app->config->get('elfinder.roots', []); 84 | if (empty($roots)) { 85 | $dirs = (array) $this->app['config']->get('elfinder.dir', []); 86 | foreach ($dirs as $dir) { 87 | $roots[] = [ 88 | 'driver' => 'LocalFileSystem', // driver for accessing file system (REQUIRED) 89 | 'path' => public_path($dir), // path to files (REQUIRED) 90 | 'URL' => url($dir), // URL to files (REQUIRED) 91 | 'accessControl' => $this->app->config->get('elfinder.access') // filter callback (OPTIONAL) 92 | ]; 93 | } 94 | 95 | $disks = (array) $this->app['config']->get('elfinder.disks', []); 96 | foreach ($disks as $key => $root) { 97 | if (is_string($root)) { 98 | $key = $root; 99 | $root = []; 100 | } 101 | $disk = app('filesystem')->disk($key); 102 | if ($disk instanceof FilesystemAdapter) { 103 | $defaults = [ 104 | 'driver' => 'Flysystem', 105 | 'filesystem' => $disk->getDriver(), 106 | 'alias' => $key, 107 | 'accessControl' => $this->app->config->get('elfinder.access') // filter callback (OPTIONAL) 108 | ]; 109 | $root = array_merge($defaults, $root); 110 | if (!isset($root['URL'])) { 111 | $root['URLCallback'] = function($path) use ($disk) { 112 | return $disk->url($path); 113 | }; 114 | } 115 | $roots[] = $root; 116 | } 117 | } 118 | } 119 | 120 | if (app()->bound('session.store')) { 121 | $sessionStore = app('session.store'); 122 | $session = new LaravelSession($sessionStore); 123 | } else { 124 | $session = null; 125 | } 126 | 127 | $rootOptions = $this->app->config->get('elfinder.root_options', array()); 128 | foreach ($roots as $key => $root) { 129 | $roots[$key] = array_merge($rootOptions, $root); 130 | } 131 | 132 | $opts = $this->app->config->get('elfinder.options', array()); 133 | $opts = array_merge($opts, ['roots' => $roots, 'session' => $session]); 134 | 135 | // run elFinder 136 | $connector = new Connector(new \elFinder($opts)); 137 | $connector->run(); 138 | return $connector->getResponse(); 139 | } 140 | 141 | protected function getViewVars() 142 | { 143 | $dir = 'packages/barryvdh/' . $this->package; 144 | $locale = str_replace("-", "_", $this->app->config->get('app.locale')); 145 | if (!file_exists($this->app['path.public'] . "/$dir/js/i18n/elfinder.$locale.js")) { 146 | $locale = false; 147 | } 148 | $csrf = true; 149 | return compact('dir', 'locale', 'csrf'); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/ElfinderServiceProvider.php: -------------------------------------------------------------------------------- 1 | mergeConfigFrom($configPath, 'elfinder'); 24 | $this->publishes([$configPath => config_path('elfinder.php')], 'config'); 25 | 26 | $this->app->singleton('command.elfinder.publish', function($app) 27 | { 28 | $publicPath = $app['path.public']; 29 | return new Console\PublishCommand($app['files'], $publicPath); 30 | }); 31 | $this->commands('command.elfinder.publish'); 32 | } 33 | 34 | /** 35 | * Define your route model bindings, pattern filters, etc. 36 | * 37 | * @param \Illuminate\Routing\Router $router 38 | * @return void 39 | */ 40 | public function boot(Router $router) 41 | { 42 | $viewPath = __DIR__.'/../resources/views'; 43 | $this->loadViewsFrom($viewPath, 'elfinder'); 44 | $this->publishes([ 45 | $viewPath => base_path('resources/views/vendor/elfinder'), 46 | ], 'views'); 47 | 48 | if (!defined('ELFINDER_IMG_PARENT_URL')) { 49 | define('ELFINDER_IMG_PARENT_URL', $this->app['url']->asset('packages/barryvdh/elfinder')); 50 | } 51 | 52 | $config = $this->app['config']->get('elfinder.route', []); 53 | $config['namespace'] = 'Barryvdh\Elfinder'; 54 | 55 | $router->group($config, function($router) 56 | { 57 | $router->get('/', ['as' => 'elfinder.index', 'uses' =>'ElfinderController@showIndex']); 58 | $router->any('connector', ['as' => 'elfinder.connector', 'uses' => 'ElfinderController@showConnector']); 59 | $router->get('popup/{input_id}', ['as' => 'elfinder.popup', 'uses' => 'ElfinderController@showPopup']); 60 | $router->get('filepicker/{input_id}', ['as' => 'elfinder.filepicker', 'uses' => 'ElfinderController@showFilePicker']); 61 | $router->get('tinymce', ['as' => 'elfinder.tinymce', 'uses' => 'ElfinderController@showTinyMCE']); 62 | $router->get('tinymce4', ['as' => 'elfinder.tinymce4', 'uses' => 'ElfinderController@showTinyMCE4']); 63 | $router->get('tinymce5', ['as' => 'elfinder.tinymce5', 'uses' => 'ElfinderController@showTinyMCE5']); 64 | $router->get('ckeditor', ['as' => 'elfinder.ckeditor', 'uses' => 'ElfinderController@showCKeditor4']); 65 | }); 66 | } 67 | 68 | /** 69 | * Get the services provided by the provider. 70 | * 71 | * @return array 72 | */ 73 | public function provides() 74 | { 75 | return array('command.elfinder.publish'); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/Session/LaravelSession.php: -------------------------------------------------------------------------------- 1 | store = $store; 14 | } 15 | 16 | /** 17 | * {@inheritdoc} 18 | */ 19 | public function start() 20 | { 21 | $this->store->start(); 22 | 23 | return $this; 24 | } 25 | 26 | /** 27 | * {@inheritdoc} 28 | */ 29 | public function close() 30 | { 31 | $this->store->save(); 32 | 33 | return $this; 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function get($key, $empty = null) 40 | { 41 | return $this->store->get($key, $empty); 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function set($key, $data) 48 | { 49 | $this->store->put($key, $data); 50 | 51 | return $this; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | public function remove($key) 58 | { 59 | $this->store->remove($key); 60 | 61 | return $this; 62 | } 63 | } 64 | --------------------------------------------------------------------------------