Example #1
0
def revisions(request, id, post_type = None):
    assert post_type in ('question', 'answer')
    post = get_object_or_404(models.Post, post_type=post_type, id=id)

    if post.deleted:
        if request.user.is_anonymous() \
            or not request.user.is_administrator_or_moderator():
            raise Http404

    revisions = list(models.PostRevision.objects.filter(post=post))
    revisions.reverse()
    for i, revision in enumerate(revisions):
        if i == 0:
            revision.diff = sanitize_html(revisions[i].html)
            revision.summary = _('initial version')
        else:
            revision.diff = htmldiff(
                sanitize_html(revisions[i-1].html),
                sanitize_html(revision.html)
            )

    data = {
        'page_class':'revisions-page',
        'active_tab':'questions',
        'post': post,
        'revisions': revisions,
    }
    return render(request, 'revisions.html', data)
Example #2
0
def revisions(request, id, post_type = None):
    assert post_type in ('question', 'answer')
    post = get_object_or_404(models.Post, post_type=post_type, id=id)

    if post.deleted:
        if request.user.is_anonymous() \
            or not request.user.is_administrator_or_moderator():
            raise Http404

    revisions = list(models.PostRevision.objects.filter(post=post))
    revisions.reverse()
    for i, revision in enumerate(revisions):
        if i == 0:
            revision.diff = sanitize_html(revisions[i].html)
            revision.summary = _('initial version')
        else:
            revision.diff = htmldiff(
                sanitize_html(revisions[i-1].html),
                sanitize_html(revision.html)
            )

    data = {
        'page_class':'revisions-page',
        'active_tab':'questions',
        'post': post,
        'revisions': revisions,
    }
    return render(request, 'revisions.html', data)
Example #3
0
 def as_html(self, include_tags=True):
     markdowner = markup.get_parser()
     if include_tags:
         return QUESTION_REVISION_TEMPLATE % {
             "title": self.title,
             "html": sanitize_html(markdowner.convert(self.text)),
             "tags": " ".join(['<a class="post-tag">%s</a>' % tag for tag in self.tagnames.split(" ")]),
         }
     else:
         return QUESTION_REVISION_TEMPLATE_NO_TAGS % {
             "title": self.title,
             "html": sanitize_html(markdowner.convert(self.text)),
         }
Example #4
0
def revisions(request, id, post_type=None):
    assert post_type in ("question", "answer")
    post = get_object_or_404(models.Post, post_type=post_type, id=id)
    revisions = list(models.PostRevision.objects.filter(post=post))
    revisions.reverse()
    for i, revision in enumerate(revisions):
        if i == 0:
            revision.diff = sanitize_html(revisions[i].html)
            revision.summary = _("initial version")
        else:
            revision.diff = htmldiff(sanitize_html(revisions[i - 1].html), sanitize_html(revision.html))

    data = {"page_class": "revisions-page", "active_tab": "questions", "post": post, "revisions": revisions}
    return render_into_skin("revisions.html", data, request)
Example #5
0
 def as_html(self):
     markdowner = markup.get_parser()
     return QUESTION_REVISION_TEMPLATE % {
         'title': self.title,
         'html': sanitize_html(markdowner.convert(self.text)),
         'tags': ' '.join(['<a class="post-tag">%s</a>' % tag
                           for tag in self.tagnames.split(' ')]),
     }
Example #6
0
    def as_html(self, **kwargs):
        markdowner = markup.get_parser()
        sanitized_html = sanitize_html(markdowner.convert(self.text))

        if self.is_question_revision():
            return self.QUESTION_REVISION_TEMPLATE_NO_TAGS % {"title": self.title, "html": sanitized_html}
        elif self.is_answer_revision():
            return sanitized_html
Example #7
0
 def test_sanitize_html_with_extra_attrs(self):
     setattr(django_settings, 'ASKBOT_ALLOWED_HTML_ATTRIBUTES',
             html_utils.ALLOWED_HTML_ATTRIBUTES + ('id', ))
     html = '<p id="foo" class="bar">TEXT</p>'
     new_html = sanitize_html(html)
     self.assertIn('id="foo"', new_html)
     self.assertIn('class="bar"', new_html)
     delattr(django_settings, 'ASKBOT_ALLOWED_HTML_ATTRIBUTES')
Example #8
0
 def test_sanitize_html_with_extra_attrs(self):
     setattr(django_settings, 'ASKBOT_ALLOWED_HTML_ATTRIBUTES',
             html_utils.ALLOWED_HTML_ATTRIBUTES + ('id',))
     html = '<p id="foo" class="bar">TEXT</p>'
     new_html = sanitize_html(html)
     self.assertIn('id="foo"', new_html)
     self.assertIn('class="bar"', new_html)
     delattr(django_settings, 'ASKBOT_ALLOWED_HTML_ATTRIBUTES')
Example #9
0
 def as_html(self):
     markdowner = markup.get_parser()
     return QUESTION_REVISION_TEMPLATE % {
         'title': self.title,
         'html': sanitize_html(markdowner.convert(self.text)),
         'tags': ' '.join(['<a class="post-tag">%s</a>' % tag
                           for tag in self.tagnames.split(' ')]),
     }
Example #10
0
 def test_sanitize_html_with_extra_elements(self):
     setattr(django_settings, 'ASKBOT_ALLOWED_HTML_ELEMENTS',
             html_utils.ALLOWED_HTML_ELEMENTS + ('ham',))
     html = '<p id="foo" class="bar">TEXT</p><p><ham></ham></p>'
     new_html = sanitize_html(html)
     self.assertIn('<ham>', new_html)
     self.assertNotIn('foo', new_html)
     self.assertIn('bar', new_html)
     delattr(django_settings, 'ASKBOT_ALLOWED_HTML_ELEMENTS')
Example #11
0
 def test_sanitize_html_with_extra_elements(self):
     setattr(django_settings, 'ASKBOT_ALLOWED_HTML_ELEMENTS',
             html_utils.ALLOWED_HTML_ELEMENTS + ('ham', ))
     html = '<p id="foo" class="bar">TEXT</p><p><ham></ham></p>'
     new_html = sanitize_html(html)
     self.assertIn('<ham>', new_html)
     self.assertNotIn('foo', new_html)
     self.assertIn('bar', new_html)
     delattr(django_settings, 'ASKBOT_ALLOWED_HTML_ELEMENTS')
Example #12
0
    def as_html(self, **kwargs):
        markdowner = markup.get_parser()
        sanitized_html = sanitize_html(markdowner.convert(self.text))

        if self.is_question_revision():
            return self.QUESTION_REVISION_TEMPLATE_NO_TAGS % {
                'title': self.title,
                'html': sanitized_html
            }
        elif self.is_answer_revision():
            return sanitized_html
 def forwards(self, orm):
     "Write your forwards methods here."
     # Note: Don't use "from appname.models import ModelName".
     # Use orm.ModelName to refer to models in this application,
     # and orm['appname.ModelName'] for models in other applications.
     users = orm['auth.User'].objects.all()
     count = users.count()
     message = 'Sanitizing user descriptions'
     for user in ProgressBar(users.iterator(), count, message):
         user.about = sanitize_html(user.about)
         user.save()
Example #14
0
def revisions(request, id, post_type=None):
    assert post_type in ('question', 'answer')
    post = get_object_or_404(models.Post, post_type=post_type, id=id)
    revisions = list(models.PostRevision.objects.filter(post=post))
    revisions.reverse()
    for i, revision in enumerate(revisions):
        if i == 0:
            revision.diff = sanitize_html(revisions[i].html)
            revision.summary = _('initial version')
        else:
            revision.diff = htmldiff(sanitize_html(revisions[i - 1].html),
                                     sanitize_html(revision.html))

    data = {
        'page_class': 'revisions-page',
        'active_tab': 'questions',
        'post': post,
        'revisions': revisions,
    }
    return render_into_skin('revisions.html', data, request)
Example #15
0
def revisions(request, id, post_type = None):
    assert post_type in ('question', 'answer')
    post = get_object_or_404(models.Post, post_type=post_type, id=id)
    revisions = list(models.PostRevision.objects.filter(post=post))
    revisions.reverse()
    for i, revision in enumerate(revisions):
        if i == 0:
            revision.diff = sanitize_html(revisions[i].html)
            revision.summary = _('initial version')
        else:
            revision.diff = htmldiff(
                sanitize_html(revisions[i-1].html),
                sanitize_html(revision.html)
            )

    data = {
        'page_class':'revisions-page',
        'active_tab':'questions',
        'post': post,
        'revisions': revisions,
    }
    return render_into_skin('revisions.html', data, request)
Example #16
0
def edit_user(request, id):
    """View that allows to edit user profile.
    This view is accessible to profile owners or site administrators
    """
    user = get_object_or_404(models.User, id=id)
    if not(request.user == user or request.user.is_superuser):
        raise Http404
    if request.method == "POST":
        form = forms.EditUserForm(user, request.POST)
        if form.is_valid():
            if 'email' in form.cleaned_data and askbot_settings.EDITABLE_EMAIL:
                new_email = sanitize_html(form.cleaned_data['email'])
                set_new_email(user, new_email)

            if askbot_settings.EDITABLE_SCREEN_NAME:
                new_username = sanitize_html(form.cleaned_data['username'])
                if user.username != new_username:
                    group = user.get_personal_group()
                    user.username = new_username
                    group.name = format_personal_group_name(user)
                    group.save()

            user.real_name = sanitize_html(form.cleaned_data['realname'])
            user.website = sanitize_html(form.cleaned_data['website'])
            user.location = sanitize_html(form.cleaned_data['city'])
            user.date_of_birth = form.cleaned_data.get('birthday', None)
            user.about = sanitize_html(form.cleaned_data['about'])
            user.country = form.cleaned_data['country']
            user.show_country = form.cleaned_data['show_country']
            user.show_marked_tags = form.cleaned_data['show_marked_tags']
            user.save()
            # send user updated signal if full fields have been updated
            award_badges_signal.send(None,
                            event = 'update_user_profile',
                            actor = user,
                            context_object = user
                        )
            return HttpResponseRedirect(user.get_profile_url())
    else:
        form = forms.EditUserForm(user)

    data = {
        'active_tab': 'users',
        'page_class': 'user-profile-edit-page',
        'form' : form,
        'marked_tags_setting': askbot_settings.MARKED_TAGS_ARE_PUBLIC_WHEN,
        'support_custom_avatars': ('avatar' in django_settings.INSTALLED_APPS),
        'view_user': user,
    }
    return render(request, 'user_profile/user_edit.html', data)
Example #17
0
def edit_user(request, id):
    """View that allows to edit user profile.
    This view is accessible to profile owners or site administrators
    """
    user = get_object_or_404(models.User, id=id)
    if not(request.user == user or request.user.is_superuser):
        raise Http404
    if request.method == "POST":
        form = forms.EditUserForm(user, request.POST)
        if form.is_valid():
            new_email = sanitize_html(form.cleaned_data['email'])

            set_new_email(user, new_email)

            if askbot_settings.EDITABLE_SCREEN_NAME:
                new_username = sanitize_html(form.cleaned_data['username'])
                if user.username != new_username:
                    group = user.get_personal_group()
                    user.username = new_username
                    group.name = format_personal_group_name(user)
                    group.save()

            user.real_name = sanitize_html(form.cleaned_data['realname'])
            user.website = sanitize_html(form.cleaned_data['website'])
            user.location = sanitize_html(form.cleaned_data['city'])
            user.date_of_birth = form.cleaned_data.get('birthday', None)
            user.about = sanitize_html(form.cleaned_data['about'])
            user.country = form.cleaned_data['country']
            user.show_country = form.cleaned_data['show_country']
            user.show_marked_tags = form.cleaned_data['show_marked_tags']
            user.save()
            # send user updated signal if full fields have been updated
            award_badges_signal.send(None,
                            event = 'update_user_profile',
                            actor = user,
                            context_object = user
                        )
            return HttpResponseRedirect(user.get_profile_url())
    else:
        form = forms.EditUserForm(user)

    data = {
        'active_tab': 'users',
        'page_class': 'user-profile-edit-page',
        'form' : form,
        'marked_tags_setting': askbot_settings.MARKED_TAGS_ARE_PUBLIC_WHEN,
        'support_custom_avatars': ('avatar' in django_settings.INSTALLED_APPS),
        'view_user': user,
    }
    return render_into_skin('user_profile/user_edit.html', data, request)
Example #18
0
def edit_user(request, id):
    """View that allows to edit user profile.
    This view is accessible to profile owners or site administrators
    """
    user = get_object_or_404(models.User, id=id)
    if not(request.user == user or request.user.is_superuser):
        raise Http404
    if request.method == "POST":
        form = forms.EditUserForm(user, request.POST)
        if form.is_valid():
            new_email = sanitize_html(form.cleaned_data['email'])

            set_new_email(user, new_email)

            if askbot_settings.EDITABLE_SCREEN_NAME:
                user.username = sanitize_html(form.cleaned_data['username'])

            user.real_name = sanitize_html(form.cleaned_data['realname'])
            user.website = sanitize_html(form.cleaned_data['website'])
            user.location = sanitize_html(form.cleaned_data['city'])
            user.date_of_birth = form.cleaned_data.get('birthday', None)
            user.about = sanitize_html(form.cleaned_data['about'])
            user.country = form.cleaned_data['country']
            user.show_country = form.cleaned_data['show_country']

            user.save()
            # send user updated signal if full fields have been updated
            award_badges_signal.send(None,
                            event = 'update_user_profile',
                            actor = user,
                            context_object = user
                        )
            return HttpResponseRedirect(user.get_profile_url())
    else:
        form = forms.EditUserForm(user)
    data = {
        'active_tab': 'users',
        'page_class': 'user-profile-edit-page',
        'form' : form,
        'gravatar_faq_url' : reverse('faq') + '#gravatar',
    }
    return render_into_skin('user_profile/user_edit.html', data, request)
Example #19
0
def edit_user(request, id):
    """View that allows to edit user profile.
    This view is accessible to profile owners or site administrators
    """
    user = get_object_or_404(models.User, id=id)
    if not (request.user == user or request.user.is_superuser):
        raise Http404
    if request.method == "POST":
        form = forms.EditUserForm(user, request.POST)
        if form.is_valid():
            new_email = sanitize_html(form.cleaned_data["email"])

            set_new_email(user, new_email)

            if askbot_settings.EDITABLE_SCREEN_NAME:
                user.username = sanitize_html(form.cleaned_data["username"])

            user.real_name = sanitize_html(form.cleaned_data["realname"])
            user.website = sanitize_html(form.cleaned_data["website"])
            user.location = sanitize_html(form.cleaned_data["city"])
            user.date_of_birth = form.cleaned_data.get("birthday", None)
            user.about = sanitize_html(form.cleaned_data["about"])
            user.country = form.cleaned_data["country"]
            user.show_country = form.cleaned_data["show_country"]

            user.save()
            # send user updated signal if full fields have been updated
            award_badges_signal.send(None, event="update_user_profile", actor=user, context_object=user)
            return HttpResponseRedirect(user.get_profile_url())
    else:
        form = forms.EditUserForm(user)
    data = {
        "active_tab": "users",
        "page_class": "user-profile-edit-page",
        "form": form,
        "support_custom_avatars": ("avatar" in django_settings.INSTALLED_APPS),
        "view_user": user,
    }
    return render_into_skin("user_profile/user_edit.html", data, request)
Example #20
0
def markdown_input_converter(text):
    """markdown to html converter"""
    text = get_parser().convert(text)
    text = sanitize_html(text)
    return urlize_html(text)
Example #21
0
def plain_text_input_converter(text):
    """plain text to html converter"""
    return sanitize_html(urlize('<p>' + text + '</p>'))
Example #22
0
    def process_context(self, context):
        to_user = context.get('to_user')
        from_user = context.get('from_user')
        post = context.get('post')
        update_activity = context.get('update_activity')
        update_type = self.get_update_type(update_activity)

        origin_post = post.get_origin_post()

        from askbot.models import Post
        if update_type == 'question_comment':
            assert(isinstance(post, Post) and post.is_comment())
            assert(post.parent and post.parent.is_question())
        elif update_type == 'answer_comment':
            assert(isinstance(post, Post) and post.is_comment())
            assert(post.parent and post.parent.is_answer())
        elif update_type == 'answer_update':
            assert(isinstance(post, Post) and post.is_answer())
        elif update_type == 'new_answer':
            assert(isinstance(post, Post) and post.is_answer())
        elif update_type == 'question_update':
            assert(isinstance(post, Post) and post.is_question())
        elif update_type == 'new_question':
            assert(isinstance(post, Post) and post.is_question())
        elif update_type == 'post_shared':
            pass
        else:
            raise ValueError('unexpected update_type %s' % update_type)

        if update_type.endswith('update'):
            assert('comment' not in update_type)
            revisions = post.revisions.all()[:2]
            assert(len(revisions) == 2)
            content_preview = htmldiff(
                    sanitize_html(revisions[1].html),
                    sanitize_html(revisions[0].html),
                    ins_start = '<b><u style="background-color:#cfc">',
                    ins_end = '</u></b>',
                    del_start = '<del style="color:#600;background-color:#fcc">',
                    del_end = '</del>'
                )
            #todo: remove hardcoded style
        else:
            content_preview = post.format_for_email(is_leaf_post=True, recipient=to_user)

        #add indented summaries for the parent posts
        content_preview += post.format_for_email_as_parent_thread_summary(recipient=to_user)

        #content_preview += '<p>======= Full thread summary =======</p>'
        #content_preview += post.thread.format_for_email(recipient=to_user)

        if update_type == 'post_shared':
            user_action = _('%(user)s shared a %(post_link)s.')
        elif post.is_comment():
            if update_type.endswith('update'):
                user_action = _('%(user)s edited a %(post_link)s.')
            else:
                user_action = _('%(user)s posted a %(post_link)s')
        elif post.is_answer():
            if update_type.endswith('update'):
                user_action = _('%(user)s edited an %(post_link)s.')
            else:
                user_action = _('%(user)s posted an %(post_link)s.')
        elif post.is_question():
            if update_type.endswith('update'):
                user_action = _('%(user)s edited a %(post_link)s.')
            else:
                user_action = _('%(user)s posted a %(post_link)s.')
        else:
            raise ValueError('unrecognized post type')

        post_url = site_url(post.get_absolute_url())
        user_url = site_url(from_user.get_absolute_url())

        if to_user.is_administrator_or_moderator() and askbot_settings.SHOW_ADMINS_PRIVATE_USER_DATA:
            user_link_fmt = '<a href="%(profile_url)s">%(username)s</a> (<a href="mailto:%(email)s">%(email)s</a>)'
            user_link = user_link_fmt % {
                'profile_url': user_url,
                    'username': from_user.username,
                    'email': from_user.email
            }
        elif post.is_anonymous:
            user_link = from_user.get_name_of_anonymous_user()
        else:
            user_link = '<a href="%s">%s</a>' % (user_url, from_user.username)

        user_action = user_action % {
            'user': user_link,
            'post_link': '<a href="%s">%s</a>' % (post_url, _(post.post_type))
        }

        can_reply = to_user.can_post_by_email()
        from askbot.models import get_reply_to_addresses
        reply_address, alt_reply_address = get_reply_to_addresses(to_user, post)

        if can_reply:
            reply_separator = const.SIMPLE_REPLY_SEPARATOR_TEMPLATE % \
                          _('To reply, PLEASE WRITE ABOVE THIS LINE.')
            if post.post_type == 'question' and alt_reply_address:
                data = {
                  'addr': alt_reply_address,
                  'subject': urllib.quote(
                            ('Re: ' + post.thread.title).encode('utf-8')
                          )
                }
                reply_separator += '<p>' + const.REPLY_WITH_COMMENT_TEMPLATE % data
                reply_separator += '</p>'
            else:
                reply_separator = '<p>%s</p>' % reply_separator
                reply_separator += user_action
        else:
            reply_separator = user_action

        return {
           'admin_email': askbot_settings.ADMIN_EMAIL,
           'recipient_user': to_user,
           'update_author_name': from_user.username,
           'receiving_user_name': to_user.username,
           'receiving_user_karma': to_user.reputation,
           'reply_by_email_karma_threshold': askbot_settings.MIN_REP_TO_POST_BY_EMAIL,
           'can_reply': can_reply,
           'content_preview': content_preview,
           'update_type': update_type,
           'update_activity': update_activity,
           'post': post,
           'post_url': post_url,
           'origin_post': origin_post,
           'thread_title': origin_post.thread.title,
           'reply_separator': reply_separator,
           'reply_address': reply_address,
           'is_multilingual': getattr(django_settings, 'ASKBOT_MULTILINGUAL', False)
        }
Example #23
0
def parse_post_text(post):
    """typically post has a field to store raw source text
    in comment it is called .comment, in Question and Answer it is 
    called .text
    also there is another field called .html (consistent across models)
    so the goal of this function is to render raw text into .html
    and extract any metadata given stored in source (currently
    this metadata is limited by twitter style @mentions
    but there may be more in the future

    function returns a dictionary with the following keys
    html
    newly_mentioned_users - list of <User> objects
    removed_mentions - list of mention <Activity> objects - for removed ones
    """

    text = post.get_text()

    if post._escape_html:
        text = cgi.escape(text)

    if post._urlize:
        text = html.urlize(text)

    if post._use_markdown:
        text = sanitize_html(markup.get_parser().convert(text))

    #todo, add markdown parser call conditional on
    #post.use_markdown flag
    post_html = text
    mentioned_authors = list()
    removed_mentions = list()
    if '@' in text:
        op = post.get_origin_post()
        anticipated_authors = op.get_author_list(include_comments=True,
                                                 recursive=True)

        extra_name_seeds = markup.extract_mentioned_name_seeds(text)

        extra_authors = set()
        for name_seed in extra_name_seeds:
            extra_authors.update(
                User.objects.filter(username__istartswith=name_seed))

        #it is important to preserve order here so that authors of post
        #get mentioned first
        anticipated_authors += list(extra_authors)

        mentioned_authors, post_html = markup.mentionize_text(
            text, anticipated_authors)

        #find mentions that were removed and identify any previously
        #entered mentions so that we can send alerts on only new ones
        from askbot.models.user import Activity
        if post.pk is not None:
            #only look for previous mentions if post was already saved before
            prev_mention_qs = Activity.objects.get_mentions(mentioned_in=post)
            new_set = set(mentioned_authors)
            for prev_mention in prev_mention_qs:

                user = prev_mention.get_mentioned_user()
                if user is None:
                    continue
                if user in new_set:
                    #don't report mention twice
                    new_set.remove(user)
                else:
                    removed_mentions.append(prev_mention)
            mentioned_authors = list(new_set)

    data = {
        'html': post_html,
        'newly_mentioned_users': mentioned_authors,
        'removed_mentions': removed_mentions,
    }
    return data
Example #24
0
def moderation_queue(request):
    """Lists moderation queue items"""
    if not request.user.is_administrator_or_moderator():
        raise Http404

    activity_types = get_activity_types()

    #2) load the activity notifications according to activity types
    #todo: insert pagination code here
    memo_set = request.user.get_notifications(activity_types)
    memo_set = memo_set.select_related(
                    'activity',
                    'activity__content_type',
                    'activity__object_id',
                    'activity__question__thread',
                    'activity__user',
                    'activity__user__gravatar',
                ).order_by(
                    '-activity__active_at'
                )[:const.USER_VIEW_DATA_SIZE]

    #3) "package" data for the output
    queue = list()
    for memo in memo_set:
        obj = memo.activity.content_object
        if obj is None:
            memo.activity.delete()
            continue#a temp plug due to bug in the comment deletion

        act = memo.activity
        if act.activity_type == const.TYPE_ACTIVITY_MARK_OFFENSIVE:
            #todo: two issues here - flags are stored differently
            #from activity of new posts and edits
            #second issue: on posts with many edits we don't know whom to block
            act_user = act.content_object.author
            act_message = _('post was flagged as offensive')
            act_type = 'flag'
            ip_addr = None
        else:
            act_user = act.user
            act_message = act.get_activity_type_display()
            act_type = 'edit'
            ip_addr = act.content_object.ip_addr

        item = {
            'id': memo.id,
            'timestamp': act.active_at,
            'user': act_user,
            'ip_addr': ip_addr,
            'is_new': memo.is_new(),
            'url': act.get_absolute_url(),
            'snippet': act.get_snippet(),
            'title': act.question.thread.title,
            'message_type': act_message,
            'memo_type': act_type,
            'question_id': act.question.id,
            'content': sanitize_html(obj.html or obj.text),
        }
        queue.append(item)

    queue.sort(lambda x,y: cmp(y['timestamp'], x['timestamp']))
    reject_reasons = models.PostFlagReason.objects.all().order_by('title')
    data = {
        'active_tab': 'users',
        'page_class': 'moderation-queue-page',
        'post_reject_reasons': reject_reasons,
        'messages' : queue,
    }
    template = 'moderation/queue.html'
    return render(request, template, data)
Example #25
0
def edit_user(request, id):
    """View that allows to edit user profile.
    This view is accessible to profile owners or site administrators
    """
    user = get_object_or_404(models.User, id=id)
    if not(request.user.pk == user.pk or request.user.is_superuser):
        raise Http404
    if request.method == "POST":
        form = forms.EditUserForm(user, request.POST)
        if form.is_valid():
            if 'email' in form.cleaned_data and askbot_settings.EDITABLE_EMAIL:
                new_email = sanitize_html(form.cleaned_data['email'])
                set_new_email(user, new_email)

            prev_username = user.username
            if askbot_settings.EDITABLE_SCREEN_NAME:
                new_username = strip_all_tags(form.cleaned_data['username'])
                if user.username != new_username:
                    group = user.get_personal_group()
                    user.username = new_username
                    group.name = format_personal_group_name(user)
                    group.save()

            #Maybe we need to clear post caches, b/c
            #author info may need to be updated on posts and thread summaries
            if need_to_invalidate_post_caches(user, form):
                #get threads where users participated
                thread_ids = models.Post.objects.filter(
                                    Q(author=user) | Q(last_edited_by=user)
                                ).values_list(
                                    'thread__id', flat=True
                                ).distinct()
                threads = models.Thread.objects.filter(id__in=thread_ids)
                for thread in threads:
                    #for each thread invalidate cache keys for posts, etc
                    thread.invalidate_cached_data(lazy=True)

            user.real_name = strip_all_tags(form.cleaned_data['realname'])
            user.website = sanitize_html(form.cleaned_data['website'])
            user.location = sanitize_html(form.cleaned_data['city'])
            user.date_of_birth = form.cleaned_data.get('birthday', None)
            user.about = sanitize_html(form.cleaned_data['about'])
            user.country = form.cleaned_data['country']
            user.show_country = form.cleaned_data['show_country']
            user.show_marked_tags = form.cleaned_data['show_marked_tags']
            user.save()
            # send user updated signal if full fields have been updated
            award_badges_signal.send(None,
                            event = 'update_user_profile',
                            actor = user,
                            context_object = user
                        )
            return HttpResponseRedirect(user.get_profile_url())
    else:
        form = forms.EditUserForm(user)

    data = {
        'active_tab': 'users',
        'page_class': 'user-profile-edit-page',
        'form' : form,
        'marked_tags_setting': askbot_settings.MARKED_TAGS_ARE_PUBLIC_WHEN,
        'support_custom_avatars': ('avatar' in django_settings.INSTALLED_APPS),
        'view_user': user,
    }
    return render(request, 'user_profile/user_edit.html', data)
Example #26
0
def plain_text_input_converter(text):
    """plain text to html converter"""
    return sanitize_html(urlize('<p>' + text + '</p>'))
Example #27
0
 def as_html(self):
     markdowner = markup.get_parser()
     return sanitize_html(markdowner.convert(self.text))
Example #28
0
def edit_user(request, id):
    """View that allows to edit user profile.
    This view is accessible to profile owners or site administrators
    """
    user = get_object_or_404(models.User, id=id)
    if not(request.user == user or request.user.is_superuser):
        raise Http404
    if request.method == "POST":
        form = forms.EditUserForm(user, request.POST)
        if form.is_valid():
            if 'email' in form.cleaned_data and askbot_settings.EDITABLE_EMAIL:
                new_email = sanitize_html(form.cleaned_data['email'])
                set_new_email(user, new_email)

            prev_username = user.username
            if askbot_settings.EDITABLE_SCREEN_NAME:
                new_username = strip_all_tags(form.cleaned_data['username'])
                if user.username != new_username:
                    group = user.get_personal_group()
                    user.username = new_username
                    group.name = format_personal_group_name(user)
                    group.save()

            #Maybe we need to clear post caches, b/c
            #author info may need to be updated on posts and thread summaries
            if need_to_invalidate_post_caches(user, form):
                #get threads where users participated
                thread_ids = models.Post.objects.filter(
                                    Q(author=user) | Q(last_edited_by=user)
                                ).values_list(
                                    'thread__id', flat=True
                                ).distinct()
                threads = models.Thread.objects.filter(id__in=thread_ids)
                for thread in threads:
                    #for each thread invalidate cache keys for posts, etc
                    thread.invalidate_cached_data(lazy=True)

            user.real_name = strip_all_tags(form.cleaned_data['realname'])
            user.website = sanitize_html(form.cleaned_data['website'])
            user.location = sanitize_html(form.cleaned_data['city'])
            user.date_of_birth = form.cleaned_data.get('birthday', None)
            user.about = sanitize_html(form.cleaned_data['about'])
            user.country = form.cleaned_data['country']
            user.show_country = form.cleaned_data['show_country']
            user.show_marked_tags = form.cleaned_data['show_marked_tags']
            user.save()
            # send user updated signal if full fields have been updated
            award_badges_signal.send(None,
                            event = 'update_user_profile',
                            actor = user,
                            context_object = user
                        )
            return HttpResponseRedirect(user.get_profile_url())
    else:
        form = forms.EditUserForm(user)

    data = {
        'active_tab': 'users',
        'page_class': 'user-profile-edit-page',
        'form' : form,
        'marked_tags_setting': askbot_settings.MARKED_TAGS_ARE_PUBLIC_WHEN,
        'support_custom_avatars': ('avatar' in django_settings.INSTALLED_APPS),
        'view_user': user,
    }
    return render(request, 'user_profile/user_edit.html', data)
Example #29
0
def parse_post_text(post):
    """typically post has a field to store raw source text
    in comment it is called .comment, in Question and Answer it is 
    called .text
    also there is another field called .html (consistent across models)
    so the goal of this function is to render raw text into .html
    and extract any metadata given stored in source (currently
    this metadata is limited by twitter style @mentions
    but there may be more in the future

    function returns a dictionary with the following keys
    html
    newly_mentioned_users - list of <User> objects
    removed_mentions - list of mention <Activity> objects - for removed ones
    """

    text = post.get_text()

    if post._escape_html:
        text = cgi.escape(text)

    if post._urlize:
        text = html.urlize(text)

    if post._use_markdown:
        text = sanitize_html(markup.get_parser().convert(text))

    #todo, add markdown parser call conditional on
    #post.use_markdown flag
    post_html = text
    mentioned_authors = list()
    removed_mentions = list()
    if '@' in text:
        op = post.get_origin_post()
        anticipated_authors = op.get_author_list(
                                    include_comments = True,
                                    recursive = True 
                                )

        extra_name_seeds = markup.extract_mentioned_name_seeds(text)

        extra_authors = set()
        for name_seed in extra_name_seeds:
            extra_authors.update(User.objects.filter(
                                        username__startswith = name_seed
                                    )
                            )

        #it is important to preserve order here so that authors of post 
        #get mentioned first
        anticipated_authors += list(extra_authors)

        mentioned_authors, post_html = markup.mentionize_text(
                                                text, 
                                                anticipated_authors
                                            )

        #find mentions that were removed and identify any previously
        #entered mentions so that we can send alerts on only new ones
        from askbot.models.user import Activity
        if post.pk is not None:
            #only look for previous mentions if post was already saved before
            prev_mention_qs = Activity.objects.get_mentions(
                                        mentioned_in = post
                                    )
            new_set = set(mentioned_authors)
            for prev_mention in prev_mention_qs:

                user = prev_mention.get_mentioned_user()
                if user is None:
                    continue
                if user in new_set:
                    #don't report mention twice
                    new_set.remove(user)
                else:
                    removed_mentions.append(prev_mention)
            mentioned_authors = list(new_set)

    data = {
        'html': post_html,
        'newly_mentioned_users': mentioned_authors,
        'removed_mentions': removed_mentions,
    }
    return data
Example #30
0
def plain_text_input_converter(text):
    """plain text to html converter"""
    return sanitize_html(urlize("<p>" + text + "</p>"))
Example #31
0
def moderation_queue(request):
    """Lists moderation queue items"""
    if not request.user.is_administrator_or_moderator():
        raise Http404

    activity_types = get_activity_types()

    #2) load the activity notifications according to activity types
    #todo: insert pagination code here
    memo_set = request.user.get_notifications(activity_types)
    memo_set = memo_set.select_related(
        'activity', 'activity__content_type', 'activity__object_id',
        'activity__question__thread', 'activity__user').order_by(
            '-activity__active_at')[:const.USER_VIEW_DATA_SIZE]

    #3) "package" data for the output
    queue = list()
    for memo in memo_set:
        obj = memo.activity.content_object
        if obj is None:
            memo.activity.delete()
            continue  #a temp plug due to bug in the comment deletion

        act = memo.activity
        if act.activity_type == const.TYPE_ACTIVITY_MARK_OFFENSIVE:
            #todo: two issues here - flags are stored differently
            #from activity of new posts and edits
            #second issue: on posts with many edits we don't know whom to block
            act_user = act.content_object.author
            act_message = _('post was flagged as offensive')
            act_type = 'flag'
            ip_addr = None
        else:
            act_user = act.user
            act_message = act.get_activity_type_display()
            act_type = 'edit'
            ip_addr = act.content_object.ip_addr

        item = {
            'id': memo.id,
            'timestamp': act.active_at,
            'user': act_user,
            'ip_addr': ip_addr,
            'is_new': memo.is_new(),
            'url': act.get_absolute_url(),
            'snippet': act.get_snippet(),
            'title': act.question.thread.title,
            'message_type': act_message,
            'memo_type': act_type,
            'question_id': act.question.id,
            'content': sanitize_html(obj.html or obj.text),
        }
        queue.append(item)

    queue.sort(key=lambda x: x['timestamp'], reverse=True)
    reject_reasons = models.PostFlagReason.objects.all().order_by('title')
    data = {
        'active_tab': 'users',
        'page_class': 'moderation-queue-page',
        'post_reject_reasons': reject_reasons,
        'messages': queue,
    }
    template = 'moderation/queue.html'
    return render(request, template, data)
Example #32
0
    def process_context(self, context):
        to_user = context.get('to_user')
        from_user = context.get('from_user')
        post = context.get('post')
        update_activity = context.get('update_activity')
        update_type = self.get_update_type(update_activity)

        origin_post = post.get_origin_post()

        from askbot.models import Post
        if update_type == 'question_comment':
            assert (isinstance(post, Post) and post.is_comment())
            assert (post.parent and post.parent.is_question())
        elif update_type == 'answer_comment':
            assert (isinstance(post, Post) and post.is_comment())
            assert (post.parent and post.parent.is_answer())
        elif update_type == 'answer_update':
            assert (isinstance(post, Post) and post.is_answer())
        elif update_type == 'new_answer':
            assert (isinstance(post, Post) and post.is_answer())
        elif update_type == 'question_update':
            assert (isinstance(post, Post) and post.is_question())
        elif update_type == 'new_question':
            assert (isinstance(post, Post) and post.is_question())
        elif update_type == 'post_shared':
            pass
        else:
            raise ValueError('unexpected update_type %s' % update_type)

        if update_type.endswith('update'):
            assert ('comment' not in update_type)
            revisions = post.revisions.all()[:2]
            assert (len(revisions) == 2)
            content_preview = htmldiff(
                sanitize_html(revisions[1].html),
                sanitize_html(revisions[0].html),
                ins_start='<b><u style="background-color:#cfc">',
                ins_end='</u></b>',
                del_start='<del style="color:#600;background-color:#fcc">',
                del_end='</del>')
            #todo: remove hardcoded style
        else:
            content_preview = post.format_for_email(is_leaf_post=True,
                                                    recipient=to_user)

        #add indented summaries for the parent posts
        content_preview += post.format_for_email_as_parent_thread_summary(
            recipient=to_user)

        #content_preview += '<p>======= Full thread summary =======</p>'
        #content_preview += post.thread.format_for_email(recipient=to_user)

        if update_type == 'post_shared':
            user_action = _('%(user)s shared a %(post_link)s.')
        elif post.is_comment():
            if update_type.endswith('update'):
                user_action = _('%(user)s edited a %(post_link)s.')
            else:
                user_action = _('%(user)s posted a %(post_link)s')
        elif post.is_answer():
            if update_type.endswith('update'):
                user_action = _('%(user)s edited an %(post_link)s.')
            else:
                user_action = _('%(user)s posted an %(post_link)s.')
        elif post.is_question():
            if update_type.endswith('update'):
                user_action = _('%(user)s edited a %(post_link)s.')
            else:
                user_action = _('%(user)s posted a %(post_link)s.')
        else:
            raise ValueError('unrecognized post type')

        post_url = site_url(post.get_absolute_url())
        user_url = site_url(from_user.get_absolute_url())

        if to_user.is_administrator_or_moderator(
        ) and askbot_settings.SHOW_ADMINS_PRIVATE_USER_DATA:
            user_link_fmt = '<a href="%(profile_url)s">%(username)s</a> (<a href="mailto:%(email)s">%(email)s</a>)'
            user_link = user_link_fmt % {
                'profile_url': user_url,
                'username': from_user.username,
                'email': from_user.email
            }
        elif post.is_anonymous:
            user_link = from_user.get_name_of_anonymous_user()
        else:
            user_link = '<a href="%s">%s</a>' % (user_url, from_user.username)

        user_action = user_action % {
            'user': user_link,
            'post_link': '<a href="%s">%s</a>' % (post_url, _(post.post_type))
        }

        can_reply = to_user.can_post_by_email()
        from askbot.models import get_reply_to_addresses
        reply_address, alt_reply_address = get_reply_to_addresses(
            to_user, post)

        if can_reply:
            reply_separator = const.SIMPLE_REPLY_SEPARATOR_TEMPLATE % \
                          _('To reply, PLEASE WRITE ABOVE THIS LINE.')
            if post.post_type == 'question' and alt_reply_address:
                data = {
                    'addr':
                    alt_reply_address,
                    'subject':
                    urllib.quote(('Re: ' + post.thread.title).encode('utf-8'))
                }
                reply_separator += '<p>' + const.REPLY_WITH_COMMENT_TEMPLATE % data
                reply_separator += '</p>'
            else:
                reply_separator = '<p>%s</p>' % reply_separator
                reply_separator += user_action
        else:
            reply_separator = user_action

        return {
            'admin_email':
            askbot_settings.ADMIN_EMAIL,
            'recipient_user':
            to_user,
            'update_author_name':
            from_user.username,
            'receiving_user_name':
            to_user.username,
            'receiving_user_karma':
            to_user.reputation,
            'reply_by_email_karma_threshold':
            askbot_settings.MIN_REP_TO_POST_BY_EMAIL,
            'can_reply':
            can_reply,
            'content_preview':
            content_preview,
            'update_type':
            update_type,
            'update_activity':
            update_activity,
            'post':
            post,
            'post_url':
            post_url,
            'origin_post':
            origin_post,
            'thread_title':
            origin_post.thread.title,
            'reply_separator':
            reply_separator,
            'reply_address':
            reply_address,
            'is_multilingual':
            getattr(django_settings, 'ASKBOT_MULTILINGUAL', False)
        }
Example #33
0
def markdown_input_converter(text):
    """markdown to html converter"""
    text = urlize(text)
    text = get_parser().convert(text)
    return sanitize_html(text)
Example #34
0
 def test_sanitize_html(self):
     html = '<p id="foo" class="bar">TEXT</p>'
     new_html = sanitize_html(html)
     self.assertNotIn('foo', new_html)
     self.assertIn('bar', new_html)
Example #35
0
 def test_sanitize_html(self):
     html = '<p id="foo" class="bar">TEXT</p>'
     new_html = sanitize_html(html)
     self.assertNotIn('foo', new_html)
     self.assertIn('bar', new_html)
Example #36
0
 def as_html(self):
     markdowner = markup.get_parser()
     return sanitize_html(markdowner.convert(self.text))