//Dans la suite de mes tutos sur le HTTP, voici l'arme ultime :

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++
+             The POSTman v1 par sirius_black           +
+ No licence, Open Source, GPL et tout ce qu'on veut :) +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/


import java.net.*; //on charge les librairies réseau pour avoir le type Socket et le type URL
import java.io.*; //on charge les Entrées/Sorties standards pour pouvoir utiliser les différents flux (Stream)
public class HttpClient{ //On déclare une classe HttpClient qui possède son propre point d'entrée
    URL url; //On déclare une variable de type URL qui nous permettra de décomposer une URL
    Socket socket; //Notre Socket
    String texte; //String qui récupérera le résultat de notre requête
    String req; //La String qui contiendra notre requête
    int port; //le port HTTP (généralement 80)
    InputStream input; //InputStream et OutputStream sont les flux de base. Ils ne peuvent pas être instancié
    OutputStream output; // (pas de new()) car ce sont des classes dites 'abstraites'.
    BufferedReader breader; // Les classes Buffered* sont des classes filles des classes InputStream* et OutputStream*
                            // elles même filles de InputStream et OutputStream
    BufferedWriter bwriter;
    

    public static void usage() //On arrive ici si il n'y a pas le bon nombre d'arguments
    {
	    System.out.println("Usage: java HttpClient complete_URL [headers_to_send]");
	    System.out.println("\tcomplete_URL must look like:");
	    System.out.println("\thttp://host/page.ext?variable1=value1&variable2=value2");
	    System.out.println("\n\theaders_to_send must look like:");
	    System.out.println("\thead1:value1&head2:value2");
	    System.exit(0); //On quitte
// Le programme sert à transformer une méthode GET en méthode POST. On l'utilise de cette façon :
// java HttpClient http://www.google.fr/main/index.php?login=toto&pass=titi Referer:http://membres.lycos.fr/lotfree&User-Agent:POSTman1
    }

    public void sendReq() //la fonction qui enverra nos données
    {
	    try{
	        req=req.concat("\r\n"+url.getQuery()+"\r\n\r\n"); //on ajoute les variables à la requête
            System.out.println("--------------------Requête-------------------");
	        System.out.println(req); //on l'affiche
	        output.write(req.getBytes()); // on envoie notre requête sous la forme d'une suite de Byte à notre
                                          // flux de sortie lié à notre socket
	        texte=new String(); // l'allocation ne se fait pas obligatoirement dans le constructeur
	        texte=breader.readLine(); //Le type BufferedReader permet de faire une lecture ligne après ligne
            while(texte!=null){ //tant que ya de quoi lire on lit
		        System.out.println(texte); //et on l'affiche
		        texte=breader.readLine(); //c ici kon lit
	        }
	    }
	    catch(IOException ex){
            System.out.println(System.err);
	    }
    }

//ya une belle surcharge du constructeur par là :)

    public HttpClient(String param1,String param2) //Le constructeur avec deux arguments : URL_avec_données et headers
    {
	    this(param1); //On fait appel au constructeur avec un seul argument (toujours appeler en premier dans ce cas)
	    param2=param2.replaceAll("&","\r\n"); //On découpe les headers avec le '&' comme spérarateur
	    req=req.concat(param2+"\r\n");
    }
    
    public HttpClient(String param) //Constructeur appelé dans tous les cas (param= URL_avec_données)
    {
	    try{
	        url=new URL(param);
            //On transforme la String passée en argument en une variable de type URL qui nous permettra de récupérer
            // nom d'hôte, déterminer le port, récupérer les arguments, le chemin de la page sur le serveur etc
            // /!\ Attention : l'URL passée en argument doit commencer par 'http://'
            System.out.println("Host: "+url.getHost()); //On affiche les données trouvées
	        if(url.getPort()==-1)port=80; //Si le port n'est pas spécifié, on prend le 80 par défaut
	        else port=url.getPort();
	        System.out.println("Port: "+port);
	        System.out.println("Path: "+url.getPath());
	        System.out.println("Query: "+url.getQuery());
	        socket=new Socket(url.getHost(),port); // Constructeur de la Socket : Socket(String host,int port)
	    
	        input=socket.getInputStream(); //On lie un flux d'entrée à notre Socket (pas de new car classe InputStream abstraite)
	        breader=new BufferedReader(new InputStreamReader(input));
            // A partir du Stream de base on crée un InputStreamReader à partir duquel on crée un BufferedReader
	    
            //Pareil avec les flux de sortie. Il n'est pas rare de voire ce genre de constructions en Java
	        output=socket.getOutputStream();
	        bwriter=new BufferedWriter(new OutputStreamWriter(output));
	    
            //La requête POST est formée selon le standard HTTP/1.1
	        req=new String("POST /"+url.getPath()+" HTTP/1.1\r\nHost: "+url.getHost()+"\r\n");
	        req=req.concat("Content-Type:application/x-www-form-urlencoded\r\n");
	        req=req.concat("Content-Length:"+(url.getQuery()).length()+"\r\n");
            //Le prog plante s'il n'y a pas de données (après le ?)
	    }
	    catch(Exception exp){exp.printStackTrace();System.out.println(System.err);}
        //Les exceptions permettent de gérer les erreurs. Il est obligatoire de les mettre quand cela est demandé
        //Le compilateur dit automatiquement si une instruction nécessite que l'on utilise une exception
        //et quel type d'exception doit être utilisé
    }
    
    public static void main(String args[]) //Le point d'entrée
    {
	    HttpClient connexion=null;
	    if (args.length==0 || args.length>2) usage(); // si ya pas le bon nombre d'arguments on affiche l'aide
        if (args.length==1) connexion=new HttpClient(args[0]); //Si ya un seul argument
	    if (args.length==2) connexion=new HttpClient(args[0],args[1]); //Si yen a 2
        connexion.sendReq(); // Dans tout les cas (si on a les arguments) on envoie la requête
    }
}