#-*- coding: utf-8 -*-
# Copyright (C) 1998-2012 by the Free Software Foundation, Inc.
#
# This file is part of HyperKitty.
#
# HyperKitty 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 3 of the License, or (at your option)
# any later version.
#
# HyperKitty 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
# HyperKitty. If not, see .
#
# Author: Aamir Khan
# Author: Aurelien Bompard
#
import re
import os
import urllib
import django.utils.simplejson as simplejson
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import redirect, render, render_to_response
from django.template import RequestContext, loader
from django.conf import settings
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger, InvalidPage
from django.core.urlresolvers import reverse
from django.core.mail import EmailMessage
from django.contrib.auth.decorators import (login_required,
permission_required,
user_passes_test)
from hyperkitty.lib import get_store, get_months, get_votes
from hyperkitty.models import Rating
from forms import *
def index(request, mlist_fqdn, message_id_hash):
'''
Displays a single message identified by its message_id_hash (derived from
message_id)
'''
search_form = SearchForm(auto_id=False)
t = loader.get_template('message.html')
store = get_store(request)
message = store.get_message_by_hash_from_list(mlist_fqdn, message_id_hash)
if message is None:
raise Http404
message.sender_email = message.sender_email.strip()
# Extract all the votes for this message
message.likes, message.dislikes = get_votes(message_id_hash)
message.likestatus = "neutral"
if message.likes - message.dislikes >= 10:
message.likestatus = "likealot"
elif message.likes - message.dislikes > 0:
message.likestatus = "like"
#elif message.likes - message.dislikes < 0:
# message.likestatus = "dislike"
mlist = store.get_list(mlist_fqdn)
c = RequestContext(request, {
'mlist' : mlist,
'message': message,
'message_id_hash' : message_id_hash,
'months_list': get_months(store, mlist.name),
'use_mockups': settings.USE_MOCKUPS,
'reply_form': ReplyForm(),
})
return HttpResponse(t.render(c))
def attachment(request, mlist_fqdn, message_id_hash, counter, filename):
"""
Sends the numbered attachment for download. The filename is not used for
lookup, but validated nonetheless for security reasons.
"""
store = get_store(request)
message = store.get_message_by_hash_from_list(mlist_fqdn, message_id_hash)
if message is None:
raise Http404
attachment = store.get_attachment_by_counter(
mlist_fqdn, message.message_id, int(counter))
if attachment is None or attachment.name != filename:
raise Http404
# http://djangosnippets.org/snippets/1710/
response = HttpResponse(attachment.content)
response['Content-Type'] = attachment.content_type
response['Content-Length'] = attachment.size
if attachment.encoding is not None:
response['Content-Encoding'] = attachment.encoding
# Follow RFC2231, browser support is sufficient nowadays (2012-09)
response['Content-Disposition'] = 'attachment; filename*=UTF-8\'\'%s' \
% urllib.quote(attachment.name.encode('utf-8'))
return response
def vote(request, mlist_fqdn, message_id_hash):
""" Add a rating to a given message identified by messageid. """
if not request.user.is_authenticated():
return HttpResponse('You must be logged in to vote',
content_type="text/plain", status=403)
value = int(request.POST['vote'])
# Checks if the user has already voted for a this message.
try:
v = Rating.objects.get(user=request.user, messageid=message_id_hash,
list_address=mlist_fqdn)
if v.vote == value:
return HttpResponse("You've already cast this vote",
content_type="text/plain", status=403)
except Rating.DoesNotExist:
v = Rating(list_address=mlist_fqdn, messageid=message_id_hash, vote=value)
v.user = request.user
v.vote = value
v.save()
# Extract all the votes for this message to refresh it
status = { "like": 0, "dislike": 0 }
for vote in Rating.objects.filter(messageid=message_id_hash):
if vote.vote == 1:
status["like"] += 1
elif vote.vote == -1:
status["dislike"] += 1
return HttpResponse(simplejson.dumps(status),
mimetype='application/javascript')
@login_required
def reply(request, mlist_fqdn, message_id_hash):
""" Sends a reply to the list.
TODO: unit tests, make sure a message-id is generated
"""
if request.method != 'POST':
return HttpResponse("Something went wrong", content_type="text/plain", status=500)
form = ReplyForm(request.POST)
if not form.is_valid():
return HttpResponse(form.errors.as_text(), content_type="text/plain", status=400)
store = get_store(request)
message = store.get_message_by_hash_from_list(mlist_fqdn, message_id_hash)
subject = message.subject
if not message.subject.lower().startswith("re:"):
subject = "Re: %s" % subject
reply = EmailMessage(
subject=subject,
body=form.cleaned_data["message"],
from_email='"%s %s" <%s>' %
(request.user.first_name, request.user.last_name,
request.user.email),
to=[mlist_fqdn],
cc=['aurelien@bompard.org'],
headers={
"In-Reply-To": "<%s>" % message.message_id,
"References": "<%s>" % message.message_id,
})
reply.send()
return HttpResponse("The reply has been sent successfully.", mimetype="text/plain")
@login_required
def new_message(request, mlist_fqdn):
""" Sends a new thread-starting message to the list.
TODO: unit tests, make sure a message-id is generated
"""
store = get_store(request)
mlist = store.get_list(mlist_fqdn)
context = {
"mlist": mlist,
}
return render_to_response("message_new.html", context,
context_instance=RequestContext(request))