Comment créer sa webapp ?

Il y a deux cas de figure : soit la webapp a besoin d’une base de donnée pour fonctionner soit non. On va donc commencer par le plus compliqué happy smiley à partir d’un cas concret qui nécessite l’utilisation d’une base de donnée : le moteur de blog DotClear

Il faut compter environ 2H la première fois qu’on prépare une webapp, mais une fois qu’on l’a fait, 20 à 30mn suffisent ensuite. C’est relativement simple si on connait déjà un peu comment fonctionne la webapp qu’on veut portabiliser.

Je vous conseille (voir je vous impose !) la lecture de la FAQ avant de poursuivre, car les informations sur les fichiers de configurations qui y sont données ne seront pas répétées ici !

Webapp avec base de donnée

Préparation

Comme en cuisine, il nous faut quelques ingrédients.
Donc, on va commencer en partant du modèle de webapp qui contient le strict minimum pour construire sa webapp portable. Fermez d’abord toutes les webapps qui pourraient être lancées.

Téléchargeons Webapps Template Portable. Téléchargeons aussi la dernière version .zip de Dotclear. Dézippons ces deux fichiers dans 2 dossiers différents.

C’est parti !

Faites une copie du dossier WebAppPortable et renommez-le en DotclearPortable (l’autre dossier servira dans la suite du tutoriel).
Dans ce dossier, renommez le fichier WebAppPortable.exe en DotclearPortable.exe (on s’occupera de l’icône plus tard)

Bien, normalement, si vous double-cliquez sur DotclearPortable.exe, que se passe-t-il ?

Je résume à gros traits avant de rentrer dans les détails.

1. DotclearPortable.exe va lancer Others/Framakey-WebAppManager/Framakey-WebAppManager.exe (que je vais appeler “WAM” ou “le Manager” dans le reste de ce tutoriel).
2. WAM va charger son fichier de configuration situé dans Others/Framakey-WebAppManager/Framakey-WebAppManager.ini
3. WAM va charger le fichier de configuration de la webapp situé dans App/AppInfo/appinfo.ini
4. WAM va charger et générer les menus des scripts génériques Others/Framakey-WebAppManager/scripts.generic.ini et des scripts spécifiques App/AppInfo/scripts.ini
5. WAM va lancer le serveur web (ZMWS) et le gestionnaire de base de données (MySQL)
6. WAM va exécuter le script de démarrage, situé dans App/AppInfo/startup.ini, qui va notamment servir à indiquer à l’application quel sont les ports utilisés.

Voilà dans les grandes lignes. Pour ceux qui n’auraient pas suivis, on a donc 2 dossiers clés :

  • Others/Framakey-WebAppManager/ dans lequel se trouve des informations valables pour toutes les webapps, ou propre à WAM.
  • App/AppInfo/ dans lequel on retrouve les informations spécifiques à la webapp.

Commençons donc par ce dernier dossier.

Un peu de ménage

Le Webapp Template Portable est fourni avec une pseudo application appelé “app” qui sert juste pour l’exemple.

  1. supprimez le dossier App/app/ qui contient l’application.
  2. supprimez le dossier App/data/app/ qui correspond à sa base MySQL
  3. renommez le fichier App/Appinfo/startup.ini en _script.ini pour le désactiver temporairement. Ce fichier correspond au script qui permet au serveur d’attribuer les bons ports web et MySQL lorsqu’il y a plusieurs webapps qui tournent en même temps.

Maintenant, ouvrons App/AppInfo/appinfo.ini
Ce fichier est en effet le plus important. C’est lui qui décrit notre webapp.
Modifions le en :

[Format]
Type=PortableAppsFormat
Version=0.9.14

[Details]
Name=DotclearPortable
AppID=DotclearPortable
Publisher=Framakey.org
Homepage=http://framakey.org/WebApp/DotclearPortable
Category=Webapps Blog
Description=Le moteur de blog qui fait tourner le Framablog ;)
Language=Français

[License]
Shareable=true
OpenSource=true
Freeware=true
CommercialUse=true

[Version]
PackageVersion=2.2.2
DisplayVersion=2.2.2

[Control]
Icons=1
Start=DotclearPortable.exe

[Framakey]
; Cette section contient des information générique à toute les applis portables de la Framakey
Name=DotclearPortable
Repository=Testing
FramasoftPage=
AppWebsite=http://fr.dotclear.org/
License=GNU/GPL
LongDesc=<p>Le moteur de blog qui fait tourner le Framablog ;)<p>
; Date de création de la webapps portable. À n'inscrire qu'une fois la portabilisation terminée
Date=2011/02/26
Dir=DotclearPortable
; Taille du dossier. À n'inscrire qu'une fois la portabilisation terminée
Size=60462867

[WebAppSpecific]
; Important : il s'agit de l'identifiant de l'application. Les espaces sont autorisés, mais à vos risques et périls :P
ShortName=Dotclear
; nom du dossier de la WebApp dans le dossier /App/
ApplicationPath=dotclear
; nom de la base de données
DatabaseName=dotclear

; les champs suivants parlent d'eux mêmes
Website=http://fr.dotclear.org/
Support=http://forum.dotclear.net/
Framasoft=http://www.framasoft.net/article1955.html
FramasoftSupport=http://forum.framasoft.org/viewforum.php?f=134

; chemin relatif du logo qui sera affiché dans le splashcreen
Logo=logo.jpg

Les lignes commençant par “;” sont des commentaires, vous n’êtes pas obligés de les laisser. winking smiley
En réalité, seules les entrées [Version] et [WebAppSpecific] seront utilisées, mais pour une compatibilité avec les autres outils de la Framakey, comme Synapps par exemple, il est préférable de tout remplir.

Nous avons changé le plus important, à savoir les valeurs ShortName, ApplicationPath et DatabaseName.

Dernière étape, copions le dossier dotclear précédemment téléchargé et dézippé dans le dossier App (de façon à obtenir App/dotclear/index.php) et créons le dossier App/data/dotclear pour la base de donnée.

Après le ménage, l’habillage.

Récupérez un logo de Dotclear (les logos sont souvent proposés sur les sites officiels, sinon Google Images ou Wikimedia peuvent donner des résultats intéressants.

Redimensionnez cette image avec Gimp (ou autre), mettez une largeur et une hauteur de 128 pixels, de préférence avec un fond transparent. Enregistrez-là en écrasant App/AppInfo/appicon_128.png, faites de même en ajoutant un fond blanc pour le fichier logo.jpg et en redimensionnant pour les fichiers appicon_64.png (64px), appicon_32.png (32px), appicon_16.png (16px), appicon.ico (16px) et appicon48.ico (48px).

Dans le dossier Other, il y a un utilitaire CreationLanceur.exe qui permet de recréer le lanceur avec l’icône et le nom qui va bien. Lancez-le et allez chercher le fichier appicon48.ico.

Vous y êtes ? Félicitations, la moitié du chemin est faite !

Beta testons tous en choeur

Lancez DotClearPortable.exe.
Vous noterez que dans le splashscreen c’est “Dotclear” ainsi que son logo qui s’affichent, car c’est la variable ShortName qui est utilisée.

Si vous cliquez sur l’icône près de l’horloge (qui devrait maintenant avoir l’icône de Dotclear) et cliquez sur Ouvrir Dotclear, vous devriez tomber sur la page d’installation.

  • Sélectionnez MySQL comme type de base de donnée
  • Remplissez les champs : “Nom d’hôte : localhost”, “Nom de la base de donnée = dotclear” (en minuscules) et “Nom d’utilisateur : root”. Il n’y a pas de mot de passe (il ne va y avoir que la base dotclear dans votre webapp).
  • Validez et…

Paf, une erreur “Mysql Innodb engine not available” (ha ben oui, je portabilise en même temps que je fais le tuto, moi ! :P )

Pourquoi cette erreur ?
Parce que Dotclear a besoin d’une option MySQL (le moteur InnoDB) qui est désactivé par défaut dans les webapps. Mais qu’à cela ne tienne, c’est simple à corriger winking smiley

  • Quittez votre webapp
  • Rendez vous dans Others/Framakey-WebAppManager/Framakey-WebAppManager.ini
  • ajoutez skip-innodb=False sous l’entrée [MySQL] de façon à obtenir
[MYSQL]
port=Auto
skip-innodb=False
  • Redémarrez votre webApp et reprenez la procédure, tout devrait mieux se passer winking smiley
  • finissez l’installation (ici j’ai mis “admin” et “framasoft” comme login/password)

Dotclear va maintenant créer la base et finir l’installation.

Il faut savoir que chaque webapp a ses particularités, certaines vous demanderons d’installer des extensions php, d’autres voudrons qu’on modifie des paramètres dans le php.ini… Bref, si besoin n’hésitez pas à poser des questions sur le forum.

Victoire !?!

Bon, nous avons maintenant un Dotclear fonctionnel. Et ça c’est une bonne nouvelle.

Mais ce n’est pas encore une webapp portable. Par exemple, si je lance Drupal Portable puis Dotclear Portable, Dotclear va toujours croire qu’il doit se lancer à l’adresse 127.0.0.1, port web 80, et port mysql 3306. Or Drupal Portable “squatte” déjà ces deux emplacements.

Il va donc falloir peaufiner notre application pour qu’au démarrage, elle sache se mettre à jour toute seule comme une grande.

Une femme dans chaque port, et un port pour chaque webapp

Sous ce titre ridicule se cache la partie un peu “tricky” (non, pas l’ancien de Massive Attack !) de la portabilisation. Prenez une inspiration ou deux, concentrez vous (Tricky, l’artiste cette fois, est pas mal pour ça), et lançons nous.

Il va falloir demander à WAM d’exécuter à chaque lancement de Dotclear Portable une succession d’instructions de mise à jour.

Il faudra systématiquement adapter :
- le port MySQL (pour Dotclear et Eskuel). Par défaut, c’est 3306.
- le port web (pour que ZMWS “trouve” dotclear). Par défaut, c’est le port 80.
Là, il faut connaitre un peu l’application en question, mais n’importe quel développeur connaissant Dotclear saura vous aiguiller.
Notez que la procédure revient en fait quasi systématiquement :
1. à modifier un (ou plusieurs parfois) fichier de configuration (pour le port MySQL le plus souvent)
2. à adapter une ou deux entrées la base de données pour le port web.

Rassurez-vous, c’est plus simple à faire qu’à expliquer winking smiley

Commençons par le plus simple, le port de Eskuel (Eskuel c’est l’équivalent de PhpMyAdmin en plus léger. Il vous permet de gérer le contenu de la base de données).
Cette partie est indispensable pour toute webapp avec une base de donnée.

  • Arrêtez Dotclear Portable
  • Supprimez le “_” créé précédemment sur le fichier _startup.ini pour qu’il soit de nouveau actif.
  • Ouvrez App/AppInfo/startup.ini avec un éditeur de texte
  • Videz son contenu en ne gardant que cette partie là
[UpdateEskuelPort]
Name=Syncronize Eskuel Port
Description=Update Eskuel config with the Open MySQL Port
Type=REPLACE
File={$root_path_absolute}\ZMWS\_web.zmwsc\_vhosts.zmwsc\127.0.0.2\eskuel\config.inc.php
SearchPattern=127.0.0.1(:\d*)?
ReplaceValue=127.0.0.1:{$mysql_port}

Que dit ce morceau de script ?
“Je crée un nouveau script ‘UpdateEskuelPort’ avec un nom et une description. Ce script est de type ‘REPLACE’, c’est donc un rechercher-remplacer. Il va ouvrir le fichier config.inc.php de Eskuel, chercher la chaine ‘127.0.0.1′ (suivi ou non du signe ‘deux points’ et d’un ou plusieurs chiffres). C’est ce qu’on appelle une expression régulière, et Wikipédia vous renseignera mieux que moi. Ensuite on remplace ce qu’on a trouvé par ‘127.0.0.1:’ suivi du premier port mysql libre qu’on aura trouvé (3306, 3307, 3308, etc).”

Ainsi, à chaque démarrage de Dotclear Portable, le port de l’application Eskuel sera mis à jour.

Si vous voulez savoir à quoi correspondent , et compagnie, lisez la FAQ

Et pour notre Dotclear ?

D’abord, il faut repérer le fichier MySQL ou se fait la connexion à la base de données.
C’est le plus souvent le fichier de configuration principal.
Pour Dotclear, c’est donc : App/dotclear/inc/config.php
Ensuite, on cherche la ligne qui indique l’hôte MySQL.

Pour nous, il s’agit de :

define(‘DC_DBHOST’,’localhost’);

Il faudra donc la remplacer à chaque démarrage par

define(‘DC_DBHOST’,’localhost:XXXX’);

où XXXX sera le numéro de port MySQL.

On va donc ajouter à startup.ini une nouvelle entrée :

[UpdateMySQLPort]
Name=Update Eskuel Port
Description=Update Eskuel config with the Open MySQL Port
Type=REPLACE
File={$root_path_absolute}\App\{$ApplicationPath}\inc\config.php
SearchPattern=define\('DC_DBHOST','localhost(:\d*)?'\);
ReplaceValue=define('DC_DBHOST','localhost:{$mysql_port}');

Notez que dans le motif de recherche on a échappé les caractères spéciaux avec des
Relançons DotClear portable, puis ouvrons config.php. On trouve maintenant la ligne

define(‘DC_DBHOST’,’localhost:3306′);

Magnifique, ça a marché winking smiley

Maintenant, il faut faire la même chose pour le port web.
Pour l’instant, on sait que l’adresse est http://127.0.0.1/dotclear (ce qui correspond en fait à http://127.0.0.1:80/dotclear (80 étant le port web par défaut).
Cependant, si d’autres WebApps sont lancés, on y accèdera peut être par http://127.0.0.1:8080/dotclear ou http://127.0.0.1:8081/dotclear
Il faut donc là aussi indiquer à WAM de mettre à jour le port.

Souvent, cette information se trouve dans la base de données. Pour Dotclear, l’info se trouve en partie dans le même fichier config.php que tout à l’heure. On trouve :

define(‘DC_ADMIN_URL’,’http://127.0.0.1/dotclear/admin/’);

On va donc encore ajouter un script à notre startup.ini

[UpdateWebPort]
Name=Update web Port
Description=Update dotclear config with the open web Port
Type=REPLACE
File={$root_path_absolute}\App\{$ApplicationPath}\inc\config.php
SearchPattern=define\('DC_ADMIN_URL','http://127.0.0.1(:\d*)?/dotclear/admin/'\);
ReplaceValue=define('DC_ADMIN_URL','http://127.0.0.1:{$zmws_port}/dotclear/admin/');

Voilà pour l’admin.

Oui, mais pour les billets ?
Lancez Eskuel (Menu de Dotclear Portable > MySQL > Eskuel).
On voit dans la table “dc_blog” que l’URL du blog est indiquée en dur.

On va donc vouloir executer la requête suivante à chaque démarrage de DotclearPortable :

[UpdateBlogUrlValues]
Name=Update Options table
Description=Update dotclear "blog" table with some real config values
Type=SQL
Query=UPDATE `dc_blog` SET `blog_url`='http://127.0.0.1:{$zmws_port}/dotclear/index.php?' WHERE `blog_status`='1';

Cette dernière entrée dans le fichier startup.ini va donc correspondre à une requête SQL mettant à jour le port Web dans la base de données.

Maintenant, testons tout cela :

  • Quittons DotclearPortable
  • Lançons WebAppsPortable (la copie qu’on a mise de côté)
  • Puis lançons DotclearPortable

Ca marche !

Ha oui, mais non !
Ça va marcher la première fois, mais Dotclear utilisant un (performant) système de cache, ce dernier pourrait nous mettre dans la mouise si le port venait à changer une prochaine fois.

Donc, on va se logguer en administrateur dans dotclear ( http://127.0.0.1:8080/dotclear/admin/ ), et dans le menu de gauche “about:config” passer la valeur “tpl_use_cache” à “no” (à faire dans l’onglet “blog settings” et dans l’onglet “global settings”).

Évidemment, on perdra en performance, mais les WebApps ne sont pas destinées à être utilisée en production avec des milliers de visiteurs par jour. Donc s’il s’agit d’un blog en construction, désactiver le cache sera plutôt un avantage.

Voilà !

Finalisation

Les petits trucs à faire avant de mettre en ligne la webapp :

  • créez le fichier de restauration de la base de donnée : faites un export de la base de donnée et renommer le fichier .sql obtenu dans le dossier AppInfo en master.sql.
  • faites une capture d’écran pour remplacer les fichiers screenshot.png et screenshot_128.png
  • modifiez la page help.fr.html
  • modifiez la date de création de la webapp et la taille de l’archive dans le fichier appinfo.ini

Enfin, modifiez le fichier script.ini. Le fichier donné en exemple contient les scripts spécifiques à la webapp qui peuvent être intéressant à mettre en place mais qui restent optionnels. Vous pouvez effacer/modifier tout ou partie de ce fichier selon les besoins et vos compétences.
La partie [ResetLogPass] sert à réinitialiser le compte principal (identifiant/mot de passe). Pour la créer il suffit de lire le fichier master.sql et de copier la requête qui génère le compte.
La partie [Synchronize] est une simple reprise de ce qui a été mis dans le startup.ini pour mettre à jour le port MySQL
La partie [EditAdmin] sert à modifier le fichier de configuration de la webapp (pour Dotclear le fichier inc/config.php)
La partie [OpenAdmin] sert à ouvrir la page d’administration de la webapp.
Vous êtes évidemment libre d’ajouter d’autres fonctionnalités. Consultez la FAQ pour en savoir plus.
Les fichiers startup.ini et scripts.ini sont disponibles en ligne sur les pages de téléchargement des webapps ce qui permet de s’en inspirer et de les améliorer collectivement.

Webapp sans base de donnée

Pour les webapps sans base de donnée, la première chose à faire c’est d’ajouter, dans le fichier appinfo.ini, la ligne :

NeedMySQL=False

(par rapport au Webapp Template Portable il suffit d’enlever le “;” devant).
Ensuite, c’est la même chose que précédemment sauf qu’on peut faire davantage le ménage :

  • supprimez les dossiers App/data, ZMWS/HeidiSQL, ZMWS/mysql et ZMWS\_web.zmwsc\_vhosts.zmwsc\127.0.0.2
  • dans les fichiers App/AppInfo/startup.ini, App/AppInfo/scripts.ini et ‘’Other/Framakey-WebAppManager/scripts.generic.ini

‘’ tout ce qui à trait à MySQL peut être enlevés (en gros il ne doit pas y avoir de section contenant la variable ni de requête “Type=SQL” à exécuter).

Voilà ! C’est tout.