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)
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)), }
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)
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(' ')]), }
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 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')
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')
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')
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')
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()
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)
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)
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)
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)
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)
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)
def markdown_input_converter(text): """markdown to html converter""" text = get_parser().convert(text) text = sanitize_html(text) return urlize_html(text)
def plain_text_input_converter(text): """plain text to html converter""" return sanitize_html(urlize('<p>' + text + '</p>'))
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) }
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
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)
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)
def as_html(self): markdowner = markup.get_parser() return sanitize_html(markdowner.convert(self.text))
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)
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
def plain_text_input_converter(text): """plain text to html converter""" return sanitize_html(urlize("<p>" + text + "</p>"))
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)
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) }
def markdown_input_converter(text): """markdown to html converter""" text = urlize(text) text = get_parser().convert(text) return sanitize_html(text)
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)