Guest User

Untitled

a guest
Jul 19th, 2018
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.00 KB | None | 0 0
  1. cat aur/forms.py
  2. from django import forms
  3. from django.core.files import File
  4.  
  5. from aur.models import *
  6. import aur.Package as PKGBUILD
  7.  
  8. import os
  9. import sys
  10.  
  11. import registration.backends.default from DefaulBackend
  12.  
  13. class PackageSearchForm(forms.Form):
  14. # Borrowed from AUR2-BR
  15. def __init__(self, *args, **kwargs):
  16. super(PackageSearchForm, self).__init__(*args, **kwargs)
  17. repository_choices = [('all', 'All')]
  18. repository_choices += [(repository.name.lower(), repository.name)
  19. for repository in Repository.objects.all()]
  20. self.fields['repository'].choices = repository_choices
  21.  
  22. repository = forms.ChoiceField(initial='all', choices=(), required=False)
  23. query = forms.CharField(max_length=30, label="Keywords", required=False)
  24. searchby = forms.ChoiceField(
  25. initial='name',
  26. required=False,
  27. label="Search By",choices=(
  28. ('name', 'Package Name'),
  29. ('maintainer', 'Maintainer'),
  30. )
  31. )
  32. lastupdate = forms.DateTimeField(label="Last Update", required=False)
  33. limit = forms.ChoiceField(initial='25', required=False, choices=(
  34. (25, 25),
  35. (50, 50),
  36. (75, 75),
  37. (100, 100),
  38. (150, 150),
  39. ))
  40.  
  41. def get_or_default(self, key):
  42. if not self.is_bound:
  43. return self.fields[key].initial
  44. return self.cleaned_data.get(key) or self.fields[key].initial
  45.  
  46. def search(self):
  47. if self.is_bound and not self.is_valid():
  48. return None
  49. repository = self.get_or_default('repository')
  50. lastupdate = self.get_or_default('lastupdate')
  51. query = self.get_or_default('query')
  52.  
  53. # Find the packages by searching the description and package name, or
  54. # maintainer
  55. if query:
  56. if self.get_or_default('searchby') == 'maintainer':
  57. results = Package.objects.filter(maintainers__username__icontains=query)
  58. else:
  59. results = Package.objects.filter(name__icontains=query)
  60. results |= Package.objects.filter(description__icontains=query)
  61. # Split query to search for each word as a tag
  62. for keyword in query.split():
  63. results |= Package.objects.filter(tags__exact=keyword)
  64. else:
  65. results = Package.objects.all()
  66. # Restrict results
  67. if repository != 'all':
  68. results = results.filter(repository__name__iexact=repository)
  69. if lastupdate:
  70. results = results.filter(updated__gte=lastupdate)
  71. return results
  72.  
  73.  
  74. class PackageField(forms.FileField):
  75. widget = forms.widgets.FileInput
  76. def __init__(self, *args, **kwargs):
  77. super(PackageField, self).__init__(*args, **kwargs)
  78.  
  79. def clean(self, data, initial=None):
  80. import tempfile
  81. import tarfile
  82. file = super(PackageField, self).clean(data, initial)
  83.  
  84. errors = list()
  85. # Save the uploaded file to disk
  86. directory = tempfile.mkdtemp()
  87. filename = os.path.join(directory, file.name)
  88. fp = open(filename, "wb")
  89. for chunk in file.chunks():
  90. fp.write(chunk)
  91. fp.close()
  92.  
  93. # Try to parse the PKGBUILD
  94. try:
  95. pkg = PKGBUILD.Package(filename)
  96. except:
  97. raise forms.ValidationError(sys.exc_info()[1])
  98. # Add path of the tarball so we can reference in other places
  99. pkg['filename'] = filename
  100. # Validate PKGBUILD
  101. pkg.validate()
  102. if not pkg.is_valid() or pkg.has_warnings():
  103. errors.extend(pkg.get_errors())
  104. errors.extend(pkg.get_warnings())
  105. # Check if we have everything we need
  106. for arch in pkg['arch']:
  107. try:
  108. Architecture.objects.get(name=arch)
  109. except Architecture.DoesNotExist:
  110. errors.append('architecture %s does not exist' % arch)
  111. if pkg['install']:
  112. try:
  113. tar = tarfile.open(filename)
  114. except tarfile.ReadError:
  115. errors.append('install files are missing')
  116. else:
  117. files = tar.getnames()
  118. for file in pkg['install']:
  119. filepath = os.path.join(pkg['name'], file)
  120. if not filepath in files:
  121. errors.append('install file "%s" is missing' % file)
  122. del files
  123. # Report errors or return the validated package
  124. if errors:
  125. raise forms.ValidationError(errors)
  126. else:
  127. return pkg
  128.  
  129.  
  130. class PackageSubmitForm(forms.Form):
  131. repository = forms.ChoiceField(choices=())
  132. package = PackageField(label="PKGBUILD")
  133.  
  134. # Borrowed from AUR2-BR
  135. def __init__(self, *args, **kwargs):
  136. super(PackageSubmitForm, self).__init__(*args, **kwargs)
  137. repo_choices = [(repo.name.lower(), repo.name) for repo in Repository.objects.all()]
  138. self.fields['repository'].choices = repo_choices
  139.  
  140. @transaction.commit_manually
  141. def save(self, user):
  142. import hashlib
  143. import tarfile
  144. pkg = self.cleaned_data['package']
  145. tmpdir = os.path.dirname(pkg['filename'])
  146. updating = False
  147. creating = False
  148. try:
  149. package = Package.objects.get(name=pkg['name'])
  150. except Package.DoesNotExist:
  151. package = Package(name=pkg['name'])
  152. creating = True
  153. else:
  154. updating = True
  155. package.version = pkg['version']
  156. package.release = pkg['release']
  157. package.description = pkg['description']
  158. package.url = pkg['url']
  159. package.repository=Repository.objects.get(name__iexact=self.cleaned_data['repository'])
  160. # Save the package so we can reference it
  161. package.save()
  162. if creating:
  163. package.maintainers.add(user)
  164. else:
  165. # TODO: Check if user can upload/overwrite the package
  166. pass
  167. # Check for, and add dependencies
  168. for dependency in pkg['depends']:
  169. # This would be nice, but we don't have access to the official
  170. # repositories
  171. try:
  172. dep = Package.objects.get(name=dependency)
  173. except Package.DoesNotExist:
  174. # Fail silently
  175. pass
  176. else:
  177. package.depends.add(dep)
  178. # Add provides
  179. for provision in pkg['provides']:
  180. object, created = Provision.objects.get_or_create(name=provision)
  181. package.provides.add(object)
  182. # Add licenses
  183. for license in pkg['licenses']:
  184. object, created = License.objects.get_or_create(name=license)
  185. package.licenses.add(object)
  186. # Add architectures
  187. for arch in pkg['arch']:
  188. object = Architecture.objects.get(name=arch)
  189. package.architectures.add(object)
  190. tar = tarfile.open(pkg['filename'], "r")
  191. tmpdir_sources = os.path.join(tmpdir, 'sources')
  192. tar.extractall(tmpdir_sources)
  193. pkgbuild = os.path.join(tmpdir_sources, pkg['name'], 'PKGBUILD')
  194. # Remove all sources. It's easier and cleaner this way.
  195. if updating:
  196. PackageFile.objects.filter(package=pkg['name']).delete()
  197. package.tarball.delete()
  198. # Hash and save PKGBUILD
  199. fp = File(open(pkgbuild, "r"))
  200. source = PackageFile(package=package)
  201. source.filename.save('%(name)s/sources/PKGBUILD', fp)
  202. source.save()
  203. fp.seek(0)
  204. md5hash = hashlib.md5(''.join(fp.readlines()))
  205. hash = PackageHash(hash=md5hash.hexdigest(), file=source, type='md5')
  206. hash.save()
  207. fp.close()
  208. # Save tarball
  209. # TODO: Tar the saved sources instead of using the uploaded one, for
  210. # security
  211. fp = File(open(pkg['filename'], "rb"))
  212. package.tarball.save(os.path.join('%(name)s', os.path.basename(pkg['filename'])), fp)
  213. fp.close()
  214. # Save source files
  215. for index in range(len(pkg['source'])):
  216. source_filename = pkg['source'][index]
  217. source = PackageFile(package=package)
  218. # If it's a local file, save to disk, otherwise record as url
  219. source_file = os.path.join(tmpdir_sources, package.name, source_filename)
  220. if os.path.exists(source_file):
  221. fp = File(open(source_file, "r"))
  222. source.filename.save('%(name)s/sources/' + source_filename, fp)
  223. fp.close()
  224. else:
  225. # TODO: Check that it _is_ a url, otherwise report an error
  226. # that files are missing
  227. source.url = source_filename
  228. source.save()
  229. # Check for, and save, any hashes this file may have
  230. for hash_type in ('md5', 'sha1', 'sha256', 'sha384', 'sha512'):
  231. if pkg[hash_type + 'sums']:
  232. PackageHash(hash=pkg[hash_type + 'sums'][index],
  233. file=source, type=hash_type).save()
  234. # Save install files
  235. for file in pkg['install']:
  236. source = PackageFile(package=package)
  237. source_path = os.path.join(tmpdir_sources, pkg['name'], file)
  238. fp = File(open(source_path, "r"))
  239. source.filename.save('%(name)s/install/' + file, fp)
  240. fp.close()
  241. source.save()
  242. transaction.commit()
  243. # Remove temporary files
  244. for root, dirs, files in os.walk(tmpdir, topdown=False):
  245. for name in files:
  246. os.remove(os.path.join(root, name))
  247. for name in dirs:
  248. os.rmdir(os.path.join(root, name))
  249. os.rmdir(tmpdir)
  250.  
  251. class AddGroupDefaultBackend(DefaultBackend):
  252. def register(self, *args, **kwargs):
  253. new_user = super(AddGroupDefaultBackend, self).register(*args, **kwargs)
  254. new_user.groups.add(Group.objects.get(name = 'User'))
  255. return new_user
Add Comment
Please, Sign In to add comment