diff --git a/AUTHORS b/AUTHORS index c897ef4..b09e61a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1,2 @@ Maciej Bliziński +Olivier Le Thanh Duong diff --git a/NEWS b/NEWS deleted file mode 100644 index e69de29..0000000 diff --git a/README b/README deleted file mode 100644 index 15a247f..0000000 --- a/README +++ /dev/null @@ -1,24 +0,0 @@ - django-phpbb - Django PhpBB integration - - - - Copyright (C) 2008 Maciej Bliziński - Copyright (C) 2010 Olivier Le Thanh Duong - - djangophpbb is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Comments are welcome. - - - Maciej Bliziński diff --git a/README.md b/README.md new file mode 100644 index 0000000..f57430e --- /dev/null +++ b/README.md @@ -0,0 +1,111 @@ +--------------------------------------- +django-phpbb - Django-PhpBB integration +--------------------------------------- + +In case of django-phpbb, using it means that when you're coding a Django +application, you have a set of classes and functions at your disposal, providing +a glue between phpBB3 and Django. + +## Authentication ## + +### A prerequisite: Django authentication ### + +First, prerequisites. Make sure your [Django +authentication](http://docs.djangoproject.com/en/dev/topics/auth/#topics-auth) +is working. + +If your Django website uses authentication already, you probably have the +following lines in your `urls.py`. + + (r'^accounts/login/$', 'django.contrib.auth.views.login', ), + (r'^accounts/logout/$', 'django.contrib.auth.views.logout', ), + +If there are no such lines in your `urls.py`, your application probably doesn't +use authentication. Consult the Django documentation for instructions to get +your authentication to work. + +## PYTHONPATH ## + +The django-phpbb directory must be in PYTHONPATH (or sys.path). + +## Adding phpbb3 authentication backend ## + +Edit your `settings.py` and make sure the following lines are present: + + MIDDLEWARE_CLASSES = ( + ... + 'django.contrib.auth.middleware.AuthenticationMiddleware', + ) + TEMPLATE_CONTEXT_PROCESSORS = ( + ... + "django.core.context_processors.auth", + ) + INSTALLED_APPS = ( + 'django.contrib.auth', + ... + 'phpbb', + ) + AUTHENTICATION_BACKENDS = ( + 'phpbb.backends.PhpbbBackend', + 'django.contrib.auth.backends.ModelBackend', + ) + + +Once you've done that, the authentication backend should be enabled and users +should be able to log in using not only Django passwords, but also passwords +checked against the phpbb3 database. + +## phpBB3 classes ## + +You can access phpBB3 forum objects using provided classes. Look up the source +code to see the details of the classes. (Sorry for not providing any better +documentation at this time.) + +Fire up Django shell and try using django-phpbb classes: + + ./manage.py shell + from django.contrib.phpbb import models as p3m + forum = p3m.PhpbbForum.objects.get(pk=1) + dir(forum) + forum.forum_name + forum.phpbbtopic_set.all()[:5] + +## Predefined views ## + +You need to have a `base.html` template that django-phpbb's template expect to +extend. + +To enable predefined views, add this line to your `urls.py`: + + (r'^forum/', include('phpbb.urls')), + +Also, make django-phpbb templates available: + + TEMPLATE_DIRS = ( + ... + "/some-directory/django-phpbb/phpbb/templates", + ) + +_The views currently contain bits and pieces of the original website they've +been cut from. The views are going to be reworked. Consider them more as a guide +to see how you can implement your own forum browsing rather than a complete +solution._ + +License +------- + +Copyright (C) 2008 Maciej Bliziński +Copyright (C) 2010 Olivier Le Thanh Duong + +django-phpbb is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA diff --git a/TODO b/TODO index 0b1199b..62175d5 100644 --- a/TODO +++ b/TODO @@ -6,6 +6,8 @@ To do list: - Option 1: use http://code.google.com/p/postmarkup/ - Issues: Doesn't support integration with a real phpBB database - Option 2: port original bbcode[1]. +- Add support for access control, at the very least determining which forums + should be publicly visible and which shouldn't. [1] http://code.phpbb.com/repositories/entry/5/trunk/phpBB/includes/bbcode.php http://code.phpbb.com/repositories/entry/5/trunk/phpBB/includes/message_parser.php diff --git a/phpbb/admin.py b/phpbb/admin.py index 064cfea..54e1a93 100644 --- a/phpbb/admin.py +++ b/phpbb/admin.py @@ -63,7 +63,7 @@ class PhpbbAclRoleOptionAdmin(admin.ModelAdmin): # 'auth_option', # 'auth_global') admin.site.register(pm.PhpbbAclOption, PhpbbAclRoleOptionAdmin) -#admin.site.register(pm.PhpbbAclRoleDatum) +# admin.site.register(pm.PhpbbAclRoleDatum) # Composite keys support needed # admin.site.register(pm.PhpbbAclGroup) admin.site.register(pm.PhpbbGroup) diff --git a/phpbb/backends.py b/phpbb/backends.py index ce4b9a8..b980779 100644 --- a/phpbb/backends.py +++ b/phpbb/backends.py @@ -39,7 +39,7 @@ class PhpbbBackend: def authenticate(self, username=None, password=None): """Authenticate user against phpBB3 database. - + Check if the user exists in Django users. If not, create it. Then authenticate.""" logging.debug("PhpbbBackend::authenticate()") @@ -67,7 +67,7 @@ def authenticate(self, username=None, password=None): logging.info("Creating new Django user '%s'" % username) if username: user = User(username = username, password = "") - user.is_staff = True + user.is_staff = False user.is_superuser = False user.email = phpbb_user.user_email @@ -117,4 +117,3 @@ def has_module_perms(self, user_obj, app_label): if perm[:perm.index('.')] == app_label: return True return False - diff --git a/phpbb/bbcode.py b/phpbb/bbcode.py index 2b75e8d..bd65854 100644 --- a/phpbb/bbcode.py +++ b/phpbb/bbcode.py @@ -45,7 +45,7 @@ class BitField(object): http://code.phpbb.com/repositories/entry/5/trunk/phpBB/includes/functions_content.php""" def __init__(self, bitfield=""): self.data = bitfield.decode("base64") - + def get(self, n): byte = n >> 3 if len(self.data) >= byte + 1: @@ -118,7 +118,7 @@ class BbCode(object): - user is passed to the constructor (on original code, a global variable is used) """ - + def __init__(self, user, bitfield=""): self.user = user if bitfield: diff --git a/phpbb/bbcode_unittest.py b/phpbb/bbcode_test.py old mode 100644 new mode 100755 similarity index 98% rename from phpbb/bbcode_unittest.py rename to phpbb/bbcode_test.py index 063495f..63c6fc4 --- a/phpbb/bbcode_unittest.py +++ b/phpbb/bbcode_test.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python # -*- coding: utf-8 -*- # This file is part of django-phpbb, integration between Django and phpBB # Copyright (C) 2007-2008 Maciej Bliziński @@ -57,13 +58,13 @@ def setUp(self): def testGet0(self): self.assertEquals(self.b1.get(0), 0) - + def testGet3(self): self.assertEquals(self.b1.get(3), 16) - + def testGet4(self): self.assertEquals(self.b1.get(4), 0) - + def testSet0(self): self.b1.set(0) self.assertEquals(self.b1.get(0), 128) @@ -71,14 +72,14 @@ def testSet0(self): def testSet1(self): self.b1.set(0) self.assertEquals(self.b1.get_bin(), "10010000") - + def testGetBin(self): self.assertEquals(self.b1.get_bin(), "00010000") def testGetAllSet(self): self.b1.set(7) self.assertEquals(self.b1.get_all_set(), [3, 7]) - + def testGetBlob(self): self.assertEquals(self.b1.get_blob(), '\x10') @@ -92,7 +93,7 @@ def testMerge(self): self.assertEquals(b1.get(0), 128) self.assertEquals(b1.get(1), 64) del b1, b2 - + def tearDown(self): del self.b1 diff --git a/phpbb/feeds.py b/phpbb/feeds.py index 03dfe7c..399a724 100644 --- a/phpbb/feeds.py +++ b/phpbb/feeds.py @@ -19,16 +19,21 @@ # Boston, MA 02110-1301 USA from django.utils.translation import gettext_lazy as _ -from django.contrib.syndication.feeds import Feed +from django.contrib.syndication.views import Feed from models import PhpbbPost +from phpbb import querysets class LatestPhpbbPosts(Feed): + """Returns the newest forum posts. + + FIXME: Show only public forums. Needs composite primary keys, currently not + supported in Django. + + """ title = u"Forum" link = "/forum/" description = _("Newest posts on the forum.") def items(self): - return (PhpbbPost.objects.order_by('-post_time_int'). - exclude(topic__forum__forum_id=15). - exclude(topic__forum__forum_id=6)[:20]) + return querysets.postqs.order_by('-post_time_int')[:20] def item_link(self, obj): return obj.get_external_url() diff --git a/phpbb/models.py b/phpbb/models.py index 3f0aa43..9442f23 100644 --- a/phpbb/models.py +++ b/phpbb/models.py @@ -17,6 +17,7 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA +import settings from django.db import models from django.utils.translation import gettext_lazy as _ from django.contrib.auth.models import User @@ -27,6 +28,7 @@ from django.utils.translation import gettext_lazy as _ from django.conf import settings + class PhpbbUser(models.Model): """Model for phpBB user.""" user_id = models.IntegerField(primary_key=True) @@ -48,7 +50,7 @@ def user_regdate(self): def user_lastvisit(self): return datetime.fromtimestamp(self.user_lastvisit_int) class Meta: - db_table = 'phpbb_users' + db_table = settings.PHPBB_TABLE_PREFIX + 'users' ordering = ['username'] @@ -76,11 +78,11 @@ def __unicode__(self): def __str__(self): return str(self.forum_name) def get_absolute_url(self): - return u"/forum/%s/%s/" % (self.forum_id, self.get_slug()) + return u"/archiwum/%s/%s/" % (self.forum_id, self.get_slug()) def get_slug(self): return slugify(self.forum_name) class Meta: - db_table = 'phpbb_forums' + db_table = settings.PHPBB_TABLE_PREFIX + 'forums' ordering = ['forum_name'] @@ -106,20 +108,19 @@ def topic_last_post_time(self): def __unicode__(self): return self.get_title() def get_absolute_url(self): - return "/forum/%s/%s/%s/" % ( - _("topics"), - self.topic_id, - self.get_slug()) - + return "/archiwum/%s/%s/%s/" % ( + _("topics"), + self.topic_id, + self.get_slug()) def get_external_url(self): - return (settings.PHPBB_URL + "/viewtopic.php?t=%s" - % (self.topic_id)) + return (settings.PHPBB_URL + "/viewtopic.php?f=%s&t=%s" + % (self.forum.forum_id, self.topic_id)) def get_slug(self): return slugify(self.get_title()) def topic_time(self): return datetime.fromtimestamp(self.topic_time_int) class Meta: - db_table = 'phpbb_topics' + db_table = settings.PHPBB_TABLE_PREFIX + 'topics' ordering = ['-topic_time_int'] @@ -153,7 +154,7 @@ def get_page(self): """TODO: find out, which post in the row it is.""" return 1 class Meta: - db_table = 'phpbb_posts' + db_table = settings.PHPBB_TABLE_PREFIX + 'posts' ordering = ['post_time_int'] @@ -170,7 +171,7 @@ class PhpbbGroup(models.Model): def __unicode__(self): return u"PhpbbGroup(%s, %s)" % (self.id, self.group_name) class Meta: - db_table = 'phpbb_groups' + db_table = settings.PHPBB_TABLE_PREFIX + 'groups' ordering = ['id'] class PhpbbUserGroup(models.Model): @@ -192,7 +193,7 @@ class PhpbbAclRole(models.Model): def __unicode__(self): return force_unicode(self.role_name) class Meta: - db_table = 'phpbb_acl_roles' + db_table = settings.PHPBB_TABLE_PREFIX + 'acl_roles' ordering = ['role_name'] @@ -205,7 +206,7 @@ class PhpbbAclOption(models.Model): def __unicode__(self): return self.auth_option class Meta: - db_table = 'phpbb_acl_options' + db_table = settings.PHPBB_TABLE_PREFIX + 'acl_options' ordering = ['auth_option_id'] @@ -220,7 +221,7 @@ class Meta: ## role_id = models.ForeignKey(PhpbbAclRole, ## db_column='role_id') ## auth_option = models.ForeignKey(PhpbbAclOption, -## db_column='auth_option_id') +## db_column='auth_option_id') ## auth_setting = models.IntegerField() ## def __unicode__(self): ## return u"%s, %s => %s" % (self.role_id, @@ -228,7 +229,7 @@ class Meta: ## self.auth_setting) ## class Meta: ## primary_key = ('role_id', 'auth_option') -## db_table = 'phpbb_acl_roles_data' +## db_table = 'phpbb3_acl_roles_data' ## verbose_name_plural = 'Phpbb acl role data' ## unique_together = (('role_id', 'auth_option'),) ## @@ -237,9 +238,9 @@ class Meta: ## group = models.ForeignKey(PhpbbGroup, db_column="group_id") ## forum = models.ForeignKey(PhpbbForum, db_column="forum_id") ## auth_option = models.ForeignKey(PhpbbAclOption, -## db_column="auth_option_id") +## db_column="auth_option_id") ## auth_role = models.ForeignKey(PhpbbAclRole, -## db_column="auth_role_id") +## db_column="auth_role_id") ## auth_setting = models.IntegerField() ## def __unicode__(self): ## return ((u"PhpbbAclGroup(%s, %s, %s, %s)") @@ -249,7 +250,7 @@ class Meta: ## self.auth_setting)) ## class Meta: ## primary_key = ('forum', 'group', 'auth_option', 'auth_role') -## db_table = 'phpbb_acl_groups' +## db_table = 'phpbb3_acl_groups' ## ordering = ['group', 'auth_role'] @@ -260,7 +261,7 @@ class PhpbbConfig(models.Model): def __unicode__(self): return self.config_name class Meta: - db_table = 'phpbb_config' + db_table = settings.PHPBB_TABLE_PREFIX + 'config' ordering = ['config_name'] verbose_name = 'Phpbb config entry' verbose_name_plural = 'Phpbb config entries' diff --git a/phpbb/password.py b/phpbb/password.py index 46c17d6..54778e7 100644 --- a/phpbb/password.py +++ b/phpbb/password.py @@ -2,9 +2,8 @@ class PhpbbPassword(object): """PhpBB3 password compatibility class. - -Ported from: -http://code.phpbb.com/repositories/entry/5/trunk/phpBB/includes/functions.php + Ported from: + http://code.phpbb.com/repositories/entry/5/trunk/phpBB/includes/functions.php """ itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" @@ -66,7 +65,7 @@ def _hash_encode64(self, input, count, itoa64=itoa64): def _hash_crypt_private(self, password, setting, itoa64=itoa64): """The crypt function/replacement - + 'setting' means 'hash' or 'salt' here.""" output = self.wrong if type(password) != str: diff --git a/phpbb/password_unittest.py b/phpbb/password_test.py old mode 100644 new mode 100755 similarity index 98% rename from phpbb/password_unittest.py rename to phpbb/password_test.py index 1c1b9e5..9781c9b --- a/phpbb/password_unittest.py +++ b/phpbb/password_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python import password import unittest diff --git a/phpbb/querysets.py b/phpbb/querysets.py new file mode 100644 index 0000000..2665951 --- /dev/null +++ b/phpbb/querysets.py @@ -0,0 +1,16 @@ +from django.conf import settings +import phpbb.models + +# TODO: get rid of hardcoded forum IDs +# They could be fixed by implementing permission tables +# from phpbb, but this runs into bug 373. +# +# http://code.djangoproject.com/ticket/373 +# +# More information: +# http://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys +forumqs = phpbb.models.PhpbbForum.objects +postqs = phpbb.models.PhpbbPost.objects +for excluded_forum_id in settings.PHPBB_BLOCKED_FORUMS: + forumqs = forumqs.exclude(forum_id=excluded_forum_id) + postqs = postqs.exclude(forum__forum_id=excluded_forum_id) diff --git a/phpbb/settings.py b/phpbb/settings.py new file mode 100644 index 0000000..11d9ab1 --- /dev/null +++ b/phpbb/settings.py @@ -0,0 +1,17 @@ +from django.conf import settings + +# These defaults can be overriden in project's settings.py + +PHPBB_TABLE_PREFIX = getattr(settings, 'PHPBB_TABLE_PREFIX', 'phpbb_') +PHPBB_BLOCKED_FORUMS = getattr(settings, 'PHPBB_BLOCKED_FORUMS', []) +PHPBB_SMILIES_URL = getattr(settings, 'PHPBB_SMILIES_URL', '') +PHPBB_URL = getattr(settings, 'PHPBB_URL', '') +PHPBB_FORUM_DETAIL_TMPL = getattr(settings, + 'PHPBB_FORUM_DETAIL_TMPL', + 'phpbb/forum_detail.html') +PHPBB_TOPIC_DETAIL_TMPL = getattr(settings, + 'PHPBB_TOPIC_DETAIL_TMPL', + 'phpbb/topic_detail.html') +PHPBB_TOPIC_ARCHIVE_DETAIL_TMPL = getattr(settings, + 'PHPBB_TOPIC_ARCHIVE_DETAIL_TMPL', + 'phpbb/topic_archive_detail.html') diff --git a/phpbb/sitemap.py b/phpbb/sitemap.py index e3e0ae1..d4f61b3 100644 --- a/phpbb/sitemap.py +++ b/phpbb/sitemap.py @@ -20,8 +20,21 @@ # TODO: Implement sitemap caching. from django.contrib import sitemaps +from phpbb import settings from models import PhpbbTopic, PhpbbPost, PhpbbForum -from urls import forumqs + +# TODO: get rid of hardcoded forum IDs +# They could be fixed by implementing permission tables +# from phpbb, but this runs into bug 373. +# +# http://code.djangoproject.com/ticket/373 +# +# More information: +# http://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys +forumqs = (PhpbbForum.objects) +for excluded_forum_id in settings.PHPBB_BLOCKED_FORUMS: + forumqs = forumqs.exclude(forum_id=excluded_forum_id) + class PhpbbForumSitemap(sitemaps.Sitemap): def items(self): diff --git a/phpbb/templates/phpbb/forum_detail.html b/phpbb/templates/phpbb/forum_detail.html deleted file mode 100644 index 6751197..0000000 --- a/phpbb/templates/phpbb/forum_detail.html +++ /dev/null @@ -1,59 +0,0 @@ -{% extends "phpbb/index.html" %} -{% load i18n %} -{% load phpbb %} - - -{% block sidebar %} -{% endblock %} - -{% block bartitle %}{{ object }}{% endblock %} - -{% block content %} -{% block forum_detail %} -

{{ object }}

-{% trans "Forum main page" %} -→ -{{ object }} -{% endblock %} - -{% if is_paginated %} - -{% endif %} - -
    -{% for topic in topics %} -
  • -{{ topic }} -
    -{{ topic.topic_poster.username }}, - {% trans "answers" %}: {{ topic.topic_replies }}, {% trans "last" %} {{ topic.topic_last_post.poster.username }}, {{ topic.topic_last_post.post_time|timesince }} {% trans "ago" %} -» - -
  • -{% endfor %} -
- - -{% if is_paginated %} -{% if has_next %} - wcześniejsze → -{% endif %} - -{% endif %} - -{% endblock %} diff --git a/phpbb/templates/phpbb/index.html b/phpbb/templates/phpbb/index.html deleted file mode 100644 index af94e86..0000000 --- a/phpbb/templates/phpbb/index.html +++ /dev/null @@ -1,28 +0,0 @@ -{% extends "base.html" %} -{% comment %} -This template assumes you have a 'base.html' file that can be extended. -{% endcomment %} -{% load phpbb %} -{% load i18n %} -{% block sitetitle %} -{{ sitename }} -{% endblock %} -{% block subtitle %} -{{ site_desc }} -{% endblock %} - -{% block sidebar %} - {% if last_forum_posts %} -

{% trans "Who is online" %}

-
    - {% for post in last_forum_posts %} -
  • -

    {{ post.poster.get_username }}: - {{ post.forumposttext.get_post_text|bbcode|removetags:"br"|truncatewords:"19" }} - »

    -
  • - {% endfor %} -
- {% endif %} - -{% endblock %} diff --git a/phpbb/templates/phpbb/phpbbforum_list.html b/phpbb/templates/phpbb/phpbbforum_list.html deleted file mode 100644 index cd4e8be..0000000 --- a/phpbb/templates/phpbb/phpbbforum_list.html +++ /dev/null @@ -1,34 +0,0 @@ -{% extends "phpbb/index.html" %} -{% load i18n %} -{% load phpbb %} - -{% block content %} - - {% trans "Forum" %} - {% trans "Atopic Dermatitis" %} - {% trans "Main Page" %} - - -

Przeglądasz w tej chwili archiwum naszego forum. -Nie można tutaj pisać nowych postów. -Jeżeli chcesz pisać, zapraszamy -tutaj.

-

{% trans "Unanswered topics" %}

- -
    - {% for object in object_list %} -
  • - {{ object }} -
      - {% for forum in object.child.all %} - - {{ forum }} - -
      - {{ forum.forum_desc }}
      - {% endfor %} -
    -
  • - {% endfor %} -
-{% endblock %} diff --git a/phpbb/templates/phpbb/topic_detail.html b/phpbb/templates/phpbb/topic_detail.html deleted file mode 100644 index 678e74e..0000000 --- a/phpbb/templates/phpbb/topic_detail.html +++ /dev/null @@ -1,62 +0,0 @@ -{% extends "phpbb/index.html" %} -{% load i18n %} -{% load phpbb %} -{% block bartitle %}{{ object }}{% endblock %} - -{% block sidebar %} - - -{% endblock %} - -{% block content %} -

{{ object }}

-{% trans "Forum main page" %} -→ -{{ object.forum }} -{% if is_paginated %} - -{% endif %} - -
    -{% for post in posts %} -
  • -{% ifequal post.poster.user_avatar_type 1 %} - - -{% endifequal %} - -{{ post.poster }}: -{{ post.post_text|bbcode }} -
  • -{% endfor %} -
-{% if is_paginated %} -{% if has_next %}późniejsze →{% endif %} - -{% endif %} -{% endblock %} diff --git a/phpbb/templates/phpbb/unanswered.html b/phpbb/templates/phpbb/unanswered.html deleted file mode 100644 index fdc7f21..0000000 --- a/phpbb/templates/phpbb/unanswered.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends "phpbb/forum_detail.html" %} -{% block content %} -{% load i18n %} -{% load phpbb %} -
    -{% for topic in topics %} -
  • -{{ topic.get_title }} -({{ topic.topic_first_post.poster }}) -
    -{{ topic.topic_first_post.post_text|bbcode }} -
    -{% trans "answer" %} -
  • -{% endfor %} -
- -{% endblock %} diff --git a/phpbb/templatetags/phpbb.py b/phpbb/templatetags/phpbb.py index f3ee9b6..a487b6f 100644 --- a/phpbb/templatetags/phpbb.py +++ b/phpbb/templatetags/phpbb.py @@ -23,62 +23,18 @@ from django import template from django.conf import settings -register = template.Library() - +# Requires http://code.google.com/p/postmarkup +from postmarkup import render_bbcode -SUBS = ( - #lists - (r'\[\*:[^\]]+\](.*?)\n \[/\*:[^\]]+\]',r'
  • \1
  • '), - (r'\[\*:[^\]]+\](.*?)\[/\*:[^\]]+\]',r'
  • \1
  • '), - (r'\[list:[^\]]+\](.*?)\[/list:[^\]]+\]',r'
      \1
    '), - # URLS - (r'\[url=([^\]]*)\]([^\[]*)\[/url\]', r'\2'), - (r'\[url=([^\]]*):\w+\](.*?)\[/url:\w+\]', r'\2'), - (r'\[url\](.*?)\[/url\]', r'\1'), - # IMG - (r'\[img:\w+\]([^\[]*)\[/img:\w+\]', r''), - # Smilies path - ('{SMILIES_PATH}', settings.PHPBB_SMILIES_URL), - # [u], [i], [b] - (r'\[b:[^\]]*\]([^\[]*)\[/b:[^\]]*\]', r'\1'), - (r'\[i:[^\]]*\]([^\[]*)\[/i:[^\]]*\]', r'\1'), - (r'\[u:[^\]]*\]([^\[]*)\[/u:[^\]]*\]', r'\1'), #DEPRECATED, FIXME +from django.utils.safestring import mark_safe -# (r'\[\*:[^\]]*\]([^\[]*)\[/i:[/\*^\]]*\]', r'\1'), - #quote - (r'\[quote:\w+\]([^\[]*)\[/quote:\w+\]', r'
    \1
    '), - (r'\[quote="(.+?)":\w+\](.*)\[/quote:\w+\]', r'
    \1:
    \2
    '), - (r'\[quote="(.+?)":\w+\](.*)\[/quote:\w+\]', r'
    \1:
    \2
    '), - # size - (r'\[size=([0-9]+):\w+\](.*)\[/size:\w+\]', r'\2'), - # Automatically convert http:// in url - (r'(\s)http://([\w,.?=%/-]+)', r'\2(\s)'), - # Return to the line - (r'\n', r'
    \n'), - ## No idea, really - #(r'\?+', r'?'), - # Remove all tags, don't know why you would want that - #(r']+>', r' '), - #(r']+>', r' '), - #(r']+>', r' '), - #(r']+>', r' '), - ) - -# Compiled subs -CSUBS = [(re.compile(a,re.S),b) for a,b in SUBS] +register = template.Library() @register.filter @stringfilter def bbcode(s): - for pattern, replacement in CSUBS: - s = pattern.sub(replacement, s) - - return s - -bbcode.is_safe = True + return mark_safe(render_bbcode(s)) @register.filter def withlink(obj): - return "%s" % (obj.get_absolute_url(), str(obj)) - - + return "%s" % (obj.get_absolute_url(), str(obj)) diff --git a/phpbb/urls.py b/phpbb/urls.py.example similarity index 70% rename from phpbb/urls.py rename to phpbb/urls.py.example index 55e96cf..3efd8fc 100644 --- a/phpbb/urls.py +++ b/phpbb/urls.py.example @@ -19,25 +19,17 @@ from django.conf.urls.defaults import * from django.utils.translation import gettext_lazy as _ -import views -import models +import phpbb.views +import phpbb.models +import phpbb.querysets -forumqs = (models.PhpbbForum.objects. - # FIXME: hardcoded forum IDs - exclude(forum_id=15). - exclude(forum_id=6).filter(parent__forum_id=0)) - -forum_context = views.phpbb_config_context(None) +forum_context = phpbb.views.phpbb_config_context(None) urlpatterns = patterns('', - # TODO: add context with Django config - # (r'^$', 'django.views.generic.list_detail.object_list', - # {'queryset': forumqs, - # 'extra_context': forum_context}), - (r'^%s/(?P[0-9]+)/(?P[\w-]*)/page(?P[0-9]+)/$' % ( - _("topics"),), 'phpbb.views.topic', ), + (r'^$', 'django.views.generic.list_detail.object_list', + {'queryset': querysets.forumqs, 'extra_context': forum_context}), (r'^%s/(?P[0-9]+)/(?P[\w-]*)/$' % ( - _("topics"),), 'phpbb.views.topic', ), + _("topics"),), 'phpbb.views.topic_archive', ), (r'^(?P[0-9]+)/(?P[\w-]*)/$', 'phpbb.views.forum_index', ), (r'^(?P[0-9]+)/(?P[\w-]*)/page(?P[0-9]+)/$', diff --git a/phpbb/views.py b/phpbb/views.py index 37ab812..00e543e 100644 --- a/phpbb/views.py +++ b/phpbb/views.py @@ -19,28 +19,36 @@ from models import PhpbbForum, PhpbbTopic, PhpbbPost, PhpbbConfig from django.http import HttpResponseRedirect, Http404 +from django.http import HttpResponsePermanentRedirect from django.template.context import RequestContext from django.shortcuts import get_object_or_404, render_to_response from django.core.paginator import Paginator, InvalidPage from django.core import exceptions +from django.conf import settings def phpbb_config_context(request): try: sitename = PhpbbConfig.objects.get(pk='sitename').config_value site_desc = PhpbbConfig.objects.get(pk='site_desc').config_value - except PhpbbConfig.DoesNotExist, e: + except PhpbbConfig.DoesNotExist as e: sitename = "PhpBB site" site_desc = "A forum: %s" % e return { - 'sitename': sitename, - 'site_desc': site_desc, + 'sitename': sitename, + 'site_desc': site_desc, } + +# These are example views. The django-phpbb project does currently not provide +# templates. + def forum_index(request, forum_id, slug, page_no = None, paginate_by = 10): + if forum_id in [str(x) for x in settings.PHPBB_BLOCKED_FORUMS]: + raise Http404 if page_no: try: if int(page_no) == 1: - return HttpResponseRedirect("../") + return HttpResponsePermanentRedirect("../") except ValueError: pass path_prefix = "../" @@ -56,14 +64,11 @@ def forum_index(request, forum_id, slug, page_no = None, paginate_by = 10): raise Http404 f = PhpbbForum.objects.get(pk = forum_id) if f.get_slug() != slug: - return HttpResponseRedirect(f.get_absolute_url()) + return HttpResponsePermanentRedirect(f.get_absolute_url()) topics = f.phpbbtopic_set.all().order_by('-topic_last_post_time_int') paginator = Paginator(topics, paginate_by) - print "page_no:", page_no try: - print "requesting page" page = paginator.page(page_no) - print "got page", page except InvalidPage: raise Http404 c = RequestContext(request, { @@ -79,17 +84,17 @@ def forum_index(request, forum_id, slug, page_no = None, paginate_by = 10): 'hits' : 'what hits?', 'page_list': range(1, paginator.num_pages + 1), }, [phpbb_config_context]) - return render_to_response("phpbb/forum_detail.html", { - 'object': f, - 'topics': page.object_list, - }, context_instance=c) + return render_to_response(settings.PHPBB_FORUM_DETAIL_TMPL, { + 'object': f, + 'topics': page.object_list, + }, context_instance=c) -def topic(request, topic_id, slug, page_no = None, paginate_by = 10): +def topic(request, topic_id, slug, page_no=None, paginate_by=10): if page_no: try: if int(page_no) == 1: - return HttpResponseRedirect("../") + return HttpResponsePermanentRedirect("../") except: pass path_prefix = "../" @@ -103,11 +108,13 @@ def topic(request, topic_id, slug, page_no = None, paginate_by = 10): raise Http404 try: t = PhpbbTopic.objects.get(pk = topic_id) + if t.forum.pk in settings.PHPBB_BLOCKED_FORUMS: + raise Http404 except exceptions.ObjectDoesNotExist, e: raise Http404 posts = t.phpbbpost_set.all() if t.get_slug() != slug: - return HttpResponseRedirect(t.get_absolute_url()) + return HttpResponsePermanentRedirect(t.get_absolute_url()) paginator = Paginator(posts, paginate_by) try: page = paginator.page(page_no) @@ -126,11 +133,31 @@ def topic(request, topic_id, slug, page_no = None, paginate_by = 10): 'hits' : "hits? what hits?", 'page_list': range(1, paginator.num_pages + 1), }, [phpbb_config_context]) - return render_to_response("phpbb/topic_detail.html", { + return render_to_response(settings.PHPBB_TOPIC_DETAIL_TMPL, { 'object': t, 'posts': page.object_list, - }, context_instance=c) + }, context_instance=c) + +def topic_archive(request, topic_id, slug): + try: + t = PhpbbTopic.objects.get(pk=topic_id) + if t.forum.pk in settings.PHPBB_BLOCKED_FORUMS: + raise Http404 + except exceptions.ObjectDoesNotExist: + raise Http404 + posts = t.phpbbpost_set.all() + if t.get_slug() != slug: + return HttpResponsePermanentRedirect(t.get_absolute_url()) + c = RequestContext(request, {}, [phpbb_config_context]) + return render_to_response(settings.PHPBB_TOPIC_ARCHIVE_DETAIL_TMPL, { + 'object': t, + 'posts': posts, + }, context_instance=c) +def topic_paginated_redirect(request, topic_id, slug, page_no=None, + paginate_by=10): + """Compatibility view to redirect the old paginated URLs.""" + return HttpResponsePermanentRedirect("../") def unanswered(request): topics = PhpbbTopic.objects.filter(topic_replies = 0) @@ -142,11 +169,16 @@ def unanswered(request): def handle_viewtopic(request): + """The regular phpBB forum URLs, can be used for compatibility.""" if request.GET.has_key('t'): topic_id = request.GET['t'] - t = PhpbbTopic.objects.get(pk = topic_id) - return HttpResponseRedirect(t.get_absolute_url()) + try: + topic_id_int = int(topic_id) + t = get_object_or_404(PhpbbTopic, pk=topic_id_int) + return HttpResponsePermanentRedirect(t.get_absolute_url()) + except ValueError, e: + raise Http404 if request.GET.has_key('p'): - topic_id = request.GET['p'] - t = PhpbbPost.objects.get(pk = topic_id) - return HttpResponseRedirect(t.get_absolute_url()) + post_id = request.GET['p'] + p = get_object_or_404(PhpbbPost, pk=post_id) + return HttpResponsePermanentRedirect(p.get_absolute_url()) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..5baa68e --- /dev/null +++ b/setup.py @@ -0,0 +1,21 @@ +# coding=utf-8 + +from distutils.core import setup + +setup ( + name='django-phpbb', + #version='0.0.1', + author='Maciej Bliziński', + author_email='maciej.blizinski@gmail.com', + packages=['phpbb'], + url='http://code.google.com/p/django-phpbb/', + license='COPYING', + description='Access unmodified PhpBB3 database with Django', + long_description=open('README').read(), + install_requires=[ + "Django >= 1.4", + ], + classifiers=[ + 'Development Status :: 2 - Pre-Alpha', + ] +)