49 | {% else %}
50 |
51 | {% endif %}
52 |
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 %}
{{ 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 |
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 |
--------------------------------------------------------------------------------