jeudi 20 octobre 2011

PHP : Upload et lecture d'un fichier

Comment charger un fichier, le transférer dans le dossier temporaire d'un serveur mutualisé, puis y accéder en lecture.
liens : http://www.commentcamarche.net,   
http://www.siteduzero.com

Pour rappel, je suis sur serveur mutualisé, donc ce qui marche sur mon PC, ne fonctionne pas nécessairement en ligne.

1er étape :  
Créer, à partir de la racine du site un dossier temporaire '/tmp' dans lequel seront stockés les fichiers uploadé.
Modifier les paramètres d'accès (CHMOD sous unix cf lien site du zéro), puis écrire la ligne de code ci-dessous qui permet d'indiquer au serveur le path du dossier temporaire.

<?php
      ini_set('upload_tmp_dir', $myserveur_path.'/tmp');

 ?>

2ème étape (cf site du zéro) : formulaire d'upload d'un fichier 
 action = "" car je traite dans le même fichier html, le résultat du formulaire.
 
<form method="post" action="" enctype="multipart/form-data">   
    <div >
        <input type="hidden" name="MAX_FILE_SIZE" value="2097152">   
        <input type="file" name="file_name" size="50">  
        <input type="submit" value="Envoyer"
    </div>     
</form>
<br/>

3ème étape : récupération de l'array qui reprend les paramètres du fichier chargé, par défaut je teste si un fichier a été chargé, cad si $_FILES['file_name'] existe ou est VRAI.
Puis on analyse les cas d'erreur, j'ai complété la liste fournie sur le site du zero avec le cas 6, lié a un problème de dossier temporaire.

<?php
    if (isset($_FILES['file_name']))
    {
        if ($_FILES['file_name']['error']) {        // www.commentcamarche.net   
                switch ($_FILES['file_name']['error']){   
                           case 1: // UPLOAD_ERR_INI_SIZE   
                           echo "Le fichier dépasse la limite autorisée par le serveur (fichier php.ini) !";   
                           break;   
                           case 2: // UPLOAD_ERR_FORM_SIZE   
                           echo "Le fichier dépasse la limite autorisée dans le formulaire HTML !";
                           break;   
                           case 3: // UPLOAD_ERR_PARTIAL   
                           echo "L'envoi du fichier a été interrompu pendant le transfert !";   
                           break;   
                           case 4: // UPLOAD_ERR_NO_FILE   
                           echo "Le fichier que vous avez envoyé a une taille nulle !";
                           case 6: // UPLOAD_ERR_NO_FILE   
                           echo "Missing temporary folder : ".realpath(sys_get_temp_dir( void )).'<br/>';
                           break;   
                  }   
        }   
        else {   
            // $_FILES['file_name']['error'] vaut 0 soit UPLOAD_ERR_OK   
            // ce qui signifie qu'il n'y a eu aucune erreur dans le chargement  
           
            // transfert du fichier dans un répertoir temporaire du serveur (siteduzero)
            if ((isset($_FILES['file_name']['name'])&&
                        ($_FILES['file_name']['error'] == UPLOAD_ERR_OK))) {   
                $chemin_destination = './tmp/';  
                $myfile_path = $chemin_destination.$_FILES['file_name']['name'];
                move_uploaded_file($_FILES['file_name']['tmp_name'], $myfile_path);   
            }   
           
            // open file
            $myfile = fopen($myfile_path, 'r');    //ouverture en lecture seule
           
            //load data in table, ligne à ligne et chargement dans un tableau de strings
            $index = 0;
            while($word[$index] = fgets($myfile)){         
                $index++;
            }
            $nbr_lines = $index;
            fclose($myfile);
           
        }   
    }

 ?>



dimanche 9 octobre 2011

Solution de paiement en ligne ATOS-SIPS sur serveur mutualisé : PAYMENT_N

Dans le cas du paiement en n fois, les champs capture_mode et data de la variable $parm sont modifiés :
capture_mode=PAYMENT_N
data=NB_PAYMENT=3;PERIOD=$payt_n_period;INITIAL_AMOUNT=$first_amount


Mais comme expliqué dans un autre billet, certains caractères sont supprimés ou remplacés par la passerelle imposée par l'hébergeur. Dans le cas du paiement en n fois, les caractères ";" sont supprimés ou modifiés, rendant l'exploitation du champs data inexploitable par l'API.
La solution est à la fois simple et compliquée, il s'agit de demander directement à l'hébergeur de modifier le script de la passerelle afin de prendre en charge les ";".
Mon hébergeur a accepté de modifier le script, ce qui donne le résultat suivant en reprenant l'exemple précédent :
$requete = $request_path.str_replace( ';', "--", $parm);

3.0/ Array de type managé String

String ^ sData;

Creation d'un array de type managé 1 dimension
array<String ^, 1> ^ stMonTableauString= gcnew array<String ^, 1>(SIZE);
sData = stMonTableauString[i];
Creation d'un array de type managé 2 dimensions
array<String ^, 2> ^ stMonTableauString = gcnew array<String ^, 2>(DIM_1, DIM_2);
sData = stMonTableauString [i,j];

Solution de paiement en lign ATOS-SIPS sur serveur mutualisé

Lorsque l'on utilise la solution de paiement en ligne ATOS-SIPS sur un hébergeur comme Viaduc ou OVH avec un serveur mutualisé et pour des raisons de sécurité, les hébergeurs bloquent l'exécution de l'API et obligent l'usage d'une passerelle.
La passerelle, dans certains cas, supprime des caractères essentiels au bon fonctionnement de l'API, d'où la pratique de remplacer les espaces par des &. 

Pour un tuto complet pour la mise en oeuvre de la solution ATOS SIPS de paiement en ligne, je recommande le site : http://thierry-godin.developpez.com/php/atos/.


Call_request appelle normal :
//$parm contient l'ensemble des paramètres de la solution de paiement en ligne à passer au "call_request"
$path_bin = "chemin_du_fichier_call_request";
$result=exec("$path_bin $parm");


Call_request appelle via une passerelle :
//$parm contient l'ensemble des paramètres de la solution de paiement en ligne à passer au "call_request"
$request_path = 'http://www.monsite.fr/cgi-bin/atos-sips/request.cgi?';
$requete = $request_path.$parm;
$result = print(file_get_contents($requete));


La méthode est la même pour accéder aux API auto_response et response

Call_response appelle normal :
$message="message=$HTTP_POST_VARS[DATA]";
$pathfile="pathfile=chemin_du_fichier_pathfile";
$path_bin = "chemin_du_fichier_response";
$result=exec("$path_bin $pathfile $message");

Call_response appelle via une passerelle :
    $message="message=".escapeshellcmd($_POST['DATA']);       
    $pathfile="pathfile=/xxx/xxxx/clients/xxxx/xpay/pathfile";
   
    $parm = $pathfile.'&'.$message;
   
    $requete = 'http://www.monsite.fr/cgi-bin/atos-sips/response.cgi?'.$parm;
    $result = file_get_contents($requete);

samedi 8 octobre 2011

2.3/ Lire un fichier text avec la méthode sr->Read()

Lorsque un fichier texte contient des caractères "NUL", il n'est pas possible de faire une lecture par sr->ReadLine() car la type String s'arrête au premier caractère NUL. Il faut donc utiliser une lecture octet par octet. Une solution pour ne pas perdre le code ASCII, consiste à utiliser le code suivant :

// Le tableau de caractères aChar contient toute la chaîne, en incluant les caractères NULL
array<wchar_t, 1 > ^ aChar = gcnew array<wchar_t, 1 >(200);
String ^ sFileName;



System::IO::StreamReader ^ sr = gcnew System::IO::StreamReader(sFileName);
sr->Read( aChar, 0, aChar->Length );

vendredi 7 octobre 2011

2.2/ Ouvrir plusieurs fichiers avec fenêtre de dialog

On sélectionne plusieurs fichiers puis on charge leurs path dans une table afin de pouvoir y accéder par la suite.
2 façon de sélectionner le mode multi-fichiers :

Propriété :
Multiselect  : true
ou directement dans le code :

openFileDialog->Multiselect = true;

Exemple d'usage :


#include <string>
using namespace std; 
using namespace System::Runtime::InteropServices;  //permet l'usage de Marshal::

/////////////////////////////////////////////////////////////////////
// Name : MarshalString
// Op : convert System::String into std::string
// arguments :  String ^ s,
//                string& os,

// ce code n'est pas de moi, malheureusement je ne me souviens plus de sa source...
/////////////////////////////////////////////////////////////////////
void MarshalString ( String ^ s, string& os )
{
   using namespace Runtime::InteropServices;
   const char* chars =
      (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
   os = chars;
   Marshal::FreeHGlobal(IntPtr((void*)chars));
}
 

/////////////////////////////////////////////////////////////////////

string sFileName;
int iNbr_Files;
array<String ^, 1> ^ stFilesNames = gcnew array<String ^, 1>(NBR_MAX_DE_FICHIERS);

// si la boîte de dialogue s'exécute sans erreur alors
if (openFileDialog->ShowDialog() == System::Windows::Forms::DialogResult::OK)
{
                 // Sélection de 1 ou plusieurs fichiers :
                 iNbr_Files =
openFileDialog->FileNames->Length;
                 

                  // on charge dans une table de string les noms et le path complet de chaque fichier sélectionné
                  for (int i=0; i<iNbr_Files; i++)
                 {

                               // méthode pour passer d'un type string à un type managé String ^
                               MarshalString (
openFileDialog->FileNames[i], sFileName);
                               stFilesNames[i] = Marshal::PtrToStringAnsi((IntPtr)(void*)sFileName.c_str());
 

                 } //  for (int i=0; i<openFileDialog->FileNames->Length; i++)

} // if(openFileDialog->ShowDialog() == System::Windows::Forms::DialogResult::OK)   

jeudi 6 octobre 2011

2.1/ Lire et/ou écrire dans un fichier

Pour lire dans un fichier on utilise le StreamReader
String ^ sFileName;
String ^ sLine; 

// sans sélection avec une boîte de dialogue 
sFileName = "MonFichier.txt";
// avec sélection à partir d'une boîte de dialogue ou
sFileName = openFileDialog->FileName;
// en mode Multiselect (multi fichiers) ou
sFileName = openFileDialog->FileNames[i]; 

// création du flux de lecture 

System::IO::StreamReader ^ sr = gcnew System::IO::StreamReader(sFileName);  
// on boucle tant que la lecture d'une ligne est possible
while (sLine = sr->ReadLine())
{
...
}
sr->Close();



Pour écrire dans un fichier on utilise le StreamWriter 
String ^ sText = "mon text";
String ^ sFileName;
// sans sélection avec une boîte de dialogue 
sFileName = "MonFichier.txt";

// avec sélection à partir d'une boîte de dialogue
sFileName = saveFileDialog->FileName;

// création du flux d'écriture
System::IO::StreamWriter ^ sw = gcnew System::IO::StreamWriter(sFileName);
// pour écrire une ligne de chaîne de caractères
sw->WriteLine(sText); // ou 
sw->Write(sText + "\r\n");
// ne pas oublier de fermer le flux 
sw->Close();

mercredi 5 octobre 2011

2.0/ Ouvrir et lire un fichier avec fenêtre de dialog

Sous Visual C++, dans l'onglet Form1.h [design], sélectionner :
dans la "boîte à outils" / "Boîtes de Dialogue" / "OpenFileDialog".
Cette action crée une icône dans la zone inférieure du Form1.h [design].

Propriétés importantes :
Name : donner un nom judicieux : ex : openFileDialog
Filter : type de fichier|extension|type de fichier|extension : ex : XLS|*.csv|Tous les fichiers|*.*

Exemple d'usage :

String ^ sLine;   // création d'un type mangé String sLine

// si la boîte de dialogue s'exécute sans erreur alors
if(openFileDialog->ShowDialog() == System::Windows::Forms::DialogResult::OK)
{
                // On ouvre un flux de lecture nommé sr  
                System::IO::StreamReader ^ sr = gcnew System::IO::StreamReader(openFileDialog->FileName);
                
                // lecture ligne par ligne : tant qu'il est possible de lire une ligne du fichier, sLine prend la chaîne        
                // de caractères  correspondant à la ligne.
                while (sLine = sr->ReadLine())
               {
                            ...
               }
               sr->Close();  // cloture du flux afin de libérer la ressource
}

mardi 4 octobre 2011

1.2/ Générer l'executable

Lorsque l'on compile les fichiers d'un projet Visual C++, par défaut, le compilateur ne génère que la version "debug". Afin d'obtenir un exécutable indépendant procéder comme suit :

Menu : Générer/Gestionnaire de Configuration

Dans "Configuration", basculer la combobox de "Debug" à "Release". Un nouveau directory est créé au niveau du projet contenant l'exécutable.

1.1/ Message Box

Pour faire apparaître une boîte de dialogue de type message box : 

MessageBox::Show(L"Bonjour");


ou

String ^ sMessage = "Bonjour":

MessageBox::Show(sMessage);

lundi 3 octobre 2011

1/ Créer un projet en Visual C++

L'exemple suivant utilise la dernière version gratuite de Visual C++ 2010 Express.

1/ Installer  Visual C++ 2010 Express disponible au lien suivant : download

2/ Appuyer sur "Nouveau projet...
3/ Sélectioner "Application Windows Forms"



 
4/ Dans la même fenêtre, en bas, « Nom »  indiquez un nom de projet, puis validez en cliquant sur « ok »
5/ Vous obtenez la fenêtre suivante :
-          Form1.h[Design] : permet de modifier l’apparence de la fenêtre en ajoutant, déplaçant, supprimant ou modifiant les éléments qui enrichiront l’interface comme : boutons, textes, onglets, menus etc….
-          Explorateur de solution (à gauche) vous permet de naviguer et ajouter/supprimer des fichiers à votre projet
-          En haut à droite 2 icones importantes :  
o   Icone    : correspond à la « boîte à outils » et permet de sélectionner les différents éléments appelés « Windows Form » : boutons, textes, etc.. à ajouter sur la fenêtre Form1
o   Icone   : ouvre la Fenêtre des propriétés et vous donne accès à une interface visuelle permettant de modifier toutes les propriétés de chacun des « Windows Form »




6/ Exemple avec bouton permettant de fermer la fenêtre
- appuyez sur l’icône dans le menu en haut à droite  puis parcourez les différentes listes de « Windows Form », cherchez le « Button », sélectionnez-le et glissez le sur la fenêtre Form1.
- Pour l’exemple positionnez le en bas à droite de la fenêtre principale


-          Puis appuyez sur l’icône dans le menu en haut à droite  (propriétés)
Dans un premier temps nous allons nous focaliser sur 2 propriétés :
o   Apparence / Text : (par défaut) Button1, changez le contenu du texte en écrivant « Close », qui correspond au texte affiché sur le bouton,
o   Design / (Name) : (par défaut) button1, changez le contenu du texte en écrivant « bouton_Close », qui correspond à l’appellation de ce bouton dans le code. Plus le nom est explicite, plus il est facile de le retrouver dans le code.

7/ Afin de lier une fonction à l’interface graphique du bouton « Close », double cliquez sur le bouton. Cette action ouvre une nouvelle fenêtre Form1.h. Nous allons rapidement analyser la structure du code rédigé automatiquement.
On distingue 3 zones :

Zone 1 : débute en haut du fichier avec l’instruction  #pragma once  et se termine à l’instruction  #pragma region 
A priori, pas besoin d’ajouter du code dans cette zone, il est à noter qu’à chaque fois que vous ajoutez une « Windows Form », une ligne commençant par :   private: System::Windows::Forms::  est ajouté suivi du nom que vous lui avez donné.
Vous serez peut être amené à compléter la zone  using namespace   si vous utilisez d‘autres librairies.


Zone 2 :   débute en haut du fichier avec l’instruction  #pragma region  et se termine à l’instruction  #pragma endregion
C’est dans cette zone que chaque nouveau composant « Windows Form » est décrit avec ses propriétés propres contenant par exemple : position dans la fenêtre, taille, text, couleurs etc…

Lorsque nous avons « double cliquez » sur le bouton close dans la fenêtre Form1.h [Design], nous avons indiquez au compilateur que nous souhaitions lier un événement « clique «  au bouton « Close ». Ainsi , le compilateur a ajouté une ligne dans cette zone pour lier l’événement au composant

this->bouton_Close->Click += gcnew System::EventHandler(this, &Form1::bouton_Close_Click);

et ouvert une nouvelle fonction dans la zone 3.

Zone 3 :   débute en haut du fichier avec l’instruction  #pragma endregion et se termine à la dernière « } »
A la création d’un événement, le compilateur ajoute une nouvelle fonction :

private: System::Void bouton_Close_Click(System::Object^  sender, System::EventArgs^  e) {
       Close() ;                 
}

C’est dans cette fonction, que nous allons décrire l’action à réaliser lorsque l’on clique sur le bouton. Dans notre exemple, j’ai ajouté la fonction « Close() ; » afin de fermer la fenêtre.

8/ Un pression sur F7 afin de compiler le code, puis F5 afin de l’exécuter. Si tout va bien la fenêtre apparaît avec le bouton, lorsque l’on clique dessus la fenêtre se ferme.
Voilà comment simplement créer une interface windows en Visual C++.