Tag Suggestion for symfony
I just have created a patch for sfFormExtraPlugin. It provides a new form widget called sfWidgetFormJqueryTagSuggestion designed to suggest tags. It is based on the Tag Suggestion jQuery plugin of Remy Sharp.

You can download it from GitHub, just copy the files to the corresponding directories of your existing sfFormExtraPlugin installation or wait for upstream inclusion of my patch.
This widget integrates easily with sfPropelActAsTaggableBehaviorPlugin. Here is how to use it with this plugin.
You must have sfFormExtraPlugin with my patch and sfPropelActAsTaggableBehaviorPlugin properly installed and working. We consider that you have a model called Article with the taggable behavior.
Add jQuery to your javascripts
Like many others sfFormExtraPlugin widgets, the sfWidgetFormJqueryTagSuggestion requires jQuery to work. If you already have it installed, you can skip this step. Either, download jQuery to the web/js/ directory of your project, open the config/view.yml file of your application and set it like that:
default:
javascripts: [jquery-1.3.2.min.js]
Of course, change the filename if needed.
Put Javascripts and CSS into your web directory
sfFormExtraPlugin need some CSS and Javascripts to work properly, run the symfony plugin:publish-assets command to put them into corrects directories.
Create a static function to retrieve matching tags
Its time to extend the TagPeer model class to add it a method allowing to retrieve tags corresponding to a query. Creates a new file called MyTagPeer.class.php into the lib/model/ directory of your project containing the following code:
class MyTagPeer extends TagPeer {
/**
* Gets tags for a selector
*
* @param string $q
* @param int $limit
* @return array
*/
static public function retrieveForSelect($q, $limit = 10)
{
$criteria = new Criteria();
$criteria->add(TagPeer::NAME, '%'.$q.'%', Criteria::LIKE);
$criteria->addAscendingOrderByColumn(TagPeer::NAME);
$criteria->setLimit($limit);
$tags = array();
foreach (TagPeer::doSelect($criteria) as $tag) {
$tags[] = $tag->getName();
}
return $tags;
}
}
Do not forget to run symfony cc to clear the cache after that.
Create a controller method to send the result as JSON
We have the model, we need the controller. Create a new module called tag by running symfony generate:module yourapp tag and add the following method to the tagActions class:
/**
* Displays a JSON encoded tags array
*
* @param sfWebRequest $request
* @return string
*/
public function executeSelect(sfWebRequest $request)
{
$this->getResponse()->setContentType('application/json');
$tags = MyTagPeer::retrieveForSelect($request->getParameter('tag'));
return $this->renderText(json_encode($tags));
}
Open your routing.yml file and add the following line to be able to access this action:
tag_select:
url: /select-tag
param: { module: tag, action: select }
Modify your form to add the new tags suggestion widget
Open the form class you want to add this widget and add the following line to the end of the configure method:
$this->widgetSchema['tags'] = new sfWidgetFormJqueryTagSuggestion(array('url' => $this->getOption('url'), 'separator' => ', '));
We use the comma as separator instead of the space by default because this is the separator used by sfPropelActAsTaggableBehaviorPlugin.
Next, modify your call to the form in your actions to pass the AJAX URL as form option:
$this->form = new ArticleForm($article,
array('url' => $this->generateUrl('article_select_tag'))
);
It’s done!
Code’N'Roll: my new Rock’N'Roll microblog
Patch to use sfXssSafePlugin with symfony 1.2
HTML Purifier is a awesome PHP filter library designed to secure and add standard compliance to HTML. In websites including user generated content, this library allow to have mutlimedia pages including image, text formating and YouTube videos in a secure and SEO proof way thanks to rich text editors like Tiny MCE or FCK Editor and HTML purifier.

A plugin called sfXssSafePlugin is designed to integrate this library as an escapement strategy in symfony. If you have tried it with symfony 1.2 you can see this message:
HTML Purifier autoloader registrar is not compatible
with non-static object methods due to PHP Bug #44144;
Please do not use HTMLPurifier.autoload.php (or any
file that includes this file); instead, place the code:
spl_autoload_register(array(’HTMLPurifier_Bootstrap’, ‘autoload’))
after your own autoloaders.
There are also some strict standards and constants compatibility problems. I’ve just wrote a patch to get this plugin working with symfony 1.2.
- Install sfXssSafePlugin like described in its README file
- Download my patch in the plugin’s folder
- Go into the plugin’s folder and run patch lib/helper/XssSafeHelper.php < XssSafeHelper.php.patch
- Edit your application configuration file (ie: apps/frontend/config/frontendConfiguration.class.php) and add the following code into the
configure()method:require_once(sfConfig::get('sf_plugins_dir').'/sfXssSafePlugin/lib/vendor/htmlpurifier/HTMLPurifier/Bootstrap.php'); spl_autoload_register(array('HTMLPurifier_Bootstrap', 'autoload'));
It’s done ! I’ve submitted this patch to the plugin’s author. I hope it will be upstream soon
Feedburner: Switching to Google account with MyBrand enabled
Since I’ve migrated my FeedBurner account to Google I encounter a lot of problems, especially with the MyBrand service. MyBrand is a service allowing to use custom domain names with FeedBurner. Instead of something like http://feeds.feedburner.com/lapin-blanc, your feed address become http://feeds.lapin-blanc.net/lapin-blanc. I’ve already explained why it’s better !
![]()
My subdomain for feeds was rss.lapin-blanc.net. There is no way to get this subdomain working since I’ve switched to Google accounts. I’ve followed the Tim Heuer’s tutorial but the message The domain « rss.lapin-blanc.net » you specified is already in use.
is still displayed when I try to recreate my main custom URL in the MyBrand settings page. I’ve just managed to get my « backup » domain called feeds.lapin-blanc.net working.
So I’ve created this quick-and-dirty hack:
- Set a working MyBrand domain. For me:
feeds.lapin-blanc.net. - Point the DNS entry of your primary feeds domain on your web server. For me me: replace
rss 10800 IN CNAME <my-login>.feedproxy.ghs.google.com.byrss 10800 IN CNAME www. - Create a virtual host on your web server to redirect permanently the old addresses to the new one. For me (using Debian GNU/Linux):
Create a file called/etc/apache2/sites-available/rss.lapin-blanc.netcontaining:<VirtualHost *> ServerName rss.lapin-blanc.net RewriteEngine On RewriteRule ^(.*) http://feeds.lapin-blanc.net$1 [L,R=301] </VirtualHost>Next type in a shell
a2ensite rss.lapin-blanc.net && /etc/init.d/apache2 reload. - Change all occurrences of your old feeds URL to the new in your site to reduce the number of HTTP requests.
Your burned feed must work without losing readers. This a temporary solution, and I think that the only useful long term solution is to go away from FeedBurner…
Build your own website thumbnail generator with Django
On many website you can see a awesome link preview effect using a thumbnail of the page. There is some web services such as Websnapr or Thumbalizr providing an API to make your own webpages screenshots but it can be annoying to rely on third party projects: free accounts can only display a small among of screenshots and, cannot customize the size of the image, you cannot render Flash animations or Javascript…
![]()
We will build a website thumbnail generator using CutyCapt, a Webkit based free software designed to make screenshots of web pages, and Django, the powerful Python web framework.
The first step is to download and install CutyCapt. On a Debian-based system (such as Ubuntu) just type the following commands:
sudo apt-get install subversion libqt4-webkit libqt4-dev g++
svn co https://cutycapt.svn.sourceforge.net/svnroot/cutycapt
cd cutycapt/CutyCapt
qmake
make
./CutyCapt --url=http://lapin-blanc.net --out=example.png
Try to open the example.png (i.e: eog example.png), if the install is OK you must see a screenshot of this blog.
I assume your Django installation is working fine. Start a new project if needed (django-admin.py startproject mysite) and create an application called webthumb
with python manage.py startapp in your project.

Edit your urls.py file to add a new pattern to the tuple urlpatterns. It will match screenshots requests and call the thumb view:
(r'^thumb/(?P.*)', 'mysite.webthumb.views.thumb'),
Now create a view called thumb in webthumb/view.py with this code:
import os
import subprocess
import md5
from django.http import HttpResponse
CUTYCAPT = '/home/keyes/cutycapt/CutyCapt/CutyCapt'
THUMBS_DIR = '/home/keyes/Documents/Projets/kakofony/thumbs/'
def thumb(request, url):
hash = md5.new(url).hexdigest()
path = THUMBS_DIR + hash + '.png'
print path
if not os.path.isfile(path):
try:
subprocess.check_call([CUTYCAPT,\
'--url=' + url,\
'--min-width=200',\
'--out=' + path])
except subprocess.CalledProcessError:
return django.http.HttpResponseServerError
img = open(path, 'rb').read()
return django.http.HttpResponse(img, mimetype='image/png')
Adapt the variables CUTYCAPT and THUMBS_DIR with your settings. Of course the directory pointed by THUMBS_DIR must be writeable (chmod 777).
You can now embed website thumbnails in your websites just with this HTML markup <img src="http://localhost/thumb/http://lapin-blanc.net" alt="Lapin Blanc" />.
Enjoy !
The last update of Aptana block Django development server
The last update of Aptana Studio come with a new built-in Jetty-based HTTP server running on port 8000… the same as Django development server. There is no good way to disable the preview server feature of the popular editor, but our favorite web framework can be launched on another port. Just type python manage.py runserver 8080 instead of python manage.py and access to your work on http://localhost:8080.
![]()
MessengerFX’s security problem corrected
Some times ago I found a Cross Site Scripting vulnerability in MessengerFX, a popular web-based Windows Live Messenger client. Friday I received from the team saying that the problem is now corrected:
Hi Kevin,
First of all i want to thank you for your warn. We fixed that problem and
now its working correctly.[...]
If you find any other problem please let me know. Thanks again.
It was serious : Every software’s feature is available through Javascript. Any contact of a MessengerFX user can crash his browser, and futhermore get its contact list, add, remove, ban and unban contacts, read and send messages to any other contact of the victim ! Basically, an attacker just need to be listed in the contacts list of an MessengerFX user and this attacker can take control over the account.
In fact, all Javascript code is now removed server-side, so it’s impossible to send some snippets to a friend and the code is still executed locally (in the browser of the sender). The team explain that a new version of their app will be released soon and will better handle things like this.
hosting.py 0.2 released
hosting.py is a web server account manager for Debian GNU/Linux and derivatives, such as Ubuntu Linux I am maintaining.
I am proud to announce that the version 0.2 is out !
hosting.py now supports MySQL accounts and databases management and his core is modular. The documentation as been rewrited and detailled.
hosting.py needs contributors. Testers and developers are wanted.
- Testers: just fill bugs on Google code
- Contributors: contact me [dunglas <at> gmail <dot> com]
Downloads and details on Google Code.
hosting.py: Debian/Ubuntu webserver administration tool
hosting.py allows to easily create and manage accounts on shared servers running Debian GNU/Linux (and derivatives, such as Ubuntu Linux). It includes support for Apache virtual hosts, UNIX accounts, MySQL databases and privileges. hosting.py is a command line tool wrote in Python by Kévin Dunglas.
Philosophy
The philosophy behind this tools is « keep it simple ». hosting.py is designed for small web hosting services. hosting.py will not have advanced features like virtual mail or FTP account creation. It creates the base configuration and settings for a web hosting account. Mail, FTP or whatever must be handled by the configuration of the system to use the UNIX account.
Status
hosting.py doesn’t currently support MySQL user and database creation. This will be committed soon.
Install
hosting.py need Debian etch or Ubuntu and Python 2.5 to work. Get the source via SVN : svn checkout http://debian-hosting.googlecode.com/svn/trunk/ debian-hosting-read-only
It’s done ! Type python hosting.py --help to get started.
Optionally you can adjust the configuration by editing the variables in the head of the hosting.py file.
MessengerFX allows your contacts to take control over your WLM
I have paste some HTML code to a Edouard using MessengerFX, a popular web Windows Live Messenger client based on AJAX, and - surprise, the code has been interpreted. Oh?! A XSS vulnerability ? Yes, and such a big one!
Every software’s feature is available through Javascript. Any contact of a MessengerFX user can crash his browser, and furthermore get its contact list, add, remove, ban and unban contacts, read and send messages to any other contact of the victim ! Basically, an attacker just need to be listed in the contacts list of an MessengerFX user and this attacker can take control over the account.

And the worst is coming… Using Javascript, it seems easy to write a worm that will, i.e. recursively delete every contacts of the MessengerFX users - say using the vulnerability to get the contact list and delete them one by one. The worm can also try to shutdown the WLM network with a DDOS attack by a heavy load of messages at the same timeusing infected MessengerFX users WLM accounts.
MessengerFX is popular and growing, such a flaw can be very dangerous for a lot of people. I have send a mail to the development team and I hope they will correct their application soon… Because the fix is as simple as a htmlspecialchars() call. MessengerFX users, don’t use it anymore and try Meebo or the official Microsoft WLM web based client. Web developers, never trust the user-submitted data and always escape thos inputs!!
Edit october 6 2008 : the problem is now corrected.

