Mots-clé : web

Exemple : cocktails

Pour avoir la moyenne

Lorsqu’on vient sur le site :

  • Si on n’est pas connecté, afficher le formulaire de connexion
  • Si on est connecté :
    • Appel AJAX #1 : aller demander la liste des cocktails et l’afficher
    • Appel AJAX #2 : lorsqu’on clique sur un cocktail, aller chercher le détail de ce cocktail et l’afficher

Pour dépasser un peu la moyenne

  • Formulaire de connexion
  • Gestion des erreurs / avertissements de base (avertissement si mot de passe trop court, erreur si login existant etc)

Pour dépasser largement moyenne

Possibilité de créer des cocktails


Créer un ingrédient

Appel AJAX simple à faire, nous l’avons vu en cours : envoi d’un formulaire :


Créer une unité

Appel AJAX simple à faire, nous l’avons vu en cours : envoi d’un formulaire :


Créer un cocktail

Le seul appel AJAX complexe à faire, voici l’interface utilisateur, à vous d’écrire le code JavaScript qui va derrière :

Pour avoir la note maximale

  • Ecrire tout correctement, parfaitement indenté (tous les éditeurs modernes vous font l’indentation automatique, servez-vous en !)
  • Tout écrire sous forme de classe (dans le cas de ce projet Cocktails, classe Ingredient, classe Unite, etc)
  • Tout séparer dans des fichiers selon cette organisation : un fichier JavaScript par classe, le nom du fichier = le nom de la classe en minuscule (dans le cas de ce projet Cocktails, classe ingredient.js, classe unite.js, etc)
  • Ecriture complète en ECMA6(plus de var, que des let, fonctions de la forme () = >{} etc)
  • Callbacks avancés avec gestion des closures

Django : Not naive datetime (blah) (tzinfo is already set)

Django a une manière de gérer la date et l’heure de façon très pratique… encore faut-il la comprendre !

Il y a la date et l’heure qui prend en compte le fuseau horaire.
Imaginez qu’un type en Chine envoie une date et une heure avec le fuseau horaire de Chine sur votre serveur, via un formulaire Web.
Le plus pratique est donc d’enregistrer au format UTC = 0 décalage horaire en se souvenant que l’heure est basée sur le fuseau de Chine.
Comme ça, si un Français demande cette heure, hop, il voit que c’est pour un fuseau +1 (ou +2 selon la saison) et fait le calcul tout seul.
Génial non ?

Seule chose à laquelle il faut faire attention : Python a son package datetime, et il y a une fonction now() qui n’est pas la même que la fonction now() de Django !

Donc si vous voulez enregistrer une date « style Django », il faut faire cet import :

from django.utils.timezone import now

Ensuite, vous pourrez, par exemple, faire des différences de secondes qui fonctionneront :
def is_expired(self, nb_seconds):
    return (now()-self.date_last_update).total_seconds() > nb_seconds

(Attention au code précédent : deux choses : le now() qui doit être importé comme je l’ai dit, et total_seconds() auquel il faut faire attention, car il y a une propriété seconds qui ne fait pas du tout la même chose….)

et surtout ne pas faire from datetime import datetime

Si vous faites comme moi et faites le mauvais import, l’heure ne sera pas « recentrée » à fuseau + 0 afin que tout le monde puisse la lire !

Django et authomatic : comment s’enregistrer en un click

Les étapes à faire

Installer :

  • Python 2.7 maximum car google ne fournit des sources Python que pour la 2.7
  • Django (version en cours = 1.8)
  • Et puis ce qui n’est pas précisé avec authomatic :
    • Installer defusedxml
    • Installer google app engine (faut le chercher sur le site de google)
    • Installer Python openid
  • Installer enfin authomatic

Personnellement j’ai crée un dossier que j’ai appelé third_party.
Ce qui fait que mon arborescence est comme cela :

.
├── locale
│   ├── en
│   ├── fr
│   └── sv
├── produits
│   ├── migrations
│   └── templatetags
├── pyweb
├── static
│   ├── css
│   ├── fonts
│   ├── images
│   ├── js
│   └── produits
├── templates
│   └── produits
└── third_party
   ├── authomatic_0_1_0
   ├── defusedxml-0.4.1
   ├── google_appengine_1_9_25
   └── python-openid_2_2_5

Enfin, les associations dans authomatic :

Dans Facebook il faudra aller dans le coin des développeurs, et créer une application jusqu’à arriver à un écran comme celui-ci :
Informations facebook

Même chose pour gmail :
Informations gmail

Et enfin la relation dans le code :
Code dans authomatic

Pour terminer : Facebook ne renvoyait pas les emails, lorsqu’on s’authentifiait.
C’est un bogue connu depuis que Facebook a modifié son API très récemment.
La solution est ici : editez votre fichier \authomatic\providers\oauth2.py.

Allez à la classe Facebook.
Copiez-collez ce code, qui ne change presque rien (je vous laisse chercher) sauf l’URL user_info_url qui a été modifiée pour la v2.4 : et voilà, il ne vous reste plus qu’à suivre le tutoriel de authomatic avec Django, qui est assez bien fait, et tout devrait fonctionner !

class Facebook(OAuth2):
    """
    Facebook |oauth2| provider.
    
    * Dashboard: https://developers.facebook.com/apps
    * Docs: http://developers.facebook.com/docs/howtos/login/server-side-login/
    * API reference: http://developers.facebook.com/docs/reference/api/
    * API explorer: http://developers.facebook.com/tools/explorer

    Supported :class:`.User` properties:

    * city
    * country
    * email
    * first_name
    * gender
    * id
    * last_name
    * link
    * locale
    * location
    * name
    * picture
    * timezone
    * username

    Unsupported :class:`.User` properties:

    * birth_date
    * nickname
    * phone
    * postal_code

    """
    user_authorization_url = 'https://www.facebook.com/dialog/oauth'
    access_token_url = 'https://graph.facebook.com/oauth/access_token'
    # Correction merci à miohtama :
    # https://github.com/peterhudec/authomatic/issues/112
    user_info_url = 'https://graph.facebook.com/me?fields=' \
                    'id,email,name,first_name,last_name,address,gender,' \
                    'hometown,link,timezone,verified,website,locale,languages'
    user_info_scope = ['email', 'user_about_me', 'user_birthday',
                       'user_location']

lua : avantages et inconvénients

Résumé

Je viens de créer ma première application Web en lua.

Pour ceux qui ne savent pas ce que c’est : google est votre ami, mais pour résumer :

Je commence par les inconvénients parce qu’ils sont tellement particuliers qu’il faut les avoir en tête avant d’aller plus loin. Si jamais ça ne vous rebute pas trop, lisez les avantages et ce sera à vous de juger, si, en mettant le tout sur votre balance, ça penche plus vers le positif ou vers le négatif.

En résumé, tous les avantages qui suivent font que, même s’il faut pas mal se débrouiller au début parce qu’il manque beaucoup d’outils « déjà faits », au final le langage est tellement lisible qu’on arrive assez rapidement à se faire ses outils, et en allant un peu plus loin, la maintenance (qui est la chose la plus coûteuse sur les grosses applications) se retrouve améliorée au lieu d’être dégradée. Après, c’est un constat qui n’engage que moi, mais de très grosses applications, notamment nmap tournent d’ores et déjà avec une liste faramineuse de plugins, tous écrits en lua, et facilement compréhensibles.

Inconvénients

Voici les inconvénients de base, qui ne sont pas propres au langage :

  • il faut tout faire soi-même :
    • aucune gestion avancée des fichiers (de base, sans aucun module complémentaire, il ne sait même pas dire si un fichier existe ou pas)
    • côté Web, aucune gestion des sessions
    • côté Web, rien de base en ce qui concerne le json (j’ai plus d’une demi journée à chercher une implémentation entièrement potable de json)

Voici les inconvénients du langage même :

  • Il ne connait pas les classes d’origine, il faut faire un hack pour « simuler » des classes
  • Par conséquence, il n’y a aucune notion d’héritage, à moins de hacker là aussi.
  • Tous les entiers sont des flottants par défaut
  • Aucune possibilité de trace simple. Si on veut remonter dans la pile d’appels, on ne peut sortir qu’une seule ligne (on précise le niveau de la pile)
  • Toutes les variables sont globales par défaut, sauf si on précise systématiquement local
  • La syntaxe permet des horreurs innommables : si jamais on ne passe qu’un seul paramètre, les parenthèses ne sont pas obligatoires, ce qui donne quelque chose de possible comme : mafonction{a=12,b=13}
  • Les séparateurs ne sont pas clairement définis – et c’est volontaire pour permettre plus de liberté, donc on peut écrire ceci : local a = { b=15; c=23 } ou ceci : local a = { b=15, c=23 }. Imaginez le problème… On voit déjà qu’en Php, en laissant un peu de liberté, on arrive à un bazar gigantesque à l’échelle planétaire, je vous raconte même pas ce qu’il est possible de faire ici
  • Les packages en tant que tel n’existent pas, et il faut là aussi faire des bidouilles pour « simuler » des packages
  • Il y a ici aussi, comme en JavaScript, la notion de « closure » afin de pouvoir faire sortir des variables hors d’un contexte d’où elles ne sont pas censées sortir. Certains voient les closures comme un avantage, moi qui ait programmé en C – et un peu en C++ – je vois les closures comme une solution pour pallier à un défaut du langage, en bidouillant.
  • Le signe différent n’existe pas sous la forme classique <> ou encore != mais il s’écrit ainsi : ~=
  • Pour supprimer une variable (unset() en Php), il faut la mettre à nil. Bizarre. Supprimer l’indice 12 : a[12] = nil
  • Attention tenez vous bien j’ai gardé le pire pour la fin : les indices des tableaux commencent à 1. Ce n’est pas une blague. En C, C++, Java, JavaScript, Python, bref, dans tous les langages que je connais, les indices de tableau commencent à 0, et là non, ils commencent à 1. C’est à la limite la seule et unique chose qui me rebute énormément tellement c’est problématique, car, de plus, une des grosses forces mises en avant du lua, c’est le fait qu’il gère extrêmement bien les tables. Oui, mais les indices des tableaux commencent à 1.

Avantages

Je ne sais pas pourquoi, mais lua me plaît. Et je pense que tous les développeurs qui aiment bien ce langage sont un peu comme moi. Il a énormément d’inconvénients, pourtant il des côtés tellement pratiques qu’au final, on l’aime bien. Un peu comme moi (…).

Parmi les avantages que j’apprécie particulièrement :

  • Pas d’accolades ouvrantes / fermantes, mais juste le début d’une déclaration (function, if, ou for), et la fin avec un end. C’est juste plus lisible qu’ouvrir des accolades et fermer des accolades (et croyez moi, je m’y connais bien dans ce domaine !)
  • Les assignations multiples : il est possible d’assigner plusieurs choses en une seule ligne, et ça reste lisible (j’insiste sur ce dernier point : ça reste lisible). Exemple concret : a, b = b, a;. Ce code va inverser les deux valeurs.
  • Même chose que précédemment mais pour les fonctions : elles peuvent renvoyer plusieurs valeurs, et par là même, on peut faire plusieurs assignations et ça reste lisible. Exemple simple : x, y = getCoordonneesJoueur(); ou plus classique handle, error = ouvrirFichier(nomfichier). Avec ce dernier code, si handle vaut nil alors on affiche error qui est rempli.
  • Machine virtuelle : il tourne systématiquement dans une machine virtuelle, ce qui implique par là même une impossibilité technique de défaillance, et c’est vous-même qui précisez, pour les modules qui tourneront, quelles sont les fonctions sont accessibles – ou pas. Si la NASA se sert activement de LUA ce n’est pas pour rien. Ce qui me permet d’enchaîner sur le point suivant.
  • Un des gros intérêts est de pouvoir créer des plugins, les lire et les interpréter, un peu comme en Php, eval(). Comme ces plugins sont dans une machine virtuelle très stable et éprouvée, vous pouvez mettre en place un système de plugins très performant, efficace et stable. Rien que le fait de pouvoir faire cela peut être une motivation pour apprendre le lua, car il y a très peu de langages qui tournent de manière aussi sécurisée, et aussi rapidement que lua (voire aucun).

Le tag <blink> : il est né à partir d’une bonne cuite. Histoire vraie.

Vous ne me croiriez pas si j’étais le seul à le dire, mais le tag blink qui fait clignoter le texte de manière affreuse et agressive, est né d’une grosse fête entre ingénieurs, qui, bien échaudés par quelques verres, se sont marrés en pensant à une idée stupide.

L’histoire tout en langue de Shakespeare ici.

Activemq : principe de messagerie interne producteur / consommateur

J’ai eu un besoin que je pensais assez particulier, mais qui, en fait, dans certains cas, semble tellement récurrent que beaucoup de choses ont déjà été faites dans ce sens.
Mon besoin est simple :

J’ai un site distant qui est d’accord pour qu’on l’interroge en lui demandant des informations sur des Ids, mais pas très souvent : une demande toute les 5 secondes. Par contre, lors de la demande, on peut lui faire passer plein d’Ids (jusqu’à 100 !).

Donc j’ai fait un script Php, lancé à la main, qui tourne en boucle, et qui va interroger ce fameux site, toutes les 5 secondes.
Une fois ce script fait, j’ai besoin que l’on puisse préciser « à la main » les Ids. Je fais donc un site Internet, et je mets à disposition de tout le monde la possibilité d’entrer des Ids « à la main ».

Problème

La demande Internet peut se faire n’importe quand, et il faut que la réponse soit rapide, donc que la demande soit immédiatement inclue dans le « paquet » lors de la prochaine interrogation. De plus, il peut y avoir plein de demandes à la fois. Et elles doivent toutes s’ajouter facilement.

Solutions

Plusieurs solutions sont possibles :

  1. Utiliser une sorte de dossiers « partagés » où d’un côté le Web/Php dépose un fichier avec un Id, et attend dans un autre dossier la réponse comportant le même nom de fichier ; gros problème : ce n’est pas une méthode 100% fiable ;
  2. Faire un serveur interne qui attend des informations, et lorsque son timer tombe, hop, fait la demande. Gros problème : écrire un vrai serveur Web en Php n’est pas une chose facile, et je n’ai pas le temps de faire tout ça ;
  3. Faire une écriture en base de données pour chaque demande Web, et du côté script, faire un simple « SELECT * FROM… WHERE DATE_DEMANDE IS NULL » (ou quelque chose comme ça). Problème bloquant : comment faire pour signaler à chaque demande Web que leur réponse est disponible ?
  4. Dernière solution : utiliser quelque chose qui existe déjà et tourne très bien : un serveur producteur/consommateur (je l’appelle comme ça mais ce n’est pas le vrai nom). Il implémente en gros tout ce que je demande : d’un côté le client qui envoie des messages, et peut – ou pas – attendre un retour de manière bloquante, et de l’autre côté, le serveur qui lit les messages qui arrivent quand il en a envie, et peut leur répondre facilement – quand je dis « facilement », je parle du point de vue du code à faire en Php.

Solution finale

La dernière solution existe, tourne depuis bien longtemps, fait partie de l’association Apache, et a une implémentation en Php, soit tout ce que je veux : cliquez ici pour plus d’informations : http://activemq.apache.org/

Résumé mémo pour mon installation sous Linux (car si je change de serveur j’aurais besoin de me souvenir de ce qui suit !) :

  • apt-get install activemq
  • Ce qui m’a fait perdre beaucoup de temps : la configuration est la même que le principe available/enabled de la configuration du serveur Web Apache, à la différence près qu’une configuration n’est pas un fichier simple, mais un dossier. Il faut donc faire un lien symbolique dans le dossier enabled sur le dossier d’exemple : sudo ln -s ../instances-available/main/
  • Pour le lancer, faire le grand classique et ne pas suivre d’autres suggestions moisies qu’on trouve un peu partout sur le Web. Simplement service activemq start
  • Enfin, installer en Php. Sur Debian, si on enlève le temps de recherche, ça prend deux minutes maximum : pecl install stomp. L’installation de stomp pour activemq va compiler une extension pour Php. Il suffit de l’inclure dans /etc/php.ini (je l’ai ajouté en fin de fichier, ça a parfaitement fonctionné) : extension=stomp.so. Au cas où, n’oubliez pas de redémarrer le serveur Web ! service apache2 restart

Et voilà tout fonctionne ! Le meilleur exemple – et plus parlant – à mon sens se trouve ici. Code très simple et efficace.

Ingesup – Y-nov à terminer après les vacances

Terminer l’appel à la déconnexion en AJAX

$(document).ready(function () {
    $('div[role="navigation"]')
        .find('form')
        .submit(function () {
            $(this).fadeOut(function() {

                $.ajax({
                    url:    $(this).attr('action'),
                    method: $(this).attr('method'),
                    params: $(this).serialize()
                })
                .done(function (data) {
                    if (data.success) {
                        /* montrer le bouton de déconnexion */      
                    } else {
                        /* montrer un message d'erreur (PAS alert) et
                         * remontrer la form de connexion      
                         */
                        
                    }
                })
                .error(function () {
                    alert('Erreur');
                });
            });

            return false;
        });
});

Mots clés de tentatives de hack

Voici tous les mots clés les plus essayés afin de trouver des failles sur mes sites Web 

123flashchat.php 99billdo.php abf_js.php aboutinfo.php
about.php account.php acc.php add.cgi.php
add_link.php addpost_newpoll.php addressbook.php add_rss.php
addsite.php addvip.php ad_main.php adminhead.php
admin.loudmouth.php admin.php agenda2.php3 agenda.php3
ains_main.php ajouter.php akocomments.php annonce.php
announcements.php anzagien.php api.php archive.php
artlist.php athena.php auth.cookie.inc.php authenticate.php
auth.header.inc.php auth.sessions.inc.php auto_check_renewals.php autoindex.php
b2verifauth.php bb_admin.php BE_config.php bild.php
bingoserver.php3 block.php bp_ncom.php bp_news.php
buddy.php builddb.php calcul-page.php calendar.php
cal.func.php cart_content.php cart.php catalogshop.php
challenge.php change_preferences2.php chat.php checkout.php
CheckUpload.php ch_readalso.php circ.php classified.php
classified_right.php class.mysql.php clearinfo.php clear.php
click.php client.php cls_fast_template.php cn_config.php
comments.php common.inc.php common.php config.inc.php
config.inc.php3 config.php configuration.php configuration.php.bak
configuration.php.old confirmUnsubscription.php conf.php connect.php
connexion.php contacts.php content.php convert-date.php
corpo.php CoupleDB.php cp2.php crea.php
create_file.php creat_news_all.php cron.php cross.php
custom_vars.php datei.php debugger.php defaults_setup.php
defines.php depouilg.php3 development.php dfcode.php
dialog.php digg.php direct.php displayCategory.php
display.php dix.php3 dosearch.php download.php
dp_logs.php editor.php edit.php editprofile.php
editsite.php email_subscribe.php environment.php errors.php
es_custom_menu.php es_desp.php eshow.php es_offer.php
eventcal2.php.php event.php eventscroller.php examplefile.php
example.php ezusermanager_pwd_forgott.php faq.php fcring.php
feed.php Flickrclient.php fonctions_racine.php footer.inc.php
footer.php form.php forum.php frame.php
ftp.php function.inc.php function.php functions_mod_user.php
functions.php fusebox5.php galerie.php games.php
genepi.php generate.php gen_m3u.php getpage.php
get_session_vars.php global.php graph.php gruppen.php
header.inc.php header.php head.php hello_sir.php
helperfunction.php help.php help_text_vars.php hioxBannerRotate.php
hioxRandomAd.php hioxstats.php hioxupdate.php home1.php
home2.php home.php hsList.php iframe.php
i_head.php image.php importinfo.php import.php
i_nav.php inc_group.php include.php inc_manager.php
inc_newgroup.php.php inc_smb_conf.php inc_user.php index1.php
index2.php indexinfo.php indexk.php index.php
index.php3 info.php inhalt.php initialize.php
initiate.php init.php in.php install.php
ip.inc.php joinus.php jscript.php latestposts.php
latex.php lib.editor.inc.php libsecure.php license.php
linkadmin.php link_main.php list.php ListRecords.php
loader.php load_lang.php load_phplib.php login.php
login.php3 log.php maguz.php main.inc.php
mainpage.php main.php main_prepend.php mamboleto.php
manage_songs.php master.php mcf.php member.php
members_help.php menu.php menu.php3 middle.php
migrateNE2toNE3.php minica_down.php mini-pub.php mitglieder.php
MOD_forum_fields_parse.php modules.php movie_cls.php msDb.php
mysave.php naboard_pnr.php network_module_selector.php newsadmin.php
newsarchive.php news.php newticket.php noticias.php
nukebrowser.php online.php owimg.php3 page.php
param_editor.php photo_comment.php php121db.php php4you.php
phpCards.header.php phphtml.php php-include-robotsservices.php phpMyChat.php3
phpunity-postcard.php ping.php playlist.php plus.php
p-news.php pollvote.php pop.php popup_window.php
portfolio.php port.php prepare.php prepend.php
preview.php principal.php print.php process.php
profil.php protection.php qte_web.php quickie.php
quick_reply.php random2.php rdf.php reactivate.php
readmore.php read.php recent.php rechnung.php
reconfig.php redirect.php register.php releasenote.php
rempass.php report.php reset.php robotstats.inc.php
rpc.php rss2.php rss.php run.php
s01.php s02.php s03.php s04.php
save.php saveserver.php searchbot.php search.php
search_wA.php self_adherent.php services.php settings.php
settings_sql.php shopping_cart.php shoutbox.php show_archives.php
show.php signin.php sinagb.php sinapis.php
sitemap.xml.php slogin_lib.inc.php smarty.php smilies.php
social_game_play.php song.php source.php spellcheckwindowframeset.php
start.php stats.php stphpapplication.php stphpbtnimage.php
stphpform.php strload.php str.php styles.php
submit_abuse.php submit_comment.php subscp.php tags.php
taxonservice.php template_csv.php template.php themes.php
thumbnail.php timedifference.php toolbar.loudmouth.php toplist.php
top.php track.php ubbt.inc.php unavailable.php
unsubs.php upload_local.php upload_multi.php upload.php
up.php user_language.php user_new_2.php user.php
validate.php viewforum.php view_func.php view.php
viewtopic.php visible_count_inc.php visitor.php volume.php
votebox.php vote.php warn.php war.php
watermark.php window.php worldpay_notify.php wp-cache-phase1.php
wp-config.bak.php wp-config.php wp-config.php.bak wp-config.php.old
wp-login.php wptable-tinymce.php xarg_corner_bottom.php xarg_corner.php
xarg_corner_top.php xmlrpc.php xt_counter.php zipndownload.php