attachmentmodel.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. from datetime import date
  2. from time import time
  3. import hashlib
  4. from path import path
  5. from PIL import Image
  6. from django.conf import settings
  7. from django.db import models
  8. from django.utils import timezone
  9. from django.utils.translation import ugettext_lazy as _
  10. from floppyforms import ValidationError
  11. class AttachmentManager(models.Manager):
  12. def allow_more_orphans(self):
  13. if Attachment.objects.filter(post__isnull=True).count() > settings.ORPHAN_ATTACHMENTS_LIMIT:
  14. raise ValidationError(_("Too many users are currently uploading files. Please try agian later."))
  15. class Attachment(models.Model):
  16. hash_id = models.CharField(max_length=8, db_index=True)
  17. filetype = models.ForeignKey('AttachmentType')
  18. forum = models.ForeignKey('Forum', null=True, blank=True, on_delete=models.SET_NULL)
  19. thread = models.ForeignKey('Thread', null=True, blank=True, on_delete=models.SET_NULL)
  20. post = models.ForeignKey('Post', null=True, blank=True, on_delete=models.SET_NULL)
  21. user = models.ForeignKey('User', null=True, blank=True, on_delete=models.SET_NULL)
  22. user_name = models.CharField(max_length=255)
  23. user_name_slug = models.CharField(max_length=255)
  24. ip = models.GenericIPAddressField()
  25. agent = models.CharField(max_length=255)
  26. date = models.DateTimeField(default=timezone.now)
  27. session = models.CharField(max_length=255, db_index=True)
  28. name = models.CharField(max_length=255)
  29. content_type = models.CharField(max_length=255)
  30. path = models.CharField(max_length=255)
  31. size = models.PositiveIntegerField(max_length=255)
  32. objects = AttachmentManager()
  33. class Meta:
  34. app_label = 'misago'
  35. def delete(self, *args, **kwargs):
  36. try:
  37. file_path = self.file_path
  38. if file_path.exists() and not file_path.isdir():
  39. file_path.unlink()
  40. except Exception:
  41. pass
  42. try:
  43. file_path = self.thumb_path
  44. if thumb_path.exists() and not thumb_path.isdir():
  45. thumb_path.unlink()
  46. except Exception:
  47. pass
  48. super(Attachment, self).delete(*args, **kwargs)
  49. def delete_from_post(self):
  50. if self.post_id:
  51. self.post.attachments = [attachment
  52. for attachment in self.post.attachments
  53. if attachment.pk != self.pk]
  54. self.post.save(force_update=True)
  55. @property
  56. def is_image(self):
  57. IMAGES_EXTENSIONS = ('.png', '.gif', '.jpg', '.jpeg')
  58. name = self.name.lower()
  59. for extension in IMAGES_EXTENSIONS:
  60. if name[len(extension) * -1:] == extension:
  61. return extension[1:]
  62. return False
  63. @property
  64. def file_path(self):
  65. return path(settings.ATTACHMENTS_ROOT + self.path)
  66. @property
  67. def thumb_path(self):
  68. return path(unicode(self.file_path).replace('.', '_thumb.'))
  69. def use_file(self, uploaded_file):
  70. self.name = self.clean_name(uploaded_file.name)
  71. self.content_type = uploaded_file.content_type
  72. self.size = uploaded_file.size
  73. self.store_file(uploaded_file)
  74. def clean_name(self, filename):
  75. for char in '=[]()<>\\/"\'':
  76. filename = filename.replace(char, '')
  77. if len(filename) > 100:
  78. filename = filename[-100:]
  79. return filename
  80. def store_file(self, uploaded_file):
  81. datenow = date.today()
  82. current_dir = '%s-%s-%s' % (datenow.month, datenow.day, datenow.year)
  83. full_dir = path(settings.ATTACHMENTS_ROOT + current_dir)
  84. full_dir.mkdir_p()
  85. filename = hashlib.md5('%s:%s:%s' % (self.user.pk, int(time()), settings.SECRET_KEY)).hexdigest()
  86. if self.is_image:
  87. filename += '.%s' % self.is_image
  88. self.path = '%s/%s' % (current_dir, filename)
  89. with open('%s/%s' % (full_dir, filename), 'wb+') as destination:
  90. for chunk in uploaded_file.chunks():
  91. destination.write(chunk)
  92. if self.is_image:
  93. self.make_thumb()
  94. def make_thumb(self):
  95. try:
  96. image = Image.open(self.file_path)
  97. image.thumbnail((800, 600), Image.ANTIALIAS)
  98. image.save(self.thumb_path)
  99. except IOError:
  100. pass
  101. def generate_hash_id(self, seed):
  102. unique_hash = seed
  103. for i in xrange(100):
  104. unique_hash = hashlib.sha256('%s:%s' % (settings.SECRET_KEY, unique_hash)).hexdigest()
  105. self.hash_id = unique_hash[:8]