Gestion des Cookies dans un ensemble de pages JSP avec @include

J’ai rencontré pas mal de problèmes avec les JSP est les cookies, ces derniers sont assez utile pour laisser quelques traces et configuration sur le client de l’internaute qui peuvent être utiles pour l’optimisation de la navigation sur un site ou pour la suivi des statistiques.
Lors de l’intégration dans un contexte JSP utilisant des includes, il y a pas mal de petites règles à respecter pour que cela fonctionne sans quoi il y a moyen de s’arracher les cheveux !

Ce qu’il faut avoir : les Cookies doivent être envoyé dans l’entête de la réponse. Lorsque les pages générées sont de taille importante, le seveur d’application peut envoyer la page par morceaux dès qu’il y a suffisemment de données pretes. Du coup, si l’ajout du cookie est fait après le premier flush, il ne sera pas pris en compte. Il est donc important que les Cookie soient placés suffisemment tot dans la page pour éviter le flush.
Dans un contexte d’utilisation avec des include de JSP, il faut savoir en plus que le tag jsp:include a tendance à déclencher des flush (ce qui me semble étange puisque le fulsh peut être passé en option et que par défaut il ne l’est pas). Du coup, si le cookie est enregistré par une sous JSP, il ne sera pas pris en compte par le navigateur ; arrivant trop tard. La solution dans ce cas est d’utiliser un tage @include à la place du jsp:include, mais attention son utilisation est très différente puisque dans ce cas il s’agit de l’import du source importé avant la compilaton de la JSP et non de l’appèle à une autre JSP. Ce qui peut poser des problème si la modification est faite à postérieuri.

Bref, ma solution dans ce cas, réunir dans un fichier d’entête toutes les opération intervenant sur les Cookies et intégrer cette page au travers d’un @include dans toutes les pages du site en entête. L’utilisation généralisée du @include etant à proscrire à mon avis.

Option de cache des objets statiques avec apache2

Lorsque l’on modifie le CSS d’un site il est important de rafraichir la page sans quoi celle-ci est affichée avec le CSS ancienne version … résultats déplorables garantis !

Pour contourner celà, il est tout à fait possible de forcer un rafraichissement plus régulier de certains éléments comme les feuilles de style. Pour se faire, il faut ajouter à la config d’Apache quelques lignes que voici :

ExpiresActive On
ExpiresDefault “access plus 1 hours”
ExpiresByType text/css “access plus 1 hours”
ExpiresByType text/html “access plus 1 hours”
ExpiresByType image/gif “access plus 1 days”
ExpiresByType image/jpeg “access plus 1 days”
ExpiresByType image/png “access plus 1 days”

Bien sûr  il y a différentes façon de faire, et le paramétrage est à votre guise…
Attention toute fois, si l’on suit le modèle ci-dessus, les pages dynamiques (jsp, php) seront cachées elles-aussi ce qui peut vous poser des problèmes de raffrachissement ! Elles sont en effet identifiées sous le type text/html.
Une autre configuration peut être : ExpiresActive On
ExpiresDefault “access plus 1 hours”
ExpiresByType text/css “access plus 1 hours”
ExpiresByType text/html “now”
ExpiresByType image/gif “access plus 1 days”
ExpiresByType image/jpeg “access plus 1 days”
ExpiresByType image/png “access plus 1 days”

Des listes modifiables par drag & drop

Une des grosse fonctionnalité d’Ajax est d’offrir une interface dynamique de type client lourd dans un navigateur, nous avons déjà parlé de la communication en tâche de fond qui est le coeur d’Ajax, mais ce qui se passe au niveau du front end est tout aussi important. De nombreux site utilise cette technique de drag & drop pour permettre aux utilisateur de composer eux-même leur interface à leur gout. La première implémentation que nous avons pu en voir il y a quelque années était ici ; depuis les choses ont évoluées …

L’occasion de ce petit billet est un article décrivant en détail le fonctionnement de cette technique en liaison avec un base de donnée. Ce tutoriel pour php est plutôt bien fait, reprenant point par point la liaison à la base de donnée, l’utilisation des css et enfin les fonctions javascript de manipulation et  drag & drop. L’article sur les listes triées dynamiques avec ajax.

Pour ceux qui en outre souhaiterai voir une implémentation plus complète, vous trouverez un bon exemple sur Auverblog.info

Patch du driver rt2570 pour permettre le changement d’adresse MAC

Note : depuis mon patch à été ajouté directement dans les drivers natif …

Le drivers rt2570, correspondant aux chip USB ralink souffre d’un petit bug, à moins qu’il ne s’agisse d’une fonctionnalité, je ne sais pas ! il n’est pas possible de changer leur adresse MAC.

Après analyse du problème, il s’avère que lorsque l’on remonte le driver par un ifconfig rausb0 up celui-ci effectue une réinitialisation complète du périphérique incluant donc le rechargement de l’adresse MAC d’origine et venant donc écraser celle configurée précédemment par le ifconfig rausb0 hw ether ….

La solution a ce problème est assez simple, lors de l’init que l’on trouve dans rtusb_main.c il suffit de tester si l’adresse MAC du net_dev vaut 00, auquel cas on charge celle de la carte (premier appel) sinon, on conserve la valeur du net_dev qui correspond à celle forcée.
Ce qui se traduit par :

Dans la fonction usb_rtusb_open, ligne 1231 environ
RTUSBCmd_kill =0;
CreateThreads(net_dev);
memcpy(pAdapter->net->dev_addr, pAdapter->CurrentAddress, pAdapter->net->addr_len);
// Clear Reset Flag before starting receiving/transmitting
RTMP_CLEAR_FLAG(pAdapter, fRTMP_ADAPTER_RESET_IN_PROGRESS);

Va devenir:

RTUSBCmd_kill =0;
CreateThreads(net_dev);
// at every open handler, copy mac address.
// PATCH >>>>>>>>>>>>>>>>>>
if ( net_dev->dev_addr[0] == 0 && net_dev->dev_addr[1] == 0 && net_dev->dev_addr[2] == 0 &&
net_dev->dev_addr[3] == 0 && net_dev->dev_addr[4] == 0 && net_dev->dev_addr[5] == 0 ) {
// First time initialization
memcpy(pAdapter->net->dev_addr, pAdapter->CurrentAddress, pAdapter->net->addr_len);
} else {
// Next time “la vérité est ailleurs!”
memcpy(pAdapter->CurrentAddress, pAdapter->net->dev_addr, pAdapter->net->addr_len);
}
// <<<<<<<<<<<<<<<<< PATCH

// Clear Reset Flag before starting receiving/transmitting
RTMP_CLEAR_FLAG(pAdapter, fRTMP_ADAPTER_RESET_IN_PROGRESS);

Après on recompile, et la solution a l’air de fonctionner …. ??? et bien en fait non elle ne fonctionne pas !! oups.. j’aurais dû un peu plus tester … j’avais un petit oubli … voila qui est corrigé ! merci à larbig d’avoir complété le boulo.
Il semble en effet que l’adresse MAC doit être la même entre le pAdapter et le net_dev sans quoi les trames ne sont pas emises dans l’air … ennuyeux. voici donc le patch complet et cette fois testé !! sisi !! Les modifications sont cette fois dans rtusb_init.c où il faut modifier la fonction NICReadEEPROMParameters de la façon suivante :

VOID    NICReadEEPROMParameters(
        IN      PRT2570ADAPTER  pAdapter)
{
        USHORT                  i;
        int                     value;
        UCHAR                   TmpPhy;
        EEPROM_TX_PWR_STRUC     Power;
        EEPROM_ANTENNA_STRUC    Antenna;//blue
//      EEPROM_VERSION_STRUC    Version;

        DBGPRINT(RT_DEBUG_TRACE,"--> NICReadEEPROMParameters ");

        //Read MAC address.
        RTUSBReadEEPROM(pAdapter, EEPROM_MAC_ADDRESS_BASE_OFFSET, pAdapter->PermanentAddress, ETH_LENGTH_OF_ADDRESS);
        DBGPRINT_RAW(RT_DEBUG_TRACE,"MAC address ReadEEPROM : ");
        for (i = 0; i < ETH_LENGTH_OF_ADDRESS; i++)
                DBGPRINT_RAW(RT_DEBUG_TRACE,"%02x ", pAdapter->PermanentAddress[i]);
        DBGPRINT_RAW(RT_DEBUG_TRACE," ");

        if (pAdapter->PortCfg.bLocalAdminMAC != TRUE)
        {
                pAdapter->CurrentAddress[0] = pAdapter->PermanentAddress[0];
                pAdapter->CurrentAddress[1] = pAdapter->PermanentAddress[1];
                pAdapter->CurrentAddress[2] = pAdapter->PermanentAddress[2];
                pAdapter->CurrentAddress[3] = pAdapter->PermanentAddress[3];
                pAdapter->CurrentAddress[4] = pAdapter->PermanentAddress[4];
                pAdapter->CurrentAddress[5] = pAdapter->PermanentAddress[5];
        }

devient

VOID    NICReadEEPROMParameters(
        IN      PRT2570ADAPTER  pAdapter, struct net_device *net_dev)
{
        USHORT                  i;
        int                     value;
        UCHAR                   TmpPhy;
        EEPROM_TX_PWR_STRUC     Power;
        EEPROM_ANTENNA_STRUC    Antenna;//blue
//      EEPROM_VERSION_STRUC    Version;

        DBGPRINT(RT_DEBUG_TRACE,"--> NICReadEEPROMParameters ");

        //Read MAC address.
        RTUSBReadEEPROM(pAdapter, EEPROM_MAC_ADDRESS_BASE_OFFSET, pAdapter->PermanentAddress, ETH_LENGTH_OF_ADDRESS);
        DBGPRINT_RAW(RT_DEBUG_TRACE,"MAC address ReadEEPROM :");
        for (i = 0; i < ETH_LENGTH_OF_ADDRESS; i++)
                DBGPRINT_RAW(RT_DEBUG_TRACE,"%02x ", pAdapter->PermanentAddress[i]);
        DBGPRINT_RAW(RT_DEBUG_TRACE,"");

        if (pAdapter->PortCfg.bLocalAdminMAC != TRUE)
        {

           if ( net_dev->dev_addr[0] == 0 && net_dev->dev_addr[1] == 0 && net_dev->dev_addr[2] == 0 &&
             net_dev->dev_addr[3] == 0 && net_dev->dev_addr[4] == 0 && net_dev->dev_addr[5] == 0    ) {
                // Startup time ... read the original MAC
                pAdapter->CurrentAddress[0] = pAdapter->PermanentAddress[0];
                pAdapter->CurrentAddress[1] = pAdapter->PermanentAddress[1];
                pAdapter->CurrentAddress[2] = pAdapter->PermanentAddress[2];
                pAdapter->CurrentAddress[3] = pAdapter->PermanentAddress[3];
                pAdapter->CurrentAddress[4] = pAdapter->PermanentAddress[4];
                pAdapter->CurrentAddress[5] = pAdapter->PermanentAddress[5];
           } else {
                // Next time, get the MAC from net_dev->dev_addr
                printk(KERN_INFO "net_dev supplies MAC, activating this one :%02x:%02x:%02x:%02x:%02x:%02x.",
                        net_dev->dev_addr[0], net_dev->dev_addr[1], net_dev->dev_addr[2],
                        net_dev->dev_addr[3], net_dev->dev_addr[4], net_dev->dev_addr[5]);
                memcpy(pAdapter->CurrentAddress, pAdapter->net->dev_addr, pAdapter->net->addr_len);
           }
        }

La mécanique est axactement la même que celle faite précédemment : lors du premier appel on fait comme si de rien n’etait et on recupère l’adresse en EEPROM, pour les appels suivant on choisit la MAC du net_dev à la place.
Pour que ca fonctionne il reste deux petites modifications, modifier le header de cette fonction : dans rt2570sw.h

VOID  NICReadEEPROMParameters(
      IN  PRT2570ADAPTER       pAdapter);

devient :

VOID  NICReadEEPROMParameters(
      IN  PRT2570ADAPTER       pAdapter, 
      struct net_device *net_dev);

enfin il reste l’appel de la fonction de lecture à modifier, dans rtusb_main.c:

   NICReadEEPROMParameters(pAdapter, net_dev);

Ca y est !!

Taille maximum d’un fichier en PHP

Par défaut la taille maximale d’un fichier uploadé depuis PHP est fixée à 2Mo, Pour augmenter cette taille, il faut modifier le fichier /etc/php.ini et indiquer la nouvelle taille en renseignant la variable upload_max_filesize. La taille peut être indiquée en Méga : = 10M par exemple.

Configuration impression avec mozilla et KDE

Comme il arrive que l’impression par défaut configurée par Mozilla déconne un peu, il est possible d’utiliser l’impression KDE.
Pour ce faire, afficher l’écran de propriété de l’imprimante sous Mozilla (après avoir obtenu la fenetre d’envoie d’un impression) puis remplacer la ligne lpr ${MOZ_PRINTER_NAME … par kprinter –stdin

Parsing XML à l’aide de la commande sed

Suite un petit problème pour traiter une flux xml avec sed, je vous livre une solution …
Le problème est le suivant : lorsque l’on a une suite de champs que l’on souhaite remplacer comme suite: (le < > sont remplacés par % pour simplifier l’ecriture de l’article)
de:
%tag1% valeur1 %etag1% %tag1% valeur2 %etag1%
à:
valeur1 valeur2

On pourrait avoir l’approche suivante :
sed -e ‘s/%tag1%(.*)%etag1%/1/g’
Mais le résultat est le suivant:
valeur1 %etag1% %tag1% valeur2

En effet, sed va matcher la plus longue pattern possible ce qui va donner le résultat précédent. Ce qui évidemment n’est pas adapté au traitement de flux XML. La solution est de ne pas utiliser sed mais perl qui va prendre, elle, la plus petite pattern possible pour peu qu’on le lui precise de la façon suivante:
perl -p -e ‘s/%tag1%(.*?)%etag1%/1/g’
Le résultat sera alors:
valeur1 valeur2
C’est l’ajout du “?” à la suite de .* qui précise que perl doit chercher le motif le plus court.