mercredi 23 novembre 2016

Comment centrer verticalement une division dans une autre ?

Avec un code HTML comme suit :

<div class="parent">
<div class="enfant"></div>
</div>


Ecrire le CSS comme suit :

.parent { display: flex; flex-direction: column; justify-content: center; }

La division enfant sera centrée verticalement dans la division parent.

samedi 22 octobre 2016

Trois raisons de ne pas acheter de terminal Android

La biodiversité. Nous avons découvert que la biodiversité était nécessaire pour pérenniser la vie sur la terre. Dans le domaine informatique c'est la même chose : utiliser Android c'est comme manger de la viande élevée de façon intensive, manger le même blé dans le monde entier avec les effets d'intolérance que cela produit. Android équipe plus de 80% des appareils mobiles, il devient donc un mono système ce qui fait craindre une chute en cascade : si un virus touche un terminal tout le reste se cassera la figure.
La qualité. C'est un système permissif, ce qui est embêtant surtout quand il équipe la grande majorité des terminaux du monde. Plusieurs couches logicielles cohabitent, les utilisateurs ne savent pas quel explorateur, quel client mail utiliser, comment configurer leur compte, où stocker les contacts etc. Un nombre impressionnant d'applications inutilisées (à la façon Windows) encombrent le terminal. Bref on a un ordinateur que l'on utilise seulement pour téléphoner et envoyer des SMS.
La pollution. La politique du bas coût a induit des achats en nombre pour des produits très complexes utilisants des ressources rares. Un très grand nombre de terminaux Android sont jetés parce qu’ils ne valent  plus grand chose après une ou deux années de vie. Moins un terminal est acheté cher moins sa durée de vie sera longue.


samedi 8 octobre 2016

Algorithme de tri de date en C#

Dans cet algorithme on compare les valeurs 2 à 2, à chaque fois que l'on réorganise (inversion des valeurs) on recommence la comparaison des valeurs 2 à 2 depuis le début de la liste.

DateTime.Ticks représente une valeur plus facile à comparer.

L'ordre des dates est décroissant, pour inverser l'ordre changer < par > dans la ligne if (dates[i].Ticks < dates[i + 1].Ticks)

int i = 0;
DateTime[] dates = new DateTime[3];
..... affectation des dates dans le tableau ......
while (i < dates.Length - 1)
{
     if (dates[i].Ticks < dates[i + 1].Ticks)
     {
           DateTime memoire = dates[i + 1];
           dates[i + 1] = dates[i];
           dates[i] = memoire;
           i = 0;
      }
      else i++;
}

jeudi 22 septembre 2016

navigator.geolocation ne fonctionne plus sur un site non sécurisé

Depuis la mise à jour de iOS 10, la géolocalisation sur un site web en Javascript ne fonctionne plus pour les sites non sécurisés (non SSL) en http:// seul. Il faut passer à https://.

Rappel de la fonction Javascript :

navigator.geolocation.getCurrentPosition(showLocation, showError, { enableHighAccuracy: true, maximumAge: 600000 });

function showLocation(pos) {
            document.getElementById('position').style.display = 'block';
            var latitude = pos.coords.latitude;
            var longitude = pos.coords.longitude;
......;
}

function showError(err) {
            if (err.code == 1) {
                alert("Error: Access is denied!");
            } else if (err.code == 2) {
                alert("Error: Position is unavailable!");
            }        
}


jeudi 25 août 2016

Requête SQL avec incrément et contrainte

Création d'une table avec un identifiant unique qui s'incrémente automatiquement à chaque ajout (INSERT INTO), ajout de contraintes sur des clés étrangères, ici id_logement et id_saison. Les contraintes peuvent être placées à n'importe quel endroit dans la requête, du moment qu'elles sont entre les parenthèses.


CREATE TABLE tarif (id int IDENTITY(0,1) PRIMARY KEY, id_logement int NOT NULL, CONSTRAINT tarif1 FOREIGN KEY (id_logement) REFERENCES logement (id), id_saison int NOT NULL, CONSTRAINT tarif2 FOREIGN KEY (id_saison) REFERENCES saison (id), prix float, reduction float DEFAULT 0, limite int DEFAULT 1)

lundi 8 août 2016

"Je ne suis pas un robot" ou comment intégrer le reCaptcha de Google dans un site web asp.net

Récupérer les clés reCaptcha de votre site web :

https://www.google.com/recaptcha/

Appuyer sur le bouton Get reCaptcha.

Vous obtiendrez une clé du site, appelée dans la suite laclédusite, et une clé privée, appelée dans la suite lacléprivée.

Dans le fichier .aspx :

Dans le <head></head> :
<script src='https://www.google.com/recaptcha/api.js'></script>

Dans le <body></body> :
<asp:Label ID="captcha" runat="server"></asp:Label>

Dans le fichier .aspx.cs :

using System.Net;

protected void Page_Load(object sender, EventArgs e)

{
        if (!IsPostBack)
        {
               captcha.Text = 
                    "<div align=\"center\" style=\"margin:20px;\">" +
                    "<div class=\"g-recaptcha\" data-sitekey=\"laclédusite\"></div>" +
                    "</div>";
         }
}

A la fin de votre formulaire figure un bouton nommé Button1, dont l'événement OnClick est :

protected void Button1_Click(object sender, EventArgs e)
{
        string userResponse = Request.Params["g-recaptcha-response"];       
        string URI = "https://www.google.com/recaptcha/api/siteverify";
        string myParameters = "secret=lacléprivée&response=" + userResponse;
        using (WebClient wc = new WebClient())
        {
            wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
            string HtmlResult = wc.UploadString(URI, myParameters);
            if (HtmlResult.IndexOf("\"success\": true") > -1)
            {
                     ....... définir ici le traitement à réaliser .........
            }
            else 
            {
                     Response.Write("alert('Vous êtes un robot, nous ne pouvons pas vous fournir le service demandé.');");
            }
       }
}

jeudi 14 juillet 2016

Intégrer le paiement Paypal dans un site web en asp.net C#

Les procédures de connexion au serveur Paypal se sont transformées en 2016, voici une procédure simple utilisant les variables API.


1. Dans l'interface Paypal, générer et récupérer les variables de l'API :

Préférences, Paramètres du compte, Mes ventes, Accès à l'API (mettre à jour), Demander les identifiants API.
Récupérer les variables suivantes : UserAPI, PwdAPI, SignatureAPI, toutes trois précédées de codes.PAYPAL_ dans le code qui suit.

2. Dans les deux pages asp.net suivantes ajoutez quatre clauses using :

using System.Net;
using System.IO;
using System.Collections.Specialized;
using System.Text;

Dans la page de paiement (ex. paiement.aspx.cs) ajouter ce code (soit dans Page_Load soit dans une autre fonction : Button1_Click) :

string ReturnURL = "http://nomdusite/retour_paiement.aspx"; //adresse complète de redirection en cas de paiement
string CancelURL = ""; //adresse de redirection en cas de défaut de paiement (annulation ou erreur)
string Token = ""; //variable utilisée pour mémoriser le jeton
//Dans l'instruction suivante les variables de l'API sont stockées dans une page de codes nommée codes.cs
//Premier appel au serveur Paypal
StringBuilder postData = new StringBuilder();
postData.Append("METHOD=SetExpressCheckout&");
postData.Append("VERSION=95.0&");
postData.Append("PWD=" + Codes.PAYPAL_PwdAPI + "&");
postData.Append("USER=" + Codes.PAYPAL_UserAPI + "&");
postData.Append("SIGNATURE=" + Codes.PAYPAL_SignatureAPI + "&");
postData.Append("AMT=" + MONTANT.ToString().Replace(",", ".") + "&");
postData.Append("CURRENCYCODE=EUR&");
postData.Append("BRANDNAME=Achat depuis la boutique&");
postData.Append("NOSHIPPING=1&");
postData.Append("SOLUTIONTYPE=sole&");
postData.Append("PAYMENTACTION=Sale&");
postData.Append("RETURNURL=" + ReturnURL + "&");
postData.Append("LANDINGPAGE=billing&");
postData.Append("CANCELURL=" + CancelURL + "&");
WebRequest request = WebRequest.Create("https://api-3t.paypal.com/nvp");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";           
request.ContentLength = postData.ToString().Length;
var sw = new StreamWriter(request.GetRequestStream());
sw.Write(postData.ToString());
sw.Close();
WebResponse response = request.GetResponse();
StreamReader sr = null;
try
{
          //Lecture de la réponse
          sr = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
          Token += sr.ReadToEnd();
}
catch (Exception ex)
{
           Token = "ERREUR";
           //Mettre un message de retour pour informer l'internaute
}
finally
{
           if (sr != null) sr.Close();
}
try
{
          //Découpage de la chaîne pour récupérer juste le jeton
          Token = Token.Substring(6, Token.IndexOf("&TIME") - 6).Replace("%2d", "-");
          //enregistrement de la commande dans la base de données avec le token

          //Redirection vers le serveur Paypal
          Response.Redirect("https://www.paypal.com/checkoutnow?cmd=_express-checkout&useraction=commit&token=" + Token);
}
catch
{
         //Ne pas mettre d'action ici
}

Dans la page de retour de paiement (retour_paiement.aspx.cs) ajouter ce code dans la fonction Page_Load :

//On récupère les deux variables de la l'URL
string Token = "";
string PayerId = "";
NameValueCollection coll = Request.QueryString;
string[] arr1;
try
{
          arr1 = coll.GetValues("Token");
          Token = arr1[0];
}
catch
{
         Token = "-1";
}
try
{
         arr1 = coll.GetValues("PayerId");
         PayerId = arr1[0];
}
catch
{
         PayerId = "-1";
}        
string Details = "";
//connexion au serveur Paypal pour vérification
StringBuilder postData = new StringBuilder();
postData.Append("METHOD=GetExpressCheckoutDetails&");
postData.Append("VERSION=95.0&");
postData.Append("PWD=" + Codes.PAYPAL_PwdAPI + "&");
postData.Append("USER=" + Codes.PAYPAL_UserAPI + "&");
postData.Append("SIGNATURE=" + Codes.PAYPAL_SignatureAPI + "&");
postData.Append("TOKEN=" + Token + "&");
WebRequest request = WebRequest.Create("https://api-3t.paypal.com/nvp");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postData.ToString().Length;
var sw = new StreamWriter(request.GetRequestStream());
sw.Write(postData.ToString());
sw.Close();
WebResponse response = request.GetResponse();
StreamReader sr = null;
try
{
          sr = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
          Details += sr.ReadToEnd();
}
catch (Exception ex)
{
           //Message de retour pour informer d'une erreur d'identification
}
finally
{
          if (sr != null) sr.Close();
}
if (Details.IndexOf("ACK=Success") > -1)
{
          //traitement sur la base de données, récupération du montant de l'opération avec le token
          //Connexion à Paypal pour valider le paiement
         postData = new StringBuilder();
         postData.Append("METHOD=DoExpressCheckoutPayment&");
         postData.Append("VERSION=95.0&");
         postData.Append("PWD=" + Codes.PAYPAL_PwdAPI + "&");
         postData.Append("USER=" + Codes.PAYPAL_UserAPI + "&");
         postData.Append("SIGNATURE=" + Codes.PAYPAL_SignatureAPI + "&");
         postData.Append("PAYERID=" + PayerId + "&");
         postData.Append("CURRENCYCODE=EUR&");
         postData.Append("AMT=" + montant.Replace(",", ".") + "&");
         postData.Append("PAYMENTACTION=Sale&");
         postData.Append("TOKEN=" + Token + "&");
         request = WebRequest.Create("https://api-3t.paypal.com/nvp");
         request.Method = "POST";
         request.ContentType = "application/x-www-form-urlencoded";
         request.ContentLength = postData.ToString().Length;
         sw = new StreamWriter(request.GetRequestStream());
         sw.Write(postData.ToString());
         sw.Close();
          response = request.GetResponse();
          sr = null;
          try
          {
                    sr = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
                    string Reponse = sr.ReadToEnd();
                    if (Reponse.IndexOf("ACK=Success") > -1)
                    {
                              //Enregistrement du paiement dans la base de données
                             //Retour vers la page de confirmation
                             Response.Redirect("default.aspx?p=1");                    
                }
            }
            catch
            {
                       //Ne pas mettre d'action ici  
            }
}
else
{
          //Message de retour pour informer que le paiement n'a pas été enregistré





vendredi 8 juillet 2016

Validation of viewstate MAC failed

Cette désagréable erreur qui apparaît de temps à autre peut être résolue en ajoutant cette ligne de code au fichier web.config sous la balise <system.web> :









<machineKey validationKey="52B3217F9A9F7B8CE24DEFBD3EDF2B698E37B2ADE33257FAD329A242C11579D0EEDDB67F94CCF27143DCA4BBF9667DDAE78EBEDDD9EABB7C7AB874B5EC443954" decryptionKey="8A3AD1DD400FF3A09F3F5CB27C0411D2E8C7792CE523FD7B" validation="SHA1"/>

dimanche 12 juin 2016

Trouver l'adresse postale de sa position

Trouver facilement l'adresse relative à sa position. Le programme javascript suivant utilise l'API de Google pour afficher dans une zone de saisie nommée adresse l'adresse postale de sa position. En même temps la position gps est affichée dans la zone gps.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript">
        var latitude;
        var longitude;
        function showLocation(pos) {
            latitude = pos.coords.latitude;
            longitude = pos.coords.longitude;
            document.getElementById("gps").value = latitude + ", " + longitude;
            var latlng = { lat: parseFloat(latitude), lng: parseFloat(longitude) };
            try {
                var geocoder = new google.maps.Geocoder();
                geocoder.geocode({ 'location': latlng }, function (results, status) {
                    if (status === google.maps.GeocoderStatus.OK) {
                        if (results[1]) {
                            document.getElementById("adresse").value = results[0].formatted_address;
                        } else {
                            window.alert('No results found');
                        }
                    } else {
                        window.alert('Geocoder failed due to: ' + status);
                    }
                });
            }
            catch (e) {
                window.alert(e.message);
            }
        }
        function showError(err) {
            if (err.code == 1) {
                alert("Error: Access is denied!");
            } else if (err.code == 2) {
                alert("Error: Position is unavailable!");
            }
        }
    </script>
</head>
<body>       
            <input id="gps" type="text" value=""/> 
            <input id="adresse" type="text" value=""/> 
            
        <script src="https://maps.google.com/maps?file=api&amp;v=3&amp;sensor=false" type="text/javascript"></script>   
        <script type="text/javascript">
            navigator.geolocation.getCurrentPosition(showLocation, showError, { enableHighAccuracy: true, maximumAge: 600000 });        
        </script>
</body>
</html>

lundi 30 mai 2016

Comment taper des chiffres sur un Mac sans avoir à appuyer à chaque fois sur Majuscules

Par défaut, il faut taper sur la touche Majuscules pour afficher un chiffre. Si vous voulez taper des chiffres en appuyant une seule fois sur la touche Verrouillage Majuscule (Led verte) :


  • Préférences système, Langue et région, Préférences clavier, Ajouter (+) le clavier Français - numérique. Fermez Préférences système.
  • Dans la barre d'état du haut de l'écran, appuyez sur le petit drapeau et sélectionnez le clavier Français - numérique

samedi 14 mai 2016

Access is denied! Géolocalisation

Depuis avril 2016 le navigateur Google Chrome ne permet pas aux pages web non sécurisées d'utiliser la géolocalisation javascript (navigator.geolocation). Seule solution passer son site en SSL.

dimanche 8 mai 2016

Comment téléphoner ou passer des SMS depuis son iPad ou son Mac ?

Il est possible de recevoir /envoyer des appels ou des messages (SMS) depuis son Mac ou son iPad du moment que son iPhone est à proximité.

1. Vérifier sur chaque appareil : Réglages, Général, Handoff et apps suggérées, Handoff (ON)
2. Sur l'iPhone uniquement : Réglages, Téléphone, Appels, Sur d'autres appareils, Appels sur d'autres app... (ON), Autoriser les appels sur (MacBook, iPad etc.) (ON) - les appareils doivent être accessibles en Bluetooth.
3. Sur l'iPhone uniquement : Réglages, Messages, iMessage (ON), Transfert de SMS (MacBook, iPad etc.) (ON) - les appareils doivent être accessibles en Bluetooth.


dimanche 27 mars 2016

Comment créer un iframe redimensionable en largeur et en hauteur pour faire du responsive design ?

Définir une division d'une hauteur de 0px et d'un padding-bottom du pourcentage souhaité.
Mettre l'iframe, la video embeded etc. dedans avec la position absolute, le top et le left à 0, la hauteur et la largeur à 100%.

<div class="diaporama" style="position:relative;width:100%;height:0px;padding-bottom:40%;">       <iframe src="surcouf.html" frameborder="0" scrolling="no" style="position:absolute; left:0px; top:0px; width:100%; height:100%"></iframe>
 </div>

mardi 22 mars 2016

Crypter une chaine de caractères en SHA512 ASP.NET à l'aide d'une clé de crytage

   
    using System.Text;
    using System.Security.Cryptography;


    public static string Hashage(string chaine, string cle)
    {
        Encoding encoding = Encoding.ASCII;
        byte[] keyByte = PackH(cle);
        HMACSHA512 hmacsha512 = new HMACSHA512(keyByte);
        return ByteToString(hmacsha512.ComputeHash(encoding.GetBytes(chaine)));      
    }
    private static byte[] PackH(string hex)
    {
        if ((hex.Length % 2) == 1) hex += '0';
        byte[] bytes = new byte[hex.Length / 2];
        for (int i = 0; i < hex.Length; i += 2)
        {
            bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
        }
        return bytes;
    }
    private static string ByteToString(byte[] buff)
    {
        string sbinary = "";
        for (int i = 0; i < buff.Length; i++)
        {
            sbinary += buff[i].ToString("X2"); // hex format
        }
        return (sbinary);
    }

mardi 9 février 2016

Envoyer le message en noreply et permettre de répondre à l'expéditeur (replyto)

Par raison de sécurité, quand on envoie par programmation un email, on doit utiliser une adresse email valide (dont on connait le mot de passe et le serveur) :

smtp = new SmtpClient(serveur, 25);
UserInfo = new System.Net.NetworkCredential(user, password);
smtp.UseDefaultCredentials - false;
smtp.Credentials - UserInfo;

Le problème est que le destinataire répondra à cette adresse email qui est, en général, juste utilisée pour envoyer un message.

Comment faire pour que le destinataire réponde à une autre adresse email :

MailMessage mail = new MailMessage(from, to);
mail.ReplyToList.Add(new MailAddress(email));

email est l'adresse de destination de la réponse du premier destinataire (quand celui-ci fera Répondre depuis son client de messagerie).