summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xfbconnect/fb.py31
-rwxr-xr-xfbconnect/models.py2
-rwxr-xr-xfbconnect/pjson.py315
-rwxr-xr-xfbconnect/urls.py9
-rwxr-xr-xfbconnect/views.py90
-rwxr-xr-x[-rw-r--r--]settings.py0
-rwxr-xr-x[-rw-r--r--]settings_local.py.dist184
-rw-r--r--templates/authopenid/complete.html2
-rwxr-xr-xtemplates/authopenid/signin.html10
-rwxr-xr-xtemplates/base.html190
-rw-r--r--urls.py4
11 files changed, 611 insertions, 226 deletions
diff --git a/fbconnect/fb.py b/fbconnect/fb.py
index 7aeda131..a1c3e424 100755
--- a/fbconnect/fb.py
+++ b/fbconnect/fb.py
@@ -2,7 +2,13 @@ from django.conf import settings
from time import time
from datetime import datetime
from urllib import urlopen, urlencode
-from json import load as load_json
+
+try:
+ from json import load as load_json
+except:
+ from pjson import fread as load_json
+
+from models import FBAssociation
import md5
import logging
@@ -40,11 +46,12 @@ def get_user_data(cookies):
}
request_data['sig'] = generate_sig(request_data)
- fb_response = load_json(urlopen(REST_SERVER, urlencode(request_data)))
- return fb_response[0]
+ fb_response = urlopen(REST_SERVER, urlencode(request_data))
+ print(fb_response)
+ return load_json(fb_response)[0]
-def delete_cookies():
+def delete_cookies(response):
API_KEY = settings.FB_API_KEY
response.delete_cookie(API_KEY + '_user')
@@ -60,11 +67,23 @@ def check_session_expiry(cookies):
STATES = {
'FIRSTTIMER': 1,
'SESSIONEXPIRED': 2,
+ 'RETURNINGUSER': 3,
+ 'INVALIDSTATE': 4,
}
def get_user_state(request):
- if settings.FB_API_KEY in request.COOKIES:
+ API_KEY = settings.FB_API_KEY
+
+ if API_KEY in request.COOKIES:
if check_cookies_signature(request.COOKIES):
if check_session_expiry(request.COOKIES):
- return STATES['FIRSTTIMER']
+ try:
+ uassoc = FBAssociation.objects.get(fbuid=request.COOKIES[API_KEY + '_user'])
+ return (STATES['RETURNINGUSER'], uassoc.user)
+ except:
+ return (STATES['FIRSTTIMER'], get_user_data(request.COOKIES))
+ else:
+ return (STATES['SESSIONEXPIRED'], None)
+
+ return (STATES['INVALIDSTATE'], None)
diff --git a/fbconnect/models.py b/fbconnect/models.py
index 33a723e8..2172217d 100755
--- a/fbconnect/models.py
+++ b/fbconnect/models.py
@@ -3,4 +3,4 @@ from django.contrib.auth.models import User
class FBAssociation(models.Model):
user = models.ForeignKey(User)
- fbuid = models.TextField(max_length=12)
+ fbuid = models.CharField(max_length=12, unique=True)
diff --git a/fbconnect/pjson.py b/fbconnect/pjson.py
new file mode 100755
index 00000000..73ca502a
--- /dev/null
+++ b/fbconnect/pjson.py
@@ -0,0 +1,315 @@
+import string
+import types
+
+## json.py implements a JSON (http://json.org) reader and writer.
+## Copyright (C) 2005 Patrick D. Logan
+## Contact mailto:patrickdlogan@stardecisions.com
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library 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
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+class _StringGenerator(object):
+ def __init__(self, string):
+ self.string = string
+ self.index = -1
+ def peek(self):
+ i = self.index + 1
+ if i < len(self.string):
+ return self.string[i]
+ else:
+ return None
+ def next(self):
+ self.index += 1
+ if self.index < len(self.string):
+ return self.string[self.index]
+ else:
+ raise StopIteration
+ def all(self):
+ return self.string
+
+class WriteException(Exception):
+ pass
+
+class ReadException(Exception):
+ pass
+
+class JsonReader(object):
+ hex_digits = {'A': 10,'B': 11,'C': 12,'D': 13,'E': 14,'F':15}
+ escapes = {'t':'\t','n':'\n','f':'\f','r':'\r','b':'\b'}
+
+ def read(self, s):
+ self._generator = _StringGenerator(s)
+ result = self._read()
+ return result
+
+ def _read(self):
+ self._eatWhitespace()
+ peek = self._peek()
+ if peek is None:
+ raise ReadException, "Nothing to read: '%s'" % self._generator.all()
+ if peek == '{':
+ return self._readObject()
+ elif peek == '[':
+ return self._readArray()
+ elif peek == '"':
+ return self._readString()
+ elif peek == '-' or peek.isdigit():
+ return self._readNumber()
+ elif peek == 't':
+ return self._readTrue()
+ elif peek == 'f':
+ return self._readFalse()
+ elif peek == 'n':
+ return self._readNull()
+ elif peek == '/':
+ self._readComment()
+ return self._read()
+ else:
+ raise ReadException, "Input is not valid JSON: '%s'" % self._generator.all()
+
+ def _readTrue(self):
+ self._assertNext('t', "true")
+ self._assertNext('r', "true")
+ self._assertNext('u', "true")
+ self._assertNext('e', "true")
+ return True
+
+ def _readFalse(self):
+ self._assertNext('f', "false")
+ self._assertNext('a', "false")
+ self._assertNext('l', "false")
+ self._assertNext('s', "false")
+ self._assertNext('e', "false")
+ return False
+
+ def _readNull(self):
+ self._assertNext('n', "null")
+ self._assertNext('u', "null")
+ self._assertNext('l', "null")
+ self._assertNext('l', "null")
+ return None
+
+ def _assertNext(self, ch, target):
+ if self._next() != ch:
+ raise ReadException, "Trying to read %s: '%s'" % (target, self._generator.all())
+
+ def _readNumber(self):
+ isfloat = False
+ result = self._next()
+ peek = self._peek()
+ while peek is not None and (peek.isdigit() or peek == "."):
+ isfloat = isfloat or peek == "."
+ result = result + self._next()
+ peek = self._peek()
+ try:
+ if isfloat:
+ return float(result)
+ else:
+ return int(result)
+ except ValueError:
+ raise ReadException, "Not a valid JSON number: '%s'" % result
+
+ def _readString(self):
+ result = ""
+ assert self._next() == '"'
+ try:
+ while self._peek() != '"':
+ ch = self._next()
+ if ch == "\\":
+ ch = self._next()
+ if ch in 'brnft':
+ ch = self.escapes[ch]
+ elif ch == "u":
+ ch4096 = self._next()
+ ch256 = self._next()
+ ch16 = self._next()
+ ch1 = self._next()
+ n = 4096 * self._hexDigitToInt(ch4096)
+ n += 256 * self._hexDigitToInt(ch256)
+ n += 16 * self._hexDigitToInt(ch16)
+ n += self._hexDigitToInt(ch1)
+ ch = unichr(n)
+ elif ch not in '"/\\':
+ raise ReadException, "Not a valid escaped JSON character: '%s' in %s" % (ch, self._generator.all())
+ result = result + ch
+ except StopIteration:
+ raise ReadException, "Not a valid JSON string: '%s'" % self._generator.all()
+ assert self._next() == '"'
+ return result
+
+ def _hexDigitToInt(self, ch):
+ try:
+ result = self.hex_digits[ch.upper()]
+ except KeyError:
+ try:
+ result = int(ch)
+ except ValueError:
+ raise ReadException, "The character %s is not a hex digit." % ch
+ return result
+
+ def _readComment(self):
+ assert self._next() == "/"
+ second = self._next()
+ if second == "/":
+ self._readDoubleSolidusComment()
+ elif second == '*':
+ self._readCStyleComment()
+ else:
+ raise ReadException, "Not a valid JSON comment: %s" % self._generator.all()
+
+ def _readCStyleComment(self):
+ try:
+ done = False
+ while not done:
+ ch = self._next()
+ done = (ch == "*" and self._peek() == "/")
+ if not done and ch == "/" and self._peek() == "*":
+ raise ReadException, "Not a valid JSON comment: %s, '/*' cannot be embedded in the comment." % self._generator.all()
+ self._next()
+ except StopIteration:
+ raise ReadException, "Not a valid JSON comment: %s, expected */" % self._generator.all()
+
+ def _readDoubleSolidusComment(self):
+ try:
+ ch = self._next()
+ while ch != "\r" and ch != "\n":
+ ch = self._next()
+ except StopIteration:
+ pass
+
+ def _readArray(self):
+ result = []
+ assert self._next() == '['
+ done = self._peek() == ']'
+ while not done:
+ item = self._read()
+ result.append(item)
+ self._eatWhitespace()
+ done = self._peek() == ']'
+ if not done:
+ ch = self._next()
+ if ch != ",":
+ raise ReadException, "Not a valid JSON array: '%s' due to: '%s'" % (self._generator.all(), ch)
+ assert ']' == self._next()
+ return result
+
+ def _readObject(self):
+ result = {}
+ assert self._next() == '{'
+ done = self._peek() == '}'
+ while not done:
+ key = self._read()
+ if type(key) is not types.StringType:
+ raise ReadException, "Not a valid JSON object key (should be a string): %s" % key
+ self._eatWhitespace()
+ ch = self._next()
+ if ch != ":":
+ raise ReadException, "Not a valid JSON object: '%s' due to: '%s'" % (self._generator.all(), ch)
+ self._eatWhitespace()
+ val = self._read()
+ result[key] = val
+ self._eatWhitespace()
+ done = self._peek() == '}'
+ if not done:
+ ch = self._next()
+ if ch != ",":
+ raise ReadException, "Not a valid JSON array: '%s' due to: '%s'" % (self._generator.all(), ch)
+ assert self._next() == "}"
+ return result
+
+ def _eatWhitespace(self):
+ p = self._peek()
+ while p is not None and p in string.whitespace or p == '/':
+ if p == '/':
+ self._readComment()
+ else:
+ self._next()
+ p = self._peek()
+
+ def _peek(self):
+ return self._generator.peek()
+
+ def _next(self):
+ return self._generator.next()
+
+class JsonWriter(object):
+
+ def _append(self, s):
+ self._results.append(s)
+
+ def write(self, obj, escaped_forward_slash=False):
+ self._escaped_forward_slash = escaped_forward_slash
+ self._results = []
+ self._write(obj)
+ return "".join(self._results)
+
+ def _write(self, obj):
+ ty = type(obj)
+ if ty is types.DictType:
+ n = len(obj)
+ self._append("{")
+ for k, v in obj.items():
+ self._write(k)
+ self._append(":")
+ self._write(v)
+ n = n - 1
+ if n > 0:
+ self._append(",")
+ self._append("}")
+ elif ty is types.ListType or ty is types.TupleType:
+ n = len(obj)
+ self._append("[")
+ for item in obj:
+ self._write(item)
+ n = n - 1
+ if n > 0:
+ self._append(",")
+ self._append("]")
+ elif ty is types.StringType or ty is types.UnicodeType:
+ self._append('"')
+ obj = obj.replace('\\', r'\\')
+ if self._escaped_forward_slash:
+ obj = obj.replace('/', r'\/')
+ obj = obj.replace('"', r'\"')
+ obj = obj.replace('\b', r'\b')
+ obj = obj.replace('\f', r'\f')
+ obj = obj.replace('\n', r'\n')
+ obj = obj.replace('\r', r'\r')
+ obj = obj.replace('\t', r'\t')
+ self._append(obj)
+ self._append('"')
+ elif ty is types.IntType or ty is types.LongType:
+ self._append(str(obj))
+ elif ty is types.FloatType:
+ self._append("%f" % obj)
+ elif obj is True:
+ self._append("true")
+ elif obj is False:
+ self._append("false")
+ elif obj is None:
+ self._append("null")
+ else:
+ raise WriteException, "Cannot write in JSON: %s" % repr(obj)
+
+def write(obj, escaped_forward_slash=False):
+ return JsonWriter().write(obj, escaped_forward_slash)
+
+def read(s):
+ return JsonReader().read(s)
+
+def fread(f):
+ return read(f.read())
+
+
diff --git a/fbconnect/urls.py b/fbconnect/urls.py
index e4048151..9b4ff0c9 100755
--- a/fbconnect/urls.py
+++ b/fbconnect/urls.py
@@ -5,7 +5,12 @@ from views import signin, register
urlpatterns = patterns('',
url(r'^xd_receiver$', direct_to_template, {'template': 'fbconnect/xd_receiver.html'}, name='xd_receiver'),
- url(r'^%s' % _('signin/'), signin, name="fb_signin"),
- url(r'^%s' % _('register/'), register, name="fb_user_register"),
+ url(r'^%s$' % _('signin/'), signin, name="fb_signin"),
+ url(r'^%s%s$' % (_('signin/'), _('newquestion/')), signin, {'newquestion': True}, name="fb_signin_new_question"),
+ url(r'^%s%s$' % (_('signin/'), _('newanswer/')), signin, {'newanswer': True}, name="fb_signin_new_answer"),
+
+ url(r'^%s$' % _('register/'), register, name="fb_user_register"),
+ url(r'^%s%s$' % (_('register/'), _('newquestion/')), register, {'newquestion': True}, name="fb_user_register_new_question"),
+ url(r'^%s%s$' % (_('register/'), _('newanswer/')), register, {'newanswer': True}, name="fb_user_register_new_answer"),
)
diff --git a/fbconnect/views.py b/fbconnect/views.py
index 2acb1dc0..5c308e45 100755
--- a/fbconnect/views.py
+++ b/fbconnect/views.py
@@ -1,10 +1,10 @@
-from django.shortcuts import render_to_response as render
+from django.shortcuts import render_to_response as render
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.utils.safestring import mark_safe
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
-from django.contrib.auth import login
+from django.contrib.auth import login, logout
from models import FBAssociation
from forum.forms import EditUserEmailFeedsForm
from django.conf import settings
@@ -14,50 +14,84 @@ import forms
import logging
-def signin(request):
- user_state = fb.get_user_state(request)
+def signin(request, newquestion = False, newanswer = False):
+ state, context = fb.get_user_state(request)
- if user_state == fb.STATES['FIRSTTIMER']:
- return HttpResponseRedirect(reverse('fb_user_register'))
+ if state == fb.STATES['FIRSTTIMER']:
+ if newquestion:
+ register_url = 'fb_user_register_new_question'
+ elif newanswer:
+ register_url = 'fb_user_register_new_answer'
+ else:
+ register_url = 'fb_user_register'
+ return HttpResponseRedirect(reverse(register_url))
+ elif state == fb.STATES['RETURNINGUSER']:
+ return login_and_forward(request, context, newquestion, newanswer)
+ elif state == fb.STATES['SESSIONEXPIRED']:
+ response = logout(request, next_page=reverse('index'))
+ fb.delete_cookies(response)
+ return response
+
+ return HttpResponseRedirect(reverse('index'))
- return HttpResponseRedirect('/')
+def register(request, newquestion = False, newanswer = False):
+ state, context = fb.get_user_state(request)
-def register(request):
- if fb.get_user_state(request) == fb.STATES['FIRSTTIMER']:
- user_data = fb.get_user_data(request.COOKIES)
+ if state == fb.STATES['FIRSTTIMER']:
if 'bnewaccount' in request.POST.keys():
form1 = forms.FBConnectRegisterForm(request.POST)
email_feeds_form = EditUserEmailFeedsForm(request.POST)
if (form1.is_valid() and email_feeds_form.is_valid()):
- tmp_pwd = User.objects.make_random_password()
- user_ = User.objects.create_user(form1.cleaned_data['username'],
- form1.cleaned_data['email'], tmp_pwd)
-
+ tmp_pwd = User.objects.make_random_password()
+ user_ = User.objects.create_user(form1.cleaned_data['username'],
+ form1.cleaned_data['email'], tmp_pwd)
+
user_.set_unusable_password()
- uassoc = FBAssociation(user=user_, fbuid=user_data['uid'])
+ uassoc = FBAssociation(user=user_, fbuid=context['uid'])
uassoc.save()
- user_.backend = "django.contrib.auth.backends.ModelBackend"
- login(request, user_)
email_feeds_form.save(user_)
- return HttpResponseRedirect('/')
+ return login_and_forward(request, user_, newquestion, newanswer)
else:
- form1 = forms.FBConnectRegisterForm(initial={
- 'next': '/',
- 'username': user_data['name'],
- 'email': '',
+ form1 = forms.FBConnectRegisterForm(initial={
+ 'next': '/',
+ 'username': context['name'],
+ 'email': '',
})
email_feeds_form = EditUserEmailFeedsForm()
- return render('authopenid/complete.html', {
- 'form1': form1,
- 'email_feeds_form': email_feeds_form,
- 'provider':mark_safe('facebook'),
- 'login_type':'facebook',
- 'gravatar_faq_url':reverse('faq') + '#gravatar',
+ return render('authopenid/complete.html', {
+ 'form1': form1,
+ 'email_feeds_form': email_feeds_form,
+ 'provider':mark_safe('facebook'),
+ 'login_type':'facebook',
+ 'gravatar_faq_url':reverse('faq') + '#gravatar',
}, context_instance=RequestContext(request))
+ else:
+ return HttpResponseRedirect(reverse('index'))
+
+def login_and_forward(request, user, newquestion = False, newanswer = False):
+ old_session = request.session.session_key
+ user.backend = "django.contrib.auth.backends.ModelBackend"
+ login(request, user)
+
+ from forum.models import user_logged_in
+ user_logged_in.send(user=user,session_key=old_session,sender=None)
+
+ if (newquestion):
+ from forum.models import Question
+ question = Question.objects.filter(author=user).order_by('-added_at')[0]
+ return HttpResponseRedirect(question.get_absolute_url())
+
+ if (newanswer):
+ from forum.models import Answer
+ answer = Answer.objects.filter(author=user).order_by('-added_at')[0]
+ return HttpResponseRedirect(answer.get_absolute_url())
+
+ return HttpResponseRedirect('/')
+
diff --git a/settings.py b/settings.py
index e2e97cb1..e2e97cb1 100644..100755
--- a/settings.py
+++ b/settings.py
diff --git a/settings_local.py.dist b/settings_local.py.dist
index 55028ba2..443b73d1 100644..100755
--- a/settings_local.py.dist
+++ b/settings_local.py.dist
@@ -1,92 +1,92 @@
-# encoding:utf-8
-import os.path
-from django.utils.translation import ugettext as _
-
-SITE_SRC_ROOT = os.path.dirname(__file__)
-LOG_FILENAME = 'django.osqa.log'
-
-#for logging
-import logging
-logging.basicConfig(filename=os.path.join(SITE_SRC_ROOT, 'log', LOG_FILENAME), level=logging.DEBUG,)
-
-#ADMINS and MANAGERS
-ADMINS = (('Forum Admin', 'forum@example.com'),)
-MANAGERS = ADMINS
-
-#DEBUG SETTINGS
-DEBUG = False
-TEMPLATE_DEBUG = DEBUG
-INTERNAL_IPS = ('127.0.0.1',)
-
-DATABASE_NAME = 'osqa' # Or path to database file if using sqlite3.
-DATABASE_USER = '' # Not used with sqlite3.
-DATABASE_PASSWORD = '' # Not used with sqlite3.
-DATABASE_ENGINE = 'mysql' #mysql, etc
-DATABASE_HOST = ''
-DATABASE_PORT = ''
-
-#Moved from settings.py for better organization. (please check it up to clean up settings.py)
-
-#email server settings
-SERVER_EMAIL = ''
-DEFAULT_FROM_EMAIL = ''
-EMAIL_HOST_USER = ''
-EMAIL_HOST_PASSWORD = ''
-EMAIL_SUBJECT_PREFIX = '[OSQA] '
-EMAIL_HOST='osqa.net'
-EMAIL_PORT='25'
-EMAIL_USE_TLS=False
-
-#LOCALIZATIONS
-TIME_ZONE = 'America/New_York'
-
-###########################
-#
-# this will allow running your forum with url like http://site.com/forum
-#
-# FORUM_SCRIPT_ALIAS = 'forum/'
-#
-FORUM_SCRIPT_ALIAS = '' #no leading slash, default = '' empty string
-
-
-#OTHER SETTINGS
-APP_TITLE = u'OSQA: Open Source Q&A Forum'
-APP_SHORT_NAME = u'OSQA'
-APP_KEYWORDS = u'OSQA,CNPROG,forum,community'
-APP_DESCRIPTION = u'Ask and answer questions.'
-APP_INTRO = u'<p>Ask and answer questions, make the world better!</p>'
-APP_COPYRIGHT = 'Copyright OSQA, 2009. Some rights reserved under creative commons license.'
-LOGIN_URL = '/%s%s%s' % (FORUM_SCRIPT_ALIAS,'account/','signin/')
-GREETING_URL = LOGIN_URL #may be url of "faq" page or "about", etc
-
-USE_I18N = True
-LANGUAGE_CODE = 'en'
-EMAIL_VALIDATION = 'off' #string - on|off
-MIN_USERNAME_LENGTH = 1
-EMAIL_UNIQUE = False
-APP_URL = 'http://osqa.net' #used by email notif system and RSS
-GOOGLE_SITEMAP_CODE = ''
-GOOGLE_ANALYTICS_KEY = ''
-BOOKS_ON = False
-WIKI_ON = True
-USE_EXTERNAL_LEGACY_LOGIN = False
-EXTERNAL_LEGACY_LOGIN_HOST = 'login.osqa.net'
-EXTERNAL_LEGACY_LOGIN_PORT = 80
-EXTERNAL_LEGACY_LOGIN_PROVIDER_NAME = '<span class="orange">OSQA</span>'
-FEEDBACK_SITE_URL = None #None or url
-
-DJANGO_VERSION = 1.1
-RESOURCE_REVISION=4
-
-USE_SPHINX_SEARCH = False #if True all SPHINX_* settings are required
-#also sphinx search engine and djangosphinxs app must be installed
-#sample sphinx configuration file is /sphinx/sphinx.conf
-SPHINX_API_VERSION = 0x113 #refer to djangosphinx documentation
-SPHINX_SEARCH_INDICES=('osqa',) #a tuple of index names remember about a comma after the
-#last item, especially if you have just one :)
-SPHINX_SERVER='localhost'
-SPHINX_PORT=3312
-
-#Facebook settings
-FB_API_KEY='' #your api key from facebook
-FB_SECRET='' #your application secret
+# encoding:utf-8
+import os.path
+from django.utils.translation import ugettext as _
+
+SITE_SRC_ROOT = os.path.dirname(__file__)
+LOG_FILENAME = 'django.osqa.log'
+
+#for logging
+import logging
+logging.basicConfig(filename=os.path.join(SITE_SRC_ROOT, 'log', LOG_FILENAME), level=logging.DEBUG,)
+
+#ADMINS and MANAGERS
+ADMINS = (('Forum Admin', 'forum@example.com'),)
+MANAGERS = ADMINS
+
+#DEBUG SETTINGS
+DEBUG = False
+TEMPLATE_DEBUG = DEBUG
+INTERNAL_IPS = ('127.0.0.1',)
+
+DATABASE_NAME = 'osqa' # Or path to database file if using sqlite3.
+DATABASE_USER = '' # Not used with sqlite3.
+DATABASE_PASSWORD = '' # Not used with sqlite3.
+DATABASE_ENGINE = 'mysql' #mysql, etc
+DATABASE_HOST = ''
+DATABASE_PORT = ''
+
+#Moved from settings.py for better organization. (please check it up to clean up settings.py)
+
+#email server settings
+SERVER_EMAIL = ''
+DEFAULT_FROM_EMAIL = ''
+EMAIL_HOST_USER = ''
+EMAIL_HOST_PASSWORD = ''
+EMAIL_SUBJECT_PREFIX = '[OSQA] '
+EMAIL_HOST='osqa.net'
+EMAIL_PORT='25'
+EMAIL_USE_TLS=False
+
+#LOCALIZATIONS
+TIME_ZONE = 'America/New_York'
+
+###########################
+#
+# this will allow running your forum with url like http://site.com/forum
+#
+# FORUM_SCRIPT_ALIAS = 'forum/'
+#
+FORUM_SCRIPT_ALIAS = '' #no leading slash, default = '' empty string
+
+
+#OTHER SETTINGS
+APP_TITLE = u'OSQA: Open Source Q&A Forum'
+APP_SHORT_NAME = u'OSQA'
+APP_KEYWORDS = u'OSQA,CNPROG,forum,community'
+APP_DESCRIPTION = u'Ask and answer questions.'
+APP_INTRO = u'<p>Ask and answer questions, make the world better!</p>'
+APP_COPYRIGHT = 'Copyright OSQA, 2009. Some rights reserved under creative commons license.'
+LOGIN_URL = '/%s%s%s' % (FORUM_SCRIPT_ALIAS,'account/','signin/')
+GREETING_URL = LOGIN_URL #may be url of "faq" page or "about", etc
+
+USE_I18N = True
+LANGUAGE_CODE = 'en'
+EMAIL_VALIDATION = 'off' #string - on|off
+MIN_USERNAME_LENGTH = 1
+EMAIL_UNIQUE = False
+APP_URL = 'http://osqa.net' #used by email notif system and RSS
+GOOGLE_SITEMAP_CODE = ''
+GOOGLE_ANALYTICS_KEY = ''
+BOOKS_ON = False
+WIKI_ON = True
+USE_EXTERNAL_LEGACY_LOGIN = False
+EXTERNAL_LEGACY_LOGIN_HOST = 'login.osqa.net'
+EXTERNAL_LEGACY_LOGIN_PORT = 80
+EXTERNAL_LEGACY_LOGIN_PROVIDER_NAME = '<span class="orange">OSQA</span>'
+FEEDBACK_SITE_URL = None #None or url
+
+DJANGO_VERSION = 1.1
+RESOURCE_REVISION=4
+
+USE_SPHINX_SEARCH = False #if True all SPHINX_* settings are required
+#also sphinx search engine and djangosphinxs app must be installed
+#sample sphinx configuration file is /sphinx/sphinx.conf
+SPHINX_API_VERSION = 0x113 #refer to djangosphinx documentation
+SPHINX_SEARCH_INDICES=('osqa',) #a tuple of index names remember about a comma after the
+#last item, especially if you have just one :)
+SPHINX_SERVER='localhost'
+SPHINX_PORT=3312
+
+#Facebook settings
+FB_API_KEY='' #your api key from facebook
+FB_SECRET='' #your application secret
diff --git a/templates/authopenid/complete.html b/templates/authopenid/complete.html
index efed74c7..1606cfc5 100644
--- a/templates/authopenid/complete.html
+++ b/templates/authopenid/complete.html
@@ -72,7 +72,7 @@ parameters:
<form name="fregister" action="{% url user_register %}" method="POST">
{% else %}
{% ifequal login_type 'facebook' %}
- <form name="fregister" action="{% url fb_user_register %}" method="POST">
+ <form name="fregister" action="" method="POST">
{% else %}
<form name="fregister" action="{% url user_signin %}" method="POST">
{% endifequal %}
diff --git a/templates/authopenid/signin.html b/templates/authopenid/signin.html
index da1e5491..3d20d408 100755
--- a/templates/authopenid/signin.html
+++ b/templates/authopenid/signin.html
@@ -64,7 +64,15 @@
</div>
</li>
<li title="Facebook Connect">
- <fb:login-button onlogin="window.location = '{% url fb_signin %}'"></fb:login-button>
+ {% if question %}
+ <fb:login-button onlogin="window.location = '{% url fb_signin_new_question %}'"></fb:login-button>
+ {% else %}
+ {% if answer %}
+ <fb:login-button onlogin="window.location = '{% url fb_signin_new_answer %}'"></fb:login-button>
+ {% else %}
+ <fb:login-button onlogin="window.location = '{% url fb_signin %}'"></fb:login-button>
+ {% endif %}
+ {% endif %}
</li>
</ul>
<ul class="providers">
diff --git a/templates/base.html b/templates/base.html
index befdc994..b28f919e 100755
--- a/templates/base.html
+++ b/templates/base.html
@@ -1,95 +1,95 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<!-- template base.html -->
-{% load extra_filters %}
-{% load extra_tags %}
-{% load i18n %}
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
- <head>
- <title>{% block title %}{% endblock %} - {{ settings.APP_TITLE }}</title>
- {% spaceless %}
- {% block meta %}{% endblock %}
- {% endspaceless %}
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- {% if settings.GOOGLE_SITEMAP_CODE %}
- <meta name="verify-v1" content="{{settings.GOOGLE_SITEMAP_CODE}}" />
- {% endif %}
- <link rel="shortcut icon" href="{% href "/content/images/favicon.ico" %}" />
- <link href="{% href "/content/style/style.css" %}" rel="stylesheet" type="text/css" />
- <script src="http://www.google.com/jsapi" type="text/javascript"></script>
- <script type="text/javascript">google.load("jquery", "1.2.6");</script>
- <script type="text/javascript">
- var i18nLang = '{{settings.LANGUAGE_CODE}}';
- var scriptUrl = '/{{settings.FORUM_SCRIPT_ALIAS}}'
- </script>
- <script type='text/javascript' src='{% href "/content/js/com.cnprog.i18n.js" %}'></script>
- <script type='text/javascript' src='{% href "/content/js/jquery.i18n.js" %}'></script>
- <script type='text/javascript' src='{% href "/content/js/com.cnprog.utils.js" %}'></script>
- <!--<script type="text/javascript">
- var uservoiceJsHost = ("https:" == document.location.protocol) ? "https://uservoice.com" : "http://cdn.uservoice.com";
- document.write(unescape("%3Cscript src='" + uservoiceJsHost + "/javascripts/widgets/tab.js' type='text/javascript'%3E%3C/script%3E"))
- </script>
- <script type="text/javascript">
- UserVoice.Tab.show({
- key: 'cnprog',
- host: 'cnprog.uservoice.com',
- forum: 'general',
- alignment: 'left', /* 'left', 'right' */
- background_color:'#777',
- text_color: 'white', /* 'white', 'black' */
- hover_color: '#06C',
- lang: 'en' /* 'en', 'de', 'nl', 'es', 'fr' */
- })
- </script>-->
- <!-- todo move this to settings -->
- {% if user_messages %}
- <style type="text/css">
- body { margin-top:2.4em; }
- </style>
- <script type="text/javascript">
- $().ready(function() {
- $('#validate_email_alert').click(function(){notify.close(true)})
- notify.show();
- });
- </script>
- {% endif %}
-
- {% block forejs %}
- {% endblock %}
- </head>
- <body>
- <div class="notify" style="display:none">
- {% autoescape off %}
- {% if user_messages %}
- {% for message in user_messages %}
- <p class="darkred">{{ message }}<p>
- {% endfor %}
- {% endif %}
- {% endautoescape %}
- <a id="close-notify" onclick="notify.close(true)">&times;</a>
- </div>
- {% include "header.html" %}
- <div id="wrapper">
- <div id="room">
- <div id="CALeft">
- {% block content%}
- {% endblock%}
-
- </div>
- <div id="CARight">
- {% block sidebar%}
- {% endblock%}
-
- </div>
- <div id="tail" style="clear:both;">
- {% block tail %}
- {% endblock %}
- </div>
- </div>
- <div class="spacer3"></div>
- </div>
- {% include "footer.html" %}
- {% block endjs %}
- {% endblock %}
- </body>
-</html>
-<!-- end template base.html -->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!-- template base.html -->
+{% load extra_filters %}
+{% load extra_tags %}
+{% load i18n %}
+<html xmlns="http://www.w3.org/1999/xhtml"{% if fb_api_key %} xmlns:fb="http://www.facebook.com/2008/fbml"{% endif %}>
+ <head>
+ <title>{% block title %}{% endblock %} - {{ settings.APP_TITLE }}</title>
+ {% spaceless %}
+ {% block meta %}{% endblock %}
+ {% endspaceless %}
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ {% if settings.GOOGLE_SITEMAP_CODE %}
+ <meta name="verify-v1" content="{{settings.GOOGLE_SITEMAP_CODE}}" />
+ {% endif %}
+ <link rel="shortcut icon" href="{% href "/content/images/favicon.ico" %}" />
+ <link href="{% href "/content/style/style.css" %}" rel="stylesheet" type="text/css" />
+ <script src="http://www.google.com/jsapi" type="text/javascript"></script>
+ <script type="text/javascript">google.load("jquery", "1.2.6");</script>
+ <script type="text/javascript">
+ var i18nLang = '{{settings.LANGUAGE_CODE}}';
+ var scriptUrl = '/{{settings.FORUM_SCRIPT_ALIAS}}'
+ </script>
+ <script type='text/javascript' src='{% href "/content/js/com.cnprog.i18n.js" %}'></script>
+ <script type='text/javascript' src='{% href "/content/js/jquery.i18n.js" %}'></script>
+ <script type='text/javascript' src='{% href "/content/js/com.cnprog.utils.js" %}'></script>
+ <!--<script type="text/javascript">
+ var uservoiceJsHost = ("https:" == document.location.protocol) ? "https://uservoice.com" : "http://cdn.uservoice.com";
+ document.write(unescape("%3Cscript src='" + uservoiceJsHost + "/javascripts/widgets/tab.js' type='text/javascript'%3E%3C/script%3E"))
+ </script>
+ <script type="text/javascript">
+ UserVoice.Tab.show({
+ key: 'cnprog',
+ host: 'cnprog.uservoice.com',
+ forum: 'general',
+ alignment: 'left', /* 'left', 'right' */
+ background_color:'#777',
+ text_color: 'white', /* 'white', 'black' */
+ hover_color: '#06C',
+ lang: 'en' /* 'en', 'de', 'nl', 'es', 'fr' */
+ })
+ </script>-->
+ <!-- todo move this to settings -->
+ {% if user_messages %}
+ <style type="text/css">
+ body { margin-top:2.4em; }
+ </style>
+ <script type="text/javascript">
+ $().ready(function() {
+ $('#validate_email_alert').click(function(){notify.close(true)})
+ notify.show();
+ });
+ </script>
+ {% endif %}
+
+ {% block forejs %}
+ {% endblock %}
+ </head>
+ <body>
+ <div class="notify" style="display:none">
+ {% autoescape off %}
+ {% if user_messages %}
+ {% for message in user_messages %}
+ <p class="darkred">{{ message }}<p>
+ {% endfor %}
+ {% endif %}
+ {% endautoescape %}
+ <a id="close-notify" onclick="notify.close(true)">&times;</a>
+ </div>
+ {% include "header.html" %}
+ <div id="wrapper">
+ <div id="room">
+ <div id="CALeft">
+ {% block content%}
+ {% endblock%}
+
+ </div>
+ <div id="CARight">
+ {% block sidebar%}
+ {% endblock%}
+
+ </div>
+ <div id="tail" style="clear:both;">
+ {% block tail %}
+ {% endblock %}
+ </div>
+ </div>
+ <div class="spacer3"></div>
+ </div>
+ {% include "footer.html" %}
+ {% block endjs %}
+ {% endblock %}
+ </body>
+</html>
+<!-- end template base.html -->
diff --git a/urls.py b/urls.py
index 0608aaa8..b27193be 100644
--- a/urls.py
+++ b/urls.py
@@ -2,6 +2,10 @@ from django.conf.urls.defaults import *
from django.utils.translation import ugettext as _
import settings
+from django.contrib import admin
+admin.autodiscover()
+
urlpatterns = patterns('',
(r'^%s' % settings.FORUM_SCRIPT_ALIAS, include('forum.urls')),
+ (r'^admin/', include(admin.site.urls)),
)