import re import os import struct from django.forms import ModelForm from django import forms from models import Geometry facet_pattern = re.compile(r'facet normal\s+[0-9.e+-]+\s+[0-9.e+-]+\s+[0-9.e+-]+') loop_pattern = re.compile(r'outer\s+loop') vertex_pattern = re.compile(r'vertex\s+[0-9.e+-]+\s+[0-9.e+-]+\s+[0-9.e+-]+') endloop_pattern = re.compile(r'endloop') endfacet_pattern = re.compile(r'endfacet') endsolid_pattern = re.compile(r'endsolid .*') class STLUploadForm(ModelForm): def clean_file(self): stlfile = self.cleaned_data.get("file") stlfile.open() if stlfile.read(5) != "solid": #print "binary" #Skip header stlfile.seek(80) count = struct.unpack("i",stlfile.read(4))[0] if stlfile.size - 84 != count * 50: raise forms.ValidationError("Not a valid binary STL file.") else: #print "ascii" next_patterns = [facet_pattern] stlfile.readline() line = stlfile.readline().strip() matched_pattern = None vertex_count = 0 while line != "": corret = False for pattern in next_patterns: if pattern.match(line) != None: corret = True matched_pattern = pattern if not corret: raise forms.ValidationError("Not a valid ascii STL file.") if matched_pattern == facet_pattern: next_patterns = [loop_pattern] if matched_pattern == loop_pattern: vertex_count = 0 next_patterns = [vertex_pattern] if matched_pattern == vertex_pattern: vertex_count += 1 if vertex_count < 3: next_patterns = [vertex_pattern, endloop_pattern] else : next_patterns = [endloop_pattern] if matched_pattern == endloop_pattern: next_patterns = [endfacet_pattern] if matched_pattern == endfacet_pattern: next_patterns = [facet_pattern, endsolid_pattern] line = stlfile.readline().strip() if matched_pattern != endsolid_pattern: raise forms.ValidationError("Not a valid ascii STL file.") # see https://code.djangoproject.com/ticket/20020 # stlfile.close() return stlfile class GeometryForm(STLUploadForm): class Meta: model = Geometry fields = ['name', 'description', 'public', 'expiration', 'file', 'sourcefile'] class AnonymousGeometryForm(STLUploadForm): expiration = forms.ChoiceField(choices=Geometry.EXPIRATION_CHOICES[:-1]) class Meta: model = Geometry fields = ['name', 'description', 'public', 'expiration', 'file']