##// END OF EJS Templates
Allow settings max file size to 0 to disable the size check at all
neko259 -
r1842:98d46054 default
parent child Browse files
Show More
@@ -1,157 +1,157 b''
1 """
1 """
2 This module contains helper functions and helper classes.
2 This module contains helper functions and helper classes.
3 """
3 """
4 import hashlib
4 import hashlib
5 import uuid
5 import uuid
6
6
7 from boards.abstracts.constants import FILE_DIRECTORY
7 from boards.abstracts.constants import FILE_DIRECTORY
8 from random import random
8 from random import random
9 import time
9 import time
10 import hmac
10 import hmac
11
11
12 from django.core.cache import cache
12 from django.core.cache import cache
13 from django.db.models import Model
13 from django.db.models import Model
14 from django import forms
14 from django import forms
15 from django.template.defaultfilters import filesizeformat
15 from django.template.defaultfilters import filesizeformat
16 from django.utils import timezone
16 from django.utils import timezone
17 from django.utils.translation import ugettext_lazy as _
17 from django.utils.translation import ugettext_lazy as _
18 import magic
18 import magic
19 import os
19 import os
20
20
21 import boards
21 import boards
22 from boards.settings import get_bool
22 from boards.settings import get_bool
23 from neboard import settings
23 from neboard import settings
24
24
25 CACHE_KEY_DELIMITER = '_'
25 CACHE_KEY_DELIMITER = '_'
26
26
27 HTTP_FORWARDED = 'HTTP_X_FORWARDED_FOR'
27 HTTP_FORWARDED = 'HTTP_X_FORWARDED_FOR'
28 META_REMOTE_ADDR = 'REMOTE_ADDR'
28 META_REMOTE_ADDR = 'REMOTE_ADDR'
29
29
30 SETTING_MESSAGES = 'Messages'
30 SETTING_MESSAGES = 'Messages'
31 SETTING_ANON_MODE = 'AnonymousMode'
31 SETTING_ANON_MODE = 'AnonymousMode'
32
32
33 ANON_IP = '127.0.0.1'
33 ANON_IP = '127.0.0.1'
34
34
35 FILE_EXTENSION_DELIMITER = '.'
35 FILE_EXTENSION_DELIMITER = '.'
36
36
37
37
38 def is_anonymous_mode():
38 def is_anonymous_mode():
39 return get_bool(SETTING_MESSAGES, SETTING_ANON_MODE)
39 return get_bool(SETTING_MESSAGES, SETTING_ANON_MODE)
40
40
41
41
42 def get_client_ip(request):
42 def get_client_ip(request):
43 if is_anonymous_mode():
43 if is_anonymous_mode():
44 ip = ANON_IP
44 ip = ANON_IP
45 else:
45 else:
46 x_forwarded_for = request.META.get(HTTP_FORWARDED)
46 x_forwarded_for = request.META.get(HTTP_FORWARDED)
47 if x_forwarded_for:
47 if x_forwarded_for:
48 ip = x_forwarded_for.split(',')[-1].strip()
48 ip = x_forwarded_for.split(',')[-1].strip()
49 else:
49 else:
50 ip = request.META.get(META_REMOTE_ADDR)
50 ip = request.META.get(META_REMOTE_ADDR)
51 return ip
51 return ip
52
52
53
53
54 # TODO The output format is not epoch because it includes microseconds
54 # TODO The output format is not epoch because it includes microseconds
55 def datetime_to_epoch(datetime):
55 def datetime_to_epoch(datetime):
56 return int(time.mktime(timezone.localtime(
56 return int(time.mktime(timezone.localtime(
57 datetime,timezone.get_current_timezone()).timetuple())
57 datetime,timezone.get_current_timezone()).timetuple())
58 * 1000000 + datetime.microsecond)
58 * 1000000 + datetime.microsecond)
59
59
60
60
61 def get_websocket_token(user_id='', timestamp=''):
61 def get_websocket_token(user_id='', timestamp=''):
62 """
62 """
63 Create token to validate information provided by new connection.
63 Create token to validate information provided by new connection.
64 """
64 """
65
65
66 sign = hmac.new(settings.CENTRIFUGE_PROJECT_SECRET.encode())
66 sign = hmac.new(settings.CENTRIFUGE_PROJECT_SECRET.encode())
67 sign.update(settings.CENTRIFUGE_PROJECT_ID.encode())
67 sign.update(settings.CENTRIFUGE_PROJECT_ID.encode())
68 sign.update(user_id.encode())
68 sign.update(user_id.encode())
69 sign.update(timestamp.encode())
69 sign.update(timestamp.encode())
70 token = sign.hexdigest()
70 token = sign.hexdigest()
71
71
72 return token
72 return token
73
73
74
74
75 # TODO Test this carefully
75 # TODO Test this carefully
76 def cached_result(key_method=None):
76 def cached_result(key_method=None):
77 """
77 """
78 Caches method result in the Django's cache system, persisted by object name,
78 Caches method result in the Django's cache system, persisted by object name,
79 object name, model id if object is a Django model, args and kwargs if any.
79 object name, model id if object is a Django model, args and kwargs if any.
80 """
80 """
81 def _cached_result(function):
81 def _cached_result(function):
82 def inner_func(obj, *args, **kwargs):
82 def inner_func(obj, *args, **kwargs):
83 cache_key_params = [obj.__class__.__name__, function.__name__]
83 cache_key_params = [obj.__class__.__name__, function.__name__]
84
84
85 cache_key_params += args
85 cache_key_params += args
86 for key, value in kwargs:
86 for key, value in kwargs:
87 cache_key_params.append(key + ':' + value)
87 cache_key_params.append(key + ':' + value)
88
88
89 if isinstance(obj, Model):
89 if isinstance(obj, Model):
90 cache_key_params.append(str(obj.id))
90 cache_key_params.append(str(obj.id))
91
91
92 if key_method is not None:
92 if key_method is not None:
93 cache_key_params += [str(arg) for arg in key_method(obj)]
93 cache_key_params += [str(arg) for arg in key_method(obj)]
94
94
95 cache_key = CACHE_KEY_DELIMITER.join(cache_key_params)
95 cache_key = CACHE_KEY_DELIMITER.join(cache_key_params)
96
96
97 persisted_result = cache.get(cache_key)
97 persisted_result = cache.get(cache_key)
98 if persisted_result is not None:
98 if persisted_result is not None:
99 result = persisted_result
99 result = persisted_result
100 else:
100 else:
101 result = function(obj, *args, **kwargs)
101 result = function(obj, *args, **kwargs)
102 if result is not None:
102 if result is not None:
103 cache.set(cache_key, result)
103 cache.set(cache_key, result)
104
104
105 return result
105 return result
106
106
107 return inner_func
107 return inner_func
108 return _cached_result
108 return _cached_result
109
109
110
110
111 def get_file_hash(file) -> str:
111 def get_file_hash(file) -> str:
112 md5 = hashlib.md5()
112 md5 = hashlib.md5()
113 for chunk in file.chunks():
113 for chunk in file.chunks():
114 md5.update(chunk)
114 md5.update(chunk)
115 return md5.hexdigest()
115 return md5.hexdigest()
116
116
117
117
118 def validate_file_size(size: int):
118 def validate_file_size(size: int):
119 max_size = boards.settings.get_int('Forms', 'MaxFileSize')
119 max_size = boards.settings.get_int('Forms', 'MaxFileSize')
120 if size > max_size:
120 if max_size > 0 and size > max_size:
121 raise forms.ValidationError(
121 raise forms.ValidationError(
122 _('File must be less than %s but is %s.')
122 _('File must be less than %s but is %s.')
123 % (filesizeformat(max_size), filesizeformat(size)))
123 % (filesizeformat(max_size), filesizeformat(size)))
124
124
125
125
126 def get_extension(filename):
126 def get_extension(filename):
127 return filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]
127 return filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]
128
128
129
129
130 def get_upload_filename(model_instance, old_filename):
130 def get_upload_filename(model_instance, old_filename):
131 extension = get_extension(old_filename)
131 extension = get_extension(old_filename)
132 new_name = '{}.{}'.format(uuid.uuid4(), extension)
132 new_name = '{}.{}'.format(uuid.uuid4(), extension)
133
133
134 return os.path.join(FILE_DIRECTORY, new_name)
134 return os.path.join(FILE_DIRECTORY, new_name)
135
135
136
136
137 def get_file_mimetype(file) -> str:
137 def get_file_mimetype(file) -> str:
138 file_type = magic.from_buffer(file.chunks().__next__(), mime=True)
138 file_type = magic.from_buffer(file.chunks().__next__(), mime=True)
139 if file_type is None:
139 if file_type is None:
140 file_type = 'application/octet-stream'
140 file_type = 'application/octet-stream'
141 elif type(file_type) == bytes:
141 elif type(file_type) == bytes:
142 file_type = file_type.decode()
142 file_type = file_type.decode()
143 return file_type
143 return file_type
144
144
145
145
146 def get_domain(url: str) -> str:
146 def get_domain(url: str) -> str:
147 """
147 """
148 Gets domain from an URL with random number of domain levels.
148 Gets domain from an URL with random number of domain levels.
149 """
149 """
150 domain_parts = url.split('/')
150 domain_parts = url.split('/')
151 if len(domain_parts) >= 2:
151 if len(domain_parts) >= 2:
152 full_domain = domain_parts[2]
152 full_domain = domain_parts[2]
153 else:
153 else:
154 full_domain = ''
154 full_domain = ''
155
155
156 return full_domain
156 return full_domain
157
157
General Comments 0
You need to be logged in to leave comments. Login now