Permission required decorator for django

django No Comments

Very long time since last post. The new thing in my geek life is I’ve switched to Django.

My last issue today was to display an error message instead of redirecting to login page when the use doesn’t have permission. Here is a decorator which replace the permission_required of django. Feel free to rename it to avoid confusion ;-)

from django.shortcuts import render_to_response
from django.template.context import RequestContext
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.utils.http import urlquote
from django.http import HttpResponseRedirect
from django.contrib.auth.models import Permission

class permission_required(object):
    """
    decorator which redirects to login page if user is anonymous
    and display a permission denied template if user is logged in
    doesn't have permission
    """
    def __init__(self,
                 perm,
                 login_url=None,
                 redirect_field_name=REDIRECT_FIELD_NAME,
                 template='permission_denied.html'):

        if not login_url:
            from django.conf import settings
            login_url = settings.LOGIN_URL

        self.perm = perm
        self.login_url = login_url
        self.redirect_field_name = redirect_field_name
        self.template = template

    def __call__(self, func):
        def wrap(request, *args, **kwargs):
            if request.user.is_anonymous():
                path = urlquote(request.get_full_path())
                tup = self.login_url, self.redirect_field_name, path
                return HttpResponseRedirect('%s?%s=%s' % tup)

            if request.user.has_perm(self.perm):
                return func(request, *args, **kwargs)

            (app_label, codename) = self.perm.split('.', 1)
            perm_name = Permission.objects.get(codename=codename,
                                               content_type__app_label=app_label)

            return render_to_response(self.template,
                                      {'perm': perm_name},
                                      context_instance=RequestContext(request))
        return wrap

My template permission_denied.html contains :

{% extends "base.html" %}
{% load i18n %}
{% block body %}
<h2>{% trans "Permission denied" %}</h2>
<p>{% blocktrans with perm as perm %}You need to have the permission "{{ perm }}"
 to see this page{% endblocktrans %}</p>
{% endblock %}

Talk about Wisss during the Acceleo Day at RMLL 2009

Wisss, acceleo No Comments

Long time not posting here. I’ve had a lot of work and nothing really interesting to post. I just inform you that I will make a speech about Wisss during the Acceleo Day in Nantes, at L’école des Mines, next friday at 2:30 pm.

More information at :

http://2009.rmll.info/Eclipse-Acceleo-Day-Presentation,938.html

http://www.acceleo.org/wiki/index.php/EclipseAcceleoDay:Program

Array search performance

PHP No Comments

You probably have often searched for a value in an array using the in_array() function. Reading php|architect’s Guide to PHP Security by Ilia Alshanetsky, I’ve noticed that searching on values can be slower than searching on keys. I’ve wanted to compare performance between the three methods to check a value in a white list and it’s amazing how slower is in_array(), look at the result :

fga@brian:~/tmp$ php5 test_array.php
With in_array :
111
time : 0.349022865295 sec
With isset on keys :
111
time : 0.000214099884033 sec
With array_key_exists :
111
time : 0.00021505355835 sec

Searching on keys is 1000 to 10000 times faster regarding the bench on an array containing 700 000 elements.

Here is the code of the test :

<?php
// array to store white list as values
$t = array();
// array to store white list as keys
$u = array();

// elements count
$max = 700000;

$first = $last = $middle = '';
for($i=$max-1;$i>=0;$i--){
        // values are random strings
        $id = uniqid(rand());
        $t[] = $id;
        $u[$id] = '';
        // we store first, last and middle values to
        // to search for them
        switch($i) {
                case $max-1:
                        $first = $id;
                break;
                case 0:
                        $last = $id;
                break;
                case $max/2:
                        $middle = $id;
                break;
        }
}

echo "With in_array :\n";
$start_time = microtime(true);
echo in_array($first,$t);
echo in_array($last,$t);
echo in_array($middle,$t);
echo "\n";
echo "time : " . (microtime(true)-$start_time) . " sec";
echo "\n";

echo "With isset on keys :\n";
$start_time = microtime(true);
echo isset($u[$first]);
echo isset($u[$last]);
echo isset($u[$middle]);
echo "\n";
echo "time : " . (microtime(true)-$start_time) . " sec";
echo "\n";

echo "With array_key_exists :\n";
$start_time = microtime(true);
echo array_key_exists($first,$u);
echo array_key_exists($last,$u);
echo array_key_exists($middle,$u);
echo "\n";
echo "time : " . (microtime(true)-$start_time) . " sec";
echo "\n";

Zend Pdf and PNG transparency issue

Zend Framework 4 Comments

Currently working on PDF generation, I’ve noticed that drawing a big PNG image with transparency (about 600×800, 150kB) brings the script computation up to 20 seconds. I’ve raised the bug in the Zend Framework issue tracker and for now, don’t forget to remove transparency in your background image if you can.

See the bug at :  http://framework.zend.com/issues/browse/ZF-3392

Wrapping text for Zend Pdf

PHP, Zend Framework 1 Comment

A common issue in Zend_Pdf is to wrap text in a box. I’ve found partial solutions such as wrapping text each 80 characters for instance but the line width can vary regarding the font and the character width. Since we can’t rely on the character count unless using a monospaced font, we have to wrap text on the real box width.

In partial solutions, I’ve found a function which computes the real width of a string according to the font and the font size. By aggregating every chunks, I’ve made my getWrappedText() method which returns a string with the correct \n :

protected function getWrappedText($string, Zend_Pdf_Style $style,$max_width)
{
    $wrappedText = '' ;
    $lines = explode("\n",$string) ;
    foreach($lines as $line) {
         $words = explode(' ',$line) ;
         $word_count = count($words) ;
         $i = 0 ;
         $wrappedLine = '' ;
         while($i < $word_count)
         {
             /* if adding a new word isn't wider than $max_width,
             we add the word */
             if($this->widthForStringUsingFontSize($wrappedLine.' '.$words[$i]
                 ,$style->getFont()
                 , $style->getFontSize()) < $max_width) {
                 if(!empty($wrappedLine)) {
                     $wrappedLine .= ' ' ;
                 }
                 $wrappedLine .= $words[$i] ;
             } else {
                 $wrappedText .= $wrappedLine."\n" ;
                 $wrappedLine = $words[$i] ;
             }
             $i++ ;
         }
         $wrappedText .= $wrappedLine."\n" ;
     }
     return $wrappedText ;
}
/**
 * found here, not sure of the author :
 * http://devzone.zend.com/article/2525-Zend_Pdf-tutorial#comments-2535
 */
 protected function widthForStringUsingFontSize($string, $font, $fontSize)
 {
     $drawingString = iconv('UTF-8', 'UTF-16BE//IGNORE', $string);
     $characters = array();
     for ($i = 0; $i < strlen($drawingString); $i++) {
         $characters[] = (ord($drawingString[$i++]) << 8 ) | ord($drawingString[$i]);
     }
     $glyphs = $font->glyphNumbersForCharacters($characters);
     $widths = $font->widthsForGlyphs($glyphs);
     $stringWidth = (array_sum($widths) / $font->getUnitsPerEm()) * $fontSize;
     return $stringWidth;
 }

then you can draw the text easily :

$y = 700;
$lines = explode("\n",$this->getWrappedText($text,$style_text,400)) ;
foreach($lines as $line)
{
    $page2->drawText($line, 140, $y);
    $y-=15;
}

« Previous Entries