├── filebrowser ├── __init__.py ├── models.py ├── media │ └── filebrowser │ │ ├── img │ │ ├── filebrowser_type_.gif │ │ ├── tableheader_arrows.gif │ │ ├── filebrowser_icon_show.gif │ │ ├── filebrowser_type_code.gif │ │ ├── tableheader_arrow_up.gif │ │ ├── filebrowser_icon_delete.gif │ │ ├── filebrowser_icon_rename.gif │ │ ├── filebrowser_icon_select.gif │ │ ├── filebrowser_type_folder.gif │ │ ├── filebrowser_type_image.gif │ │ ├── filebrowser_type_sound.gif │ │ ├── filebrowser_type_video.gif │ │ ├── tableheader_arrow_down.gif │ │ ├── filebrowser_icon_makethumb.gif │ │ ├── filebrowser_type_document.gif │ │ ├── filebrowser_icon_show_hover.gif │ │ ├── filebrowser_icon_delete_hover.gif │ │ ├── filebrowser_icon_imagegenerator.gif │ │ ├── filebrowser_icon_rename_hover.gif │ │ ├── filebrowser_icon_select_hover.gif │ │ ├── filebrowser_icon_makethumb_hover.gif │ │ ├── filebrowser_icon_select_disabled.gif │ │ ├── filebrowser_icon_imagegenerator_hover.gif │ │ ├── filebrowser_object-tools_icon_makethumb.gif │ │ ├── filebrowser_object-tools_icon_makedirectory.gif │ │ ├── filebrowser_object-tools_icon_imagegenerator.gif │ │ ├── filebrowser_object-tools_icon_makethumb_hover.gif │ │ ├── filebrowser_object-tools_icon_multipleupload.gif │ │ ├── filebrowser_object-tools_icon_imagegenerator_hover.gif │ │ ├── filebrowser_object-tools_icon_makedirectory_hover.gif │ │ └── filebrowser_object-tools_icon_multipleupload_hover.gif │ │ ├── js │ │ ├── FB_TinyMCE.js │ │ ├── FB_CKeditor.js │ │ ├── AddFileBrowser.js │ │ ├── FB_FileBrowseField.js │ │ └── TinyMCEAdmin.js │ │ └── css │ │ └── filebrowser.css ├── templates │ └── filebrowser │ │ ├── include │ │ ├── paginator.html │ │ ├── toolbar.html │ │ ├── tableheader.html │ │ ├── filter.html │ │ └── filelisting.html │ │ ├── custom_field.html │ │ ├── rename.html │ │ ├── makedir.html │ │ ├── upload.html │ │ └── index.html ├── urls.py ├── LICENSE ├── fb_settings.py ├── forms.py ├── fields.py ├── functions.py └── views.py ├── README └── setup.py /filebrowser/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /filebrowser/models.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_type_.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_type_.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/tableheader_arrows.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/tableheader_arrows.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_show.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_show.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_type_code.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_type_code.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/tableheader_arrow_up.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/tableheader_arrow_up.gif -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | A very old version of django-filebrowser we use at the moment 2 | Don't use it, it's depeciated. 3 | Grab the current release at : http://code.google.com/p/django-filebrowser/ 4 | -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_delete.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_delete.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_rename.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_rename.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_select.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_select.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_type_folder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_type_folder.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_type_image.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_type_image.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_type_sound.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_type_sound.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_type_video.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_type_video.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/tableheader_arrow_down.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/tableheader_arrow_down.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_makethumb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_makethumb.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_type_document.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_type_document.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_show_hover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_show_hover.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_delete_hover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_delete_hover.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_imagegenerator.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_imagegenerator.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_rename_hover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_rename_hover.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_select_hover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_select_hover.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_makethumb_hover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_makethumb_hover.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_select_disabled.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_select_disabled.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_icon_imagegenerator_hover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_icon_imagegenerator_hover.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_makethumb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_makethumb.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_makedirectory.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_makedirectory.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_imagegenerator.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_imagegenerator.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_makethumb_hover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_makethumb_hover.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_multipleupload.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_multipleupload.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_imagegenerator_hover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_imagegenerator_hover.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_makedirectory_hover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_makedirectory_hover.gif -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_multipleupload_hover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/django-filebrowser/master/filebrowser/media/filebrowser/img/filebrowser_object-tools_icon_multipleupload_hover.gif -------------------------------------------------------------------------------- /filebrowser/templates/filebrowser/include/paginator.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 |

4 | {% if results_var.results_total %} 5 | {% if not results_var.results_current %} 6 | {% trans "No Files Found" %}  7 | {% endif %}{{ results_var.results_total }} Fil{{ results_var.results_total|pluralize:"e,es" }}  8 | {% for count in counter.items %} 9 | {{ count.0 }}: 10 | {{ count.1 }}  11 | {% endfor %} 12 | {% else %} 13 | {% trans "No Files" %} 14 | {% endif %} 15 |

-------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup( 4 | name='django-filebrowser', 5 | version='2.1', 6 | description='Media-Management with the Django Admin-Interface.', 7 | author='Patrick Kranzlmueller (vonautomatisch)', 8 | author_email='werkstaetten@vonautomatisch.at', 9 | url='http://code.google.com/p/django-filebrowser/', 10 | download_url='', 11 | packages=find_packages(), 12 | include_package_data=True, 13 | zip_safe=False, 14 | classifiers=[ 15 | 'Development Status :: 3 - Alpha', 16 | 'Environment :: Web Environment', 17 | 'Framework :: Django', 18 | 'Intended Audience :: Developers', 19 | 'License :: OSI Approved :: BSD License', 20 | 'Operating System :: OS Independent', 21 | 'Programming Language :: Python', 22 | 'Framework :: Django', 23 | ] 24 | ) 25 | -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/js/FB_TinyMCE.js: -------------------------------------------------------------------------------- 1 | var FileBrowserDialogue = { 2 | init : function () { 3 | // remove tinymce stylesheet. 4 | var allLinks = document.getElementsByTagName("link"); 5 | allLinks[allLinks.length-1].parentNode.removeChild(allLinks[allLinks.length-1]); 6 | }, 7 | fileSubmit : function (FileURL) { 8 | var URL = FileURL; 9 | var win = tinyMCEPopup.getWindowArg("window"); 10 | 11 | // insert information now 12 | win.document.getElementById(tinyMCEPopup.getWindowArg("input")).value = URL; 13 | 14 | // change width/height & show preview 15 | if (win.ImageDialog){ 16 | if (win.ImageDialog.getImageData) 17 | win.ImageDialog.getImageData(); 18 | if (win.ImageDialog.showPreviewImage) 19 | win.ImageDialog.showPreviewImage(URL); 20 | } 21 | 22 | // close popup window 23 | tinyMCEPopup.close(); 24 | } 25 | } 26 | 27 | tinyMCEPopup.onInit.add(FileBrowserDialogue.init, FileBrowserDialogue); 28 | 29 | -------------------------------------------------------------------------------- /filebrowser/templates/filebrowser/custom_field.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% if final_attrs.value %} 6 |

7 | 8 | 9 | 10 |

11 | {% else %} 12 | 17 | {% endif %} 18 | {% comment %} 19 | {% if final_attrs.extensions_allowed %} 20 |

{% for extension in final_attrs.extensions_allowed %}{{ extension }} {% endfor %}

21 | {% endif %} 22 | {% endcomment %} -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/js/FB_CKeditor.js: -------------------------------------------------------------------------------- 1 | 2 | function ProtectPath(path) 3 | { 4 | path = path.replace( /\\/g, '\\\\') ; 5 | path = path.replace( /'/g, '\\\'') ; 6 | return path ; 7 | } 8 | 9 | function OpenFile( fileUrl ) 10 | { 11 | window.top.opener.SetUrl( encodeURI( fileUrl ).replace( '#', '%23' ) ) ; 12 | window.top.close() ; 13 | window.top.opener.focus() ; 14 | } 15 | 16 | // Build the link to view the folder. 17 | // var sLink = '' ; 18 | 19 | /* 20 | function OpenFileBrowser( url, width, height ) 21 | { 22 | // oEditor must be defined. 23 | 24 | var iLeft = ( oEditor.FCKConfig.ScreenWidth - width ) / 2 ; 25 | var iTop = ( oEditor.FCKConfig.ScreenHeight - height ) / 2 ; 26 | 27 | var sOptions = "toolbar=no,status=no,resizable=yes,dependent=yes,scrollbars=yes" ; 28 | sOptions += ",width=" + width ; 29 | sOptions += ",height=" + height ; 30 | sOptions += ",left=" + iLeft ; 31 | sOptions += ",top=" + iTop ; 32 | 33 | window.open( url, 'FCKBrowseWindow', sOptions ) ; 34 | } 35 | */ -------------------------------------------------------------------------------- /filebrowser/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls.defaults import * 2 | 3 | urlpatterns = patterns('filebrowser.views', 4 | 5 | (r'^(?P[_a-zA-Z0-9./-]+)/mkdir/', 'mkdir'), 6 | (r'^(?P[_a-zA-Z0-9./-]+)/upload/', 'upload'), 7 | (r'^(?P[_a-zA-Z0-9./-]+)/delete/$', 'delete'), 8 | (r'^(?P[_a-zA-Z0-9./-]+)/makethumbs/$', 'makethumb'), 9 | (r'^(?P[_a-zA-Z0-9./-]+)/makethumb/(?P[a-zA-Z0-9._-]+)', 'makethumb'), 10 | (r'^(?P[_a-zA-Z0-9./-]+)/generateimages/$', 'generateimages'), 11 | (r'^(?P[_a-zA-Z0-9./-]+)/generateimages/(?P[a-zA-Z0-9._-]+)', 'generateimages'), 12 | (r'^(?P[_a-zA-Z0-9./-]+)/rename/(?P[a-zA-Z0-9._-]+)', 'rename'), 13 | (r'^mkdir/', 'mkdir'), 14 | (r'^upload/', 'upload'), 15 | (r'^delete/$', 'delete'), 16 | (r'^makethumbs/$', 'makethumb'), 17 | (r'^makethumb/(?P[a-zA-Z0-9._-]+)', 'makethumb'), 18 | (r'^generateimages/$', 'generateimages'), 19 | (r'^generateimages/(?P[a-zA-Z0-9._-]+)', 'generateimages'), 20 | (r'^rename/(?P[a-zA-Z0-9._-]+)', 'rename'), 21 | (r'^(?P[_a-zA-Z0-9./-]+)/$', 'index'), 22 | (r'^$', 'index'), 23 | 24 | ) 25 | -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/js/AddFileBrowser.js: -------------------------------------------------------------------------------- 1 | var FileBrowser = { 2 | // this is set automatically 3 | admin_media_prefix: '', 4 | // change this 5 | thumb_prefix: 'thumb_', 6 | no_thumb: 'filebrowser/img/no_thumb.gif', 7 | 8 | init: function() { 9 | // Deduce admin_media_prefix by looking at the 20 | {% endcomment %} -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/js/FB_FileBrowseField.js: -------------------------------------------------------------------------------- 1 | function FileSubmit(FileURL, ThumbURL, FileType) { 2 | 3 | // var input_id=window.name.split("___").join("."); 4 | var input_id=window.name.replace(/____/g,'-').split("___").join("."); 5 | var preview_id = 'image_' + input_id; 6 | var link_id = 'link_' + input_id; 7 | var help_id = 'help_' + input_id; 8 | input = opener.document.getElementById(input_id); 9 | preview = opener.document.getElementById(preview_id); 10 | link = opener.document.getElementById(link_id); 11 | help = opener.document.getElementById(help_id); 12 | // set new value for input field 13 | input.value = FileURL; 14 | 15 | if (ThumbURL && FileType != "") { 16 | // selected file is an image and thumbnail is available: 17 | // display the preview-image (thumbnail) 18 | // link the preview-image to the original image 19 | link.setAttribute("href", FileURL); 20 | link.setAttribute("target", "_blank"); 21 | preview.setAttribute("src", ThumbURL); 22 | help.setAttribute("style", "display:block"); 23 | } else { 24 | // hide preview elements 25 | link.setAttribute("href", ""); 26 | link.setAttribute("target", ""); 27 | preview.setAttribute("src", ""); 28 | help.setAttribute("style", "display:none"); 29 | } 30 | this.close(); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /filebrowser/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008, Patrick Kranzlmueller (vonautomatisch werkstaetten), All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions 6 | in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other 7 | materials provided with the distribution. 3. Neither the name of FileBrowser nor the names of its contributors may be used to endorse or promote 8 | products derived from this software without specific prior written permission. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 11 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 12 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 13 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 14 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 15 | DAMAGE. -------------------------------------------------------------------------------- /filebrowser/templates/filebrowser/rename.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/base_site.html" %} 2 | {% load i18n %} 3 | {% load adminmedia %} 4 | 5 | {% block coltype %}colM{% endblock %} 6 | {% block bodyclass %}change-form{% endblock %} 7 | {% block stylesheet %}{% admin_media_prefix %}css/forms.css{% endblock %} 8 | {% block extrastyle %} 9 | 10 | {% if query.pop %} 11 | 14 | {% endif %} 15 | {% endblock %} 16 | {% block breadcrumbs %}{% endblock %} 17 | 18 | {% block content %} 19 |
20 |
21 |
22 | {% if form.errors %}

Please correct the following errors.

{% endif %} 23 |
24 |
25 | {% if form.name.errors %}
    {{ form.name.errors }}
{% endif %} 26 | 27 | {{ form.name }} 28 | {% if file_extension %}{{ file_extension }}{% endif %} 29 | {% if form.name.help_text %}

{{ form.name.help_text|safe }}

{% endif %} 30 |
31 |
32 |
33 | 34 |
35 |
36 |
37 |
38 | {% endblock %} -------------------------------------------------------------------------------- /filebrowser/templates/filebrowser/makedir.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/base_site.html" %} 2 | {% load i18n %} 3 | {% load adminmedia %} 4 | 5 | {% block coltype %}colM{% endblock %} 6 | {% block bodyclass %}change-form{% endblock %} 7 | {% block stylesheet %}{% admin_media_prefix %}css/forms.css{% endblock %} 8 | 9 | {% block extrastyle %} 10 | 11 | {% if query.pop %} 12 | 13 | 16 | {% endif %} 17 | {% endblock %} 18 | 19 | 20 | {% block breadcrumbs %}{% endblock %} 21 | 22 | {% block content %} 23 |
24 |
25 |
26 | {% if form.errors %}

Please correct the following errors.

{% endif %} 27 |
28 |
29 | {% if form.dir_name.errors %}
    {{ form.dir_name.errors }}
{% endif %} 30 | 31 | {{ form.dir_name }} 32 | {% if form.dir_name.help_text %}

{{ form.dir_name.help_text|safe }}

{% endif %} 33 |
34 |
35 |
36 | 37 |
38 |
39 |
40 |
41 | {% endblock %} -------------------------------------------------------------------------------- /filebrowser/templates/filebrowser/include/tableheader.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 | 4 | 5 | {% ifequal query.pop 'pop=1' %}{% endifequal %} 6 | {% ifequal query.pop 'pop=2' %}{% endifequal %} 7 | 8 | {% ifequal query.o '8' %}
 {% endifequal %} 9 | {% ifnotequal query.o '8' %} {% endifnotequal %} 10 | 11 | {% ifnotequal counter.Image 0 %}{% if results_var.change_total %} {% endif %}{% endifnotequal %} 12 | 13 | {% ifequal query.o '11' %}{% trans 'Filename' %}{% endifequal %} 14 | {% ifnotequal query.o '11' %}{% trans 'Filename' %}{% endifnotequal %} 15 | 16 | {% if settings_var.USE_IMAGE_GENERATOR and results_var.imagegenerator_total %} {% endif %} 17 | 18 |   19 | 20 | {% ifequal query.o '1' %}{% trans 'Size' %}{% endifequal %} 21 | {% ifnotequal query.o '1' %}{% trans 'Size' %}{% endifnotequal %} 22 | 23 | {% ifequal query.o '3' %}{% trans 'Date' %}{% endifequal %} 24 | {% ifnotequal query.o '3' %}{% trans 'Date' %}{% endifnotequal %} 25 | 26 | {% if results_var.delete_total %} {% endif %} 27 | 28 | -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/css/filebrowser.css: -------------------------------------------------------------------------------- 1 | .filebrowser table td { font-size: 10px; } 2 | .filebrowser table a { font-size: 11px; } 3 | .filebrowser thead th.sorted a { padding-right: 13px; } 4 | .filebrowser td { padding: 9px 10px 7px 10px !important; } 5 | .filebrowser td.fb_icon { padding: 6px 5px 5px 5px !important; } 6 | 7 | table a.fb_deletelink, table a.fb_renamelink, table a.fb_selectlink, table a.fb_makethumblink, table a.fb_imagegeneratorlink { 8 | cursor: pointer; 9 | display: block; padding: 0; margin: 0; 10 | width: 23px; height: 17px; 11 | background-color: transparent; 12 | background-position: 0 center; 13 | background-repeat: no-repeat; 14 | } 15 | 16 | table .fb_deletelink:link, table .fb_deletelink:visited { 17 | width: 15px; 18 | background-image: url('../img/filebrowser_icon_delete.gif'); 19 | } 20 | table .fb_deletelink:hover, table .fb_deletelink:active { background-image: url('../img/filebrowser_icon_delete_hover.gif'); } 21 | table .fb_renamelink:link, table .fb_renamelink:visited { 22 | width: 14px; 23 | background-image: url('../img/filebrowser_icon_rename.gif'); 24 | } 25 | table .fb_renamelink:hover, table .fb_renamelink:active { background-image: url('../img/filebrowser_icon_rename_hover.gif'); } 26 | table .fb_selectlink:link, table .fb_selectlink:visited { background-image: url('../img/filebrowser_icon_select.gif'); } 27 | table .fb_selectlink:hover, table .fb_selectlink:active { background-image: url('../img/filebrowser_icon_select_hover.gif'); } 28 | table .fb_makethumblink:link, table .fb_makethumblink:visited { 29 | width: 50px; height: 29px; 30 | background-image: url('../img/filebrowser_icon_makethumb.gif'); 31 | } 32 | table .fb_makethumblink:hover, table .fb_makethumblink:active { background-image: url('../img/filebrowser_icon_makethumb_hover.gif'); } 33 | table .fb_imagegeneratorlink:link, table .fb_imagegeneratorlink:visited { background-image: url('../img/filebrowser_icon_imagegenerator.gif'); } 34 | table .fb_imagegeneratorlink:hover, table .fb_imagegeneratorlink:active { background-image: url('../img/filebrowser_icon_imagegenerator_hover.gif'); } 35 | -------------------------------------------------------------------------------- /filebrowser/templates/filebrowser/upload.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/base_site.html" %} 2 | {% load i18n %} 3 | {% load adminmedia %} 4 | 5 | {% block extrahead %} 6 | 7 | 8 | 9 | {% endblock %} 10 | {% block coltype %}colM{% endblock %} 11 | {% block bodyclass %}change-form{% endblock %} 12 | {% block stylesheet %}{% admin_media_prefix %}css/forms.css{% endblock %} 13 | {% block extrastyle %} 14 | 15 | {% if query.pop %} 16 | 19 | {% endif %} 20 | {% endblock %} 21 | {% block breadcrumbs %}{% endblock %} 22 | 23 | {% block content %} 24 |
25 |
26 | {{ formset.management_form }} 27 |
28 | {% if form.errors %}{{ form.errors }}{% endif %} 29 |
30 | {% for form in formset.forms %} 31 |
32 | {% if form.file.errors %}{{ form.file.errors }}{% endif %} 33 | 34 | {{ form.file }} 35 | {% if settings_var.USE_IMAGE_GENERATOR %} 36 |

{{ form.use_image_generator }} {{ form.use_image_generator.label }}

37 | {% endif %} 38 |
39 | {% endfor %} 40 |
41 | 42 |
43 |

{% trans "Help" %}

44 |
45 | {% for extension in settings_var.EXTENSIONS.items %} 46 | {% ifnotequal extension.0 'Folder' %} 47 | 48 |

{{ extension.0|safe }} ({{ extension.1|join:", "|safe }})

49 | {% endifnotequal %} 50 | {% endfor %} 51 |
52 |
53 | 54 |

{{ settings_var.MAX_UPLOAD_SIZE|safe }}

55 |
56 |
57 |
58 | 59 |
60 |
61 |
62 | 63 |
64 | {% endblock %} -------------------------------------------------------------------------------- /filebrowser/media/filebrowser/js/TinyMCEAdmin.js: -------------------------------------------------------------------------------- 1 | function CustomFileBrowser(field_name, url, type, win) { 2 | 3 | var cmsURL = "/admin/filebrowser/?pop=2"; 4 | cmsURL = cmsURL + "&type=" + type; 5 | 6 | tinyMCE.activeEditor.windowManager.open({ 7 | file: cmsURL, 8 | width: 820, // Your dimensions may differ - toy around with them! 9 | height: 500, 10 | resizable: "yes", 11 | scrollbars: "yes", 12 | inline: "no", // This parameter only has an effect if you use the inlinepopups plugin! 13 | close_previous: "no" 14 | }, { 15 | window: win, 16 | input: field_name, 17 | editor_id: tinyMCE.selectedInstance.editorId 18 | }); 19 | return false; 20 | } 21 | 22 | 23 | tinyMCE.init({ 24 | mode: "textareas", 25 | theme: "advanced", 26 | language: "en", 27 | skin: "o2k7", 28 | browsers: "gecko", 29 | dialog_type: "modal", 30 | object_resizing: true, 31 | cleanup_on_startup: true, 32 | forced_root_block: "p", 33 | remove_trailing_nbsp: true, 34 | theme_advanced_toolbar_location: "top", 35 | theme_advanced_toolbar_align: "left", 36 | theme_advanced_statusbar_location: "none", 37 | theme_advanced_buttons1: "formatselect,styleselect,bold,italic,underline,bullist,numlist,undo,redo,link,unlink,image,code,template,visualchars,fullscreen,pasteword,media,search,replace,charmap", 38 | theme_advanced_buttons2: "", 39 | theme_advanced_buttons3: "", 40 | theme_advanced_path: false, 41 | theme_advanced_blockformats: "p,h2,h3,h4,div,code,pre", 42 | theme_advanced_styles: "[all] clearfix=clearfix;[p] summary=summary;[div] code=code;[img] img_left=img_left;[img] img_left_nospacetop=img_left_nospacetop;[img] img_right=img_right;[img] img_right_nospacetop=img_right_nospacetop;[img] img_block=img_block;[img] img_block_nospacetop=img_block_nospacetop;[div] column span-2=column span-2;[div] column span-4=column span-4;[div] column span-8=column span-8", 43 | width: '700', 44 | height: '200', 45 | plugins: "advimage,advlink,fullscreen,visualchars,paste,media,template,searchreplace", 46 | advimage_styles: "Linksbündig neben Text=img_left;Rechtsbündig neben Text=img_right;Eigener Block=img_block", 47 | advlink_styles: "internal (sehmaschine.net)=internal;external (link to an external site)=external", 48 | advimage_update_dimensions_onchange: true, 49 | file_browser_callback: "CustomFileBrowser", 50 | relative_urls: false, 51 | valid_elements : "" + 52 | "-p," + 53 | "a[href|target=_blank|class]," + 54 | "-strong/-b," + 55 | "-em/-i," + 56 | "-u," + 57 | "-ol," + 58 | "-ul," + 59 | "-li," + 60 | "br," + 61 | "img[class|src|alt=|width|height]," + 62 | "-h2,-h3,-h4," + 63 | "-pre," + 64 | "-code," + 65 | "-div", 66 | extended_valid_elements: "" + 67 | "a[name|class|href|target|title|onclick]," + 68 | "img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name]," + 69 | "br[clearfix]," + 70 | "-p[class 4 |

{% trans "Filter" %}

5 |

{% trans "By Date" %}

6 | 17 |

{% trans "By Type" %}

18 | 24 | 25 | {% endcomment %} 26 | 27 | 28 |

{% trans "Filter" %}

29 | {% if query.filter_date %} 30 |
31 | {% else %} 32 |
33 | {% endif %} 34 |

{% trans "By Date" %}

35 | 46 |
47 | {% if query.filter_type %} 48 |
49 | {% else %} 50 |
51 | {% endif %} 52 |

{% trans "By Type" %}

53 |
    54 | {% if query.filter_type %}
  • {% else %}
  • {% endif %}{% trans "All" %}
  • 55 | {% for extension in settings_var.EXTENSIONS %} 56 | {% ifequal query.filter_type extension %}
  • {% else %}
  • {% endifequal %}{{ extension }}
  • 57 | {% endfor %} 58 |
59 |
-------------------------------------------------------------------------------- /filebrowser/templates/filebrowser/include/filelisting.html: -------------------------------------------------------------------------------- 1 | {% load adminmedia %} 2 | {% load i18n %} 3 | 4 | 5 | 6 | {% ifequal query.pop 'pop=1' %} 7 | 8 | 9 | 10 | {% endifequal %} 11 | 12 | {% ifequal query.pop 'pop=2' %} 13 | 14 | {% ifnotequal file.file_type 'Folder' %} 15 | 16 | {% endifnotequal %} 17 | 18 | {% endifequal %} 19 | 20 | 21 | 22 | {% ifnotequal counter.Image 0 %} 23 | {% if results_var.change_total %} 24 | 25 | {% if file.flag_makethumb %} 26 | 27 | {% else %} 28 | {% ifequal file.file_type 'Image' %} 29 | 30 | {% endifequal %} 31 | {% endif %} 32 | 33 | {% endif %} 34 | {% endifnotequal %} 35 | 36 | {% ifequal file.file_type 'Folder' %} 37 | {{ file.filename }} 38 | {% else %} 39 | {{ file.filename }}{% if file.image_dimensions %}
{{ file.image_dimensions.0 }} x {{ file.image_dimensions.1 }} px{% endif %} 40 | {% endifequal %} 41 | 42 | {% if settings_var.USE_IMAGE_GENERATOR and not file.flag_imageversion %} 43 | {% ifnotequal counter.Image 0 %} 44 | 45 | {% ifequal file.file_type 'Image' %} 46 | 47 | {% endifequal %} 48 | 49 | {% endifnotequal %} 50 | {% endif %} 51 | 52 | 53 | 54 | {{ file.filesize_str|safe }} 55 | 56 | {{ file.date }} 57 | 58 | {% if results_var.delete_total %} 59 | 60 | {% ifnotequal file.file_type 'Folder' %} 61 | 62 | {% else %} 63 | {% if file.flag_deletedir %} 64 | 65 | {% endif %} 66 | {% endifnotequal %} 67 | 68 | {% endif %} 69 | 70 | -------------------------------------------------------------------------------- /filebrowser/fb_settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | from django.conf import settings 3 | 4 | # The location of your media-files. 5 | # This is the base URL for all your media-files accessible for the FileBrowser. 6 | # Note: When you set URL_WWW to settings.MEDIA_URL you can use all your media-files with the FileBrowser. 7 | # Nevertheless, you may want to limit this to a subdirectory of settings.MEDIA_URL or a seperate media-server. 8 | # Important: If you change this setting, you should also change PATH_SERVER. 9 | URL_WWW = getattr(settings, "FILEBROWSER_URL_WWW", settings.MEDIA_URL_ROOT + '/share/img/upload/') 10 | 11 | # The FileBrowser Admin-URL. 12 | # Note: If you change this URL, you also have to change the file urls.py. 13 | URL_ADMIN = getattr(settings, "FILEBROWSER_URL_ADMIN", '/filebrowser/') 14 | 15 | # The URL to your Admin Index-Site. 16 | URL_HOME = getattr(settings, "FILEBROWSER_URL_HOME", '/') 17 | 18 | # The URL to your filebrowser media-files. 19 | # Note: You have to change this setting, if you install the media-files of the FileBrowser outside 20 | # your admin-media directory. 21 | URL_FILEBROWSER_MEDIA = getattr(settings, "FILEBROWSER_URL_FILEBROWSER_MEDIA", settings.ADMIN_MEDIA_PREFIX + "filebrowser/") 22 | print URL_FILEBROWSER_MEDIA 23 | # The URL to your TinyMCE Installation. 24 | # Note: You have to change this setting, if you install TinyMCE outside your admin-media directory. 25 | URL_TINYMCE = getattr(settings, "FILEBROWSER_URL_TINYMCE", settings.ADMIN_MEDIA_PREFIX + "tinymce/jscripts/tiny_mce/") 26 | 27 | # The server-path to media-files. This is the initial/root server-path for the FileBrowser. 28 | # Important: If you change this setting, you should also change URL_WWW. 29 | PATH_SERVER = getattr(settings, "FILEBROWSER_PATH_SERVER", os.path.join(settings.MEDIA_ROOT, 'share/img/upload/')) 30 | 31 | # The server-path to your filebrowser media-files. 32 | # Note: You have to change this setting, if you install the media-files of the FileBrowser outside 33 | # your admin-media directory. 34 | PATH_FILEBROWSER_MEDIA = getattr(settings, "FILEBROWSER_PATH_FILEBROWSER_MEDIA", os.path.join(settings.MEDIA_ROOT, 'filebrowser/')) 35 | 36 | # The server-path to your TinyMCE Installation. 37 | # Note: You have to change this setting, if you install TinyMCE outside your admin-media directory. 38 | PATH_TINYMCE = getattr(settings, "FILEBROWSER_PATH_TINYMCE", os.path.join(settings.MEDIA_ROOT, 'admin/tinymce/jscripts/tiny_mce/')) 39 | 40 | # Allowed Extensions for File Upload. Lower case is important. 41 | # Please be aware that there are Icons for the default extension settings. 42 | # Therefore, if you add a category (e.g. "Misc"), you won't get an icon. 43 | EXTENSIONS = getattr(settings, "FILEBROWSER_EXTENSIONS", { 44 | 'Folder':[''], 45 | 'Image':['.jpg', '.jpeg', '.gif','.png','.tif','.tiff'], 46 | 'Video':['.mov','.wmv','.mpeg','.mpg','.avi','.rm'], 47 | 'Document':['.pdf','.doc','.rtf','.txt','.xls','.csv'], 48 | 'Sound':['.mp3','.mp4','.wav','.aiff','.midi'], 49 | 'Code':['.html','.py','.js','.css'] 50 | }) 51 | 52 | # Max. Upload Size in Bytes. 53 | MAX_UPLOAD_SIZE = getattr(settings, "FILEBROWSER_MAX_UPLOAD_SIZE", 5000000) 54 | 55 | # The prefix for your thumbnails. 56 | # If you have an Image "myimage.jpg", your thumbnail will be "thumb_myimage.jpg" by default. 57 | THUMB_PREFIX = getattr(settings, 'FILEBROWSER_THUMB_PREFIX', 'thumb_') 58 | 59 | # The size of your thumbnails for the Admin-Interface. 60 | # Note: This Thumbnail is for diplaying your Image within the Admin-Interface. 61 | # Because of the low quality, it's not intended to use this Thumbnail on your Website. 62 | # For displaying Thumbnails on a Website, use "Image Generator" instead. 63 | THUMBNAIL_SIZE = getattr(settings, 'FILEBROWSER_THUMBNAIL_SIZE', (50, 150)) 64 | 65 | # Whether or not to use the ImageGenerator. 66 | # When this is True, you'll get a checkbox called "Use Image Generator" with every Upload-Field. 67 | # Moreover, every Image will have a button "Generate Images" to generate Image versions 68 | # (this is useful, if Images are uploaded using FTP and not the FileBrowser - 69 | # you can upload Images using FTP and generate the Image Versions afterwards). 70 | USE_IMAGE_GENERATOR = getattr(settings, 'FILEBROWSER_USE_IMAGE_GENERATOR', True) 71 | 72 | # The postfix for your "Image Versions"-directory. 73 | # If you Upload an Image called "myimage.jpg", your versions-directory will be called 74 | # "myimage_jpg_versions" by default. 75 | IMAGE_GENERATOR_DIRECTORY = getattr(settings, 'FILEBROWSER_IMAGE_GENERATOR_DIRECTORY', '_versions') 76 | 77 | # A list of Images to generate in the format (prefix, image width). 78 | IMAGE_GENERATOR_LANDSCAPE = getattr(settings, "FILEBROWSER_IMAGE_GENERATOR_LANDSCAPE", [('thumbnail_',140),('small_',300),('medium_',460),('big_',620)]) 79 | 80 | # A list of Images to generate in the format (prefix, image width). 81 | IMAGE_GENERATOR_PORTRAIT = getattr(settings, "FILEBROWSER_IMAGE_GENERATOR_PORTRAIT", [('thumbnail_',140),('small_',300),('medium_',460),('big_',620)]) 82 | 83 | # A list of Images to generate in the format (prefix, image width, image height). 84 | IMAGE_CROP_GENERATOR = getattr(settings, "FILEBROWSER_IMAGE_CROP_GENERATOR", [('cropped_',60,60),('croppedthumbnail_',140,140)]) 85 | -------------------------------------------------------------------------------- /filebrowser/forms.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django import forms 4 | from django.forms.formsets import BaseFormSet 5 | from django.utils.translation import ugettext as _ 6 | import re, os 7 | 8 | # get settings 9 | from filebrowser.fb_settings import * 10 | # get functions 11 | from filebrowser.functions import _get_file_type 12 | 13 | alnum_name_re = re.compile(r'^[a-zA-Z0-9._/-]+$') 14 | 15 | 16 | class MakeDirForm(forms.Form): 17 | 18 | def __init__(self, path_server, path, *args, **kwargs): 19 | self.PATH_SERVER = path_server 20 | self.path = path 21 | super(MakeDirForm, self).__init__(*args, **kwargs) 22 | 23 | dir_name = forms.CharField(widget=forms.TextInput(attrs=dict({ 'class': 'vTextField' }, max_length=50, min_length=3)), label=u'Directory', help_text=_('The directory will automatically be converted to lowercase. Only letters, numbers, underscores and hyphens are allowed.'), required=True) 24 | 25 | def clean_dir_name(self): 26 | 27 | if self.cleaned_data['dir_name']: 28 | # only letters, numbers and underscores are allowed. 29 | if not alnum_name_re.search(self.cleaned_data['dir_name']): 30 | raise forms.ValidationError(_('Only letters, numbers, underscores and hyphens are allowed.')) 31 | # directory must not already exist. 32 | if os.path.isdir(os.path.join(self.PATH_SERVER, self.path, self.cleaned_data['dir_name'].lower())): 33 | raise forms.ValidationError(_('The directory already exists.')) 34 | 35 | return self.cleaned_data['dir_name'] 36 | 37 | 38 | class RenameForm(forms.Form): 39 | 40 | def __init__(self, path_server, path, file_extension, *args, **kwargs): 41 | self.PATH_SERVER = path_server 42 | self.path = path 43 | self.file_extension = file_extension 44 | super(RenameForm, self).__init__(*args, **kwargs) 45 | 46 | name = forms.CharField(widget=forms.TextInput(attrs=dict({ 'class': 'vTextField' }, max_length=50, min_length=3)), label=u'Name', help_text=_('The name will automatically be converted to lowercase. Only letters, numbers, underscores and hyphens are allowed.'), required=True) 47 | 48 | def clean_name(self): 49 | 50 | if self.cleaned_data['name']: 51 | # only letters, numbers and underscores are allowed. 52 | if not alnum_name_re.search(self.cleaned_data['name']): 53 | raise forms.ValidationError(_('Only letters, numbers, underscores and hyphens are allowed.')) 54 | # file/directory must not already exist. 55 | if os.path.isdir(os.path.join(self.PATH_SERVER, self.path, self.cleaned_data['name'].lower())) or os.path.isfile(os.path.join(self.PATH_SERVER, self.path, self.cleaned_data['name'].lower() + self.file_extension)): 56 | raise forms.ValidationError(_('The file/directory already exists.')) 57 | 58 | return self.cleaned_data['name'] 59 | 60 | 61 | class BaseUploadFormSet(BaseFormSet): 62 | 63 | # this is just for passing the parameters (path_server, path) to the uploadform. 64 | # overly complicated, but necessary for the clean-methods in UploadForm. 65 | # DO NOT CHANGE ANYTHING HERE. 66 | # if you need to make modifications to the uploadform - use UploadForm below. 67 | 68 | def __init__(self, **kwargs): 69 | self.path_server = kwargs['path_server'] 70 | self.path = kwargs['path'] 71 | del kwargs['path_server'] 72 | del kwargs['path'] 73 | super(BaseUploadFormSet, self).__init__(**kwargs) 74 | 75 | def _construct_form(self, i, **kwargs): 76 | # this works because BaseFormSet._construct_form() passes **kwargs 77 | # to the form's __init__() 78 | kwargs["path_server"] = self.path_server 79 | kwargs["path"] = self.path 80 | return super(BaseUploadFormSet, self)._construct_form(i, **kwargs) 81 | 82 | 83 | class UploadForm(forms.Form): 84 | 85 | def __init__(self, *args, **kwargs): 86 | self.path_server = kwargs['path_server'] 87 | self.path = kwargs['path'] 88 | del kwargs['path_server'] 89 | del kwargs['path'] 90 | super(UploadForm, self).__init__(*args, **kwargs) 91 | 92 | file = forms.FileField(label="File") 93 | use_image_generator = forms.BooleanField(label="Use Image Generator", help_text=_('Use Image Generator.'), required=False) 94 | 95 | def clean_file(self): 96 | if self.cleaned_data['file']: 97 | filename = self.cleaned_data['file'].name 98 | 99 | # CHECK IF FILE EXISTS 100 | dir_list = os.listdir(os.path.join(self.path_server, self.path)) 101 | if filename in dir_list: 102 | raise forms.ValidationError(_('File already exists.')) 103 | 104 | # TODO: CHECK IF VERSIONS_PATH EXISTS (IF USE_IMAGE_GENERATOR IS TRUE) 105 | 106 | # CHECK FILENAME 107 | if not alnum_name_re.search(filename): 108 | raise forms.ValidationError(_('Filename is not allowed.')) 109 | 110 | # CHECK EXTENSION / FILE_TYPE 111 | file_type = _get_file_type(filename) 112 | if not file_type: 113 | raise forms.ValidationError(_('File extension is not allowed.')) 114 | 115 | # CHECK FILESIZE 116 | filesize = self.cleaned_data['file'].size 117 | if filesize > MAX_UPLOAD_SIZE: 118 | raise forms.ValidationError(_('Filesize exceeds allowed Upload Size.')) 119 | return self.cleaned_data['file'] 120 | 121 | 122 | -------------------------------------------------------------------------------- /filebrowser/fields.py: -------------------------------------------------------------------------------- 1 | """ 2 | A custom FileBrowseField. 3 | """ 4 | 5 | from django.db import models 6 | from django import forms 7 | from django.forms.widgets import Input 8 | from django.db.models.fields import Field, CharField 9 | from django.utils.safestring import mark_safe 10 | from django.forms.util import flatatt 11 | from django.utils.encoding import StrAndUnicode, force_unicode, smart_unicode, smart_str 12 | from django.template.loader import render_to_string 13 | from django.utils.translation import ugettext_lazy as _ 14 | from django.forms.fields import EMPTY_VALUES 15 | 16 | import os 17 | 18 | from filebrowser.functions import _get_file_type, _url_join 19 | from filebrowser.fb_settings import * 20 | 21 | class FileBrowseFormField(forms.Field): 22 | default_error_messages = { 23 | 'max_length': _(u'Ensure this value has at most %(max)d characters (it has %(length)d).'), 24 | 'min_length': _(u'Ensure this value has at least %(min)d characters (it has %(length)d).'), 25 | 'extension': _(u'Extension %(ext)s is not allowed. Only %(allowed)s is allowed.'), 26 | } 27 | 28 | def __init__(self, max_length=None, min_length=None, *args, **kwargs): 29 | self.max_length, self.min_length = max_length, min_length 30 | self.initial_directory = kwargs['initial_directory'] 31 | self.extensions_allowed = kwargs['extensions_allowed'] 32 | del kwargs['initial_directory'] 33 | del kwargs['extensions_allowed'] 34 | super(FileBrowseFormField, self).__init__(*args, **kwargs) 35 | 36 | def clean(self, value): 37 | "Validates max_length and min_length. Returns a Unicode object. Validates extension ..." 38 | super(FileBrowseFormField, self).clean(value) 39 | if value in EMPTY_VALUES: 40 | return u'' 41 | value = smart_unicode(value) 42 | value_length = len(value) 43 | if self.max_length is not None and value_length > self.max_length: 44 | raise forms.ValidationError(self.error_messages['max_length'] % {'max': self.max_length, 'length': value_length}) 45 | if self.min_length is not None and value_length < self.min_length: 46 | raise forms.ValidationError(self.error_messages['min_length'] % {'min': self.min_length, 'length': value_length}) 47 | file_extension = os.path.splitext(value)[1].lower() 48 | if self.extensions_allowed and not file_extension in self.extensions_allowed: 49 | raise forms.ValidationError(self.error_messages['extension'] % {'ext': file_extension, 'allowed': ", ".join(self.extensions_allowed)}) 50 | return value 51 | 52 | 53 | class FileBrowseWidget(Input): 54 | input_type = 'text' 55 | 56 | def __init__(self, attrs=None): 57 | self.initial_directory = attrs['initial_directory'] 58 | self.extensions_allowed = attrs['extensions_allowed'] 59 | if attrs is not None: 60 | self.attrs = attrs.copy() 61 | else: 62 | self.attrs = {} 63 | 64 | def render(self, name, value, attrs=None): 65 | if value is None: value = '' 66 | final_attrs = self.build_attrs(attrs, type=self.input_type, name=name) 67 | if value == "": 68 | final_attrs['initial_directory'] = _url_join(URL_ADMIN, final_attrs['initial_directory']) 69 | else: 70 | final_attrs['initial_directory'] = _url_join(URL_ADMIN, os.path.split(value)[0].replace(URL_WWW, "")) 71 | if value != '': 72 | # Only add the 'value' attribute if a value is non-empty. 73 | final_attrs['value'] = force_unicode(value) 74 | file = os.path.split(value)[1] 75 | if len(URL_WWW) < len(os.path.split(value)[0]): 76 | path = os.path.split(value)[0].replace(URL_WWW, "") 77 | else: 78 | path = "" 79 | file_type = _get_file_type(file) 80 | path_thumb = "" 81 | if file_type == 'Image': 82 | # check if thumbnail exists 83 | if os.path.isfile(os.path.join(PATH_SERVER, path, THUMB_PREFIX + file)): 84 | path_thumb = os.path.join(os.path.split(value)[0], THUMB_PREFIX + file) 85 | else: 86 | path_thumb = URL_FILEBROWSER_MEDIA + 'img/filebrowser_type_image.gif' 87 | elif file_type == "Folder": 88 | path_thumb = URL_FILEBROWSER_MEDIA + 'img/filebrowser_type_folder.gif' 89 | else: 90 | # if file is not an image, display file-icon (which is linked to the file) instead 91 | path_thumb = URL_FILEBROWSER_MEDIA + 'img/filebrowser_type_' + file_type + '.gif' 92 | final_attrs['thumbnail'] = path_thumb 93 | path_search_icon = URL_FILEBROWSER_MEDIA + 'img/filebrowser_icon_show.gif' 94 | final_attrs['search_icon'] = path_search_icon 95 | return render_to_string("filebrowser/custom_field.html", locals()) 96 | 97 | 98 | class FileBrowseField(Field): 99 | __metaclass__ = models.SubfieldBase 100 | 101 | def get_manipulator_field_objs(self): 102 | return [oldforms.TextField] 103 | 104 | def get_internal_type(self): 105 | return "CharField" 106 | 107 | def formfield(self, **kwargs): 108 | attrs = {} 109 | attrs["initial_directory"] = self.initial_directory 110 | attrs["extensions_allowed"] = self.extensions_allowed 111 | defaults = {'max_length': self.max_length} 112 | defaults['form_class'] = FileBrowseFormField 113 | defaults['widget'] = FileBrowseWidget(attrs=attrs) 114 | kwargs['initial_directory'] = self.initial_directory 115 | kwargs['extensions_allowed'] = self.extensions_allowed 116 | defaults.update(kwargs) 117 | return super(FileBrowseField, self).formfield(**defaults) 118 | 119 | def __init__(self, *args, **kwargs): 120 | try: 121 | self.initial_directory = kwargs['initial_directory'] 122 | del kwargs['initial_directory'] 123 | except: 124 | self.initial_directory = "/" 125 | try: 126 | self.extensions_allowed = kwargs['extensions_allowed'] 127 | del kwargs['extensions_allowed'] 128 | except: 129 | self.extensions_allowed = "" 130 | return super(FileBrowseField, self).__init__(*args, **kwargs) 131 | 132 | 133 | -------------------------------------------------------------------------------- /filebrowser/templates/filebrowser/index.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/base_site.html" %} 2 | {% load i18n %} 3 | {% load adminmedia %} 4 | 5 | 6 | 7 | {% block stylesheets %} 8 | {{ block.super }} 9 | 10 | 11 | {% endblock %} 12 | 13 | 14 | {% block javascripts %} 15 | {{ block.super }} 16 | 17 | {% ifequal query.pop '1' %} 18 | 19 | 20 | {% endifequal %} 21 | 22 | {% ifequal query.pop '2' %} 23 | 24 | 25 | 26 | {% if query.mce_rdomain %}{% endif %} 27 | {% endifequal %} 28 | 29 | {% ifequal query.pop '3' %} 30 | 31 | 32 | {% endifequal %} 33 | 34 | {{ media }} 35 | 36 | 37 | 38 | {% if not actions_on_top and not actions_on_bottom %} 39 | 42 | {% endif %} 43 | {% endblock %} 44 | 45 | 46 | {% block coltype %}flex{% endblock %} 47 | {% block bodyclass %}change-list filebrowser{% if query.pop %} popup{% endif %}{% endblock %} 48 | 49 | {% comment %} 50 | 51 | {% block breadcrumbs %}{% include "filebrowser/include/breadcrumbs.html" %}{% endblock %} 52 | {% endcomment %} 53 | 54 | 55 | {% block extrahead %} 56 | {% ifequal query.pop 'pop=1' %} 57 | 58 | {% endifequal %} 59 | {% ifequal query.pop 'pop=2' %} 60 | 61 | 62 | {% endifequal %} 63 | {% endblock %} 64 | {% comment %}{% block bodyclass %}change-list filebrowser{% endblock %}{% endcomment %} 65 | {% block stylesheet %}{% admin_media_prefix %}css/changelists.css{% endblock %} 66 | {% block extrastyle %} 67 | 68 | {% if query.pop %} 69 | 72 | {% endif %} 73 | {% endblock %} 74 | {% block breadcrumbs %}{% endblock %} 75 | 76 | 77 | {% block content %} 78 |
79 | {% block object-tools %} 80 | 86 | {% endblock %} 87 |
88 |
89 |
90 | {% if results_var.results_current %} 91 |
92 | 93 | {% include "filebrowser/include/tableheader.html" %} 94 | 95 | {% for file in file_dict %} 96 | {% include "filebrowser/include/filelisting.html" %} 97 | {% endfor %} 98 | 99 |
100 |
101 | {% endif %} 102 | {% include "filebrowser/include/paginator.html" %} 103 |
104 |
105 | 106 |
107 | {% include "filebrowser/include/toolbar.html" %} 108 |
109 | {% include "filebrowser/include/filter.html" %} 110 |
111 |
112 | 113 |
114 |
115 | {% endblock %} 116 | 117 | {% comment %} 118 | {% block content %} 119 |
120 | 126 |
127 | {% include "filebrowser/include/toolbar.html" %} 128 | {% include "filebrowser/include/filter.html" %} 129 |
130 | 131 | {% if results_var.results_current %} 132 | {% include "filebrowser/include/tableheader.html" %} 133 | {% endif %} 134 | 135 | {% for file in file_dict %} 136 | {% include "filebrowser/include/filelisting.html" %} 137 | {% endfor %} 138 | 139 |
140 |
141 | {% include "filebrowser/include/paginator.html" %} 142 |
143 |
144 | {% endblock %} 145 | {% endcomment %} 146 | -------------------------------------------------------------------------------- /filebrowser/functions.py: -------------------------------------------------------------------------------- 1 | 2 | from django.utils.translation import ugettext as _ 3 | from django.utils.safestring import mark_safe 4 | from time import gmtime, strftime, localtime, mktime, time 5 | from django.core.files import File 6 | import os, re, Image, decimal 7 | 8 | # get settings 9 | from filebrowser.fb_settings import * 10 | 11 | 12 | def _url_join(*args): 13 | url = "/" 14 | for arg in args: 15 | arg_split = arg.split("/") 16 | for elem in arg_split: 17 | if elem != "": 18 | url = url + elem + "/" 19 | return url 20 | 21 | 22 | def _get_path(dir_name): 23 | """ 24 | Get path. 25 | """ 26 | 27 | if dir_name: 28 | path = dir_name + "/" 29 | else: 30 | path = "" 31 | return path 32 | 33 | 34 | def _get_subdir_list(dir_name): 35 | """ 36 | Get a list of subdirectories. 37 | """ 38 | 39 | subdir_list = [] 40 | if dir_name: 41 | dirlink = '' 42 | dir_items = dir_name.split('/') 43 | dir_items.pop() 44 | for dirname in dir_items: 45 | dirlink = dirlink + dirname + '/' 46 | subdir_list.append([dirname,dirlink]) 47 | return subdir_list 48 | 49 | 50 | def _get_dir_list(dir_name): 51 | """ 52 | Get a list of directories. 53 | """ 54 | 55 | dir_list = [] 56 | if dir_name: 57 | dir_items = dir_name.split('/') 58 | dirname = dir_items.pop() 59 | dir_list.append(dirname) 60 | dir_list.append(dir_name) 61 | return dir_list 62 | 63 | 64 | def _get_breadcrumbs(query, dir_name, page): 65 | """ 66 | Get breadcrumbs. 67 | """ 68 | 69 | subdir_list = _get_subdir_list(dir_name) 70 | dir_list = _get_dir_list(dir_name) 71 | 72 | breadcrumbs = "" 73 | if not query['pop']: 74 | breadcrumbs = '%s › ' % (URL_HOME,_('Home')) 75 | breadcrumbs = breadcrumbs + '%s' % (URL_ADMIN, query['query_str_total'], 'FileBrowser') 76 | if subdir_list: 77 | for item in subdir_list: 78 | breadcrumbs = breadcrumbs + ' › %s' % (URL_ADMIN, item[1], query['query_str_total'], item[0]) 79 | if page: 80 | if dir_list: 81 | breadcrumbs = breadcrumbs + ' › %s › %s' % (URL_ADMIN, dir_list[1], query['query_str_total'], dir_list[0], _(page)) 82 | else: 83 | breadcrumbs = breadcrumbs + ' › %s' % (_(page)) 84 | elif dir_list: 85 | breadcrumbs = breadcrumbs + ' › %s' % (dir_list[0]) 86 | return mark_safe(breadcrumbs) 87 | 88 | 89 | def _get_sub_query(items, var_1, var_2, var_3): 90 | """ 91 | Get subquery. 92 | """ 93 | 94 | querystring= '' 95 | for k,v in items: 96 | if k != var_1 and k != var_2 and k != var_3: 97 | querystring = querystring + "&" + k + "=" + v 98 | return querystring 99 | 100 | 101 | def _get_query(request_var): 102 | """ 103 | Construct query. 104 | """ 105 | 106 | query = {} 107 | if request_var: 108 | query['query_str_total'] = "?" 109 | for k,v in request_var.items(): 110 | if k in ['o', 'ot', 'q', 'filter_date', 'filter_type', 'pop']: 111 | query['query_str_total'] = query['query_str_total'] + "&" + k + "=" + v 112 | #query['query_str_total'] = "?" + "&".join(["%s=%s" % (k, v) for k, v in request_var.items()]) 113 | query['query_nofilterdate'] = _get_sub_query(request_var.items(), 'filter_date', '', '') 114 | query['query_nofiltertype'] = _get_sub_query(request_var.items(), 'filter_type', '', '') 115 | query['query_nosearch'] = _get_sub_query(request_var.items(), 'q', '', '') 116 | query['query_nosort'] = _get_sub_query(request_var.items(), 'o', 'ot', '') 117 | query['query_nodelete'] = "?" + _get_sub_query(request_var.items(), 'filename', 'type', '') 118 | if request_var.get('pop'): 119 | query['pop'] = "pop=" + request_var.get('pop') 120 | query['pop_toolbar'] = request_var.get('pop') 121 | else: 122 | query['pop'] = '' 123 | query['pop_toolbar'] = "" 124 | else: 125 | query['query_str_total'] = "?" 126 | query['query_nodelete'] = "" 127 | query['pop'] = "" 128 | query['pop_toolbar'] = "" 129 | query['ot'] = request_var.get('ot', 'desc') 130 | query['o'] = request_var.get('o', '3') 131 | query['filter_type'] = request_var.get('filter_type', '') 132 | query['q'] = request_var.get('q', '') 133 | query['filter_date'] = request_var.get('filter_date', '') 134 | if query['ot'] == 'asc': 135 | query['ot_new'] = 'desc' 136 | elif query['ot'] == 'desc': 137 | query['ot_new'] = 'asc' 138 | return query 139 | 140 | 141 | def _get_filterdate(filterDate, dateTime): 142 | """ 143 | Get filterdate. 144 | """ 145 | 146 | returnvalue = '' 147 | dateYear = strftime("%Y", gmtime(dateTime)) 148 | dateMonth = strftime("%m", gmtime(dateTime)) 149 | dateDay = strftime("%d", gmtime(dateTime)) 150 | if filterDate == 'today' and int(dateYear) == int(localtime()[0]) and int(dateMonth) == int(localtime()[1]) and int(dateDay) == int(localtime()[2]): returnvalue = 'true' 151 | elif filterDate == 'thismonth' and dateTime >= time()-2592000: returnvalue = 'true' 152 | elif filterDate == 'thisyear' and int(dateYear) == int(localtime()[0]): returnvalue = 'true' 153 | elif filterDate == 'past7days' and dateTime >= time()-604800: returnvalue = 'true' 154 | return returnvalue 155 | 156 | 157 | def _get_filesize(filesize_long): 158 | """ 159 | Get filesize in a readable format. 160 | """ 161 | 162 | filesize_str = '' 163 | if filesize_long < 1000: 164 | filesize_str = str(filesize_long) + " B" 165 | elif filesize_long >= 1000 and filesize_long < 1000000: 166 | filesize_str = str(filesize_long/1000) + " kB" 167 | elif filesize_long >= 1000000: 168 | filesize_str = str(filesize_long/1000000) + " MB" 169 | return mark_safe(filesize_str) 170 | 171 | 172 | def _make_filedict(file_list): 173 | """ 174 | Make a dict out of the file_list. 175 | This is for better readability in the templates. 176 | """ 177 | 178 | file_dict = [] 179 | for item in file_list: 180 | temp_list = {} 181 | temp_list['filename'] = item[0] 182 | temp_list['filesize_long'] = item[1] 183 | temp_list['filesize_str'] = item[2] 184 | temp_list['date'] = item[3] 185 | temp_list['path_thumb'] = item[4] 186 | temp_list['link'] = item[5] 187 | temp_list['select_link'] = item[6] 188 | temp_list['file_extension'] = item[7] 189 | temp_list['file_type'] = item[8] 190 | temp_list['image_dimensions'] = item[9] 191 | temp_list['thumb_dimensions'] = item[10] 192 | temp_list['filename_lower'] = item[11] 193 | temp_list['flag_makethumb'] = item[12] 194 | temp_list['flag_deletedir'] = item[13] 195 | temp_list['flag_imageversion'] = item[14] 196 | file_dict.append(temp_list) 197 | return file_dict 198 | 199 | 200 | def _get_settings_var(http_post, path): 201 | """ 202 | Get all settings variables. 203 | """ 204 | 205 | settings_var = {} 206 | settings_var['URL_WWW'] = URL_WWW 207 | settings_var['URL_ADMIN'] = URL_ADMIN 208 | settings_var['URL_HOME'] = URL_HOME 209 | settings_var['URL_FILEBROWSER_MEDIA'] = URL_FILEBROWSER_MEDIA 210 | settings_var['URL_TINYMCE'] = URL_TINYMCE 211 | settings_var['PATH_SERVER'] = PATH_SERVER 212 | #settings_var['PATH_FILEBROWSER_MEDIA'] = PATH_FILEBROWSER_MEDIA 213 | settings_var['PATH_TINYMCE'] = PATH_TINYMCE 214 | settings_var['EXTENSIONS'] = EXTENSIONS 215 | settings_var['MAX_UPLOAD_SIZE'] = _get_filesize(MAX_UPLOAD_SIZE) 216 | settings_var['THUMB_PREFIX'] = THUMB_PREFIX 217 | settings_var['THUMBNAIL_SIZE'] = THUMBNAIL_SIZE 218 | settings_var['USE_IMAGE_GENERATOR'] = USE_IMAGE_GENERATOR 219 | settings_var['IMAGE_GENERATOR_DIRECTORY'] = IMAGE_GENERATOR_DIRECTORY 220 | settings_var['IMAGE_GENERATOR_LANDSCAPE'] = IMAGE_GENERATOR_LANDSCAPE 221 | settings_var['IMAGE_GENERATOR_PORTRAIT'] = IMAGE_GENERATOR_PORTRAIT 222 | return settings_var 223 | 224 | 225 | def _handle_file_upload(PATH_SERVER, path, file): 226 | """ 227 | Handle File Upload. 228 | """ 229 | 230 | file_path = os.path.join(PATH_SERVER, path, file.name) 231 | destination = open(file_path, 'wb+') 232 | for chunk in file.chunks(): 233 | destination.write(chunk) 234 | 235 | 236 | def _get_file_type(filename): 237 | """ 238 | Get file type as defined in EXTENSIONS. 239 | """ 240 | 241 | file_extension = os.path.splitext(filename)[1].lower() 242 | file_type = '' 243 | for k,v in EXTENSIONS.iteritems(): 244 | for extension in v: 245 | if file_extension == extension.lower(): 246 | file_type = k 247 | return file_type 248 | 249 | 250 | def _make_image_thumbnail(PATH_SERVER, path, filename): 251 | """ 252 | Make Thumbnail for an Image. 253 | """ 254 | 255 | file_path = os.path.join(PATH_SERVER, path, filename) 256 | thumb_path = os.path.join(PATH_SERVER, path, THUMB_PREFIX + filename) 257 | msg = "" 258 | try: 259 | im = Image.open(file_path) 260 | im.thumbnail(THUMBNAIL_SIZE, Image.ANTIALIAS) 261 | im.save(thumb_path) 262 | except IOError: 263 | msg = "%s: %s" % (file.name, _('Thumbnail creation failed.')) 264 | return msg 265 | 266 | 267 | def _image_generator(PATH_SERVER, path, filename): 268 | """ 269 | Generate Versions for an Image. 270 | """ 271 | 272 | file_path = os.path.join(PATH_SERVER, path, filename) 273 | versions_path = os.path.join(PATH_SERVER, path, filename.replace(".", "_").lower() + IMAGE_GENERATOR_DIRECTORY) 274 | if not os.path.isdir(versions_path): 275 | os.mkdir(versions_path) 276 | os.chmod(versions_path, 0775) 277 | im = Image.open(file_path) 278 | dimensions = im.size 279 | current_width = dimensions[0] 280 | current_height = dimensions[1] 281 | msg = "" 282 | if int(current_width) > int(current_height): 283 | generator_to_use = IMAGE_GENERATOR_LANDSCAPE 284 | else: 285 | generator_to_use = IMAGE_GENERATOR_PORTRAIT 286 | for prefix in generator_to_use: 287 | image_path = os.path.join(versions_path, prefix[0] + filename) 288 | try: 289 | # DIMENSIONS 290 | ratio = decimal.Decimal(0) 291 | ratio = decimal.Decimal(current_width)/decimal.Decimal(current_height) 292 | new_size_width = prefix[1] 293 | new_size_height = int(new_size_width/ratio) 294 | new_size = (new_size_width, new_size_height) 295 | # ONLY MAKE NEW IMAGE VERSION OF ORIGINAL IMAGE IS BIGGER THAN THE NEW VERSION 296 | # OTHERWISE FAIL SILENTLY 297 | if int(current_width) > int(new_size_width): 298 | # NEW IMAGE 299 | new_image = im.resize(new_size, Image.ANTIALIAS) 300 | new_image.save(image_path, quality=90, optimize=1) 301 | # MAKE THUMBNAIL 302 | _make_image_thumbnail(PATH_SERVER, os.path.join(path, filename.replace(".", "_").lower() + IMAGE_GENERATOR_DIRECTORY), prefix[0] + filename) 303 | except IOError: 304 | msg = "%s: %s" % (filename, _('Image creation failed.')) 305 | return msg 306 | 307 | 308 | def _image_crop_generator(PATH_SERVER, path, filename): 309 | """ 310 | Generate Cropped Versions for an Image. 311 | """ 312 | 313 | file_path = os.path.join(PATH_SERVER, path, filename) 314 | versions_path = os.path.join(PATH_SERVER, path, filename.replace(".", "_").lower() + IMAGE_GENERATOR_DIRECTORY) 315 | if not os.path.isdir(versions_path): 316 | os.mkdir(versions_path) 317 | os.chmod(versions_path, 0775) 318 | im = Image.open(file_path) 319 | dimensions = im.size 320 | current_width = dimensions[0] 321 | current_height = dimensions[1] 322 | msg = "" 323 | for prefix in IMAGE_CROP_GENERATOR: 324 | image_path = os.path.join(versions_path, prefix[0] + filename) 325 | try: 326 | # DIMENSIONS 327 | dimensions = im.size 328 | current_width = dimensions[0] 329 | current_height = dimensions[1] 330 | ratio = decimal.Decimal(0) 331 | ratio = decimal.Decimal(current_width)/decimal.Decimal(current_height) 332 | # new_size 333 | # either side of the img must be at least the crop_size_width 334 | new_size_width = prefix[1] 335 | new_size_height = int(new_size_width/ratio) 336 | if new_size_width > new_size_height: 337 | new_size_height = new_size_width 338 | new_size_width = int(new_size_height*ratio) 339 | new_size = (new_size_width, new_size_height) 340 | # crop_size 341 | # trying to crop the middle of the img 342 | crop_size_width = prefix[1] 343 | if prefix[2]: 344 | crop_size_height = prefix[2] 345 | else: 346 | crop_size_height = crop_size_width 347 | upper_left_x = int((new_size_width-crop_size_width)/2) 348 | upper_left_y = int((new_size_height-crop_size_height)/2) 349 | crop_size = (upper_left_x, upper_left_y, upper_left_x+crop_size_width, upper_left_y+crop_size_height) 350 | # NEW IMAGE 351 | im = Image.open(file_path) 352 | # resize img first 353 | new_image = im.resize(new_size, Image.ANTIALIAS) 354 | # then crop 355 | cropped_image = new_image.crop(crop_size) 356 | cropped_image.save(image_path, quality=90, optimize=1) 357 | # MAKE THUMBNAIL 358 | _make_image_thumbnail(PATH_SERVER, os.path.join(path, filename.replace(".", "_").lower() + IMAGE_GENERATOR_DIRECTORY), prefix[0] + filename) 359 | except IOError: 360 | msg = "%s: %s" % (filename, _('Image creation failed.')) 361 | return msg 362 | 363 | 364 | def _is_image_version(file): 365 | image_version = False 366 | for item in IMAGE_GENERATOR_LANDSCAPE: 367 | if file.startswith(item[0]): 368 | image_version = True 369 | for item in IMAGE_GENERATOR_PORTRAIT: 370 | if file.startswith(item[0]): 371 | image_version = True 372 | for item in IMAGE_CROP_GENERATOR: 373 | if file.startswith(item[0]): 374 | image_version = True 375 | return image_version 376 | -------------------------------------------------------------------------------- /filebrowser/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | from django.template import RequestContext as Context 3 | from django.http import HttpResponseRedirect 4 | from django.contrib.admin.views.decorators import staff_member_required 5 | from django.views.decorators.cache import never_cache 6 | from django.utils.translation import ugettext as _ 7 | from django.utils.safestring import mark_safe 8 | from time import gmtime, strftime, localtime, mktime, time 9 | import os, string, ftplib, re, Image, decimal 10 | from django import forms 11 | 12 | # get settings 13 | from filebrowser.fb_settings import * 14 | # get functions 15 | from filebrowser.functions import _get_path, _get_subdir_list, _get_dir_list, _get_breadcrumbs, _get_sub_query, _get_query, _get_filterdate, _get_filesize, _make_filedict, _get_settings_var, _handle_file_upload, _get_file_type, _make_image_thumbnail, _image_generator, _image_crop_generator, _is_image_version 16 | # get forms 17 | from filebrowser.forms import MakeDirForm, RenameForm, UploadForm, BaseUploadFormSet 18 | 19 | 20 | def index(request, dir_name=None): 21 | """ 22 | Show list of files on a server-directory. 23 | """ 24 | 25 | path = _get_path(dir_name) 26 | query = _get_query(request.GET) 27 | 28 | # INITIAL VARIABLES 29 | results_var = {'results_total': 0, 'results_current': 0, 'delete_total': 0, 'change_total': 0, 'imagegenerator_total': 0 } 30 | counter = {} 31 | for k,v in EXTENSIONS.iteritems(): 32 | counter[k] = 0 33 | 34 | dir_list = os.listdir(os.path.join(PATH_SERVER, path)) 35 | file_list = [] 36 | for file in dir_list: 37 | 38 | # VARIABLES 39 | var_filesize_long = '' # filesize 40 | var_filesize_str = '' # filesize in B, kB, MB 41 | var_date = '' # YYYY-MM-dd 42 | var_path_thumb = '' # path to thumbnail 43 | var_link = '' # link to file (using URL_WWW), link to folder (using URL_ADMIN) 44 | var_select_link = '' # link to file (using URL_WWW) 45 | var_file_extension = '' # see EXTENSIONS in fb_settings.py 46 | var_file_type = '' # Folder, Image, Video, Document, Sound, Code, ... 47 | var_image_dimensions = '' # Image Dimensions (width, height) 48 | var_thumb_dimensions = '' # Thumbnail Dimensions (width, height) 49 | var_flag_makethumb = False # True, if Image has no Thumbnail. 50 | var_flag_deletedir = False # True, if Directory is empty. 51 | var_image_version = False # True, if Image is generated with ImageGenerator. 52 | 53 | # DON'T DISPLAY FILES STARTING WITH %THUMB_PREFIX% OR "." 54 | if re.compile(THUMB_PREFIX, re.M).search(file) or \ 55 | file.startswith('.'): # ... or with a '.' \ 56 | continue 57 | else: 58 | results_var['results_total'] += 1 59 | 60 | # SIZE 61 | var_filesize_long = os.path.getsize(os.path.join(PATH_SERVER, path, file)) 62 | var_filesize_str = _get_filesize(var_filesize_long) 63 | 64 | # DATE / TIME 65 | date_time = os.path.getmtime(os.path.join(PATH_SERVER, path, file)) 66 | var_date = strftime("%Y-%m-%d", gmtime(date_time)) 67 | 68 | # EXTENSION / FLAG_EMPTYDIR / DELETE_TOTAL 69 | if os.path.isfile(os.path.join(PATH_SERVER, path, file)): # file 70 | var_file_extension = os.path.splitext(file)[1].lower() 71 | var_select_link = var_link = "%s%s%s" % (URL_WWW, path, file) 72 | elif os.path.isdir(os.path.join(PATH_SERVER, path, file)): # folder 73 | var_link = "%s%s%s" % (URL_ADMIN, path, file) 74 | var_select_link = "%s%s%s/" % (URL_WWW, path, file) 75 | if not os.listdir(os.path.join(PATH_SERVER, path, file)): 76 | var_flag_deletedir = True # only empty directories are allowed to be deleted 77 | 78 | # FILETYPE / COUNTER 79 | var_file_type = _get_file_type(file) 80 | if var_file_type: 81 | counter[var_file_type] += 1 82 | 83 | # DIMENSIONS / MAKETHUMB / SELECT 84 | if var_file_type == 'Image': 85 | try: 86 | im = Image.open(os.path.join(PATH_SERVER, path, file)) 87 | var_image_dimensions = im.size 88 | var_path_thumb = "%s%s%s%s" % (URL_WWW, path, THUMB_PREFIX, file) 89 | try: 90 | thumb = Image.open(os.path.join(PATH_SERVER, path, THUMB_PREFIX + file)) 91 | var_thumb_dimensions = thumb.size 92 | except: 93 | # if thumbnail does not exist, show makethumb-Icon instead. 94 | var_path_thumb = settings.URL_FILEBROWSER_MEDIA + 'img/filebrowser_Thumb.gif' 95 | var_flag_makethumb = True 96 | except: 97 | # if image is corrupt, change filetype to not defined 98 | var_file_type = '' 99 | # check, if image is generated with ImageGenerator 100 | var_image_version = _is_image_version(file) 101 | if var_image_version == False: 102 | results_var['imagegenerator_total'] += 1 103 | 104 | # FILTER / SEARCH 105 | flag_extend = False 106 | if query['filter_type'] != '' and query['filter_date'] != '' and file_type == query['filter_type'] and _get_filterdate(query['filter_date'], date_time): 107 | flag_extend = True 108 | elif query['filter_type'] != '' and query['filter_date'] == '' and var_file_type == query['filter_type']: 109 | flag_extend = True 110 | elif query['filter_type'] == '' and query['filter_date'] != '' and _get_filterdate(query['filter_date'], date_time): 111 | flag_extend = True 112 | elif query['filter_type'] == '' and query['filter_date'] == '': 113 | flag_extend = True 114 | if query['q'] and not re.compile(query['q'].lower(), re.M).search(file.lower()): 115 | flag_extend = False 116 | 117 | # APPEND FILE_LIST 118 | if flag_extend == True: 119 | file_list.append([file, var_filesize_long, var_filesize_str, var_date, var_path_thumb, var_link, var_select_link, var_file_extension, var_file_type, var_image_dimensions, var_thumb_dimensions, file.lower(), var_flag_makethumb, var_flag_deletedir, var_image_version]) 120 | 121 | # SORT LIST 122 | file_list.sort(lambda x, y: cmp(x[int(query['o'])], y[int(query['o'])])) 123 | if query['ot'] == "desc": 124 | file_list.reverse() 125 | 126 | # MAKE DICTIONARY (for better readability in the templates) 127 | file_dict = _make_filedict(file_list) 128 | 129 | # RESULTS 130 | results_var['results_current'] = len(file_list) 131 | for file in file_dict: 132 | if file['file_type'] == 'Image': 133 | results_var['change_total'] += 1 134 | if file['file_type'] != 'Folder': 135 | results_var['delete_total'] += 1 136 | elif file['file_type'] == 'Folder' and file['flag_deletedir'] == True: 137 | results_var['delete_total'] += 1 138 | 139 | return render_to_response('filebrowser/index.html', { 140 | 'dir': dir_name, 141 | 'file_dict': file_dict, 142 | 'results_var': results_var, 143 | 'query': query, 144 | 'counter': counter, 145 | 'settings_var': _get_settings_var(request.META['HTTP_HOST'], path), 146 | 'breadcrumbs': _get_breadcrumbs(_get_query(request.GET), dir_name, ''), 147 | 'title': _('FileBrowser'), 148 | }, context_instance=Context(request)) 149 | index = staff_member_required(never_cache(index)) 150 | 151 | 152 | def mkdir(request, dir_name=None): 153 | """ 154 | Make directory 155 | """ 156 | 157 | path = _get_path(dir_name) 158 | query = _get_query(request.GET) 159 | 160 | if request.method == 'POST': 161 | form = MakeDirForm(PATH_SERVER, path, request.POST) 162 | if form.is_valid(): 163 | server_path = os.path.join(PATH_SERVER, path, form.cleaned_data['dir_name'].lower()) 164 | try: 165 | os.mkdir(server_path) 166 | os.chmod(server_path, 0775) 167 | 168 | # MESSAGE & REDIRECT 169 | msg = _('The directory %s was successfully created.') % (form.cleaned_data['dir_name'].lower()) 170 | request.user.message_set.create(message=msg) 171 | # on redirect, sort by date desc to see the new directory on top of the list 172 | return HttpResponseRedirect(URL_ADMIN + path + "?&ot=desc&o=3&" + query['pop']) 173 | except OSError, (errno, strerror): 174 | if errno == 13: 175 | form.errors['dir_name'] = forms.util.ErrorList([_('Permission denied.')]) 176 | else: 177 | form.errors['dir_name'] = forms.util.ErrorList([_('Error creating directory.')]) 178 | else: 179 | form = MakeDirForm(PATH_SERVER, path) 180 | 181 | return render_to_response('filebrowser/makedir.html', { 182 | 'form': form, 183 | 'query': query, 184 | 'settings_var': _get_settings_var(request.META['HTTP_HOST'], path), 185 | 'breadcrumbs': _get_breadcrumbs(_get_query(request.GET), dir_name, 'Make Directory'), 186 | 'title': _('Make directory'), 187 | }, context_instance=Context(request)) 188 | mkdir = staff_member_required(never_cache(mkdir)) 189 | 190 | 191 | def upload(request, dir_name=None): 192 | """ 193 | Multipe Upload. 194 | """ 195 | 196 | from django.forms.formsets import formset_factory 197 | 198 | path = _get_path(dir_name) 199 | query = _get_query(request.GET) 200 | 201 | # PIL's Error "Suspension not allowed here" work around: 202 | # s. http://mail.python.org/pipermail/image-sig/1999-August/000816.html 203 | import ImageFile 204 | ImageFile.MAXBLOCK = 1000000 # default is 64k 205 | 206 | UploadFormSet = formset_factory(UploadForm, formset=BaseUploadFormSet, extra=5) 207 | if request.method == 'POST': 208 | formset = UploadFormSet(data=request.POST, files=request.FILES, path_server=PATH_SERVER, path=path) 209 | if formset.is_valid(): 210 | for cleaned_data in formset.cleaned_data: 211 | if cleaned_data: 212 | # UPLOAD FILE 213 | _handle_file_upload(PATH_SERVER, path, cleaned_data['file']) 214 | if _get_file_type(cleaned_data['file'].name) == "Image": 215 | # MAKE THUMBNAIL 216 | _make_image_thumbnail(PATH_SERVER, path, cleaned_data['file'].name) 217 | # IMAGE GENERATOR 218 | if cleaned_data['use_image_generator'] and (IMAGE_GENERATOR_LANDSCAPE != "" or IMAGE_GENERATOR_PORTRAIT != ""): 219 | _image_generator(PATH_SERVER, path, cleaned_data['file'].name) 220 | # GENERATE CROPPED/RECTANGULAR IMAGE 221 | if cleaned_data['use_image_generator'] and IMAGE_CROP_GENERATOR != "": 222 | _image_crop_generator(PATH_SERVER, path, cleaned_data['file'].name) 223 | # MESSAGE & REDIRECT 224 | msg = _('Upload successful.') 225 | request.user.message_set.create(message=msg) 226 | # on redirect, sort by date desc to see the uploaded files on top of the list 227 | redirect_url = URL_ADMIN + path + "?&ot=desc&o=3&" + query['pop'] 228 | return HttpResponseRedirect(redirect_url) 229 | else: 230 | formset = UploadFormSet(path_server=PATH_SERVER, path=path) 231 | 232 | return render_to_response('filebrowser/upload.html', { 233 | 'formset': formset, 234 | 'dir': dir_name, 235 | 'query': _get_query(request.GET), 236 | 'settings_var': _get_settings_var(request.META['HTTP_HOST'], path), 237 | 'breadcrumbs': _get_breadcrumbs(_get_query(request.GET), dir_name, 'Multiple Upload'), 238 | 'title': _('Select files to upload'), 239 | }, context_instance=Context(request)) 240 | upload = staff_member_required(never_cache(upload)) 241 | 242 | 243 | def makethumb(request, dir_name=None, file_name=None): 244 | """ 245 | Make Thumbnail(s) for existing Image or Directory 246 | This is useful if someone uploads images via FTP, not using the 247 | upload functionality of the FileBrowser. 248 | """ 249 | 250 | path = _get_path(dir_name) 251 | query = _get_query(request.GET) 252 | 253 | if file_name: 254 | # MAKE THUMB FOR SINGLE IMAGE 255 | file_path = os.path.join(PATH_SERVER, path, file_name) 256 | if os.path.isfile(file_path): 257 | _make_image_thumbnail(PATH_SERVER, path, file_name) 258 | else: 259 | # MAKE THUMBS FOR WHOLE DIRECTORY 260 | dir_path = os.path.join(PATH_SERVER, path) 261 | dir_list = os.listdir(dir_path) 262 | for file in dir_list: 263 | if os.path.isfile(os.path.join(PATH_SERVER, path, file)) and not os.path.isfile(os.path.join(PATH_SERVER, path, THUMB_PREFIX + file)) and not re.compile(THUMB_PREFIX, re.M).search(file) and _get_file_type(file) == "Image": 264 | _make_image_thumbnail(PATH_SERVER, path, file) 265 | 266 | # MESSAGE & REDIRECT 267 | msg = _('Thumbnail creation successful.') 268 | request.user.message_set.create(message=msg) 269 | return HttpResponseRedirect(URL_ADMIN + path + query['query_str_total']) 270 | 271 | return render_to_response('filebrowser/index.html', { 272 | 'dir': dir_name, 273 | 'query': query, 274 | 'settings_var': _get_settings_var(request.META['HTTP_HOST'], path), 275 | 'breadcrumbs': _get_breadcrumbs(_get_query(request.GET), dir_name, '') 276 | }, context_instance=Context(request)) 277 | makethumb = staff_member_required(never_cache(makethumb)) 278 | 279 | 280 | def delete(request, dir_name=None): 281 | """ 282 | Delete existing File/Directory. 283 | If file is an Image, also delete thumbnail. 284 | When trying to delete a directory, the directory has to be empty. 285 | """ 286 | 287 | path = _get_path(dir_name) 288 | query = _get_query(request.GET) 289 | msg = "" 290 | 291 | if request.GET: 292 | if request.GET.get('type') != "Folder": 293 | server_path = os.path.join(PATH_SERVER, path, request.GET.get('filename')) 294 | try: 295 | 296 | # DELETE FILE 297 | os.unlink(server_path) 298 | # TRY DELETING THUMBNAIL 299 | path_thumb = os.path.join(PATH_SERVER, path, THUMB_PREFIX + request.GET.get('filename')) 300 | try: 301 | os.unlink(path_thumb) 302 | except OSError: 303 | pass 304 | # TRY DELETING IMAGE_VERSIONS 305 | versions_path = os.path.join(PATH_SERVER, path, request.GET.get('filename').replace(".", "_").lower() + IMAGE_GENERATOR_DIRECTORY) 306 | try: 307 | dir_list = os.listdir(versions_path) 308 | for file in dir_list: 309 | file_path = os.path.join(versions_path, file) 310 | os.unlink(file_path) 311 | os.rmdir(versions_path) 312 | except OSError: 313 | pass 314 | 315 | # MESSAGE & REDIRECT 316 | msg = _('The file %s was successfully deleted.') % (request.GET.get('filename').lower()) 317 | request.user.message_set.create(message=msg) 318 | return HttpResponseRedirect(URL_ADMIN + path + query['query_nodelete']) 319 | except OSError: 320 | # todo: define error message 321 | msg = OSError 322 | else: 323 | server_path = os.path.join(PATH_SERVER, path, request.GET.get('filename')) 324 | try: 325 | os.rmdir(server_path) 326 | 327 | # MESSAGE & REDIRECT 328 | msg = _('The directory %s was successfully deleted.') % (request.GET.get('filename').lower()) 329 | request.user.message_set.create(message=msg) 330 | return HttpResponseRedirect(URL_ADMIN + path + query['query_nodelete']) 331 | except OSError: 332 | # todo: define error message 333 | msg = OSError 334 | 335 | if msg: 336 | request.user.message_set.create(message=msg) 337 | 338 | return render_to_response('filebrowser/index.html', { 339 | 'dir': dir_name, 340 | 'file': request.GET.get('filename', ''), 341 | 'query': query, 342 | 'settings_var': _get_settings_var(request.META['HTTP_HOST'], path), 343 | 'breadcrumbs': _get_breadcrumbs(_get_query(request.GET), dir_name, '') 344 | }, context_instance=Context(request)) 345 | delete = staff_member_required(never_cache(delete)) 346 | 347 | 348 | def rename(request, dir_name=None, file_name=None): 349 | """ 350 | Rename existing File/Directory. 351 | """ 352 | 353 | path = _get_path(dir_name) 354 | query = _get_query(request.GET) 355 | 356 | if os.path.isfile(os.path.join(PATH_SERVER, path, file_name)): # file 357 | file_type = _get_file_type(file_name) 358 | file_extension = os.path.splitext(file_name)[1].lower() 359 | else: 360 | file_extension = "" 361 | file_type = "" 362 | 363 | if request.method == 'POST': 364 | form = RenameForm(PATH_SERVER, path, file_extension, request.POST) 365 | if form.is_valid(): 366 | old_path = os.path.join(PATH_SERVER, path, file_name) 367 | new_path = os.path.join(PATH_SERVER, path, request.POST.get('name').lower() + file_extension) 368 | try: 369 | os.rename(old_path, new_path) 370 | 371 | # RENAME IMAGE_THUMBNAILS 372 | if file_type == 'Image': 373 | old_thumb_path = os.path.join(PATH_SERVER, path, THUMB_PREFIX + file_name) 374 | new_thumb_path = os.path.join(PATH_SERVER, path, THUMB_PREFIX + request.POST.get('name').lower() + file_extension) 375 | try: 376 | os.rename(old_thumb_path, new_thumb_path) 377 | except OSError, (errno, strerror): 378 | form.errors['name'] = forms.util.ErrorList([_('Error renaming Thumbnail.')]) 379 | 380 | # RENAME IMAGE VERSIONS? TOO MUCH MAGIC? 381 | 382 | # MESSAGE & REDIRECT 383 | if not form.errors: 384 | msg = _('Renaming was successful.') 385 | request.user.message_set.create(message=msg) 386 | # on redirect, sort by date desc to see the new stuff on top of the list 387 | return HttpResponseRedirect(URL_ADMIN + path + "?&ot=desc&o=3&" + query['pop']) 388 | except OSError, (errno, strerror): 389 | form.errors['name'] = forms.util.ErrorList([_('Error.')]) 390 | else: 391 | form = RenameForm(PATH_SERVER, path, file_extension) 392 | 393 | return render_to_response('filebrowser/rename.html', { 394 | 'form': form, 395 | 'query': query, 396 | 'file_extension': file_extension, 397 | 'settings_var': _get_settings_var(request.META['HTTP_HOST'], path), 398 | 'breadcrumbs': _get_breadcrumbs(_get_query(request.GET), dir_name, 'Rename'), 399 | 'title': _('Rename "%s"') % file_name, 400 | }, context_instance=Context(request)) 401 | rename = staff_member_required(never_cache(rename)) 402 | 403 | 404 | def generateimages(request, dir_name=None, file_name=None): 405 | """ 406 | Generate Image Versions for existing singe Image or a whole Directory. 407 | This is useful if someone uploads images via FTP, not using the 408 | upload functionality of the FileBrowser. 409 | """ 410 | 411 | path = _get_path(dir_name) 412 | query = _get_query(request.GET) 413 | 414 | if file_name: 415 | # GENERATE IMAGES 416 | if IMAGE_GENERATOR_LANDSCAPE != "" or IMAGE_GENERATOR_PORTRAIT != "": 417 | _image_generator(PATH_SERVER, path, file_name) 418 | # GENERATE CROPPED/RECTANGULAR IMAGE 419 | if IMAGE_CROP_GENERATOR != "": 420 | _image_crop_generator(PATH_SERVER, path, file_name) 421 | else: 422 | # GENERATE IMAGES FOR WHOLE DIRECTORY 423 | dir_path = os.path.join(PATH_SERVER, path) 424 | dir_list = os.listdir(dir_path) 425 | for file in dir_list: 426 | if os.path.isfile(os.path.join(PATH_SERVER, path, file)) and not re.compile(THUMB_PREFIX, re.M).search(file) and _get_file_type(file) == "Image": 427 | # GENERATE IMAGES 428 | if IMAGE_GENERATOR_LANDSCAPE != "" or IMAGE_GENERATOR_PORTRAIT != "": 429 | _image_generator(PATH_SERVER, path, file) 430 | # GENERATE CROPPED/RECTANGULAR IMAGE 431 | if IMAGE_CROP_GENERATOR != "": 432 | _image_crop_generator(PATH_SERVER, path, file) 433 | 434 | # MESSAGE & REDIRECT 435 | msg = _('Successfully generated Images.') 436 | request.user.message_set.create(message=msg) 437 | return HttpResponseRedirect(URL_ADMIN + path + query['query_str_total']) 438 | 439 | return render_to_response('filebrowser/index.html', { 440 | 'dir': dir_name, 441 | 'query': query, 442 | 'settings_var': _get_settings_var(request.META['HTTP_HOST'], path), 443 | 'breadcrumbs': _get_breadcrumbs(_get_query(request.GET), dir_name, '') 444 | }, context_instance=Context(request)) 445 | makethumb = staff_member_required(never_cache(makethumb)) 446 | 447 | 448 | --------------------------------------------------------------------------------