Routeur Nat et OpenVPN

Cet article a pour but d’expliquer de façon synthétique comment réaliser un routeur relativement simple d’emploi présentant les fonctionnalité suivante:

  • Routage NAT (Network Address Translation) entre une ip publique et un sous réseau privé
  • Possibilité de ce connecter en VPN au sous réseau privé, mais aussi de surfer sur le net via ce réseau privé (pour outrepasser les limites de hot-spot par exemple)
  • Possibilité d’ouvrir un port sur l’ip externe et le rediriger sur un autre port sur l’une des machines du réseau privé.
    Pourquoi ne pas utiliser IPCOP ou autres ? Parce qu’IPCOP ne supporte pas nativement les réglages quelques peut « spéciaux » des IP FAIL OVER d’OVH.
    Certes, il existe des scripts qui permettent de modifier les configuration de passerelles, mais cela est trop hasardeux sur un système en production car il faut être sur que le routeur redémarre sans intervention en cas de coupure.

Le routage NAT, est nommé MASQUERADE dans les firewall linux, correspond a masquer les IP des postes du réseau privé derrière l’unique adresse ip publique.
Par exemple, c’est ce que font les box internet pour permettre l’usage de plusieurs ordinateurs derrière une seule connexion.
Plus d’info ici: https://fr.wikipedia.org/wiki/Network_address_translation

 

1ère étape, installer Ubuntu (non décrit car ce n’est pas le but de ce tutoriel).

=> Installez le module ssh durant l’installation car en console hyper-v, pas de copier coller possible avec votre poste local.
=> Installez au minimum la 14.04.2 lts car le noyau 3.16 offre une meilleur compatibilité hyper-v.

 

2ème étape installer openVPN (voir tutoriel sur le sujet).

Si vous avez suivi le tutoriel sur OpenVPN le routage est déjà activé par l’activation de net.ipv4.ip_forward=1 dans sysctl.conf

=> une fois redémarré, le routage est activé. mais il n’y pas encore de NAT entre eth0 (le wan) et eth1 (le lan)

3ème étape, la mise en place du routage NAT.
Pour cela, on utilisera le firewall le plus simple, c’est UFW.

On activera également cette translation entre l’interface VPN (tun0) et le WAN (interface eth0) pour permettre aux usagers du VPN de pouvoir naviguer sur le net via le VPN.

Avant de commencer a activer un pare-feu, il est très important de ne pas perdre la main en bloquant l’interface SSH.

Si vous l’avez laisser par défaut sur le port 22,

la commande

sudo ufw allow ssh

si vous l’avez modifié (ce qui est une sécurité contre les scripts d’attaques):

sudo ufw allow votre_port_ssh/tcp

exemple: si vous avez déplacé votre port ssh en 1234

sudo ufw allow 1234/tcp

 

Pour activer le transfert des paquets entre les interfaces, il faut active le parametre DEFAULT_FORWARD_POLICY.
Dans le fichier /etc/default/ufw, changez le ce paramètre comme suit:

DEFAULT_FORWARD_POLICY="ACCEPT"

L'activation du routage nat ce fera dans le fichier before.rules situé dans /etc/ufw on ajoutera juste après les premier commentaires:
#règles pour la table NAT
*nat
:PREROUTING - [0:0]
:POSTROUTING ACCEPT \[0:0]

#on efface les règle precedentes (flush)
-F
# transmission du trafic provenant de eth1 (reseau prive) vers eth0
-A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
# transmission du trafic provenant de tun0 (VPN) vers eth0
-A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE

# Ouverture des ports
#-A PREROUTING -i <iface> -p tcp --dport <port public> -j DNAT --to-destination <adr lan>:<port prive>
# exemple d'ouverture de port  port public 8080 vers port prive 80 d'un poste:
#-A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.10:80

# ne pas oublier le 'COMMIT' sinon ces lignes ne seront pas traitée
COMMIT

puis activer UFW avec la commande

sudo UFW enable

=> La translation NAT est alors activée pour votre réseau privé mais aussi pour vos utilisateurs VPN.

=> il est possible d’ajouter d’autres ouvertures de port. aussi bien en tcp qu’en udp. Si le port privé est identique au port public, il n’est pas nécessaire de le mentionner:
exemple:

-A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.10

Dans cet exemple j’ai pris comme principe:

le wan est sur eth0
le lan est sur eth1 en 192.168.1.0/24
le vpn est sur tun0 en 10.10.10.0/24

Il convient, bien évidement d’adapter cet exemple a votre cas.

A bientôt.

Bonjour,

Ceci n’est pas un tutoriel mais plus un retour d’expérience car je n’ai pas la prétention de connaitre tout les mécanismes en place dans l’IPv6.

Suite a quelque méli-mélo  un problème commercial avec OVH, je me suis retrouvé avec un serveur en housing chez eux, mais sans IPv4 pour mes VM.

J’ai donc profité de cette latence commerciale pour tenter le faire un point sur l’avancement de l’IPv6.

Afin de pouvoir accrocher des nom d’hote sur mon domaine, j’ai décidé d’affecter des IPv6 statiques sur mes différentes VM.

Attribution:

En IPv6, le fournisseur vous fourni un sous réseau IPv6, généralement de classe /64 et vous laisse donc les 64 autres bits a votre disposition soit 18 milliards de milliards d’adresses !

Passerelle:

Chez FREE, l’adresse de la freebox est généralement la 1ere IP de la plage  donc l’adresse 2001:xxxx:xxxx:xxxx::1
Chez OVH, selon leur documentation, les octets bas des 5 derniers nombres sont a ff cela donne donc quelque chose du genre
2001:xxxx:xxxx:xxff:ff:ff:ff:ff   c’est a dire en affichant l’adresse avec les zero non significatifs cela donne 2001:xxxx:xxxx:xxff:00ff:00ff:00ff:0ff …

=> Oups !!! OVH semble avoir oublié le but d’un masque de sous réseau => Tout ce qui est en dehors du masque est défini comme extérieur et donc à la passerelle située OBLIGATOIREMENT dans le sous réseau…
Le masque réellement fonctionnel avec une telle passerelle est donc /56

Expérimentation sous Windows:

Depuis ma machine virtuelle équipée d’un Windows 2008 Sp2, l’IPv6 se configure sans difficulté. Microsoft n’est pas regardant sur le fait que la passerelle ne se trouve pas dans le même sous réseau…
En faisant pointer les DNS IPv6 vers ceux de Google dont je le rappel les ip sont:

2001:4860:4860::8888 et
2001:4860:4860::8844

L’accès à google est immédiat. Un petit test sur www.ipv6-test.com confirme que tout vas bien.

1ère observation: Sur un poste uniquement IPv6, on n’a accès a aucun site dont le serveur n’est qu’en IPv4.
2ème observation, plus curieuse: Windows Update ne fonctionne pas… il n’est pas IPv6 ready en 2015 alors qu’ils intègrent pourtant l’IPv6 depuis 2008 dans leurs logiciels ?!

Hormis ce problème de défaut de préparation du système de mise à jour, le système s’accoutume bien de l’IPv6 statique, et fonctionne de façon stable, même en désactivant totalement l’IPv4.
La connexion au bureau distant par exemple fonctionne très bien, ainsi qu’un serveur web IIS situé sur ce poste.
En revanche les petits logiciels annexes, une très vieille version de Serv-U (version 6.4) et freeFTPd ne fonctionnent pas mais cela parait assez logique.

Expérimentation sous Ubuntu 14.04.2

L’installation de l’IPv6 statique se fait dans le fichier /etc/network/interfaces

1ère observation: La mise à jour via apt-get update && apt-get upgrade -y fonctionne nickel. Preuve que les dépôts Ubuntu ont une longueur d’avance sur leurs alter-égo de Microsoft.
2ème observation: SSH fonctionne nickel. La connexion réalisée avec Winscp et Putty depuis mon poste abouti parfaitement.
3ème observation: La suppression de la config de l’IPv4 mène a un dysfonctionnement et a plus de 2 mn d’attente a chaque redémarrage. Donc j’ai laisser un config réseau bidon pour qu’il passe outre ce problème.

Sauf qu’Ubuntu, contrairement a Microsoft, ne tolère pas cette erreur de masque… Et au bout d’un délai aléatoire se plante, perte de connectivité totale du serveur jusqu’au reboot.

L’incohérence a pour effet de lui faire perdre sa route par défaut … Donc seul les postes dans le même sous réseau que lui peuvent continuer a dialoguer avec lui… et … c’est bête pour un serveur situé dans un datacentre !

conclusions

Même les grands de l’informatique tel qu’OVH peuvent se perdre dans la complexité de l’IPv6.
Les choses avances tout doucement sur cette évolution inévitable. Il y’a plein de pièges a connaitre, les mécanismes sont beaucoup plus complexes qu’en IPv4 et on est encore loin de pouvoir faire du FULL IPv6 sous peine de ce couper d’une grande partie du monde…

A bientôt

 

Récupérer les dimensions d’un fichier PDF en PHP

Stockage de l’information de dimension

Les dimensions d’un fichier PDF sont stockées dans une unité nommé le « point pica » ou DTP .
Pour résumer, un point pica correspond à 1/72 de pouce. Pour plus d’information, lire ce lien

Conversion de la taille de point pica en millimètre

Un pouce correspond à 25,4 mm

La conversion en millimètre s’obtient donc en multipliant la taille en point pica par 25,4/72
donc, par exemple, si dans un fichier PDF on trouve une taille de 595×842

cela donnera:
595×25,4/72 = 209,90 mm
842×25,4/72 = 297,04 mm

=> Ce qui correspond a un format A4 portrait.

On observera que selon le logiciel utilisé pour la génération du fichier, on aura un variation dans la précision de cette mesure. de même, certains logiciels ajoute derrière ces mesures le format normé (A4 ou autre) correspondant et d’autres non. D’où la difficulté de l’opération.

D’autre part un fichier PDF peut comporter des pages de différentes tailles et/ou orientations.

Récupération de ces information depuis PHP

PHP peut récupérer ces informations via différents outils Linux. Certains donnent une dimension globale, bien souvent la taille de la 1ère page, d’autres au contraire sont capable de vous donner la taille page par page.
Dans presque tout les cas, il faudra filtrer le résultat pour récupérer les informations de hauteur et de largeur.

Plusieurs solutions sont possibles, j’ai choisi pdfinfo pour sa vélocité et ses fonctionnalités.

pdfinfo s’installe avec la commande

sudo apt-get install poppler-utils

ce logiciel, lancé sans parametre renvoi par défaut la taille de la 1ère page ainsi que d’autres informations dont le nombre de pages.
exemple:

pdfinfo test.pdf

nous renvoi:

Title: fichier de test
Subject:
Keywords:
Author: D.FERET
Creator: PDFCreator Version 0.9.9
Producer: GPL Ghostscript 8.70
CreationDate: Fri Sep 27 14:24:08 2013
ModDate: Fri Sep 27 14:24:08 2013
Tagged: no
Form: none
Pages: 3
Encrypted: no
Page size: 595 x 842 pts (A4)
Page rot: 0
File size: 33923 bytes Optimized: no PDF version: 1.4

Ce qui est insuffisant car on récupère que la taille de la 1ère page. Pour demander des informations plus détaillées, on spécifiera la plage de pages a analyser ( donc de 1 à -1 puisque, normalement, on ne connait pas a l’avance le nombre de pages du fichier ):

pdfinfo test.pdf -f 1 -l -1

nous renvoi:

Title: fichier de test
Subject:
Keywords:
Author: D.FERET
Creator:        PDFCreator Version 0.9.9
Producer:       GPL Ghostscript 8.70
CreationDate:   Fri Sep 27 14:24:08 2013
ModDate:        Fri Sep 27 14:24:08 2013
Tagged:         no
Form:           none
Pages:          3
Encrypted:      no
Page    1 size: 595 x 842 pts (A4)
Page    1 rot:  0
Page    2 size: 595 x 842 pts (A4)
Page    2 rot:  0
Page    3 size: 595 x 842 pts (A4)
Page    3 rot:  0
File size: 33923 bytes
Optimized: no
PDF version: 1.4

On observe que les résultats utiles sont noyés dans le texte et il va devoir les extraire grâce a des expressions régulières pour garantir le résultat.

Le script PHP

Au début du script, on lancera la commande avec la commande exec qui permet de récupérer le résultat dans un tableau $lignes:

// série de constante pour constituer plus facilement nos expressions régulières.
CONST ER_SEP = '.*?'; // Séparateur (espace et autre)
CONST ER_FLOAT = '([+-]?\\d*\\.?\\d+)(?![-+0-9\\.])';  // chiffre a virgule ou entier
CONST ER_ENTIER = '(\\d+)';  //nombre entier
CONST ER_ENTIERSIGNE = '([+-]?\\d+)'; //nombre entier avec ou sans signe + ou -

function getDimensionsPDF($nom_du_fichier_pdf){
   $commande = escapeshellcmd('pdfinfo "' . $nom_du_fichier_pdf . '" -f 1 -l -1');
   $lignes = array(); exec($commande,$lignes);

Ensuite 3 cas seront possibles:
La ligne comportant la dimension ET la taille normé
La ligne comportant la dimension SANS la taille normé
La ligne comportant l’information de rotation.

On aura donc besoin de 3 expressions régulières pour récupérer les informations. On passera en revu chaque ligne pour savoir si elle répondent à l’une des 3 expressions.

    // composition des 3 expressions régulières permettant de récupérer les lignes utiles.
    $expRegLigneAvecFormatNorme = "/^Page " . ER_SEP . ER_ENTIER . ER_SEP ."size:" . ER_SEP . ER_FLOAT . ER_SEP . ER_FLOAT . ER_SEP . "pts". ER_SEP . $Format . "$/";
    $expRegLigneSansNorme = "/^Page " . ER_SEP . ER_ENTIER . ER_SEP . "size:" . ER_SEP . ER_FLOAT . ER_SEP . ER_FLOAT . ER_SEP . "pts$/";
    $expRegLigneRotation = "/^Page " .  ER_SEP . ER_ENTIER . ER_SEP . "rot:" . ER_SEP . ER_ENTIERSIGNE . "$/";$pages = [];
    foreach ($lignes as $ligne) {

        if (preg_match($expRegLigneAvecFormatNorme, $ligne, $resultats)) { // ligne avec format normé en bout de ligne
        list(,$numeroPage,$largeur,$hauteur,$format)=$resultats;
        $pages[$numeroPage]["Largeur"] = $this->pts2mm($largeur);
        $pages[$numeroPage]["Hauteur"] = $this->pts2mm($hauteur);
        $pages[$numeroPage]["Format"] = trim($format, '()');

    } elseif (preg_match($expRegLigneSansNorme, $ligne, $resultats)) { // ligne sans format normé
        list(,$numeroPage,$largeur,$hauteur)=$resultats;
        $pages[$numeroPage]["Largeur"] = $this->pts2mm($largeur);
        $pages[$numeroPage]["Hauteur"] = $this->pts2mm($hauteur);

    } elseif (preg_match($expRegLigneRotation, $ligne, $resultats)) { // ligne contenant le numéro de page et la rotation
        list(,$numeroPage,$rotation)=$resultats;
        $pages[$numeroPage]["Rotation"] = $rotation;
    }    
 }
 return $pages;
}

function pts2mm($valeur)
{ //petite fonction qui converti un taille de pts pica en mm
    if (is_numeric($valeur)) {
        return round((float)$valeur * 25.4 / 72);
    }
    return 0;
}

Voila, j’espère que cette méthode pourra vous être utile. A bientôt.

Compacter le vhdx d’un serveur Ubuntu virtualisé sur Hyper-v

Attention, AVANT TOUTE CHOSES:

  • Pour éviter tout problème, d’abord faire une sauvegarde de la machine virtuelle avant cette opération a faire à vos risques & périls
  • L’opération est longue, donc à faire a un moment ou la machine peut être arrêté suffisamment longtemps (genre 2h)

 La problématique:

Hyper-v fait croitre un disque dynamique mais ne le réduit jamais. Lorsqu’une machine travaille beaucoup en création/effacement de fichiers, le volume s’accroit sans jamais décroitre une fois l’activité terminée. Ce qui peut poser des problèmes de place et aussi des difficultés pour sauvegarder un vhdx devenu gigantesque.

Dans cette exemple, un serveur Ubuntu nommé srv-travail (serveur web de test) et autre nommé srv-web (serveur proxy) tous deux passés de Ubuntu V12 à V14.

0-avancompactage

Sur un Windows virtualisé, seule l’étape 2 de ce tutoriel serait nécessaire: il suffit d’ordonner à hyper-v de compacter l’image.
Mais un serveur Ubuntu virtualisé, le contenu de l’image n’est pas directement « comprise » par hyper-v, il faut faire une étape supplémentaire assez longue qui consiste à remplir l’espace vide de 0.

Ceci peut se faire grâce à la commande zerofree

Sauf que bien sûr, cette opération ne marche pas sur un volume en activité donc, il faut le faire en étant « offline ».
On peut donc facilement réaliser cette opération avec un système portable nommé SystemRescueCD

Il peut être téléchargé sur ce lien

http://sourceforge.net/projects/systemrescuecd/files/latest/download?source=typ_redirect

1ère Étape: le vidage de l’espace libéré

  • Arrêter votre machine virtuelle Ubuntu,
  • Chargez le l’image iso dans le lecteur cdrom virtuel de votre machine,
    1-insertioncd
  • Redémarrez votre machine => celle-ci va se lancer sur SystemRescueCD
    2-demarragesystemrescuecd
  • Choisissez l’option 1, le chargement se lance pour ne s’interrompre uniquement pour demander la définition du clavier.
  • Tapez fr puis entrer
  • Vous arrivez alors sur l’interface.
    3-arrivesurinterface
  • A ce point, deux possibilités soit votre système est installé sur un LVM, soit il est basé sur un partition normale:

Si votre système est créé sur une partition LVM:

vgchange -a y

=> cette instruction vous renvoi un warning a ignorer, mais aussi le nom du volume LVM.

  • zerofree /dev/[nom du volume LVM]/root

Si votre système est créé sur une partition normale:

Vous trouverez alors votre VHDX en /dev/sda1

  • zerofree /dev/sda1

Si vous avez réussi, l’opération est longue (genre 20mn à 1h). Si cela rend la main presque immédiatement, c’est qu’en sda1 est monté une partition de boot toute petite pour un volume LVM donc dans ce cas il faut suivre le process pour un volume LVM

Exemple en LVM sur la seconde machine, srv-web:

4-operationsurlvm

 

2ème étape: le compactage

Comme d’habitude ce qui fonctionnait très bien sur les versions précédentes (Windows 2008r2) ne fonctionne plus sur les version actuelles (Windows 2012r2), quand on demande le compactage du volume sous un Windows 2012r2… il ne se passe rien ! Génial ! Donc il faut le faire en PowerShell

Click droit sur votre icône Powershell puis « Exécuter en tant qu’Administrateur »
Dans la console PowerShell, vous devrez saisir les 3 instructions suivantes

Mount-VHD -Path "[chemin et nom du fichier]" -ReadOnly
Optimize-VHD -Path "[chemin et nom du fichier]" -Mode Full

5-compactagevhdx
Là aussi, cela dure assez longtemps… voire très longtemps…

Dismount-VHD "[chemin et nom du fichier]"

A noter que les commandes Mount et Dismount sont optionnelles, mais elles permettent de verrouiller le VHDX pendant l’opération pour diminuer les risques sur un environnement multi utilisateurs.

Opération terminée. Ejectez le cdrom du lecteur virtuel de la VM puis redémarrez.

Résultats

7-resultat

Dans mon exemple, j’ai gagné 6Go sur la VM srv-travail et 9Go sur la VM srv-travail. Sur d’autre machines ou j’ai effectué l‘opération, le gain a même été bien plus important. Ainsi sur un serveur de prod le vdhx est passé de 156Go à 27Go.

Dépasser les 2To sur un serveur HP Gen8 non équipé uEFI

Les serveurs HP de la gen8, contrairement à leurs équivalents IBM, ne sont pas équipés de rom uEFI.

C’est pourtant le pré-requis indispensable pour pouvoir booter sur un disque au format GPT, seul format Microsoft permettant le partitionnement de plus de 2To, capacité aujourd’hui très courante.

La seule solution est donc de créer deux lecteurs logiques sur le raid. L’un de 300Go par exemple qui restera en mbr pour être compatible avec le bios, et l’autre, qui servira pour les données qui sera converti en GPT depuis Windows après l’installation du système.

La 1ère étape est donc de créer cette configuration dans le raid avant de procéder a l’installation via l’intelligent provisionning:

hp1

Lors de cette étape, au moment de la création de la baie, il faudra refuser la proposition de lecteur logique incluant tout l’espace et lui redéfinir la taille à 300Go.
Une fois appliquée, créez un second lecteur logique avec la capacité restante.

hp2

hp3

Une fois cette configuration réalisée, vous pouvez installer le système d’exploitation, en indiquant a l’intelligent provisionning de ne pas toucher au réglage de la carte raid.

hp4

hp5

Une fois le système d’exploitation installé, vous pouvez alors convertir votre lecteur logique dédié au données en GPT.

hp6

Puis ensuite le formater.

hp7

Et enfin, vous aurez accès a l’ensemble de l’espace de votre RAID.

hp8

Billet d’humeur: Je trouve cependant très dommage que contrairement a IBM dont les serveurs de la série X sont équipé d’uEFI  depuis plus de 5 ans, HP, partenaire étroit de Microsoft, promoteur de l’uEFI depuis 2005, ne fasse que commencer a intégrer ce standard dans la gen9 et obligent ses utilisateurs au bricolage indiqué ci dessus. Standard pourtant intégré dans de simple cartes mères de PC à 99€…

 

Montage permanent d’un dossier ftp

Suivant l’article précédent permettant de monter un partage Windows de façon permanent sous Ubuntu.

Ceci est réaliser grâce a curlftp

apt-get install curlftp

Ensuite on ajoute le point de montage dans fstab:

vi /etc/fstab et ajouter la ligne

curlftpfs#(login):(pass)@(adresse) (dossier de montage) fuse rw,user,allow_other,uid=1000,utf8,_netdev 0 0

Puis

modprobe fuse

Référence:

http://doc.ubuntu-fr.org/curlftpfs

Remerciements à Maxime pour cette information.

Mettre à jour Windows 8.0 en 8.1 sans faire toutes les mises à jours du 8.0

En mettant a rude épreuve la patience de ses utilisateurs et l’écologie, Microsoft est très loin du « Green IT » dans sa démarche de mise à jour des ordinateurs neufs pré-installés en Windows 8.0 vers Windows 8.1.

En effet, il faut d’abord installer toutes les mises a jours (soit parfois 140 Mises à jours (près de 1,5Go) pour ensuite écraser le système par un autre… donc bien inutilement, puisque le système est remplacé.
(Réparer vous votre voiture avant de la mettre à la casse ?)

– Le coût carbone d’une telle démarche est lamentable.
– La perte de temps pour l’utilisateur l’est tout autant (surtout quand on sait que Windows 8.1 lui même dépasse les 3Go à télécharger et installer).
– Cerise sur le gâteau, sur certains ordinateurs neufs, il y a tellement de mise à jour a effectuer que le système se plante en tentant de les installer toutes.

 

Il existe une astuce pour éviter de faire l’ensemble des mises à jour du système que l’on va écraser:

1ère étape: on installe le correctif suivant:
http://support.microsoft.com/kb/2871389

Dans la barre d’adresse d’internet explorer, tapez

ms-windows-store:WindowsUpgrade

=> cela vous emmènera directement sur le store sur le package d’installation de 8.1.

Prévoyez cependant beaucoup de temps pour le téléchargement et l’installation de cette mise à jour très longue, a faire de préférence en branchant un câble réseau plutôt qu’en WIFI car en cas de coupure wifi… dommage.

Dans un monde pour Microsoft Windows n’est plus le système ultra dominant tel qu’il l’était il y a 10 ans, il serait peut-être temps que MICROSOFT prenne exemple sur MacOS qui passe en YOSEMITE sans toutes ces difficultés, idem pour UBUNTU lors d’une dist-upgrade. L’époque de la lourdeur institutionnalisée est révolue.

Bouton upload sans submit ni zone de texte (AJAX)

Après avoir chercher sur différents forums et site pour réaliser cela, voici une synthèse qui fonctionne.

Ce bouton permet de faire un upload de fichier en cliquant sur un seul bouton => dès que le fichier est sélectionnés, il est envoyé en POST en ajax.

Partie Javascript:

 $('.Bimport').click(function(e){
       e.preventDefault();
       $('Input[name="fichiercsv"]').click();
   });

   $('Input[name="fichiercsv"]').change(function (){
       $("#formimportcsv").submit();
   });

   $("body").on('submit','#formimportcsv', function(e) {
       e.preventDefault();
       $.ajax({
           type: 'POST',
           url: "/importcsv",
           data: new FormData(this),
           contentType: false,
           cache: false,    
           processData:false,  
           success: function (retour) {
               alert(retour);
               window.location.reload();
           },
           dataType: "html"
       });
  });

Partie HTML:

<form class="form-inline" action="/importcsv" method="post" role="form" id="formimportcsv" enctype="multipart/form-data">
    <a class='btn btn-primary Bimport' href=''>Import fichier TXT</a>
    <input type="file" style='position:absolute;z-index:2;top:0;left:0;filter: alpha(opacity=0);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0;background-color:transparent;color:transparent;' accept=".txt" name="fichiercsv" size="255">
</form>

 

Partie PHP (Laravel):

définir la route /importcsv » vers la fonction suivante:

public function importcsv(){
    $erreur="";

    if (!isset($_FILES["fichiercsv"])) {
         return "pas de réception de File";
    } else {

        if ($_FILES["fichiercsv"]["error"])
        {
            switch ($_FILES['fichiercsv']['error']){
                case 1: // UPLOAD_ERR_INI_SIZE
                     return "Le fichier dépasse la limite autorisée par le serveur (fichier php.ini) !";
                    break;
                case 2: // UPLOAD_ERR_FORM_SIZE
                     return "Le fichier dépasse la limite autorisée dans le formulaire HTML !";
                    break;
                case 3: // UPLOAD_ERR_PARTIAL
                     return "L'envoi du fichier a été interrompu pendant le transfert !";
                    break;
                case 4: // UPLOAD_ERR_NO_FILE
                     return "Le fichier que vous avez envoyé a une taille nulle !";
                    break;
            }

        }
        else {
            $typeautorises = Array('text/plain');
            if (!in_array($_FILES["fichiercsv"]["type"], $typeautorises)) {
                return 'Format non accepté';
            } else {
                if (!$_FILES["fichiercsv"]["name"]) {
                    return 'Nom de fichier vide';
                } else {
                    if ($_FILES["fichiercsv"]["size"] == 0) {
                        return 'Fichier reçu vide';
                    } else {
                    
                    // votre traitement ici

                    }

                }
            }
        }
    }
    return "Importation OK";
}

 

Explications:

  • Le champ input est invisible et le click du bouton affiché déclenche un click sur le champ caché.
  • Une fois le fichier choisi, l’évènement change déclenche la soumission du formulaire
  • La soumission est interceptée et envoyée en ajax.
  • La fonction PHP analyse la validité du fichier, puis exécute votre traitement.
  • Le texte renvoyé par la fonction PHP est affiché dans une boite d’alerte, puis la fenêtre html est réactualisée.

Compter pages couleurs et noires d’un PDF

Voici une routine qui devrait être utile à tout les développeurs d’applications pré-presse. Le principe peut-être retranscrit dans n’importe quel langage et s’appuie sur l’outil ghostscript.

<?php
/**
 * Created by Dominique FERET.
 * Date: 26/08/2014
 * Time: 09:56
 */
/**
 * Fonction qui analyse la nature des pages d'un pdf.
 * @param $nomfichier   => chemin et nom du fichier.
 * @return $this        => retourne un tableau encodé en JSON contenant la liste des pages de chaque type et leur comptes
 */
function analysepdf($nomfichier)
{
    header('content-type: application/json');
    mb_internal_encoding("UTF-8");

    $o = new stdClass();
    if (file_exists($nomfichier)){
        $commande = 'gs  -o - -q -sDEVICE=inkcov "' . $nomfichier . '"';
        $lignes = array();
        exec($commande, $lignes);
        $noir = 0;
        $couleur = 0;
        $blanche = 0;
        $pagesblanches=array();
        $pagesnoires=array();
        $pagescouleurs=array();
        $numeropage=0;
        foreach ($lignes as $ligne) {

            $cyan = substr($ligne, 1, 7);
            $magenta = substr($ligne, 10, 7);
            $yellow = substr($ligne, 19, 7);
            $black = substr($ligne, 28, 7);
            if (is_numeric($cyan)&& is_numeric($magenta) && is_numeric($yellow) && is_numeric($black)){ // si la ligne contient bien une ligne de valeurs
                $numeropage++; // on ajoute 1 a la ligne en cours
                if((($cyan+$magenta+$yellow)==0)){
                    $noir++;
                    if($black==0) {
                        $pagesblanches[]=$numeropage;
                        $blanche++;
                    }
                    $pagesnoires[]=$numeropage;
                }else{
                    $couleur++;
                    $pagescouleurs[]=$numeropage;
                }
            }

        }
        $o->listepagescouleurs=implode(",",$pagescouleurs);
        $o->listepagesnoires=implode(",",$pagesnoires);
        $o->listepagesblanches=implode(",",$pagesblanches);
        $o->totalpages = $numeropage;
        $o->pagesnoires = $noir;
        $o->pagescouleurs = $couleur;
        $o->pagesblanches = $blanche;
    }
    return json_encode($o);
}

Ubuntu 14.04 se bloque sous hyper-v

prompt

A l’instar de Windows, Ubuntu 14.04 comporte des « fonctionnalités »… appellé « bug » par le commun des mortels. :)
Ubuntu 14.04 virtualisé sous hyper-v, au bout d’un certain temps « gèle » aléatoirement. Le noyau 3.13 serait en cause ce qui explique pourquoi ubuntu 12.04LTS n’a pas ce problème.

 

 

La solution en attendant un correctif du noyau  (Edit du 17/10: ce problème est aujourd’hui réglé):

cd /etc/default
sudo vi grub

ajouter "nohz=off elevator=deadline transparent_hugepage=always" dans les paramètres de la ligne "GRUB_CMDLINE_LINUX_DEFAULT"

sauvegardez puis faire:

sudo update-grub

Ensuite dans le fichier /etc/sysctl.conf

Ajouter les lignes suivante

kernel.sched_min_granularity_ns=10000000
kernel.sched_wakeup_granularity_ns=15000000
vm.dirty_ratio=10
vm.dirty_background_ratio=5
vm.swappiness=10

Sauvegardez puis redémarrez

=> le système devrait être plus stable.

 

Modification du 9 Mai 2015:

Dans sa distribution 14.04.2, Ubuntu distribue le noyau 3.16. Celui bénéfie d’une meilleur integration dans un Hyper-v sous windows 2012r2. (Windows ne signale plus l’intégration comme dégradée). Pour en bénéficier, il suffit d’installer ce noyau en utilisant la commande:

sudo apt-get install linux-image-generic-lts-utopic