Fermer2
flankerLe 02/01/2009 à 21:01
Voilà, pour faire un listing Apache un peu plus joli que celui de base, je me suis dit que j'allais récupérer les icônes de fichier. Comme je suis un gros flemmard, récupérer les icônes .icns à la main pour chaque type de fichier (puis les convertir en gif ou png) m'a semblé insurmontable, et j'ai fait un script grin #!/usr/bin/php <?php $TMP_DIR = '.'; $DST_DIR = 'icones'; if(count($argv) <= 1) die("usage : ". $argv[0]. " file.app \n");  $file_app = $argv[1]; $info_plist = "$file_app/Contents/Info.plist"; if(!is_file($info_plist)) die("Invalid .app file\n"); echo "$file_app \n"; $xml_file = "$TMP_DIR/info.xml"; if(!is_dir($TMP_DIR)) `mkdir -p "$TMP_DIR"`; if(!is_dir($DST_DIR)) `mkdir -p "$DST_DIR"`; // on le convertit directement en XML `/usr/bin/plutil -convert xml1 -o "$xml_file" "$info_plist"`; $xml = simplexml_load_file($xml_file); unlink($xml_file); $loc_types = FALSE; $document_types = FALSE; $xml = $xml->children(); foreach($xml->children() as $child) {      if(($child->getName() == 'key') && ((string) $child == 'CFBundleDocumentTypes')) {           $loc_types = TRUE;           }      elseif(($loc_types) && ($child->getName() == 'array')) {           $document_types = $child;           break;      }      else           $loc_types = FALSE; } if($document_types === FALSE) die();// pas d'association de fichiers foreach($document_types->children() as $child) {      if($child->getName() != 'dict') continue;      $loc_extensions = FALSE;      $loc_iconfile = FALSE;      $loc_typefile = FALSE;      $loc_mimes = FALSE;      $extensions = FALSE;      $mimes = FALSE;      $iconefile = FALSE;      $typefile = "";      foreach($child->children() as $subchild) {           if(($subchild->getName() == 'key') && ((string) $subchild == 'CFBundleTypeExtensions')) {                $loc_extensions = TRUE;                $loc_iconfile = FALSE;                $loc_typefile = FALSE;                $loc_mimes = FALSE;           }           elseif(($subchild->getName() == 'key') && ((string) $subchild == 'CFBundleTypeIconFile')) {                $loc_extensions = FALSE;                $loc_typefile = FALSE;                $loc_iconfile = TRUE;                $loc_mimes = FALSE;           }           elseif(($subchild->getName() == 'key') && ((string) $subchild == 'CFBundleTypeMIMETypes')) {                $loc_extensions = FALSE;                $loc_mimes = TRUE;                $loc_typefile = FALSE;                $loc_iconfile = TRUE;           }           elseif(($subchild->getName() == 'key') && ((string) $subchild == 'CFBundleTypeName')) {                $loc_extensions = FALSE;                $loc_iconfile = FALSE;                $loc_typefile = TRUE;                $loc_mimes = FALSE;           }           elseif(($subchild->getName() == 'array') && ($loc_mimes)) {                $mimes = $subchild;                $loc_extensions = FALSE; $loc_iconfile = FALSE; $loc_typefile = FALSE; $loc_mimes = FALSE;           }           elseif(($subchild->getName() == 'array') && ($loc_extensions)) {                $extensions = $subchild;                $loc_extensions = FALSE; $loc_iconfile = FALSE; $loc_typefile = FALSE; $loc_mimes = FALSE;           }           elseif(($subchild->getName() == 'string') && ($loc_iconfile)) {                $iconefile = 'Resources/' . (string) $subchild ;                if((substr($iconefile, -5) != '.icns')&&(substr($iconefile, -5) != '.tiff'))                     $iconefile .= '.icns';                $loc_extensions = FALSE; $loc_iconfile = FALSE; $loc_typefile = FALSE; $loc_mimes = FALSE;           }           elseif(($subchild->getName() == 'string') && ($loc_typefile)) {                $typefile = (string) $subchild;                $loc_extensions = FALSE; $loc_iconfile = FALSE; $loc_typefile = FALSE; $loc_mimes = FALSE;           }      }      if(($iconefile === FALSE) || ($extensions === FALSE)) continue;      $fileextensions = array();      foreach($extensions->children() as $subchild) {           if($subchild->getName() != 'string') continue;           $fileextension = (string) $subchild;           $fileextensions[] = $fileextension;           echo "$fileextension ";      }      echo " : $iconefile \n";      //pour chacune des extensions, on va  créer un dossier contenant toutes les informations       foreach($fileextensions as $ext) {           $ext = strtolower($ext);           if($ext == '*') continue;           $src_file = "$file_app/Contents/$iconefile";           if(!is_file($src_file)) continue;           $dst = "$DST_DIR/$ext";           $b = basename($src_file);           $t = strrpos($b, '.');           if(($t = strrpos($b, '.')) !== FALSE) { $pic_base = substr($b, 0, $t); $pic_ext = substr($b, $t + 1); }           else { $pic_base = $b; $pic_ext = ''; }           if($pic_ext !== 'icns') continue;// ce n'est pas un fichier icns, on zappe           if(!is_dir($dst)) mkdir($dst);// on crée un dossier qui va bien            // maintenant, on calcule le nom du fichier icns           $md5 = FALSE;//pour éviter les fichiers en double !            $c = FALSE;           while(is_file("$dst/$pic_base.icns")) {                if($md5 === FALSE) $md5 = md5_file($src_file);                if(md5_file("$dst/$pic_base.icns") == $md5) { $c = TRUE; break; }// le fichier existe déjà, on zappe                if(($t = strrpos($pic_base, '-')) !== FALSE) {                     $i = (int) substr($pic_base, $t + 1);                      if($i > 0) { $i++; $pic_base = substr($pic_base, 0, $t) . "- $i"; }                     else $pic_base .= " - 1";                }                else $pic_base .= " - 1";           }           if($c) continue;// le fichier existe déjà, on zappe           //on a le nom du fichier ICNS           //on peut copier le fichier dans la destination           copy("$file_app/Contents/$iconefile", "$dst/$pic_base.icns");           `icns2png -x -s 16 -d 32 -o "$dst" "$dst/$pic_base.icns" 2> /dev/null`;           `icns2png -x -s 32 -d 32 -o "$dst" "$dst/$pic_base.icns" 2> /dev/null`;           `icns2png -x -s 128 -d 32 -o "$dst" "$dst/$pic_base.icns" 2> /dev/null`;           $infos = "<icns>${pic_base}.icns</icns>";           `echo "$infos" >> "$dst/infos.xml"`;           if(is_file("$dst/${pic_base}_16x16x32.png")) {                `convert "$dst/${pic_base}_16x16x32.png" "$dst/${pic_base}_16x16x32.gif" 2> /dev/null`;                $infos = "<png16>${pic_base}_16x16x32.png</png16>\n<gif16>${pic_base}_16x16x32.gif</gif16>";                `echo "$infos" >> "$dst/infos.xml"`;           }           if(is_file("$dst/${pic_base}_32x32x32.png")) {                `convert "$dst/${pic_base}_32x32x32.png" "$dst/${pic_base}_32x32x32.gif" 2> /dev/null`;                $infos = "<png32>${pic_base}_32x32x32.png</png32>\n<gif32>${pic_base}_32x32x32.gif</gif32>";                `echo "$infos" >> "$dst/infos.xml"`;           }           if(is_file("$dst/${pic_base}_128x128x32.png")) {                `convert "$dst/${pic_base}_128x128x32.png" "$dst/${pic_base}_128x128x32.gif" 2> /dev/null`;                $infos = "<png128>${pic_base}_128x128x32.png</png128>\n<gif128>${pic_base}_128x128x32.gif</gif128>";                `echo "$infos" >> "$dst/infos.xml"`;           }           //maintenant, on va chercher des informations           if(!is_file("$dst/filext.html")) {                `curl -o $dst/filext.html http://filext.com/file-extension/$ext 2> /dev/null`;                $filext = file_get_contents("$dst/filext.html");                $mimes = array();                if(strpos($filext, "<h3>Ooops </h3>") === FALSE) {//le type existe bel et bien                     $t = strpos($filext, '<h3>');                     $filext = substr($filext, 0, $t);                     $next = 0;                     while(($next = strpos($filext, '<table width="100%" border="1" align="center" cellpadding="3" cellspacing="1" bordercolor="#0000CC">', $next + 1)) !== FALSE) {                          $t1 = strpos($filext, '<strong>MIME Type</strong>', $next);                          $t1 = strpos($filext, '<tr>', $t1);                          $t1 = strpos($filext, '<td>', $t1);                          $t2 = strpos($filext, '</td>', $t1);                          $t = trim(substr($filext, $t1 + 4, $t2 - $t1 - 4));                          if((strpos($t, 'spacer.gif') === FALSE) && ($t !== '')) {                               $t = explode(' <br> ', $t);                               foreach($t as $u) {                                    if(strpos($u, '/') !== FALSE) $mimes[] = $u;                                    $infos = "<mime>$u</mime>";                                    `echo "$infos" >> "$dst/infos.xml"`;                               }                          }                     }                }           } #          `curl -o http://www.fileinfo.net/extension/$ext $TMP_DIR/$ext`;           $infos = "<short_desc>$typefile</short_desc>";           `echo "$infos" >> "$dst/infos.xml"`;      } } ?> Et je me suis dit que ça pourrait en intéresser d'autres


Ce qu'il fait :
- il prend en argument un dossier .app,
- va lire le Info.plist (préalablement converti en XML),
- extrait les différents extension de fichier reconnus par cette application et les icônes qui lui sont associées.
- Chaque extension va avoir droit à son dossier personnel.
- Ensuite, il recopie pour chaque extension l'icône .ICNS kivabien
- extrait les images du .ICNS au format .PNG (en 16x16, 32x32 et 128x128) (demande icns2png),
- convertit les images PNG au format .GIF (demande convert)
- va chercher sur filext des informations
- finit par créer un fichier info.xml (toujours dans le même dossier), contenant les noms des icônes, les mime_type et une courte description.

Par exemple, si je lance ce script sur Safari.app, je vais avoir un dossier css, avec infos.xml contenant
<icns>document.icns</icns>
<png16>document_16x16x32.png</png16>
<gif16>document_16x16x32.gif</gif16>
<png32>document_32x32x32.png</png32>
<gif32>document_32x32x32.gif</gif32>
<png128>document_128x128x32.png</png128>
<gif128>document_128x128x32.gif</gif128>
<mime>text/css</mime>
<mime>application/css-stylesheet</mime>
<short_desc>CSS style sheet</short_desc>


(bon, j'avais oublié que ce n'était pas du XML valide, mais c'est nettement plus chiant de faire du valide sad )
Du coup, comme toutes les informations sont dans le XML, c'est facile d'adapter le paquet d'icônes obtenues à un autre usage, et je me suis dit que ça pourrait en intéresser d'autres smile

Pour le lancer, je me suis fait un meta-script
for i in /Applications/*.app; do ./bin/app2icns.php "$i"; done; 
for i in /Applications/Utilities/*.app; do ./bin/app2icns.php "$i"; done; 
for i in /System/Library/CoreServices/*.app; do ./bin/app2icns.php "$i"; done; 
for i in /Developer/Applications/*.app; do ./bin/app2icns.php "$i"; done; 
for i in /Developer/Applications/Utilities/*.app; do ./bin/app2icns.php "$i"; done; 


En revanche, je n'ai pas tellement d'idée pour régler les conflits sad (vu que plein d'applications redéfinissent des icônes pour les mêmes extensions)


(je ne distribue pas le résultat parce que les icônes ont sûrement des ©, mais on peut toujours me demander ^^)