diff --git a/lms/djangoapps/certificates/views.py b/lms/djangoapps/certificates/views.py index cf50c6b96e..fad986c6ea 100644 --- a/lms/djangoapps/certificates/views.py +++ b/lms/djangoapps/certificates/views.py @@ -1,6 +1,5 @@ import json import logging -import settings import uuid from django.conf import settings diff --git a/lms/djangoapps/simplewiki/models copy.py b/lms/djangoapps/simplewiki/models copy.py deleted file mode 100644 index ade95ed491..0000000000 --- a/lms/djangoapps/simplewiki/models copy.py +++ /dev/null @@ -1,367 +0,0 @@ -import difflib -import os - -from django import forms -from django.contrib.auth.models import User -from django.core.urlresolvers import reverse -from django.db import models -from django.db.models import signals -from django.utils.translation import ugettext_lazy as _ -from markdown import markdown - -from wiki_settings import * -from util.cache import cache - - -class ShouldHaveExactlyOneRootSlug(Exception): - pass - -class Article(models.Model): - """Wiki article referring to Revision model for actual content. - 'slug' and 'parent' field should be maintained centrally, since users - aren't allowed to change them, anyways. - """ - - title = models.CharField(max_length=512, verbose_name=_('Article title'), - blank=False) - slug = models.SlugField(max_length=100, verbose_name=_('slug'), - help_text=_('Letters, numbers, underscore and hyphen.'), - blank=True) - created_by = models.ForeignKey(User, verbose_name=_('Created by'), blank=True, null=True) - created_on = models.DateTimeField(auto_now_add = 1) - modified_on = models.DateTimeField(auto_now_add = 1) - parent = models.ForeignKey('self', verbose_name=_('Parent article slug'), - help_text=_('Affects URL structure and possibly inherits permissions'), - null=True, blank=True) - locked = models.BooleanField(default=False, verbose_name=_('Locked for editing')) - permissions = models.ForeignKey('Permission', verbose_name=_('Permissions'), - blank=True, null=True, - help_text=_('Permission group')) - current_revision = models.OneToOneField('Revision', related_name='current_rev', - blank=True, null=True, editable=True) - related = models.ManyToManyField('self', verbose_name=_('Related articles'), symmetrical=True, - help_text=_('Sets a symmetrical relation other articles'), - blank=True, null=True) - - def attachments(self): - return ArticleAttachment.objects.filter(article__exact = self) - - @classmethod - def get_root(cls): - """Return the root article, which should ALWAYS exist.. - except the very first time the wiki is loaded, in which - case the user is prompted to create this article.""" - try: - return Article.objects.filter(slug__exact = "")[0] - except: - raise ShouldHaveExactlyOneRootSlug() - - def get_url(self): - """Return the Wiki URL for an article""" - url = self.slug + "/" - if self.parent_id: - parent_url = cache.get("wiki_url-" + str(self.parent_id)) - if parent_url is None: - parent_url = self.parent.get_url() - - url = parent_url + url - - cache.set("wiki_url-" + str(self.id), url, 60*60) - - return url - - def get_abs_url(self): - """Return the absolute path for an article. This is necessary in cases - where the template system isn't used for generating URLs...""" - # TODO: Remove and create a reverse() lookup. - return WIKI_BASE + self.get_url() - - @models.permalink - def get_absolute_url(self): - return ('wiki_view', [self.get_url()]) - - @classmethod - def get_url_reverse(cls, path, article, return_list=[]): - """Lookup a URL and return the corresponding set of articles - in the path.""" - if path == []: - return return_list + [article] - # Lookup next child in path - try: - a = Article.objects.get(parent__exact = article, slug__exact=str(path[0])) - return cls.get_url_reverse(path[1:], a, return_list+[article]) - except Exception, e: - return None - - def can_read(self, user): - """ Check read permissions and return True/False.""" - if user.is_superuser: - return True - if self.permissions: - perms = self.permissions.can_read.all() - return perms.count() == 0 or (user in perms) - else: - return self.parent.can_read(user) if self.parent else True - - def can_write(self, user): - """ Check write permissions and return True/False.""" - if user.is_superuser: - return True - if self.permissions: - perms = self.permissions.can_write.all() - return perms.count() == 0 or (user in perms) - else: - return self.parent.can_write(user) if self.parent else True - - def can_write_l(self, user): - """Check write permissions and locked status""" - if user.is_superuser: - return True - return not self.locked and self.can_write(user) - - def can_attach(self, user): - return self.can_write_l(user) and (WIKI_ALLOW_ANON_ATTACHMENTS or not user.is_anonymous()) - - def __unicode__(self): - if self.slug == '' and not self.parent: - return unicode(_('Root article')) - else: - return self.get_url() - - class Meta: - unique_together = (('slug', 'parent'),) - verbose_name = _('Article') - verbose_name_plural = _('Articles') - -def get_attachment_filepath(instance, filename): - """Store file, appending new extension for added security""" - dir_ = WIKI_ATTACHMENTS + instance.article.get_url() - dir_ = '/'.join(filter(lambda x: x!='', dir_.split('/'))) - if not os.path.exists(WIKI_ATTACHMENTS_ROOT + dir_): - os.makedirs(WIKI_ATTACHMENTS_ROOT + dir_) - return dir_ + '/' + filename + '.upload' - -class ArticleAttachment(models.Model): - article = models.ForeignKey(Article, verbose_name=_('Article')) - file = models.FileField(max_length=255, upload_to=get_attachment_filepath, verbose_name=_('Attachment')) - uploaded_by = models.ForeignKey(User, blank=True, verbose_name=_('Uploaded by'), null=True) - uploaded_on = models.DateTimeField(auto_now_add = True, verbose_name=_('Upload date')) - - def download_url(self): - return reverse('wiki_view_attachment', args=(self.article.get_url(), self.filename())) - - def filename(self): - return '.'.join(self.file.name.split('/')[-1].split('.')[:-1]) - - def get_size(self): - try: - size = self.file.size - except OSError: - size = 0 - return size - - def filename(self): - return '.'.join(self.file.name.split('/')[-1].split('.')[:-1]) - - def is_image(self): - fname = self.filename().split('.') - if len(fname) > 1 and fname[-1].lower() in WIKI_IMAGE_EXTENSIONS: - return True - return False - - def get_thumb(self): - return self.get_thumb_impl(*WIKI_IMAGE_THUMB_SIZE) - - def get_thumb_small(self): - return self.get_thumb_impl(*WIKI_IMAGE_THUMB_SIZE_SMALL) - - def mk_thumbs(self): - self.mk_thumb(*WIKI_IMAGE_THUMB_SIZE, **{'force':True}) - self.mk_thumb(*WIKI_IMAGE_THUMB_SIZE_SMALL, **{'force':True}) - - def mk_thumb(self, width, height, force=False): - """Requires Python Imaging Library (PIL)""" - if not self.get_size(): - return False - - if not self.is_image(): - return False - - base_path = os.path.dirname(self.file.path) - orig_name = self.filename().split('.') - thumb_filename = "%s__thumb__%d_%d.%s" % ('.'.join(orig_name[:-1]), width, height, orig_name[-1]) - thumb_filepath = "%s%s%s" % (base_path, os.sep, thumb_filename) - - if force or not os.path.exists(thumb_filepath): - try: - import Image - img = Image.open(self.file.path) - img.thumbnail((width,height), Image.ANTIALIAS) - img.save(thumb_filepath) - except IOError: - return False - - return True - - def get_thumb_impl(self, width, height): - """Requires Python Imaging Library (PIL)""" - - if not self.get_size(): - return False - - if not self.is_image(): - return False - - self.mk_thumb(width, height) - - orig_name = self.filename().split('.') - thumb_filename = "%s__thumb__%d_%d.%s" % ('.'.join(orig_name[:-1]), width, height, orig_name[-1]) - thumb_url = settings.MEDIA_URL + WIKI_ATTACHMENTS + self.article.get_url() +'/' + thumb_filename - - return thumb_url - - def __unicode__(self): - return self.filename() - -class Revision(models.Model): - - article = models.ForeignKey(Article, verbose_name=_('Article')) - revision_text = models.CharField(max_length=255, blank=True, null=True, - verbose_name=_('Description of change')) - revision_user = models.ForeignKey(User, verbose_name=_('Modified by'), - blank=True, null=True, related_name='wiki_revision_user') - revision_date = models.DateTimeField(auto_now_add = True, verbose_name=_('Revision date')) - contents = models.TextField(verbose_name=_('Contents (Use MarkDown format)')) - contents_parsed = models.TextField(editable=False, blank=True, null=True) - counter = models.IntegerField(verbose_name=_('Revision#'), default=1, editable=False) - previous_revision = models.ForeignKey('self', blank=True, null=True, editable=False) - - # Deleted has three values. 0 is normal, non-deleted. 1 is if it was deleted by a normal user. It should - # be a NEW revision, so that it appears in the history. 2 is a special flag that can be applied or removed - # from a normal revision. It means it has been admin-deleted, and can only been seen by an admin. It doesn't - # show up in the history. - deleted = models.IntegerField(verbose_name=_('Deleted group'), default=0) - - def get_user(self): - return self.revision_user if self.revision_user else _('Anonymous') - - # Called after the deleted fied has been changed (between 0 and 2). This bypasses the normal checks put in - # save that update the revision or reject the save if contents haven't changed - def adminSetDeleted(self, deleted): - self.deleted = deleted - super(Revision, self).save() - - def save(self, **kwargs): - # Check if contents have changed... if not, silently ignore save - if self.article and self.article.current_revision: - if self.deleted == 0 and self.article.current_revision.contents == self.contents: - return - else: - import datetime - self.article.modified_on = datetime.datetime.now() - self.article.save() - - # Increment counter according to previous revision - previous_revision = Revision.objects.filter(article=self.article).order_by('-counter') - if previous_revision.count() > 0: - if previous_revision.count() > previous_revision[0].counter: - self.counter = previous_revision.count() + 1 - else: - self.counter = previous_revision[0].counter + 1 - else: - self.counter = 1 - if (self.article.current_revision and self.article.current_revision.deleted == 0): - self.previous_revision = self.article.current_revision - - # Create pre-parsed contents - no need to parse on-the-fly - ext = WIKI_MARKDOWN_EXTENSIONS - ext += ["wikipath(base_url=%s)" % reverse('wiki_view', args=('/',))] - self.contents_parsed = markdown(self.contents, - extensions=ext, - safe_mode='escape',) - super(Revision, self).save(**kwargs) - - def delete(self, **kwargs): - """If a current revision is deleted, then regress to the previous - revision or insert a stub, if no other revisions are available""" - article = self.article - if article.current_revision == self: - prev_revision = Revision.objects.filter(article__exact = article, - pk__not = self.pk).order_by('-counter') - if prev_revision: - article.current_revision = prev_revision[0] - article.save() - else: - r = Revision(article=article, - revision_user = article.created_by) - r.contents = unicode(_('Auto-generated stub')) - r.revision_text= unicode(_('Auto-generated stub')) - r.save() - article.current_revision = r - article.save() - super(Revision, self).delete(**kwargs) - - def get_diff(self): - if (self.deleted == 1): - yield "Article Deletion" - return - - if self.previous_revision: - previous = self.previous_revision.contents.splitlines(1) - else: - previous = [] - - # Todo: difflib.HtmlDiff would look pretty for our history pages! - diff = difflib.unified_diff(previous, self.contents.splitlines(1)) - # let's skip the preamble - diff.next(); diff.next(); diff.next() - - for d in diff: - yield d - - def __unicode__(self): - return "r%d" % self.counter - - class Meta: - verbose_name = _('article revision') - verbose_name_plural = _('article revisions') - -class Permission(models.Model): - permission_name = models.CharField(max_length = 255, verbose_name=_('Permission name')) - can_write = models.ManyToManyField(User, blank=True, null=True, related_name='write', - help_text=_('Select none to grant anonymous access.')) - can_read = models.ManyToManyField(User, blank=True, null=True, related_name='read', - help_text=_('Select none to grant anonymous access.')) - def __unicode__(self): - return self.permission_name - class Meta: - verbose_name = _('Article permission') - verbose_name_plural = _('Article permissions') - -class RevisionForm(forms.ModelForm): - contents = forms.CharField(label=_('Contents'), widget=forms.Textarea(attrs={'rows':8, 'cols':50})) - class Meta: - model = Revision - fields = ['contents', 'revision_text'] -class RevisionFormWithTitle(forms.ModelForm): - title = forms.CharField(label=_('Title')) - class Meta: - model = Revision - fields = ['title', 'contents', 'revision_text'] -class CreateArticleForm(RevisionForm): - title = forms.CharField(label=_('Title')) - class Meta: - model = Revision - fields = ['title', 'contents',] - -def set_revision(sender, *args, **kwargs): - """Signal handler to ensure that a new revision is always chosen as the - current revision - automatically. It simplifies stuff greatly. Also - stores previous revision for diff-purposes""" - instance = kwargs['instance'] - created = kwargs['created'] - if created and instance.article: - instance.article.current_revision = instance - instance.article.save() - -signals.post_save.connect(set_revision, Revision) diff --git a/lms/djangoapps/simplewiki/views copy.py b/lms/djangoapps/simplewiki/views copy.py deleted file mode 100644 index 553e6e8d19..0000000000 --- a/lms/djangoapps/simplewiki/views copy.py +++ /dev/null @@ -1,525 +0,0 @@ -# -*- coding: utf-8 -*- -from django.conf import settings as settings -from django.contrib.auth.decorators import login_required -from django.core.context_processors import csrf -from django.core.urlresolvers import reverse -from django.db.models import Q -from django.http import HttpResponse, HttpResponseRedirect -from django.utils import simplejson -from django.utils.translation import ugettext_lazy as _ -from mitxmako.shortcuts import render_to_response - -from models import Revision, Article, CreateArticleForm, RevisionFormWithTitle, RevisionForm -import wiki_settings - -def view(request, wiki_url): - (article, path, err) = fetch_from_url(request, wiki_url) - if err: - return err - - perm_err = check_permissions(request, article, check_read=True, check_deleted=True) - if perm_err: - return perm_err - d = {'wiki_article': article, - 'wiki_article_revision':article.current_revision, - 'wiki_write': article.can_write_l(request.user), - 'wiki_attachments_write': article.can_attach(request.user), - 'wiki_current_revision_deleted' : not (article.current_revision.deleted == 0), - 'wiki_title' : article.title + " - MITX 6.002x Wiki" - } - d.update(csrf(request)) - return render_to_response('simplewiki_view.html', d) - -def view_revision(request, revision_number, wiki_url, revision=None): - (article, path, err) = fetch_from_url(request, wiki_url) - if err: - return err - - try: - revision = Revision.objects.get(counter=int(revision_number), article=article) - except: - d = {'wiki_article': article, - 'wiki_err_norevision': revision_number,} - d.update(csrf(request)) - return render_to_response('simplewiki_error.html', d) - - - perm_err = check_permissions(request, article, check_read=True, check_deleted=True, revision=revision) - if perm_err: - return perm_err - - d = {'wiki_article': article, - 'wiki_article_revision':revision, - 'wiki_write': article.can_write_l(request.user), - 'wiki_attachments_write': article.can_attach(request.user), - 'wiki_current_revision_deleted' : not (revision.deleted == 0), - } - d.update(csrf(request)) - return render_to_response('simplewiki_view.html', d) - - -def root_redirect(request): - try: - root = Article.get_root() - except: - err = not_found(request, '/') - return err - - return HttpResponseRedirect(reverse('wiki_view', args=(root.get_url()))) - -def create(request, wiki_url): - - url_path = get_url_path(wiki_url) - - if url_path != [] and url_path[0].startswith('_'): - d = {'wiki_err_keyword': True, - 'wiki_url': '/'.join(url_path) } - d.update(csrf(request)) - return render_to_response('simplewiki_error.html', d) - - # Lookup path - try: - # Ensure that the path exists... - root = Article.get_root() - # Remove root slug if present in path - if url_path and root.slug == url_path[0]: - url_path = url_path[1:] - - path = Article.get_url_reverse(url_path[:-1], root) - if not path: - d = {'wiki_err_noparent': True, - 'wiki_url_parent': '/'.join(url_path[:-1]) } - d.update(csrf(request)) - return render_to_response('simplewiki_error.html', d) - - perm_err = check_permissions(request, path[-1], check_locked=False, check_write=True, check_deleted=True) - if perm_err: - return perm_err - # Ensure doesn't already exist - article = Article.get_url_reverse(url_path, root) - if article: - return HttpResponseRedirect(reverse('wiki_view', args=(article[-1].get_url(),))) - - # TODO: Somehow this doesnt work... - #except ShouldHaveExactlyOneRootSlug, (e): - except: - if Article.objects.filter(parent=None).count() > 0: - return HttpResponseRedirect(reverse('wiki_view', args=('/',))) - # Root not found... - path = [] - url_path = [""] - - if request.method == 'POST': - f = CreateArticleForm(request.POST) - if f.is_valid(): - article = Article() - article.slug = url_path[-1] - if not request.user.is_anonymous(): - article.created_by = request.user - article.title = f.cleaned_data.get('title') - if path != []: - article.parent = path[-1] - a = article.save() - new_revision = f.save(commit=False) - if not request.user.is_anonymous(): - new_revision.revision_user = request.user - new_revision.article = article - new_revision.save() - import django.db as db - return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) - else: - f = CreateArticleForm(initial={'title':request.GET.get('wiki_article_name', url_path[-1]), - 'contents':_('Headline\n===\n\n')}) - - d = {'wiki_form': f, - 'wiki_write': True, - 'create_article' : True, - } - d.update(csrf(request)) - - return render_to_response('simplewiki_edit.html', d) - -def edit(request, wiki_url): - (article, path, err) = fetch_from_url(request, wiki_url) - if err: - return err - - # Check write permissions - perm_err = check_permissions(request, article, check_write=True, check_locked=True, check_deleted=False) - if perm_err: - return perm_err - - if wiki_settings.WIKI_ALLOW_TITLE_EDIT: - EditForm = RevisionFormWithTitle - else: - EditForm = RevisionForm - - if request.method == 'POST': - f = EditForm(request.POST) - if f.is_valid(): - new_revision = f.save(commit=False) - new_revision.article = article - - if request.POST.__contains__('delete'): - if (article.current_revision.deleted == 1): #This article has already been deleted. Redirect - return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) - new_revision.contents = "" - new_revision.deleted = 1 - elif not new_revision.get_diff(): - return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) - - if not request.user.is_anonymous(): - new_revision.revision_user = request.user - new_revision.save() - if wiki_settings.WIKI_ALLOW_TITLE_EDIT: - new_revision.article.title = f.cleaned_data['title'] - new_revision.article.save() - return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) - else: - startContents = article.current_revision.contents if (article.current_revision.deleted == 0) else 'Headline\n===\n\n' - - f = EditForm({'contents': startContents, 'title': article.title}) - d = {'wiki_form': f, - 'wiki_write': True, - 'wiki_article': article, - 'wiki_title' : article.title, - 'wiki_attachments_write': article.can_attach(request.user), - 'create_article' : False, - } - d.update(csrf(request)) - - return render_to_response('simplewiki_edit.html', d) - -def history(request, wiki_url, page=1): - (article, path, err) = fetch_from_url(request, wiki_url) - if err: - return err - - perm_err = check_permissions(request, article, check_read=True, check_deleted=False) - if perm_err: - print "returned error " , perm_err - return perm_err - - page_size = 10 - - try: - p = int(page) - except ValueError: - p = 1 - - history = Revision.objects.filter(article__exact = article).order_by('-counter').select_related('previous_revision__counter', 'revision_user', 'wiki_article') - - if request.method == 'POST': - if wiki_settings.WIKI_REQUIRE_LOGIN_EDIT and not request.user.is_authenticated(): - return HttpResponseRedirect('/') - - if request.POST.__contains__('revision'): #They selected a version, but they can be either deleting or changing the version - perm_err = check_permissions(request, article, check_write=True, check_locked=True) - if perm_err: - return perm_err - - redirectURL = reverse('wiki_view', args=(article.get_url(),)) - try: - r = int(request.POST['revision']) - revision = Revision.objects.get(id=r) - if request.POST.__contains__('change'): - article.current_revision = revision - article.save() - elif request.POST.__contains__('view'): - redirectURL = reverse('wiki_view_revision', args=(revision.counter, article.get_url(),)) - - #The rese of these are admin functions - elif request.POST.__contains__('delete') and request.user.is_superuser: - if (revision.deleted == 0): - revision.adminSetDeleted(2) - elif request.POST.__contains__('restore') and request.user.is_superuser: - if (revision.deleted == 2): - revision.adminSetDeleted(0) - elif request.POST.__contains__('delete_all') and request.user.is_superuser: - Revision.objects.filter(article__exact = article, deleted = 0).update(deleted = 2) - elif request.POST.__contains__('lock_article'): - print "changing locked article " , article.locked - article.locked = not article.locked - print "changed locked article " , article.locked - article.save() - except: - pass - finally: - return HttpResponseRedirect(redirectURL) - # - # - # - # - # - # %else: - # - # - - page_count = (history.count()+(page_size-1)) / page_size - if p > page_count: - p = 1 - beginItem = (p-1) * page_size - - next_page = p + 1 if page_count > p else None - prev_page = p - 1 if p > 1 else None - - d = {'wiki_page': p, - 'wiki_next_page': next_page, - 'wiki_prev_page': prev_page, - 'wiki_write': article.can_write_l(request.user), - 'wiki_attachments_write': article.can_attach(request.user), - 'wiki_article': article, - 'wiki_title': article.title, - 'wiki_history': history[beginItem:beginItem+page_size], - 'show_delete_revision' : request.user.is_superuser,} - d.update(csrf(request)) - - return render_to_response('simplewiki_history.html', d) - - -def revision_feed(request, page=1): - page_size = 10 - - try: - p = int(page) - except ValueError: - p = 1 - - history = Revision.objects.order_by('-revision_date').select_related('revision_user', 'article', 'previous_revision') - - page_count = (history.count()+(page_size-1)) / page_size - if p > page_count: - p = 1 - beginItem = (p-1) * page_size - - next_page = p + 1 if page_count > p else None - prev_page = p - 1 if p > 1 else None - - d = {'wiki_page': p, - 'wiki_next_page': next_page, - 'wiki_prev_page': prev_page, - 'wiki_history': history[beginItem:beginItem+page_size], - 'show_delete_revision' : request.user.is_superuser,} - d.update(csrf(request)) - - return render_to_response('simplewiki_revision_feed.html', d) - -def search_articles(request): - # blampe: We should check for the presence of other popular django search - # apps and use those if possible. Only fall back on this as a last resort. - # Adding some context to results (eg where matches were) would also be nice. - - # todo: maybe do some perm checking here - - if request.method == 'POST': - querystring = request.POST['value'].strip() - else: - querystring = "" - - - results = Article.objects.all() - - if request.user.is_superuser: - results = results.order_by('current_revision__deleted') - else: - results = results.filter(current_revision__deleted = 0) - - - if querystring: - for queryword in querystring.split(): - # Basic negation is as fancy as we get right now - if queryword[0] == '-' and len(queryword) > 1: - results._search = lambda x: results.exclude(x) - queryword = queryword[1:] - else: - results._search = lambda x: results.filter(x) - - results = results._search(Q(current_revision__contents__icontains = queryword) | \ - Q(title__icontains = queryword)) - - results = results.select_related('current_revision__deleted') - - results = sorted(results, key=lambda article: (article.current_revision.deleted, article.get_url().lower()) ) - - if len(results) == 1 and querystring: - return HttpResponseRedirect(reverse('wiki_view', args=(results[0].get_url(),))) - else: - d = {'wiki_search_results': results, - 'wiki_search_query': querystring,} - d.update(csrf(request)) - return render_to_response('simplewiki_searchresults.html', d) - - -def search_add_related(request, wiki_url): - (article, path, err) = fetch_from_url(request, wiki_url) - if err: - return err - - perm_err = check_permissions(request, article, check_read=True) - if perm_err: - return perm_err - - search_string = request.GET.get('query', None) - self_pk = request.GET.get('self', None) - if search_string: - results = [] - related = Article.objects.filter(title__istartswith = search_string) - others = article.related.all() - if self_pk: - related = related.exclude(pk=self_pk) - if others: - related = related.exclude(related__in = others) - related = related.order_by('title')[:10] - for item in related: - results.append({'id': str(item.id), - 'value': item.title, - 'info': item.get_url()}) - else: - results = [] - - json = simplejson.dumps({'results': results}) - return HttpResponse(json, mimetype='application/json') - -def add_related(request, wiki_url): - - (article, path, err) = fetch_from_url(request, wiki_url) - if err: - return err - - perm_err = check_permissions(request, article, check_write=True, check_locked=True) - if perm_err: - return perm_err - - try: - related_id = request.POST['id'] - rel = Article.objects.get(id=related_id) - has_already = article.related.filter(id=related_id).count() - if has_already == 0 and not rel == article: - article.related.add(rel) - article.save() - except: - pass - finally: - return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) - -def remove_related(request, wiki_url, related_id): - (article, path, err) = fetch_from_url(request, wiki_url) - if err: - return err - - perm_err = check_permissions(request, article, check_write=True, check_locked=True) - if perm_err: - return perm_err - - try: - rel_id = int(related_id) - rel = Article.objects.get(id=rel_id) - article.related.remove(rel) - article.save() - except: - pass - finally: - return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) - -def random_article(request): - from random import randint - num_arts = Article.objects.count() - article = Article.objects.all()[randint(0, num_arts-1)] - return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) - -def encode_err(request, url): - d = {'wiki_err_encode': True} - d.update(csrf(request)) - return render_to_response('simplewiki_error.html', d) - -def not_found(request, wiki_url): - """Generate a NOT FOUND message for some URL""" - d = {'wiki_err_notfound': True, - 'wiki_url': wiki_url} - d.update(csrf(request)) - return render_to_response('simplewiki_error.html', d) - -def get_url_path(url): - """Return a list of all actual elements of a url, safely ignoring - double-slashes (//) """ - return filter(lambda x: x!='', url.split('/')) - -def fetch_from_url(request, url): - """Analyze URL, returning the article and the articles in its path - If something goes wrong, return an error HTTP response""" - - err = None - article = None - path = None - - url_path = get_url_path(url) - - try: - root = Article.get_root() - except: - err = not_found(request, '/') - return (article, path, err) - - if url_path and root.slug == url_path[0]: - url_path = url_path[1:] - - path = Article.get_url_reverse(url_path, root) - if not path: - err = not_found(request, '/' + '/'.join(url_path)) - else: - article = path[-1] - return (article, path, err) - - -def check_permissions(request, article, check_read=False, check_write=False, check_locked=False, check_deleted=False, revision = None): - read_err = check_read and not article.can_read(request.user) - - write_err = check_write and not article.can_write(request.user) - - locked_err = check_locked and article.locked - - if revision == None: - revision = article.current_revision - deleted_err = check_deleted and not (revision.deleted == 0) - if (request.user.is_superuser): - deleted_err = False - locked_err = False - - if read_err or write_err or locked_err or deleted_err: - d = {'wiki_article': article, - 'wiki_err_noread': read_err, - 'wiki_err_nowrite': write_err, - 'wiki_err_locked': locked_err, - 'wiki_err_deleted': deleted_err,} - d.update(csrf(request)) - # TODO: Make this a little less jarring by just displaying an error - # on the current page? (no such redirect happens for an anon upload yet) - # benjaoming: I think this is the nicest way of displaying an error, but - # these errors shouldn't occur, but rather be prevented on the other pages. - return render_to_response('simplewiki_error.html', d) - else: - return None - -#################### -# LOGIN PROTECTION # -#################### - -if wiki_settings.WIKI_REQUIRE_LOGIN_VIEW: - view = login_required(view) - history = login_required(history) - search_articles = login_required(search_articles) - root_redirect = login_required(root_redirect) - revision_feed = login_required(revision_feed) - random_article = login_required(random_article) - search_add_related = login_required(search_add_related) - not_found = login_required(not_found) - view_revision = login_required(view_revision) - -if wiki_settings.WIKI_REQUIRE_LOGIN_EDIT: - create = login_required(create) - edit = login_required(edit) - add_related = login_required(add_related) - remove_related = login_required(remove_related) - -if wiki_settings.WIKI_CONTEXT_PREPROCESSORS: - settings.TEMPLATE_CONTEXT_PROCESSORS += wiki_settings.WIKI_CONTEXT_PREPROCESSORS diff --git a/lms/djangoapps/simplewiki/views_attachments.py b/lms/djangoapps/simplewiki/views_attachments.py deleted file mode 100644 index e75802413f..0000000000 --- a/lms/djangoapps/simplewiki/views_attachments.py +++ /dev/null @@ -1,153 +0,0 @@ -import os - -from django.contrib.auth.decorators import login_required -from django.core.servers.basehttp import FileWrapper -from django.db.models.fields.files import FieldFile -from django.http import HttpResponse, HttpResponseForbidden, Http404 -from django.template import loader, Context - -from models import ArticleAttachment, get_attachment_filepath -from views import check_permissions, fetch_from_url - -from wiki_settings import ( - WIKI_ALLOW_ANON_ATTACHMENTS, - WIKI_ALLOW_ATTACHMENTS, - WIKI_ATTACHMENTS_MAX, - WIKI_ATTACHMENTS_ROOT, - WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS, - WIKI_REQUIRE_LOGIN_VIEW, - WIKI_REQUIRE_LOGIN_EDIT, -) - - -def add_attachment(request, wiki_url): - - (article, path, err) = fetch_from_url(request, wiki_url) - if err: - return err - - perm_err = check_permissions(request, article, check_write=True, check_locked=True) - if perm_err: - return perm_err - - if not WIKI_ALLOW_ATTACHMENTS or (not WIKI_ALLOW_ANON_ATTACHMENTS and request.user.is_anonymous()): - return HttpResponseForbidden() - - if request.method == 'POST': - if request.FILES.__contains__('attachment'): - attachment = ArticleAttachment() - if not request.user.is_anonymous(): - attachment.uploaded_by = request.user - attachment.article = article - - file = request.FILES['attachment'] - file_rel_path = get_attachment_filepath(attachment, file.name) - chunk_size = request.upload_handlers[0].chunk_size - - filefield = FieldFile(attachment, attachment.file, file_rel_path) - attachment.file = filefield - - file_path = WIKI_ATTACHMENTS_ROOT + attachment.file.name - - if not request.POST.__contains__('overwrite') and os.path.exists(file_path): - c = Context({'overwrite_warning' : True, - 'wiki_article': article, - 'filename': file.name}) - t = loader.get_template('simplewiki_updateprogressbar.html') - return HttpResponse(t.render(c)) - - if file.size > WIKI_ATTACHMENTS_MAX: - c = Context({'too_big' : True, - 'max_size': WIKI_ATTACHMENTS_MAX, - 'wiki_article': article, - 'file': file}) - t = loader.get_template('simplewiki_updateprogressbar.html') - return HttpResponse(t.render(c)) - - def get_extension(fname): - return attachment.file.name.split('.')[-2] - if WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS and not \ - get_extension(attachment.file.name) in WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS: - c = Context({'extension_err' : True, - 'extensions': WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS, - 'wiki_article': article, - 'file': file}) - t = loader.get_template('simplewiki_updateprogressbar.html') - return HttpResponse(t.render(c)) - - # Remove existing attachments - # TODO: Move this until AFTER having removed file. - # Current problem is that Django's FileField delete() method - # automatically deletes files - for a in article.attachments(): - if file_rel_path == a.file.name: - a.delete() - def receive_file(): - destination = open(file_path, 'wb+') - size = file.size - cnt = 0 - c = Context({'started' : True,}) - t = loader.get_template('simplewiki_updateprogressbar.html') - yield t.render(c) - for chunk in file.chunks(): - cnt += 1 - destination.write(chunk) - c = Context({'progress_width' : (cnt*chunk_size) / size, - 'wiki_article': article,}) - t = loader.get_template('simplewiki_updateprogressbar.html') - yield t.render(c) - c = Context({'finished' : True, - 'wiki_article': article,}) - t = loader.get_template('simplewiki_updateprogressbar.html') - destination.close() - attachment.save() - yield t.render(c) - - return HttpResponse(receive_file()) - - return HttpResponse('') - -# Taken from http://www.djangosnippets.org/snippets/365/ -def send_file(request, filepath): - """ - Send a file through Django without loading the whole file into - memory at once. The FileWrapper will turn the file object into an - iterator for chunks of 8KB. - """ - filename = filepath - wrapper = FileWrapper(file(filename)) - response = HttpResponse(wrapper, content_type='text/plain') - response['Content-Length'] = os.path.getsize(filename) - return response - -def view_attachment(request, wiki_url, file_name): - - (article, path, err) = fetch_from_url(request, wiki_url) - if err: - return err - - perm_err = check_permissions(request, article, check_read=True) - if perm_err: - return perm_err - - attachment = None - for a in article.attachments(): - if get_attachment_filepath(a, file_name) == a.file.name: - attachment = a - - if attachment: - filepath = WIKI_ATTACHMENTS_ROOT + attachment.file.name - if os.path.exists(filepath): - return send_file(request, filepath) - - raise Http404() - -#################### -# LOGIN PROTECTION # -#################### - -if WIKI_REQUIRE_LOGIN_VIEW: - view_attachment = login_required(view_attachment) - -if WIKI_REQUIRE_LOGIN_EDIT or not WIKI_ALLOW_ANON_ATTACHMENTS: - add_attachment = login_required(add_attachment)