Quelques balises HTML pour blogueurs [fr]

[en] A few HTML tags for bloggers. Don't use the visual editor is my recommendation. It sometimes creates hairy problems.

Je recommande en général de ne pas utiliser “l’éditeur visuel” lorsqu’on écrit des billets dans WordPress. L’éditeur visuel vous montre directement, dans le texte que vous écrivez, le gras en gras, les listes sous forme de liste avec des petits points devant, les liens en bleu souligné, etc. Malheureusement les éditeurs visuels sont imparfaits et génèrent souvent plus de problèmes qu’ils n’en résolvent.

Pour désactiver l’éditeur visuel, allez sous “Users/Utilisateurs” et puis sous “Your Profile/Votre Profil”. Tout en bas de cette page, il y a une case à cocher. Vérifiez qu’elle soit décochée, et mettez à jour les réglages.

Votre éditeur de billets est maintenant décoré d’une rangée de boutons un peu différente d’avant: sélectionnez du texte, cliquez sur le bouton approprié, et des caractères étranges apparaîtront de part et d’autre du texte que vous aviez sélectionné. C’est du HTML. HTML?! Pas de panique, c’est pas si compliqué. Voici ce que vous avez besoin de savoir:

  • le HTML, c’est en fait des petits “codes secrets” qui disent au navigateur de formatter d’une façon particulière le texte qu’ils entourent (par exemple: mettre en gras, faire une liste, faire un paragraphe, faire un lien).
  • ces codes secrets se nomment “balises”. Les balises vont toujours par deux: une qui ouvre, une qui ferme.

Exemple:

<em>du texte mis en italiques (emphasis)</em>

Ce qui est entre parenthèses angulaires < et > ne va pas s’afficher dans votre texte. Ce sont juste des indications que va interpréter le navigateur web. En l’occurence, il mettra le texte ci-dessus en italiques.

Voici quelques balises que vous rencontrerez en utilisant les boutons de WordPress:

  • <em> ... </em> met le texte qu’elles délimitent en italiques
  • <strong> ... </strong> en gras
  • <a href="http://quelquechose.com"> ... </a> crée un lien qui nous enverra sur http://quelquechose.com si on clique dessus
  • <ul> ... </ul>, <ol> ... </ol> et <li> ... </li> sont utilisés pour faire des listes (explications ultérieures).

Finally out of MySQL encoding hell [en]

[fr] Description de comment je me suis sortie des problèmes d'encodage qui résultaient en l'affichage de hiéroglyphes sur tous les sites hébergés sur mon serveur.

It took weeks, mainly because I was busy with a car accident and the end of school, but it also took about two real whole days of head-banging on the desk to get it fixed.

Here’s what happened: remember, a long time ago, I had trouble with stuff in my database which was supposed to be UTF-8 but seemed to be ISO-8859-1? And then, sometime later, I had a weird mixture of UTF-8 and ISO-8859-1 in the same database?

Well, somewhere along the line this is what I guess happened: my database installation must have been serving UTF-8 content as ISO-8859-1, leading me to believe it was ISO-8859-1 when it was in fact UTF-8. That led me to try to convert it to UTF-8 — meaning I took UTF-8 strings and ran them through a converter supposed to turn ISO-8859-1 into UTF-8. The result? Let’s call it “double-UTF-8” (doubly encoded UTF-8), for want of a better name.

Anyway, that’s what I had in my database. When we upgraded MySQL and PHP on the server, I suddenly started seeing a load of junk instead of my accented characters:

encoding-problem-2

What I was seeing looked furiously like UTF-8 looks when your server setup is messed up and serves it as ISO-8859-1 instead. But, as you can see on the picture above, this page was being served as UTF-8 by the server. How did I know it wasn’t ISO-8859-1 in my database instead of this hypothetical “double-UTF-8”? Well, for one, I knew the page was served as UTF-8, and I also know that ISO-8859-1 (latin-1) served as UTF-8 makes accented characters look like question marks. Then, if I wanted to be sure, I could just change the page encoding in Firefox to ISO-8859-1 (that should make it look right if it was ISO-8859-1, shouldn’t it?) Well, it made it look worse.

Another indication was that when the MySQL connection encoding (in my.cnf) was set back to latin-1 (ISO-8859-1), the pages seemed to display correctly, but WordPress broke.

The first post on the picture I’m showing here looks “OK”, because it was posted after the setup was changed. It really is UTF-8.

Now how did we solve this? My initial idea was to take the “double-UTF-8” content of the database (and don’t forget it was mixed with the more recent UTF-8 content) and convert it “from UTF-8 to ISO-8859-1”. I had a python script we had used to fix the last MySQL disaster which converted everything to UTF-8 — I figured I could reverse it. So I rounded up a bunch of smart people (dda_, sbp, bonsaikitten and Blackb|rd — and countless others, sorry if I forgot you!) and got to work.

It proved a hairier problem than expected. What also proved hairy was explaining the problem to people who wanted to help and insisted in misunderstanding the situation. In the end, we produced a script (well, “they” rather than “we”) which looked like it should work, only… it did nothing. If you’re really interested in looking at it, here it is — but be warned, don’t try it.

We tried recode. We tried iconv. We tried changing my.cnf settings, dumping the databases, changing them back, and importing the dumps. Finally, the problem was solved manually.

  1. Made a text file listing the databases which needed to be cured (dblist.txt).
  2. Dumped them all: for db in $(cat dblist.txt); do mysqldump --opt -u user -ppassword ${db} > ${db}-20060712.sql; done
  3. Sent them over to Blackb|rd who did some search and replace magic in vim, starting with this list of characters (just change the browser encoding to latin-1 to see what they look like when mangled)
  4. Imported the corrected dumps back in: for db in $(cat dblist.txt); do mysql -u user -ppassword ${db} < ${db}-20060712.sql; done

Blackb|rd produced a shell script for vim (?) which I’ll link to as soon as I lay my hands on the URL again. The list of characters to convert was produced by trial and error, knowing that corrupted characters appeared in the text file as A tilde or A circonflexe followed by something else. I’d then change the my.cnf setting back to latin-1 to view the character strings in context and allow Blackbr|d to see what they needed to be replaced with.

Thanks. Not looking forward to the next MySQL encoding problem. They just seem to get worse and worse. (And yes, I do use UTF-8 all over the place.)

Radio sans moi et deux blogs à  visiter [fr]

[en] A radio show on blogs without me (I was busy teaching) and two Swiss politically oriented blogs worth visiting.

Très rapidement (mais alors très, parce que là , j’ai assez de boulot pour me garder occupée ces deux prochaines semaines même si je n’enseignais pas), notons une émission sur la RSR1 ce matin, qui portait sur les blogs.

On saluera deux faits:

  • le sujet tournait plutôt autour du blog politique/blog d’entreprise, plutôt que l’éternel blog d’ado
  • comme j’enseigne entre 9h00 et 9h30 le lundi matin, l’émission s’est faite sans moi 😉

On saluera aussi la personne responsable du site internet de la RSR1, à  qui l’on rappellera en passant que l’attribut id doit être unique sur une page. <DIV id=smallbold align=left> (sic) à  perte de vue sur la page, ça ne le fait vraiment pas. Ah oui, et j’ai remarqué (deux-trois autres personnes aussi) que le serveur ramait passablement. Une petite cure d’amaigrissement à  coups de standards web serait peut-être à  conseiller.

Une mention cependant pour la possibilité de télécharger la chronique en MP3.

J’en profite pour vous envoyer vous balader sur deux sites romands “politisés” (prenez-en de la graine, vous autres, on en veut plus comme ça):

Mise à  jour 04.02.2006: merci à  Flippy, qui me dit les avoir eu via Fredoche, pour ces liens. Faites circuler!

SwissBlogs Needs Your Help [en]

SwissBlogs is putting together a team of motivated people to improve it drastically.

[fr] Je cherche à monter une équipe de personnes motivées pour faire vivre SwissBlogs, un des répertoires de blogs suisses les plus en vue. Au programme, entre autres:

  1. amélioration générale de l'interface (formulaire qui se pré-remplit avec les informations meta du weblog, possibilité d'éditer ses infos)
  2. intégration avec blog.ch
  3. version italienne
  4. processus de modération plus efficace

Si vous voulez faire partie de l'équipe, contactez-moi! Je cherche aussi des modérateurs, pour approuver les nouveaux sites ajoutés à la liste. Le site est en PHP/MySQL pas trop propre 🙂

SwissBlogs, one of the best-known Swiss blog directories, has become too much for one person (me) to maintain, even with a little help (Matt). Plus, you all know by now, that if I’m pretty good at having ideas and launching stuff, I’m much less good at keeping them going. I guess that’s just who I am.

I am therefore looking for motivated (and multilingual!) people to help me keep this directory going, and improve it (it has hardly changed since I quickly threw a few lines of dirty code together over 18 months ago).

I would like to put together a team of 5-6 people. Here is a quick list of what I’m thinking about for the coming developments of the directory:

  1. provide italian translation of interface
  2. allow people to edit their own data (add username/password functionality)
  3. automatically fill-in the form with as much data as possible pulled from the blog page meta tags (like ViaBloga does with their blogrolling system)
  4. more integration with blog.ch: it initially used the SwissBlogs list, but now the two lists have grown separately — people sign up on blog.ch but not on SwissBlogs, and vice-versa
  5. in particular, blog.ch information can be used to determine if a blog is still active or not
  6. add screenshots of blogs
  7. improve moderation process
  8. better sorting and filing of blogs (add tags?)
  9. improve general usability of form/site, and redesign…

Of course, we also need moderators — people who will check new blogs before inclusion in the directory.

Please get in touch if you would like to be on the team, or be a moderator.

Have I posted about this already? It rings familiar but my memory and site search are failing me.

Call to WordPress Plugin Developers [en]

Call for help to WordPress plugin developers. I have a bunch of hacks and modifications I’d like to turn into plugins, but I am unfortunately as plugin-challenged as ever.

[fr] Un descriptif des plugins que j'écrirais pour WordPress si je ne faisais pas un vilain blocage sur le sujet. Ne vous gênez pas si vous voulez contribuer!

If I was fluent in WordPress plugin coding, here are the plugins I’d write. If you feel like coding one of them yourself, or helping me get it done, you’re most welcome. Carthik has already pointed me to Plunge into Plugins, which I will have a close look at once I’ve finished writing this post.

Of course, if you know of a plugin which does precisely what I’m describing here, leave a link to it in the comments!

Keywords plugin

This would be a pretty straightforward one:

  • add a “keywords” text input to post.php
  • save the value of that text input to a custom field called “keywords”
  • add those keywords as an HTML meta tag on the individual post pages.
Excerpt plugin

This one would also be pretty straightforward, as all it would do is add the “excerpt” field to the “simple” post.php layout.

Customize post.php plugin

This would be more complex, but allow for more flexibility than the previous plugin. I don’t yet have a clear idea of how to make it work, but the basic principle would be to allow the user to select which fields should appear on the post.php page. Instead of having “simple” and “advanced” controls, this would add the option to have “custom” controls and define them.

TopicExchange plugin

As far as functionality is concerned, this plugin would do what my TopicExchange hack did:

  • add a “trackback TopicExchange channels” text input to post.php
  • store the space-separated list of keywords in a meta value named (e.g.) ite_topic (one record for each value)
  • for each value, trackback the appropriate TopicExchange channel
  • display the trackbacked channels (with link) on each post.
Bilingual plugin

This would be a clean version of my language hacks:

  • add a small “language” text input to post.php (with a default value)
  • add an “other language excerpt” textarea, which posts to the corresponding custom value
  • display the “other language excerpt” at the top of each post
  • provide a function to return the post language, and the other-excerpt language (so it can be declared in a lang attribute, allowing the use of language-dependant CSS formatting, in addition to being semantically correct)
  • if this is not already possible with the date function in the WordPress core, provide an alternative date function which will format the date correctly corresponding on the language of the post
  • optional: figure out a way to adapt text like “comments”, “categories” etc. to the post language; make the plugin usable with more than two languages.
Smart Linkroll plugin

I love the way ViaBloga manages blogrolls and would love to see a plugin for WordPress that does the same thing. In ViaBloga, you simply enter the URL of the site you want to add to your links. ViaBloga then retrieves the title, description, RSS feed address, and even (yes!) a screenshot for the site. No need to fill in fields manually anymore…

Wiki-Keywords plugin

I haven’t through this through yet completely, but it seems to me that a plugin which would add wiki-like capability to WordPress, like ViaBloga does with keywords, could be an interesting idea to explore.

Technorati plugin

This is really a simple one: add a function which will allow easy display of the Technorati cosmos of each post, like I have done manually for this weblog.

On the subject of multilingual blogging, Kevin Marks has some interesting markup suggestions I need to look at more closely.

Scripts for a WordPress Weblog Farm [en]

A first step to WordPress-farming: a shell script and a PHP script which allow you to easily install a whole lot of WordPress weblogs in only a few minutes (I installed over 30 in less than 5 minutes). Scripts require adapting to your environment, of course.

Update 03.11.06: Batiste made me realise I should point the many people landing here in the search of multi-user WordPress to WordPress MU. All that I describe in this post is very pretty, but nowadays completely obsolete.

Here is the best solution I’ve managed to come up with in half a day to finally install over 30 WordPress weblogs in under 5 minutes (once the preparation work was done).

A shell script copies the image of a WordPress install to multiple directories and installs them. A PHP script then changes a certain number of options and settings in each weblog. It can be used later to run as a “patch” on all installed weblog if a setting needs modifying globally.

Here are the details of what I did.

I first downloaded and unzipped WordPress into a directory.

wget http://wordpress.org/latest.tar.gz
tar -xzvf latest.tar.gz
mv wordpress wp-farm-image

I cleaned up the install (removing wp-comments-popup.php and the import*.php files, for example), added a language directory (as I’m wp-farming in French) and modified index.php to my liking; in particular, I edited the import statement for the stylesheet so that it looked like this:

@import url( http://edublogs.net/styles/toni/style.css );

The styles directory is a directory in which I place a bunch of WordPress styles. I don’t need the style switcher capability, but I do need to styles. Later, users will be able to change styles simply by editing that line in their index.php (or I can do it for them).

Another very important thing I did was rename wp-config-sample.php to config-sample and fill in the database and language information. I replaced wp_ by xxx_ so that I had $table_prefix = 'xxx_';.

To make it easier to install plugins for everyone, correct the language files, and edit whatever may be in wp-images, I moved these three directories out of the image install and replaced them with symbolic links, taking inspiration from Shelley’s method for installing multiple WordPress weblogs.

mv image/wp-content common
mv image/wp-images common
mv image/wp-includes/languages common
ln -s common/wp-content image/wp-content
ln -s common/wp-images image/wp-images
ln -s common/languages image/wp-includes/languages

I also added an .htaccess file (after some painful tweaking on a test install).

Once my image was ready, I compiled a list of all the users I had to open weblogs for (one username per line) in a file named names.txt, which I placed in the root directory all the weblog subfolders were going to go in.

I then ran this shell script (many thanks to all those of you who helped me with it — you saved my life):

for x in `cat names.txt`
do
cp -rv /home/edublogs/wp-farm/image/ $x
cat $x/wp-config.php | sed "s/xxx/${x}/" > config.tmp
mv config.tmp $x/wp-config.php
wget http://st-prex.edublogs.net/$x/wp-admin/install.php?step=1
wget http://st-prex.edublogs.net/$x/wp-admin/install.php?step=2
wget http://st-prex.edublogs.net/$x/wp-admin/install.php?step=3
done

This assumes that my WordPress install image was located in /home/edublogs/wp-farm/image/ and that the weblog addresses were of the form http://st-prex.edublogs.net/username/.

This script copies the image to a directory named after the user, edits wp-config to set the table prefix to the username, and then successively wgets the install URLs to save me from loading them all in my browser.

After this step, I had a bunch of installed but badly configured weblogs (amongst other things, as I short-circuited the form before the third install step, they all think their siteurl is example.com).

Entered the PHP patch which tweaks settings directly in the database. I spent some time with a test install and PHPMyAdmin to figure out which fields I wanted to change and which values I wanted to give them, but overall it wasn’t too complicated to do. You’ll certainly need to heavily edit this file before using it if you try and duplicate what I did, but the basic structure and queries should remain the same.

I edited the user list at the top of the file, loaded it in my browser, and within less than a few seconds all my weblogs were correctly configured. I’ll use modified versions of this script later on when I need to change settings for all the weblogs in one go (for example, if I want to quickly install a plugin for everyone).

In summary:

  1. compile list of users
  2. prepare image install
  3. run shell script
  4. run PHP script

If you try to do this, I suggest you start by putting only two users in your user list, and checking thoroughly that everything installs and works correctly before doing it for 30 users. I had to tweak the PHP script quite a bit until I had all my settings correctly configured.

Hope this can be useful to some!

Update 29.09.2005: WARNING! Hacking WordPress installs to build a farm like this one is neat, but it gets much less neat when your weblog farm is spammed with animal porn comments. You then realise (oh, horror!) that none of the anti-spam plugins work on your beautiful construction, so you weed them out by hand as you can, armed with many a MySQL query. And then the journalist steps in — because, frankly, “sex with dogs” on a school website is just too good to be true. And then you can spend half a day writing an angry reaction to the shitty badly-researched article.

My apologies for the bad language. Think of how you’re going to deal with spam beforehand when you’re setting up a school blog project.

MagpieRSS Caching Problem [en]

I have a caching problem using the PHP MagpieRSS library to parse feeds. Any help welcome.

[fr] J'ai un problème de cache utilisant la librarie PHP MagpieRSS. Toute aide bienvenue!

I’ve been stuck on a problem with MagpieRSS for weeks. This is a desperate call for help.

At the top of my sidebar, I have two lists of links which are generated by parsing RSS feeds: Delicious Linkball and Recently Playing. They don’t update.

If I delete the cache files, the script creates them all right. If I keep an eye on the cache files, I see their timestamp is updated every hour, but not the contents. I’ve uploaded the PHP code which parses the feeds.

Any suggestions welcome. I’m not far from giving up and setting cron jobs to regularly delete the cache files. Thanks in advance.

Update 13:00: The Recently Playing list updates once an hour (when the cache is “force-refreshed”), it seems — but not the Delicious Links one.

14:00: Some progress: http://del.icio.us/rss/steph/ doesn’t seem to update unless I clear the cache on my machine. (Huh?) http://ws.audioscrobbler.com/rdf/history/Steph-Tara, on the other hand, is — but why does the cache update only once an hour, and not each time the feed is modified?

15:00: crschmidt just pointed out that the last-modified date on my del.icio.us RSS feed was horribly wrong. Might be something that was done at the time when my caching problems were causing me to nastily abuse the poor del.icio.us server. I’ve sent a mail to Joshua to see if indeed this could be the problem.

15:50: Still thanks to the excellent crschmidt, I’ve finally understood how this caching is supposed to work. (Yes, I know, we’re starting to have lots of edits on this post.) There is a setting which determines how old the cache must be to become “stale”. As long as the cache is not stale, any requests made will use the cache directly, without pulling the feed in question. If the cache is stale, a request is sent to the server hosting the feed to check if it has changed since it was last accessed. If it has changed (i.e., if Last-Modified is more recent than the cache), it gets a fresh version of the feed. Otherwise, nothing happens (the cache age is just “reset”).

Now, for a LinkLog service like del.icio.us, setting the cache age to a couple of hours is more than enough as far as I’m concerned. However, for a list of recently played songs, every few minutes should be better. MagpieRSS seems to allow this to be set on a per-call basis by defining MAGPIE_CACHE_AGE, but it doesn’t seem to be working for me. Another variable is set on a per-installation basis: var $MAX_AGE = 1800; — but changing that won’t really help, as I want different values for Recently Playing and Delicious Links. Suggestions on this secondary problem welcome too!

16:40: After exchanging a few e-mails with Joshua, it seems that there was indeed a problem with the Last-Modified date on my feed. Not quite sure how it came about (somebody requesting the feed when I hadn’t posted in some time?), but it should be fixed now. I’ve cleared my cache files to see if my 30-minute “stale time” is working or not.

17:30: (See how I’m updating every 50 minutes? Freaky.) So, the not-so-nice things about PHP constants is that they are constant and (?) local to the function in which they are defined. (Not sure I go that bit right, but.) Important thing here is to note that MAGPIE_CACHE_AGE can’t be used to set different “stale cache” ages for different feeds. The stale cache age needs to be set at the bottom of rss_fetch.inc (the only place I hadn’t touched) — so my cache is now refreshing every half-hour. (Which is a bit too often for del.icio.us, and not often enough for Audioscrobblers.) oqp says he can write a wrapper to get around this limitation — I’m waiting impatiently for him to do it!

Backlinks [en]

See this nice summary page on referrer linking. I’m very tempted to try to write my own home-cooked one in PHP – you know, like, badly coded, slow, and works only on my server. Might be fun to do though.

[Update 9.7]: a certain number of hours of coding later, here is my php and mysql backlinks script source code. Enjoy!

PHP [en]

I’m back from Prague (with a little cold) and I have updated the PHP basics tutorial so that it reflects my current templating methods. Comments welcome!