summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--askbot/conf/forum_data_rules.py15
-rw-r--r--askbot/const/message_keys.py3
-rw-r--r--askbot/doc/source/changelog.rst3
-rw-r--r--askbot/doc/source/contributors.rst1
-rw-r--r--askbot/doc/source/management-commands.rst2
-rw-r--r--askbot/feed.py2
-rw-r--r--askbot/forms.py6
-rw-r--r--askbot/management/commands/askbot_add_test_content.py14
-rw-r--r--askbot/migrations/0125_add_show_tags_field_to_user.py296
-rw-r--r--askbot/models/__init__.py50
-rw-r--r--askbot/models/post.py12
-rw-r--r--askbot/models/repute.py7
-rw-r--r--askbot/models/user.py1
-rw-r--r--askbot/skins/common/media/js/tag_selector.js1
-rw-r--r--askbot/skins/common/templates/question/closed_question_info.html2
-rw-r--r--askbot/skins/default/media/style/style.less35
-rw-r--r--askbot/skins/default/templates/badge.html2
-rw-r--r--askbot/skins/default/templates/email/ask_for_signature.html2
-rw-r--r--askbot/skins/default/templates/email/insufficient_rep_to_post_by_email.html2
-rw-r--r--askbot/skins/default/templates/email/macros.html2
-rw-r--r--askbot/skins/default/templates/feedback.html2
-rw-r--r--askbot/skins/default/templates/help.html2
-rw-r--r--askbot/skins/default/templates/macros.html32
-rw-r--r--askbot/skins/default/templates/main_page/javascript.html2
-rw-r--r--askbot/skins/default/templates/reopen.html2
-rw-r--r--askbot/skins/default/templates/user_profile/macros.html24
-rw-r--r--askbot/skins/default/templates/user_profile/user.html4
-rw-r--r--askbot/skins/default/templates/user_profile/user_edit.html12
-rw-r--r--askbot/skins/default/templates/user_profile/user_moderate.html4
-rw-r--r--askbot/skins/default/templates/user_profile/user_network.html2
-rw-r--r--askbot/skins/default/templates/user_profile/user_reputation.html2
-rw-r--r--askbot/skins/default/templates/user_profile/user_stats.html18
-rw-r--r--askbot/skins/default/templates/widgets/question_summary.html2
-rw-r--r--askbot/skins/default/templates/widgets/user_list.html2
-rw-r--r--askbot/skins/default/templates/widgets/user_navigation.html2
-rw-r--r--askbot/utils/html.py3
-rw-r--r--askbot/views/readers.py11
-rw-r--r--askbot/views/users.py23
-rw-r--r--askbot/views/writers.py4
-rw-r--r--askbot_requirements_dev.txt1
40 files changed, 532 insertions, 80 deletions
diff --git a/askbot/conf/forum_data_rules.py b/askbot/conf/forum_data_rules.py
index 7d98c9e8..a26aa4b3 100644
--- a/askbot/conf/forum_data_rules.py
+++ b/askbot/conf/forum_data_rules.py
@@ -200,6 +200,21 @@ settings.register(
)
)
+MARKED_TAG_DISPLAY_CHOICES = (
+ ('always', _('Always, for all users')),
+ ('never', _('Never, for all users')),
+ ('when-user-wants', _('Let users decide'))
+)
+settings.register(
+ livesettings.StringValue(
+ FORUM_DATA_RULES,
+ 'MARKED_TAGS_ARE_PUBLIC_WHEN',
+ default = 'always',
+ choices = MARKED_TAG_DISPLAY_CHOICES,
+ description = _('Publicly show user tag selections')
+ )
+)
+
settings.register(
livesettings.BooleanValue(
FORUM_DATA_RULES,
diff --git a/askbot/const/message_keys.py b/askbot/const/message_keys.py
index 0ee99e0c..9ac82e57 100644
--- a/askbot/const/message_keys.py
+++ b/askbot/const/message_keys.py
@@ -33,6 +33,9 @@ _('click to see the most answered questions')
_('click to see least voted questions')
_('by votes')
_('click to see most voted questions')
+_('interesting')
+_('ignored')
+_('subscribed')
def get_i18n_message(key):
messages = {
diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst
index 5cd1def9..430d98de 100644
--- a/askbot/doc/source/changelog.rst
+++ b/askbot/doc/source/changelog.rst
@@ -4,13 +4,14 @@ Changes in Askbot
Development version
-------------------
* Welcome email for the case when replying by email is enabled (Evgeny)
-* Detection of email signature based on the response to the welome email (Evgeny)
+* Detection of email signature based on the response to the welcome email (Evgeny)
* Hide "website" and "about" section of the blocked user profiles
to help prevent user profile spam (Evgeny)
* Added a function to create a custom user profile tab,
the feature requires access to the server (Evgeny)
* Added optional top banner to the question page (Evgeny)
* Made "bootstrap mode" default and created instead "large site mode" (Evgeny)
+* Added interesting/ignored/subscribed tags to the user profile page (Paul Backhouse, Evgeny)
0.7.43 (May 14, 2012)
---------------------
diff --git a/askbot/doc/source/contributors.rst b/askbot/doc/source/contributors.rst
index a0881532..69348b84 100644
--- a/askbot/doc/source/contributors.rst
+++ b/askbot/doc/source/contributors.rst
@@ -40,6 +40,7 @@ Programming and documentation
* `Jim Tittsler <http://wikieducator.org/User:JimTittsler>`_
* Silvio Heuberger
* `Alexandros <https://github.com/alexandros-z>`_
+* `Paul Backhouse <https://github.com/powlo>`_
Translations
------------
diff --git a/askbot/doc/source/management-commands.rst b/askbot/doc/source/management-commands.rst
index 4efbef6e..b96251dc 100644
--- a/askbot/doc/source/management-commands.rst
+++ b/askbot/doc/source/management-commands.rst
@@ -195,5 +195,5 @@ the developers of the Askbot project:
+--------------------------------+-------------------------------------------------------------+
| `askbot_add_test_content` | Creates content with dummy data for testing |
+--------------------------------+-------------------------------------------------------------+
-| `askbot_create_test_fixture` | Creates a test fixture at `askbot/tests/test_data.json` |
+| `askbot_create_test_fixture` | Creates a test fixture at `askbot/tests/test_data.json` |
+--------------------------------+-------------------------------------------------------------+
diff --git a/askbot/feed.py b/askbot/feed.py
index 776aad5e..285bb452 100644
--- a/askbot/feed.py
+++ b/askbot/feed.py
@@ -123,7 +123,7 @@ class RssLastestQuestionsFeed(Feed):
def item_author_link(self, item):
"""get url of the author's profile
"""
- return item.author.get_profile_url()
+ return askbot_settings.APP_URL + item.author.get_profile_url()
def item_pubdate(self, item):
"""get date of creation for the item
diff --git a/askbot/forms.py b/askbot/forms.py
index cced18e9..81382a2c 100644
--- a/askbot/forms.py
+++ b/askbot/forms.py
@@ -979,6 +979,11 @@ class EditUserForm(forms.Form):
required=False
)
+ show_marked_tags = forms.BooleanField(
+ label=_('Show tag choices'),
+ required=False
+ )
+
birthday = forms.DateField(
label=_('Date of birth'),
help_text=_('will not be shown, used to calculate age, format: YYYY-MM-DD'),
@@ -1009,6 +1014,7 @@ class EditUserForm(forms.Form):
country = user.country
self.fields['country'].initial = country
self.fields['show_country'].initial = user.show_country
+ self.fields['show_marked_tags'].initial = user.show_marked_tags
if user.date_of_birth is not None:
self.fields['birthday'].initial = user.date_of_birth
diff --git a/askbot/management/commands/askbot_add_test_content.py b/askbot/management/commands/askbot_add_test_content.py
index 6b14df59..ace629d0 100644
--- a/askbot/management/commands/askbot_add_test_content.py
+++ b/askbot/management/commands/askbot_add_test_content.py
@@ -14,21 +14,23 @@ NUM_COMMENTS = 20
# karma. This can be calculated dynamically - max of MIN_REP_TO_... settings
INITIAL_REPUTATION = 500
+BAD_STUFF = "<script>alert('hohoho')</script>"
+
# Defining template inputs.
-USERNAME_TEMPLATE = "test_user_%s"
+USERNAME_TEMPLATE = BAD_STUFF + "test_user_%s"
PASSWORD_TEMPLATE = "test_password_%s"
EMAIL_TEMPLATE = "test_user_%s@askbot.org"
-TITLE_TEMPLATE = "Test question title No.%s"
-TAGS_TEMPLATE = ["tag-%s-0", "tag-%s-1"] # len(TAGS_TEMPLATE) tags per question
+TITLE_TEMPLATE = "Test question title No.%s" + BAD_STUFF
+TAGS_TEMPLATE = [BAD_STUFF + "tag-%s-0", BAD_STUFF + "tag-%s-1"] # len(TAGS_TEMPLATE) tags per question
-CONTENT_TEMPLATE = """Lorem lean startup ipsum product market fit customer
+CONTENT_TEMPLATE = BAD_STUFF + """Lorem lean startup ipsum product market fit customer
development acquihire technical cofounder. User engagement
**A/B** testing *shrink* a market venture capital pitch."""
-ANSWER_TEMPLATE = """Accelerator photo sharing business school drop out ramen
+ANSWER_TEMPLATE = BAD_STUFF + """Accelerator photo sharing business school drop out ramen
hustle crush it revenue traction platforms."""
-COMMENT_TEMPLATE = """Main differentiators business model micro economics
+COMMENT_TEMPLATE = BAD_STUFF + """Main differentiators business model micro economics
marketplace equity augmented reality human computer"""
diff --git a/askbot/migrations/0125_add_show_tags_field_to_user.py b/askbot/migrations/0125_add_show_tags_field_to_user.py
new file mode 100644
index 00000000..cb7ab2bd
--- /dev/null
+++ b/askbot/migrations/0125_add_show_tags_field_to_user.py
@@ -0,0 +1,296 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding model show_marked_tags fields to the model auth_user
+ try:
+ db.add_column(
+ u'auth_user',
+ 'show_marked_tags',
+ self.gf(
+ 'django.db.models.fields.BooleanField'
+ )(default=True, blank=True)
+ )
+ except:
+ pass
+
+
+ def backwards(self, orm):
+
+ # Deleting show_marked_tags fields
+ db.delete_column(u'auth_user', 'show_marked_tags')
+
+ models = {
+ 'askbot.activity': {
+ 'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},
+ 'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Post']", 'null': 'True'}),
+ 'receiving_users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'received_activity'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
+ 'recipients': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'incoming_activity'", 'symmetrical': 'False', 'through': "orm['askbot.ActivityAuditStatus']", 'to': "orm['auth.User']"}),
+ 'summary': ('django.db.models.fields.TextField', [], {'default': "''"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.activityauditstatus': {
+ 'Meta': {'unique_together': "(('user', 'activity'),)", 'object_name': 'ActivityAuditStatus'},
+ 'activity': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Activity']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.anonymousanswer': {
+ 'Meta': {'object_name': 'AnonymousAnswer'},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['askbot.Post']"}),
+ 'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),
+ 'text': ('django.db.models.fields.TextField', [], {}),
+ 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+ },
+ 'askbot.anonymousquestion': {
+ 'Meta': {'object_name': 'AnonymousQuestion'},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),
+ 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),
+ 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+ 'text': ('django.db.models.fields.TextField', [], {}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+ 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+ },
+ 'askbot.award': {
+ 'Meta': {'object_name': 'Award', 'db_table': "u'award'"},
+ 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['askbot.BadgeData']"}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_user'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.badgedata': {
+ 'Meta': {'ordering': "('slug',)", 'object_name': 'BadgeData'},
+ 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['askbot.Award']", 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'})
+ },
+ 'askbot.emailfeedsetting': {
+ 'Meta': {'unique_together': "(('subscriber', 'feed_type'),)", 'object_name': 'EmailFeedSetting'},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'feed_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+ 'frequency': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '8'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'reported_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'subscriber': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notification_subscriptions'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.favoritequestion': {
+ 'Meta': {'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Thread']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.markedtag': {
+ 'Meta': {'object_name': 'MarkedTag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+ 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['askbot.Tag']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.post': {
+ 'Meta': {'object_name': 'Post'},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'posts'", 'to': "orm['auth.User']"}),
+ 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+ 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_posts'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_posts'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_posts'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'old_answer_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+ 'old_comment_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+ 'old_question_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['askbot.Post']"}),
+ 'post_type': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),
+ 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'thread': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'posts'", 'to': "orm['askbot.Thread']"}),
+ 'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'askbot.postrevision': {
+ 'Meta': {'ordering': "('-revision',)", 'unique_together': "(('post', 'revision'),)", 'object_name': 'PostRevision'},
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'postrevisions'", 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'revisions'", 'null': 'True', 'to': "orm['askbot.Post']"}),
+ 'revised_at': ('django.db.models.fields.DateTimeField', [], {}),
+ 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'revision_type': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),
+ 'tagnames': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '125', 'blank': 'True'}),
+ 'text': ('django.db.models.fields.TextField', [], {}),
+ 'title': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '300', 'blank': 'True'})
+ },
+ 'askbot.questionview': {
+ 'Meta': {'object_name': 'QuestionView'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'viewed'", 'to': "orm['askbot.Post']"}),
+ 'when': ('django.db.models.fields.DateTimeField', [], {}),
+ 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.replyaddress': {
+ 'Meta': {'object_name': 'ReplyAddress'},
+ 'address': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '25'}),
+ 'allowed_from_email': ('django.db.models.fields.EmailField', [], {'max_length': '150'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reply_addresses'", 'to': "orm['askbot.Post']"}),
+ 'response_post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edit_addresses'", 'null': 'True', 'to': "orm['askbot.Post']"}),
+ 'used_at': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.repute': {
+ 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},
+ 'comment': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'negative': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'positive': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Post']", 'null': 'True', 'blank': 'True'}),
+ 'reputation': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+ 'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.tag': {
+ 'Meta': {'ordering': "('-used_count', 'name')", 'object_name': 'Tag', 'db_table': "u'tag'"},
+ 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['auth.User']"}),
+ 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+ },
+ 'askbot.thread': {
+ 'Meta': {'object_name': 'Thread'},
+ 'accepted_answer': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['askbot.Post']"}),
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'answer_accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+ 'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'unused_favorite_threads'", 'symmetrical': 'False', 'through': "orm['askbot.FavoriteQuestion']", 'to': "orm['auth.User']"}),
+ 'favourite_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_threads'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'unused_last_active_in_threads'", 'to': "orm['auth.User']"}),
+ 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'threads'", 'symmetrical': 'False', 'to': "orm['askbot.Tag']"}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+ 'view_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+ },
+ 'askbot.vote': {
+ 'Meta': {'unique_together': "(('user', 'voted_post'),)", 'object_name': 'Vote', 'db_table': "u'vote'"},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['auth.User']"}),
+ 'vote': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'voted_post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['askbot.Post']"})
+ },
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),
+ 'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'consecutive_days_visit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}),
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'display_tag_filter_strategy': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),
+ 'email_tag_filter_strategy': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'gravatar': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ignored_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'interesting_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+ 'new_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),
+ 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+ 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'seen_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'show_country': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'show_marked_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}),
+ 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ }
+ }
+
+ complete_apps = ['askbot']
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index b686818f..c4c11cb4 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -13,6 +13,7 @@ from django.utils.translation import ugettext as _
from django.utils.translation import ungettext
from django.contrib.auth.models import User
from django.utils.safestring import mark_safe
+from django.utils.html import escape
from django.db import models
from django.conf import settings as django_settings
from django.contrib.contenttypes.models import ContentType
@@ -38,6 +39,7 @@ from askbot.models.repute import Award, Repute, Vote
from askbot import auth
from askbot.utils.decorators import auto_now_timestamp
from askbot.utils.slug import slugify
+from askbot.utils.html import sanitize_html
from askbot.utils.diff import textDiff as htmldiff
from askbot.utils.url_utils import strip_path
from askbot import mail
@@ -82,7 +84,7 @@ User.add_to_class(
)
)
-User.add_to_class('email_isvalid', models.BooleanField(default=False))
+User.add_to_class('email_isvalid', models.BooleanField(default=False)) #@UndefinedVariable
User.add_to_class('email_key', models.CharField(max_length=32, null=True))
#hardcoded initial reputaion of 1, no setting for this one
User.add_to_class('reputation',
@@ -122,6 +124,8 @@ User.add_to_class('interesting_tags', models.TextField(blank = True))
User.add_to_class('ignored_tags', models.TextField(blank = True))
User.add_to_class('subscribed_tags', models.TextField(blank = True))
User.add_to_class('email_signature', models.TextField(blank = True))
+User.add_to_class('show_marked_tags', models.BooleanField(default = True))
+
User.add_to_class(
'email_tag_filter_strategy',
models.SmallIntegerField(
@@ -237,6 +241,42 @@ def user_get_old_vote_for_post(self, post):
except Vote.MultipleObjectsReturned:
raise AssertionError
+def user_get_marked_tags(self, reason):
+ """reason is a type of mark: good, bad or subscribed"""
+ assert(reason in ('good', 'bad', 'subscribed'))
+ if reason == 'subscribed':
+ if askbot_settings.SUBSCRIBED_TAG_SELECTOR_ENABLED == False:
+ return Tag.objects.none()
+
+ return Tag.objects.filter(
+ user_selections__user = self,
+ user_selections__reason = reason
+ )
+
+MARKED_TAG_PROPERTY_MAP = {
+ 'good': 'interesting_tags',
+ 'bad': 'ignored_tags',
+ 'subscribed': 'subscribed_tags'
+}
+def user_get_marked_tag_names(self, reason):
+ """returns list of marked tag names for a give
+ reason: good, bad, or subscribed
+ will add wildcard tags as well, if used
+ """
+ if reason == 'subscribed':
+ if askbot_settings.SUBSCRIBED_TAG_SELECTOR_ENABLED == False:
+ return list()
+
+ tags = self.get_marked_tags(reason)
+ tag_names = list(tags.values_list('name', flat = True))
+
+ if askbot_settings.USE_WILDCARD_TAGS:
+ attr_name = MARKED_TAG_PROPERTY_MAP[reason]
+ wildcard_tags = getattr(self, attr_name).split()
+ tag_names.extend(wildcard_tags)
+
+ return tag_names
+
def user_has_affinity_to_question(self, question = None, affinity_type = None):
"""returns True if number of tag overlap of the user tag
selection with the question is 0 and False otherwise
@@ -2056,7 +2096,7 @@ def user_get_absolute_url(self):
def get_profile_link(self):
profile_link = u'<a href="%s">%s</a>' \
- % (self.get_profile_url(),self.username)
+ % (self.get_profile_url(), escape(self.username))
return mark_safe(profile_link)
@@ -2476,6 +2516,8 @@ User.add_to_class('get_absolute_url', user_get_absolute_url)
User.add_to_class('get_avatar_url', user_get_avatar_url)
User.add_to_class('get_default_avatar_url', user_get_default_avatar_url)
User.add_to_class('get_gravatar_url', user_get_gravatar_url)
+User.add_to_class('get_marked_tags', user_get_marked_tags)
+User.add_to_class('get_marked_tag_names', user_get_marked_tag_names)
User.add_to_class('strip_email_signature', user_strip_email_signature)
User.add_to_class('get_groups_membership_info', user_get_groups_membership_info)
User.add_to_class('get_anonymous_name', user_get_anonymous_name)
@@ -2644,8 +2686,8 @@ def format_instant_notification_email(
revisions = post.revisions.all()[:2]
assert(len(revisions) == 2)
content_preview = htmldiff(
- revisions[1].html,
- revisions[0].html,
+ 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">',
diff --git a/askbot/models/post.py b/askbot/models/post.py
index 673b4c6f..c08b940b 100644
--- a/askbot/models/post.py
+++ b/askbot/models/post.py
@@ -399,9 +399,8 @@ class Post(models.Model):
extra_authors = set()
for name_seed in extra_name_seeds:
- extra_authors.update(User.objects.filter(
- username__istartswith = name_seed
- )
+ extra_authors.update(
+ User.objects.filter(username__istartswith = name_seed)
)
#it is important to preserve order here so that authors of post
@@ -470,9 +469,12 @@ class Post(models.Model):
#because generic relation needs primary key of the related object
super(self.__class__, self).save(**kwargs)
if last_revision:
- diff = htmldiff(last_revision, self.html)
+ diff = htmldiff(
+ sanitize_html(last_revision),
+ sanitize_html(self.html)
+ )
else:
- diff = self.get_snippet()
+ diff = sanitize_html(self.get_snippet())
timestamp = self.get_time_of_last_edit()
diff --git a/askbot/models/repute.py b/askbot/models/repute.py
index 09e74067..33ec3a42 100644
--- a/askbot/models/repute.py
+++ b/askbot/models/repute.py
@@ -1,9 +1,10 @@
+import datetime
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import ugettext as _
-import datetime
+from django.utils.html import escape
from askbot import const
from django.core.urlresolvers import reverse
@@ -242,7 +243,7 @@ class Repute(models.Model):
return '<a href="%(url)s" title="%(link_title)s">%(question_title)s</a>' \
% {
'url': self.question.get_absolute_url(),
- 'question_title': self.question.thread.title,
- 'link_title': link_title
+ 'question_title': escape(self.question.thread.title),
+ 'link_title': escape(link_title)
}
diff --git a/askbot/models/user.py b/askbot/models/user.py
index 70aee263..e4077ea5 100644
--- a/askbot/models/user.py
+++ b/askbot/models/user.py
@@ -372,6 +372,7 @@ class GroupProfile(models.Model):
)
class Meta:
+ #added to make account merges work properly
app_label = 'askbot'
def can_accept_user(self, user):
diff --git a/askbot/skins/common/media/js/tag_selector.js b/askbot/skins/common/media/js/tag_selector.js
index d5482992..be79a9b6 100644
--- a/askbot/skins/common/media/js/tag_selector.js
+++ b/askbot/skins/common/media/js/tag_selector.js
@@ -72,6 +72,7 @@ TagDetailBox.prototype.renderFor = function(wildcard){
$.each(me._tag_names, function(idx, name){
var tag = new Tag();
tag.setName(name);
+ tag.setUrlParams(name)
//tag.setLinkable(false);
me._tags.push(tag);
me._tag_list_element.append(tag.getElement());
diff --git a/askbot/skins/common/templates/question/closed_question_info.html b/askbot/skins/common/templates/question/closed_question_info.html
index 87d9379c..f6f3f557 100644
--- a/askbot/skins/common/templates/question/closed_question_info.html
+++ b/askbot/skins/common/templates/question/closed_question_info.html
@@ -1,5 +1,5 @@
<div class="question-status">
<h3>{% trans close_reason=thread.get_close_reason_display() %}The question has been closed for the following reason <b>"{{ close_reason }}"</b> <i>by{% endtrans %}
- <a href="{{ thread.closed_by.get_profile_url() }}">{{ thread.closed_by.username }}</a> </i><br>
+ <a href="{{ thread.closed_by.get_profile_url() }}">{{ thread.closed_by.username|escape }}</a> </i><br>
{% trans closed_at=thread.closed_at %}close date {{closed_at}}{% endtrans %}</h3>
</div>
diff --git a/askbot/skins/default/media/style/style.less b/askbot/skins/default/media/style/style.less
index 343204fe..f5316829 100644
--- a/askbot/skins/default/media/style/style.less
+++ b/askbot/skins/default/media/style/style.less
@@ -1159,6 +1159,10 @@ ul.tags.marked-tags li,
ul#ab-user-tags li {
width: 160px;
margin:5px;
+ margin-left: 0;
+}
+.tags-page ul.tags {
+ margin-left: 5px;
}
ul#related-tags li {
@@ -3293,19 +3297,26 @@ p.signup_p {
.avatar-page li {
display: inline;
}
-.user-profile-page .avatar p {
- margin-bottom: 0px;
-}
-.user-profile-page .tabBar a#stats {
- margin-left: 0;
-}
-.user-profile-page img.gravatar {
- margin: 2px 0 3px 0;
-}
-.user-profile-page h3 {
- padding: 0;
- margin-top: -3px;
+
+.user-profile-page {
+ .avatar p {
+ margin-bottom: 0px;
+ }
+ .tabBar a#stats {
+ margin-left: 0;
+ }
+ img.gravatar {
+ margin: 2px 0 3px 0;
+ }
+ h3 {
+ padding: 0;
+ margin-top: -3px;
+ }
+ ul.tags {
+ margin-left: 5px;
+ }
}
+
.userList {
font-size: 13px;
}
diff --git a/askbot/skins/default/templates/badge.html b/askbot/skins/default/templates/badge.html
index d1f75617..b2c4ce8b 100644
--- a/askbot/skins/default/templates/badge.html
+++ b/askbot/skins/default/templates/badge.html
@@ -20,7 +20,7 @@
<div class="user">
<ul>
<li class="thumb">{{ gravatar(recipient, 32) }}</li>
- <li><a href="{{ recipient.get_absolute_url() }}">{{recipient.username}}</a></li>
+ <li><a href="{{ recipient.get_absolute_url() }}">{{recipient.username|escape}}</a></li>
<li>{{ macros.user_score_and_badge_summary(recipient) }}</li>
</ul>
</div>
diff --git a/askbot/skins/default/templates/email/ask_for_signature.html b/askbot/skins/default/templates/email/ask_for_signature.html
index e4449433..cafeee2b 100644
--- a/askbot/skins/default/templates/email/ask_for_signature.html
+++ b/askbot/skins/default/templates/email/ask_for_signature.html
@@ -1,6 +1,6 @@
{% import "email/macros.html" as macros %}
<p style="{{ macros.heading_style() }}">
- {% trans %}{{ username }}, please reply to this message.{% endtrans %}
+ {% trans user=username|escape %}{{ user }}, please reply to this message.{% endtrans %}
</p>
<p>
{% trans %}Your post could not be published, because we could not detect signature in your email.{% endtrans %}<br/>
diff --git a/askbot/skins/default/templates/email/insufficient_rep_to_post_by_email.html b/askbot/skins/default/templates/email/insufficient_rep_to_post_by_email.html
index da4c93ca..284cc1b0 100644
--- a/askbot/skins/default/templates/email/insufficient_rep_to_post_by_email.html
+++ b/askbot/skins/default/templates/email/insufficient_rep_to_post_by_email.html
@@ -6,7 +6,7 @@
* site_link - html for the link
#}
<p style="{{ macros.heading_style() }}">
- {% trans %}{{ username }}, your question could not be posted by email just yet.{% endtrans %}
+ {% trans user=username|escape %}{{ username }}, your question could not be posted by email just yet.{% endtrans %}
</p>
<p>
{% trans %}To make posts by email, you need to receive about {{min_upvotes}} upvotes.{% endtrans %}<br/>
diff --git a/askbot/skins/default/templates/email/macros.html b/askbot/skins/default/templates/email/macros.html
index 1acbf515..d7817bf9 100644
--- a/askbot/skins/default/templates/email/macros.html
+++ b/askbot/skins/default/templates/email/macros.html
@@ -7,7 +7,7 @@
%}
{% spaceless %}
{{ start_quote(quote_level) }}
- {% set author = post.author.username %}
+ {% set author = post.author.username|escape %}
{% if post.post_type == 'question' %}
<p>
{% if format == 'parent_subthread' %}
diff --git a/askbot/skins/default/templates/feedback.html b/askbot/skins/default/templates/feedback.html
index 85b5d00a..04b9a5b4 100644
--- a/askbot/skins/default/templates/feedback.html
+++ b/askbot/skins/default/templates/feedback.html
@@ -11,7 +11,7 @@
<form method="post" action="{% url feedback %}" accept-charset="utf-8">{% csrf_token %}
{% if user.is_authenticated() %}
<p class="message">
- {% trans user_name=user.username %}
+ {% trans user_name=user.username|escape %}
<span class='big strong'>Dear {{user_name}}</span>, we look forward to hearing your feedback.
Please type and send us your message below.
{% endtrans %}
diff --git a/askbot/skins/default/templates/help.html b/askbot/skins/default/templates/help.html
index 7dc58f5d..204fc086 100644
--- a/askbot/skins/default/templates/help.html
+++ b/askbot/skins/default/templates/help.html
@@ -4,7 +4,7 @@
<h1 class='section-title'>{% trans %}Help{% endtrans %}</h1>
<p>
{% if request.user.is_authenticated() %}
- {% trans username = request.user.username %}Welcome {{username}},{% endtrans %}
+ {% trans username = request.user.username|escape %}Welcome {{username}},{% endtrans %}
{% else %}
{% trans %}Welcome,{% endtrans %}
{% endif %}
diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html
index 485713aa..3e463c1c 100644
--- a/askbot/skins/default/templates/macros.html
+++ b/askbot/skins/default/templates/macros.html
@@ -10,7 +10,7 @@
{# follow - boolean; name - object type name; alias - e.g. users name; id - object id #}
<div
class="follow-toggle follow-user-toggle"
- id="follow-{{ name }}-{{ id }}"
+ id="follow-{{ name|escape }}-{{ id }}"
>
{% if follow %}
<div class="follow">{% trans %}follow {{alias}}{% endtrans %}</div>
@@ -29,18 +29,18 @@
<div class="face">
{{ gravatar(response.user, 48) }}
</div>
- <a style="font-size:12px" href="{{ response.user.get_absolute_url() }}">{{ response.user.username }}</a>
+ <a style="font-size:12px" href="{{ response.user.get_absolute_url() }}">{{ response.user.username|escape }}</a>
<a style="text-decoration:none;" href="{{ response.response_url }}">
{{ response.response_type }}
({{ timeago(response.timestamp) }}):<br/>
{% if inbox_section != 'flags' %}
- {{ response.response_snippet }}
+ {{ response.response_snippet|escape }}
{% endif %}
</a>
{% if inbox_section == 'flags' %}
<a class="re_expand" href="{{ response.response_url }}">
- <!--div class="re_snippet">{{ response.response_snippet }}</div-->
- <div class="re_content">{{ response.response_content }}</div>
+ <!--div class="re_snippet">{{ response.response_snippet|escape }}</div-->
+ <div class="re_content">{{ response.response_content|escape }}</div>
</a>
{% endif %}
</div>
@@ -291,14 +291,14 @@ poor design of the data or methods on data objects #}
class="tag tag-right{% if css_class %} {{ css_class }}{% endif %}"
{% if is_link %}
href="{{ search_state.add_tag(tag).full_url() }}"
- title="{% trans %}see questions tagged '{{ tag }}'{% endtrans %}"
+ title="{% trans tag=tag|escape %}see questions tagged '{{ tag }}'{% endtrans %}"
{% endif %}
rel="tag"
data-tag-name="{{ tag|replace('*', '&#10045;')|escape }}"
>{% if truncate_long_tag -%}
- {{ tag|replace('*', '&#10045;')|truncate(17, True) }}
+ {{ tag|replace('*', '&#10045;')|truncate(17, True)|escape }}
{%- else -%}
- {{ tag|replace('*', '&#10045;') }}
+ {{ tag|replace('*', '&#10045;')|escape }}
{%- endif %}</{% if not is_link or tag[-1] == '*' %}span{% else %}a{% endif %}>
{% if deletable %}
<div class="delete-icon"
@@ -402,7 +402,7 @@ for the purposes of the AJAX comment editor #}
</div>
<div class="comment-body">
{{comment.html}}
- <a class="author" href="{{comment.author.get_profile_url()}}">{{comment.author.username}}</a>
+ <a class="author" href="{{comment.author.get_profile_url()}}">{{comment.author.username|escape}}</a>
<span class="age">&nbsp;({{ timeago(comment.added_at) }})</span>
<a id="post-{{comment.id}}-edit"
class="edit">{% trans %}edit{% endtrans %}</a>
@@ -546,13 +546,13 @@ answer {% if answer.accepted() %}accepted-answer{% endif %} {% if answer.author_
{%- macro follow_user_toggle(visitor = None, subject = None) -%}
{% if visitor.is_anonymous() %}
- {{ follow_toggle(True, 'user', subject.username, subject.id) }}
+ {{ follow_toggle(True, 'user', subject.username|escape, subject.id) }}
{% else %}
{% if visitor != subject %}
{% if visitor.is_following(subject) %}
- {{ follow_toggle(False, 'user', subject.username, subject.id) }}
+ {{ follow_toggle(False, 'user', subject.username|escape, subject.id) }}
{% else %}
- {{ follow_toggle(True, 'user', subject.username, subject.id) }}
+ {{ follow_toggle(True, 'user', subject.username|escape, subject.id) }}
{% endif %}
{% endif %}
{% endif %}
@@ -572,7 +572,7 @@ answer {% if answer.accepted() %}accepted-answer{% endif %} {% if answer.author_
endtrans %}"
title="{% trans
country=user.country.name,
- person=user.username %}{{person}} is from {{country}}{%
+ person=user.username|escape %}{{person}} is from {{country}}{%
endtrans %}"
/>
{% endif %}
@@ -607,8 +607,8 @@ answer {% if answer.accepted() %}accepted-answer{% endif %} {% if answer.author_
><img class="gravatar"
width="{{size}}" height="{{size}}"
src="{{ user.get_avatar_url(size) }}"
- title="{{user.username}}"
- alt="{% trans username=user.username %}{{username}} gravatar image{% endtrans %}"
+ title="{{user.username|escape}}"
+ alt="{% trans username=user.username|escape %}{{username}} gravatar image{% endtrans %}"
/></a>
{% endspaceless %}
{%- endmacro -%}
@@ -708,7 +708,7 @@ answer {% if answer.accepted() %}accepted-answer{% endif %} {% if answer.author_
{% if user.new_response_count > 0 or user.seen_response_count > 0 %}
<a id='ab-responses' href="{{user.get_absolute_url()}}?sort=inbox&section=forum">
<img
- alt="{% trans username=user.username %}responses for {{username}}{% endtrans %}"
+ alt="{% trans username=user.username|escape %}responses for {{username}}{% endtrans %}"
{% if user.new_response_count > 0 %}
src="{{ "/images/mail-envelope-full.png"|media }}"
title="{% trans response_count=user.new_response_count %}you have {{response_count}} new response{% pluralize %}you have {{response_count}} new responses{% endtrans %}"
diff --git a/askbot/skins/default/templates/main_page/javascript.html b/askbot/skins/default/templates/main_page/javascript.html
index d968dcd5..10f8ede2 100644
--- a/askbot/skins/default/templates/main_page/javascript.html
+++ b/askbot/skins/default/templates/main_page/javascript.html
@@ -27,4 +27,4 @@
{% if request.user.is_authenticated() %}
<script type='text/javascript' src='{{"/js/tag_selector.js"|media}}'></script>
{% endif %}
-<script type="text/javascript" src="{{"/js/live_search.js"|media}}"></script>
+<script type="text/javascript" src='{{"/js/live_search.js"|media}}'></script>
diff --git a/askbot/skins/default/templates/reopen.html b/askbot/skins/default/templates/reopen.html
index 894fa3a0..52d926ce 100644
--- a/askbot/skins/default/templates/reopen.html
+++ b/askbot/skins/default/templates/reopen.html
@@ -10,7 +10,7 @@
</a>
</p>
<p>{% trans %}This question has been closed by
- <a href="{{closed_by_profile_url}}">{{closed_by_username}}</a>
+ <a href="{{closed_by_profile_url}}">{{closed_by_username|escape}}</a>
{% endtrans %}
</p>
<p>
diff --git a/askbot/skins/default/templates/user_profile/macros.html b/askbot/skins/default/templates/user_profile/macros.html
new file mode 100644
index 00000000..ac573553
--- /dev/null
+++ b/askbot/skins/default/templates/user_profile/macros.html
@@ -0,0 +1,24 @@
+{% import "macros.html" as macros %}
+
+{% macro tag_selection(tag_names, selection_type) %}
+ <a name="{{selection_type}}-tags"></a>
+ {% spaceless %}
+ <h2>{%
+ trans counter=tag_names|length, type=gettext(selection_type)|capitalize
+ %}<span class="count">{{counter}}</span> {{type}} Tag{%
+ pluralize
+ %}<span class="count">{{counter}}</span> {{type}} Tags{%
+ endtrans
+ %}
+ </h2>
+ {% endspaceless %}
+ <div class="user-stats-table">
+ <table class="tags">
+ <tr>
+ <td valign="top">
+ {{ macros.tag_list_widget(tag_names, deletable = False) }}
+ </td>
+ </tr>
+ </table>
+ </div>
+{% endmacro %}
diff --git a/askbot/skins/default/templates/user_profile/user.html b/askbot/skins/default/templates/user_profile/user.html
index fb40b206..2f06a3c9 100644
--- a/askbot/skins/default/templates/user_profile/user.html
+++ b/askbot/skins/default/templates/user_profile/user.html
@@ -9,7 +9,7 @@
{% block content %}
<h1 class="section-title">
{% spaceless %}
- {% trans username=view_user.username %}{{username}}'s profile{% endtrans %} - {% block profilesection %}{% endblock %}
+ {% trans username=view_user.username|escape %}{{username}}'s profile{% endtrans %} - {% block profilesection %}{% endblock %}
{% endspaceless %}
</h1>
{% include "user_profile/user_tabs.html" %}
@@ -21,7 +21,7 @@
{% block endjs %}
<script type="text/javascript">
var viewUserID = {{view_user.id}};
- askbot['data']['viewUserName'] = '{{ view_user.username }}';
+ askbot['data']['viewUserName'] = '{{ view_user.username|escape }}';
askbot['data']['viewUserId'] = {{view_user.id}};
askbot['urls']['edit_group_membership'] = '{% url edit_group_membership %}';
askbot['urls']['get_groups_list'] = '{% url get_groups_list %}';
diff --git a/askbot/skins/default/templates/user_profile/user_edit.html b/askbot/skins/default/templates/user_profile/user_edit.html
index 7735ba93..c95bf815 100644
--- a/askbot/skins/default/templates/user_profile/user_edit.html
+++ b/askbot/skins/default/templates/user_profile/user_edit.html
@@ -4,7 +4,7 @@
{% block title %}{% spaceless %}{% trans %}Edit user profile{% endtrans %}{% endspaceless %}{% endblock %}
{% block content %}
<h1 class="section-title">
- {{ request.user.username }} - {% trans %}edit profile{% endtrans %}
+ {{ request.user.username|escape }} - {% trans %}edit profile{% endtrans %}
</h1>
<div id="main-body" style="width:100%;padding-top:10px">
<form name="" action="{% url edit_user request.user.id %}" method="post">{% csrf_token %}
@@ -42,7 +42,7 @@
{{ form.username }}
<span class="form-error"> {{ form.username.errors }} </span></td>
{% else %}
- {{ view_user.username }}
+ {{ view_user.username|escape }}
{% endif %}
</td>
</tr>
@@ -96,6 +96,14 @@
<td style="vertical-align:top">{{ form.about.label_tag() }}:</td>
<td>{{ form.about }} <span class="form-error"> {{ form.about.errors }} </span></td>
</tr>
+ {% if marked_tags_setting == 'when-user-wants' %}
+ <tr>
+ <td>{{ form.show_marked_tags.label_tag() }}:</td>
+ <td>{{ form.show_marked_tags }}
+ <span class="form-error">{{ form.show_marked_tags.errors }}</span>
+ </td>
+ </tr>
+ {% endif %}
</table>
<div style="margin:30px 0 60px 0">
<input type="submit" value="{% trans %}Update{% endtrans %}" class="submit" >&nbsp;
diff --git a/askbot/skins/default/templates/user_profile/user_moderate.html b/askbot/skins/default/templates/user_profile/user_moderate.html
index 347ec3af..a7f05b1c 100644
--- a/askbot/skins/default/templates/user_profile/user_moderate.html
+++ b/askbot/skins/default/templates/user_profile/user_moderate.html
@@ -5,7 +5,7 @@
{% endblock %}
{% block usercontent %}
{% if request.user != view_user %}
- <h3>{% trans username=view_user.username, status=view_user.get_status_display() %}{{username}}'s current status is "{{status}}"{% endtrans %}
+ <h3>{% trans username=view_user.username|escape, status=view_user.get_status_display() %}{{username}}'s current status is "{{status}}"{% endtrans %}
</h3>
{% if user_status_changed %}
<p class="action-status"><span>{% trans %}User status changed{% endtrans %}</span></p>
@@ -40,7 +40,7 @@
</form>
{% if request.user != view_user %}
<hr/>
-<h3>{% trans username=view_user.username %}Send message to {{username}}{% endtrans %}</h3>
+<h3>{% trans username=view_user.username|escape %}Send message to {{username}}{% endtrans %}</h3>
<p>{% trans %}An email will be sent to the user with 'reply-to' field set to your email address. Please make sure that your address is entered correctly.{% endtrans %}</p>
{% if message_sent %}
<p class="action-status"><span>{% trans %}Message sent{% endtrans %}</span></p>
diff --git a/askbot/skins/default/templates/user_profile/user_network.html b/askbot/skins/default/templates/user_profile/user_network.html
index e6134e0c..f64d95b0 100644
--- a/askbot/skins/default/templates/user_profile/user_network.html
+++ b/askbot/skins/default/templates/user_profile/user_network.html
@@ -32,7 +32,7 @@
{% if request.user == view_user %}
<p>{% trans %}Your network is empty. Would you like to follow someone? - Just visit their profiles and click "follow"{% endtrans %}</p>
{% else %}
- <p>{% trans username = view_user.username %}{{username}}'s network is empty{% endtrans %}</p>
+ <p>{% trans username = view_user.username|escape %}{{username}}'s network is empty{% endtrans %}</p>
{% endif %}
{% endif %}
{% endblock %}
diff --git a/askbot/skins/default/templates/user_profile/user_reputation.html b/askbot/skins/default/templates/user_profile/user_reputation.html
index 1bb9b1ba..1cdf014a 100644
--- a/askbot/skins/default/templates/user_profile/user_reputation.html
+++ b/askbot/skins/default/templates/user_profile/user_reputation.html
@@ -11,7 +11,7 @@
{% if view_user.id == user.id %}
<h2>{% trans %}Your karma change log.{% endtrans %}</h2>
{% else %}
- <h2>{% trans user_name=view_user.username %}{{user_name}}'s karma change log{% endtrans %}</h2>
+ <h2>{% trans user_name=view_user.username|escape %}{{user_name}}'s karma change log{% endtrans %}</h2>
{% endif %}
{% for rep in reputation %}
<p>
diff --git a/askbot/skins/default/templates/user_profile/user_stats.html b/askbot/skins/default/templates/user_profile/user_stats.html
index 177df214..2ccc277f 100644
--- a/askbot/skins/default/templates/user_profile/user_stats.html
+++ b/askbot/skins/default/templates/user_profile/user_stats.html
@@ -1,5 +1,6 @@
{% extends "user_profile/user.html" %}
{% import "macros.html" as macros %}
+{% import "user_profile/macros.html" as user_profile_macros %}
<!-- user_stats.html -->
{% block profilesection %}
{% trans %}overview{% endtrans %}
@@ -9,7 +10,7 @@
{% if settings.GROUPS_ENABLED %}
<div id="user-groups">
<h2>{% trans
- username = view_user.username
+ username = view_user.username|escape
%}{{username}}'s groups{% endtrans %}
</h2>
<table id="groups-list">
@@ -110,6 +111,15 @@
</tr>
</table>
</div>
+ {% if interesting_tag_names %}
+ {{ user_profile_macros.tag_selection(interesting_tag_names, 'interesting') }}
+ {% endif %}
+ {% if ignored_tag_names %}
+ {{ user_profile_macros.tag_selection(ignored_tag_names, 'ignored') }}
+ {% endif %}
+ {% if subscribed_tag_names %}
+ {{ user_profile_macros.tag_selection(subscribed_tag_names, 'subscribed') }}
+ {% endif %}
{% if settings.BADGES_MODE == 'public' %}
<a name="badges"></a>
{% spaceless %}
@@ -136,7 +146,7 @@
<a
title="{{ award.content_object.get_snippet()|collapse }}"
href="{{ award.content_object.get_absolute_url() }}"
- >{% if award.content_type.post_type == 'answer' %}{% trans %}Answer to:{% endtrans %}{% endif %} {{ award.content_object.thread.title }}</a>
+ >{% if award.content_type.post_type == 'answer' %}{% trans %}Answer to:{% endtrans %}{% endif %} {{ award.content_object.thread.title|escape }}</a>
</li>
{% endif %}
{% endfor %}
@@ -164,5 +174,9 @@
});
});
</script>
+ <script type='text/javascript' src='{{"/js/tag_selector.js"|media}}'></script>
+ <script type="text/javascript">
+ askbot['urls']['questions'] = '{% url "questions" %}';
+ </script>
{% endblock %}
<!-- end user_stats.html -->
diff --git a/askbot/skins/default/templates/widgets/question_summary.html b/askbot/skins/default/templates/widgets/question_summary.html
index c6e7bc5d..5fd51e08 100644
--- a/askbot/skins/default/templates/widgets/question_summary.html
+++ b/askbot/skins/default/templates/widgets/question_summary.html
@@ -46,7 +46,7 @@
{% if question.is_anonymous %}
<span class="anonymous">{{ thread.last_activity_by.get_anonymous_name() }}</span>
{% else %}
- <a href="{% url user_profile thread.last_activity_by.id, thread.last_activity_by.username|slugify %}">{{thread.last_activity_by.username}}</a> {{ user_country_flag(thread.last_activity_by) }}
+ <a href="{% url user_profile thread.last_activity_by.id, thread.last_activity_by.username|slugify %}">{{thread.last_activity_by.username|escape}}</a> {{ user_country_flag(thread.last_activity_by) }}
{#{user_score_and_badge_summary(thread.last_activity_by)}#}
{% endif %}
</div>
diff --git a/askbot/skins/default/templates/widgets/user_list.html b/askbot/skins/default/templates/widgets/user_list.html
index 11f2ed50..e51abc5b 100644
--- a/askbot/skins/default/templates/widgets/user_list.html
+++ b/askbot/skins/default/templates/widgets/user_list.html
@@ -7,7 +7,7 @@
<div class="user">
<ul>
<li class="thumb">{{ gravatar(user, 32) }}</li>
- <li><a href="{% url user_profile user.id, user.username|slugify %}{% if profile_section %}?sort={{profile_section}}{% endif %}">{{user.username}}</a>{{ user_country_flag(user) }}</li>
+ <li><a href="{% url user_profile user.id, user.username|slugify %}{% if profile_section %}?sort={{profile_section}}{% endif %}">{{user.username|escape}}</a>{{ user_country_flag(user) }}</li>
<li>{{
user_score_and_badge_summary(
user,
diff --git a/askbot/skins/default/templates/widgets/user_navigation.html b/askbot/skins/default/templates/widgets/user_navigation.html
index eec7e628..717cd7ee 100644
--- a/askbot/skins/default/templates/widgets/user_navigation.html
+++ b/askbot/skins/default/templates/widgets/user_navigation.html
@@ -1,5 +1,5 @@
{%- if request.user.is_authenticated() -%}
- <a href="{{ request.user.get_absolute_url() }}">{{ request.user.username }}</a>
+ <a href="{{ request.user.get_absolute_url() }}">{{ request.user.username|escape }}</a>
<span class="user-info">
{{ macros.inbox_link(request.user) }}
{{ macros.moderation_items_link(request.user, moderation_items) }}
diff --git a/askbot/utils/html.py b/askbot/utils/html.py
index 1ce3ad35..2e3c1913 100644
--- a/askbot/utils/html.py
+++ b/askbot/utils/html.py
@@ -5,6 +5,7 @@ import re
import htmlentitydefs
from urlparse import urlparse
from django.core.urlresolvers import reverse
+from django.utils.html import escape
class HTMLSanitizerMixin(sanitizer.HTMLSanitizerMixin):
acceptable_elements = ('a', 'abbr', 'acronym', 'address', 'b', 'big',
@@ -62,7 +63,7 @@ def site_link(url_name, title):
from askbot.conf import settings
base_url = urlparse(settings.APP_URL)
url = base_url.scheme + '://' + base_url.netloc + reverse(url_name)
- return '<a href="%s">%s</a>' % (url, title)
+ return '<a href="%s">%s</a>' % (url, escape(title))
def unescape(text):
"""source: http://effbot.org/zone/re-sub.htm#unescape-html
diff --git a/askbot/views/readers.py b/askbot/views/readers.py
index 8f19a802..d7e5cecc 100644
--- a/askbot/views/readers.py
+++ b/askbot/views/readers.py
@@ -23,6 +23,7 @@ from django.core.urlresolvers import reverse
from django.core import exceptions as django_exceptions
from django.contrib.humanize.templatetags import humanize
from django.http import QueryDict
+from django.conf import settings
import askbot
from askbot import exceptions
@@ -33,6 +34,7 @@ from askbot import schedules
from askbot.models.tag import Tag
from askbot import const
from askbot.utils import functions
+from askbot.utils.html import sanitize_html
from askbot.utils.decorators import anonymous_forbidden, ajax_only, get_only
from askbot.search.state_manager import SearchState, DummySearchState
from askbot.templatetags import extra_tags
@@ -126,7 +128,7 @@ def questions(request, **kwargs):
# We have tags in session - pass it to the
# QueryDict but as a list - we want tags+
rss_query_dict.setlist("tags", search_state.tags)
- context_feed_url = '/feeds/rss/?%s' % rss_query_dict.urlencode() # Format the url with the QueryDict
+ context_feed_url = '/%sfeeds/rss/?%s' % (settings.ASKBOT_URL, rss_query_dict.urlencode()) # Format the url with the QueryDict
reset_method_count = len(filter(None, [search_state.query, search_state.tags, meta_data.get('author_name', None)]))
@@ -561,10 +563,13 @@ def revisions(request, id, post_type = None):
revisions.reverse()
for i, revision in enumerate(revisions):
if i == 0:
- revision.diff = revisions[i].html
+ revision.diff = sanitize_html(revisions[i].html)
revision.summary = _('initial version')
else:
- revision.diff = htmldiff(revisions[i-1].html, revision.html)
+ revision.diff = htmldiff(
+ sanitize_html(revisions[i-1].html),
+ sanitize_html(revision.html)
+ )
data = {
'page_class':'revisions-page',
diff --git a/askbot/views/users.py b/askbot/views/users.py
index 9d9419e1..8bc2909d 100644
--- a/askbot/views/users.py
+++ b/askbot/views/users.py
@@ -128,7 +128,7 @@ def users(request, by_group = False, group_id = None, group_slug = None):
models.User.objects.order_by(order_by_parameter),
const.USERS_PAGE_SIZE
)
- base_url = request.path + '?sort=%s&' % sortby
+ base_url = request.path + '?sort=%s&amp;' % sortby
else:
sortby = "reputation"
matching_users = models.get_users_by_text_query(search_query)
@@ -136,7 +136,7 @@ def users(request, by_group = False, group_id = None, group_slug = None):
matching_users.order_by('-reputation'),
const.USERS_PAGE_SIZE
)
- base_url = request.path + '?name=%s&sort=%s&' % (search_query, sortby)
+ base_url = request.path + '?name=%s&amp;sort=%s&amp;' % (search_query, sortby)
try:
users_page = objects_list.page(page)
@@ -297,7 +297,7 @@ def edit_user(request, id):
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,
@@ -308,10 +308,12 @@ def edit_user(request, id):
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,
}
@@ -368,6 +370,18 @@ def user_stats(request, user, context):
order_by('-user_tag_usage_count')[:const.USER_VIEW_DATA_SIZE]
user_tags = list(user_tags) # evaluate
+ when = askbot_settings.MARKED_TAGS_ARE_PUBLIC_WHEN
+ if when == 'always' or \
+ (when == 'when-user-wants' and user.show_marked_tags == True):
+ #refactor into: user.get_marked_tag_names('good'/'bad'/'subscribed')
+ interesting_tag_names = user.get_marked_tag_names('good')
+ ignored_tag_names = user.get_marked_tag_names('bad')
+ subscribed_tag_names = user.get_marked_tag_names('subscribed')
+ else:
+ interesting_tag_names = None
+ ignored_tag_names = None
+ subscribed_tag_names = None
+
# tags = models.Post.objects.filter(author=user).values('id', 'thread', 'thread__tags')
# post_ids = set()
# thread_ids = set()
@@ -453,6 +467,9 @@ def user_stats(request, user, context):
'user_tags' : user_tags,
'user_groups': user_groups,
'groups_membership_info': groups_membership_info,
+ 'interesting_tag_names': interesting_tag_names,
+ 'ignored_tag_names': ignored_tag_names,
+ 'subscribed_tag_names': subscribed_tag_names,
'badges': badges,
'total_badges' : len(badges),
}
diff --git a/askbot/views/writers.py b/askbot/views/writers.py
index 935b7cfa..232dbaea 100644
--- a/askbot/views/writers.py
+++ b/askbot/views/writers.py
@@ -17,7 +17,7 @@ from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404
from django.utils import simplejson
-from django.utils.html import strip_tags
+from django.utils.html import strip_tags, escape
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
from django.core import exceptions
@@ -545,7 +545,7 @@ def __generate_comments_json(obj, user):#non-view generates json data for the po
'object_id': obj.id,
'comment_added_at': str(comment.added_at.replace(microsecond = 0)) + tz,
'html': comment.html,
- 'user_display_name': comment_owner.username,
+ 'user_display_name': escape(comment_owner.username),
'user_url': comment_owner.get_profile_url(),
'user_id': comment_owner.id,
'is_deletable': is_deletable,
diff --git a/askbot_requirements_dev.txt b/askbot_requirements_dev.txt
index ada0d83e..b960c76e 100644
--- a/askbot_requirements_dev.txt
+++ b/askbot_requirements_dev.txt
@@ -5,6 +5,7 @@ Coffin>=0.3
South>=0.7.1
#-e git+https://github.com/matthiask/south.git#egg=south
oauth2
+Lamson
markdown2
html5lib==0.90
django-keyedcache