Une diagonale qui a du style…

capture d'écranLa page d’accueil du site du festival Paris en toutes lettres, réalisé par le studio Point-barre, présente un très joli élément de design (sur la partie inférieure de la page), reproduit sur la capture d’écran ci-contre : une diagonale entre deux paragraphes.

Je laisse à votre sagacité le soin de découvrir comment elle est réalisée et le décrire dans les commentaires de ce billet.  Question subsidiaire : est-ce programmé côté client ou côté serveur ?

Publié dans Liens | Marqué avec , , , , , , | 37 commentaires

Concours de hack (des points de CC à gagner)

Sur ce blog, j’ai mis un certain nombre d’exemples très sommaires.
Certains sont trop sommaires et présentent de ce fait des failles de sécurité parce que leur but était juste d’illustrer un point précis, sans noyer le code.

Vous êtes invités à les signaler en commentaire du billet correspondant, et à proposer des correctifs.  A la clef, pour les étudiants du cours d’IO2 (voire de NTW), un bonus sur leur note de contrôle continu, proportionnel à la contribution apportée.

Pour les autres visiteurs du blog, évitez les spoilers avant la fin du semestre, mais n’hésitez pas à laisser quelques signes pour aider les copains.

Publié dans Non classé | Marqué avec , , , , , , | 6 commentaires

javascript avec jQuery

La base

  • inclure un fichier js dans html
    <script type="text/javascript" src="..."></script>
  • télécharger la bibliothèque, la mettre quelque part dans
    votre répertoire, et la charger dans votre page, avec :
    <script type="text/javascript" src="jquery.js"></script>
  • La fonction $
    la fonction principale de jQuery, qui permet d’accéder aux
    éléments du DOM (l’arbre de la page) au moyen de sélecteurs css.
  • $(document).ready,
    événement qui fait office de main : on lui
    passe en paramètre une fonction qui sera lancée quand le document
    aura été complètement chargé.
  • Lier une fonction à un événement,
    c’est une des opérations
    principales en javascript. Les fonctions sont donc passées en
    paramètre d’autres fonctions.

Un exemple simple

Le html :

  <p>Bonjour...</p>
  <p class="test">Youhou, survole-moi !!!</p>

Le js :

$(document).ready(function(){
    $(".test").mouseenter(function() {
        $(this).replaceWith('<p>Ahahahahaha !!!</p>')
    });
});

Lorsque le document est prêt, on enclenche une action sur l’événement
mouseenter de tous les éléments de classe test (en l’occurrence,
le deuxième paragraphe).

Le paramètre de la fonction $ est un sélecteur css. La fonction est
appliquée à tous les éléments sélectionnés (ici il n’y en a qu’un).

Le résultat.

On ajoute des effets à notre exemple

Le résultat ici, utilisant ce fichier js.

C’est en pensant aux « boutons suicides » utilisés ici que j’ai ajouté la vidéo en début de billet.  Elle illustre très bien le mécanisme de déclenchement d’une action sur un événement.

Les rubriques principales de la doc (facile à lire)

J’ai utilisé chacun de ces aspects dans l’exemple.

Publié dans Cours | Marqué avec , , , , , , | 3 commentaires

Photobase, php, mysql

Exemple de site avec base de données

[Mise à jour, 3 octobre 2012 : le site exemple n'est momentanément plus accessible.  Je vais essayer d'y remédier]

Les tables

Fichier photobase-create.sql

DROP TABLE IF EXISTS photobase_users;
CREATE TABLE IF NOT EXISTS photobase_users (
  id INT(4) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(256) NOT NULL DEFAULT ''
) DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS photobase_photos;
CREATE TABLE IF NOT EXISTS photobase_photos (
  id INT(4) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  upload TIMESTAMP,
  owner INT(4)
) DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS photobase_comments;
CREATE TABLE IF NOT EXISTS photobase_comments (
  id INT(4) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  photo INT(4),
  author INT(4),
  comment TEXT
) DEFAULT CHARSET=utf8;

Fichier photobase-insert.sql

INSERT INTO photobase_users (name) VALUES
  ('alain b'),
  ('hbl'),
  ('binto'),
  ('iciautrement'),
  ('donkeykong donkeypix'),
  ('stok'),
  ('philippineroyer'),
  ('artyu'),
  ('mister blast7'),
  ('bcommebenedicte'),
  ('or2k'),
  ('zespinal'),
  ('ouranos'),
  ('miloo phototruc'),
  ('lomosapiens'),
  ('leprive')
;

INSERT INTO photobase_photos (upload, owner)
VALUES
  (20100314, 1),
  (20100315, 1),
  (20100316193210, 1),
  (20100316201403, 1),
  (20100401102002, 2),
  (20100401102132, 2),
  (20100401102345, 2),
  (20100401, 3),
  (20100401, 3),
  (20100401, 3),
  (20100402, 3),
  (20100403, 3),
  (20100310, 4),
  (20100313, 4),
  (20100322, 4),
  (20100322, 4),
  (20100403, 4)
;

INSERT INTO photobase_comments (photo, author, comment)
VALUES
  (1, 2, 'très jolie photo !'),
  (1, 1, 'merci binto lol'),
  (5, 1, 'lol'),
  (5, 3, 'mdrrrrrrr')
;

La page d’accueil (index.php)

A retenir : mysql_query,  mysql_fetch_assoc.

  ...
  <body>
    <?php include 'photobase-menus.php'; ?>
   <h1>Bienvenue sur photobase</h1>
   <h2>Utilisateurs du service</h2>
   <?php affiche_utilisateurs(); ?>
   </ul>
  </body>

La fonction se fait en trois temps.

1. Récupération des utilisateurs dans la base.


   function get_users()
   {
     global $connexion; // on verra plus tard où est définie cette variable
     $request = 'SELECT * FROM photobase_users';
     return mysql_query($request, $connexion);
   }

La chaîne SELECT * FROM photobase_users est une requête mysql, en langage sql, donc pas en php. Elle est envoyée à la base par la fonction php mysql_query.

2. Récupération des entrées renvoyées par la base

 function affiche_utilisateurs()
  {
    $users = get_users();
    echo '<ul id="users">';
    while($user = mysql_fetch_assoc($users))
      affiche_utilisateur($user);
    echo '</ul>';
  }

Chaque appel à la fonction php mysql_fetch_assoc extrait une nouvelle entrée dans le résultat renvoyé par la fonction mysql_query, et est évalué à faux quand il n’y a plus d’entrée à lire.
Il ne nous reste plus qu’à écrire la fonction d’affichage d’un utilisateur.

3. Affichage d’un utilisateur


   function url_user($user)
   {     return "user.php?id=" . $user['id'];    }

   function affiche_utilisateur($user)
   {
      echo '<li>'
       . '<a href="' . url_user($user) . '">'
       . $user['name']
       . '</a>'
       . "</li>\n";
   }

La page d’un utilisateur (user.php)

Le début du fichier (avant d’écrire quoi que ce soit, y compris le doctype).
Encore mysql_fetch_assoc.

<?php
require_once 'connect-photobase.php';
if(!isSet($_GET['id']))
  header('Location: index.php'); // redirige sur la page d'accueil
else
{
  $user_id = $_GET['id'];
  $request = "SELECT name FROM photobase_users WHERE id=$user_id";
  $res = mysql_query($request, $connexion);
  $tab = mysql_fetch_assoc($res);
  $name = $tab['name'];
}
?>

Les fonctions pour l’affichage des photos vignettes :

function photo_id_to_tiny_filename($id)
{
  return "Img/tiny-$id.jpg";
}

function photolink($id)
{
  return
    '<a href="photo.php?id='
    . $id
    . '">'
    . '<img src="'
    . photo_id_to_tiny_filename($id)
    . '" alt="'
    . $id
    . '"/>'
    . '</a>'
    ;
}

La page elle-même.
A retenir : mysql_num_row

  <?php include 'photobase-menus.php'; ?>

  <h1>Bienvenue sur la photobase de
  <?php
  echo $name;
  ?>
  </h1>

<?php
$request = 'SELECT id FROM photobase_photos '
  . " WHERE owner=$user_id ORDER BY upload DESC";
// attention à l'espace quand on coupe la chaîne !!

$photos = mysql_query($request, $connexion);
$nb = mysql_num_rows($photos);
echo "<p>$name a $nb photos.</p>\n";
if($nb > 0)
{
  echo '<table class="vignettes">';
  $done = 0;
  while($photo = mysql_fetch_assoc($photos))
    {
      if($done % 2 == 0) echo '<tr>';
      echo '<td>' . photolink($photo['id']) . "</td>\n";
      if($done % 2 == 1) echo "</tr>\n";
      $done++;
    }
  echo "</table>\n";
}
?>

Connexion à la base

La variable $connexion est définie dans le fichier connect-photobase ci-dessous (j’ai bien entendu supprimé les paramètres de ma base). Il doit donc être inclus avant les fonctions qui l’utilisent (par exemple au tout début du fichier, pour pouvoir rediriger sur une autre page en cas d’erreur de connexion).

<?php
define('SERVER', '...');
define('USER', '...');
define('PSSWD', '...');
define('BASE', '...');

$connexion = mysql_pconnect(SERVER, USER, PSSWD);

if (!$connexion) {
    echo 'Pas de connexion au serveur.';
    exit;
}

if (!mysql_select_db(BASE, $connexion)) {
    echo 'Pas d\'accès à la base.';
    exit;
}

?>

[Mise à jour, 3 octobre 2012 : j'ai modifié les pseudos de sorte qu'ils ne soient pas directement les pseudos des utilisateurs de Flickr que j'ai pris comme base de départ pour le site]

Publié dans Cours | Marqué avec , , , , , , | 4 commentaires

Plugins facebooks

Sur le site didiode :

Uniquement sur cet article (avec quelques paramètres d’affichage un peu différents) :

Voir la doc du bouton « j’aime ».

Et l’activité récente sur didiode :

La doc du plugin d’activité

Publié dans Non classé | Un commentaire

Persistance des données

Deux mécanismes pour permettre au serveur de stocker des informations
sur un visiteur, pour les retrouver plus tard (soit lors d’une visite
ultérieure, soit lors du chargement d’une autre page du site).

Avec les sessions, les informations sont stockées sur le serveur.
Avec les cookies, elles sont stockées sur le client.

Sessions

Fonction session_start ()

Si c’est la première visite, une session est créée. Sinon, les
informations de session sont rechargées.

Les informations sont stockées sur le serveur
(donc ne sont pas falsifiables).
Pour faire le lien entre la session et l’utilisateur, la fonction crée
un cookie PHPSESSID (voir ci-dessous pour les cookies) sur la machine
du client. Ce cookie ne contient aucune des informations fournies par
l’utilisateur au serveur.

La fonction session_startdoit être appelée avant tout affichage (donc même
pas un espace avant la balise php).

Exemple :

<?php
...
/* Pas d'echo avant cette ligne !!!! */
session_start ();

if (!isset($_SESSION['connu']))
{
   $_SESSION['connu'] = true;
   echo "Ceci est votre premiere visite";
}
else echo "On s'est deja vus quelque part ?";
?>

Possibilité de définir où les infos de sessions sont stockées :

session_save_path(chemin);

Cookies

Les cookies sont des éléments d’information stockés sur la machine du
client par le navigateur, que le serveur retrouvera lors d’une visite ultérieure.

setcookie('clef', 'valeur')
setcookie('clef', 'valeur', time() + nb_secondes)

Cette fonction doit être appelée avant tout affichage.

Pour l’utiliser ensuite :

isset($_COOKIE['clef'])

Exemple :

<?php
...
/* Pas d'echo avant cette ligne !!!! */
if (!isset($_COOKIE['mon-cookie']))
   setcookie('mon-cookie', 'ma-valeur');
   else
   { ... }
?>

A noter :

  • le cookie est placé par le navigateur, donc si vous lancez un autre
    navigateur, le cookie ne sera pas être utilisé
  • un cookie est falsifiable par le client : on peut modifier la valeur
    qui est stockée (certaines extensions firefox ou chrome le permettent, par exemple)
Publié dans Cours, Non classé | Marqué avec , , , , , | 2 commentaires

Paul Baran, Internet Pioneer, Dies at 84

Paul BaranSa nécro dans le NYT.

Mr. Baran’s idea was to build a distributed communications network, less vulnerable to attack or disruption than conventional networks. In a series of technical papers published in the 1960s he suggested that networks be designed with redundant routes so that if a particular path failed or was destroyed, messages could still be delivered through another.

Mr. Baran’s invention was so far ahead of its time that in the mid-1960s, when he approached AT&T with the idea to build his proposed network, the company insisted it would not work and refused.

Publié dans Liens, News | Marqué avec , , , , | Laisser un commentaire

Petit retour sur php

Rappel sur les quotes

Code php :

<?php
  $bob = 'toto';
  echo '<p>titi</p>\n';
  echo '<p>$bob</p>\n';
  echo "<p>$bob</p>";
?>

Code html produit :

<p>titi</p>
<p>$bob</p>
<p>toto</p>

Traitement des <input type="checkbox" />

Le code html :

  <form action="checkbox.php" method="get">
  <p>
    <input type="checkbox"
       id="check_entree"
       name="plats[]"
       value="entree"
       />
    <label for="check_entree">entrée</label>
    <!-- idem pour plat et dessert -->
  </p>
  <p>
    <input type="submit" value="envoyer" />
  </p>
  </form>

Notez bien les crochets dans l’attribut name.

Pour le traitement en php,
la fonction liste_plats, définie par exemple dans le head de checkbox.php :

<?php
function liste_plats()
{
   $res = '<ul>';
   foreach($_REQUEST['plats'] as $plat)
     $res .= "<li>$plat</li>\n";
   return $res . '</ul>';
}
?>

Le traitement lui-même, dans le body :

<?php
   if(isSet($_REQUEST['plats']))
     echo liste_plats();
   else
     echo '<p>ben vous mangez rien ?</p>'
?>

Voir le résultat : checkbox.html

Publié dans Cours | Marqué avec , , , , , , , | 4 commentaires

Server attention span [xkcd]

xkcd server smartphone
xkcd.com/869

Publié dans Liens | Marqué avec , , , , | Laisser un commentaire

Le partiel

Le partiel aura lieu vendredi 4 mars, dans l’amphi du cours (1A)

Contrairement à ce qui avait été annoncé, il n’y aura que 2 sessions, mais la durée est bien de 20 minutes pour chaque session. La répartition des étudiants est la suivante, selon la première lettre du nom de famille :

de A à J
14h30
de K à Z
15h

Seuls documents autorisés : une feuille A4 recto-verso, contenant ce que vous voulez, sous la forme que vous voulez, à usage individuel.

L’utilisation d’un téléphone pour quelque raison que ce soit entraînera l’exclusion de l’épreuve. (Pensez à apporter une montre).

Mise à jour du 4 mars au matin

Copier-coller de l’en-tête des sujets :

Mode d’emploi du QCM.
Vous répondrez sur la feuille (en cochant les cases correspondantes, ou en entourant les bonnes réponses, ou en barrant les mauvaises). Chaque question vaut 1 point, une réponse fausse entraîne 1/2 point de pénalité. Pour les questions ayant plusieurs réponses justes, il faut les sélectionner toutes pour gagner le point (pas de pénalité pour une réponse juste mais incomplète).

Pour les deux dernières questions, vous pouvez répondre directement sur le sujet, ou sur votre copie. Elles valent 6 points chacune.

Publié dans Cours, Non classé | Marqué avec , | Laisser un commentaire