Index: /extensions/AMetaData/JpegMetaData/JpegMetaData.class.php
===================================================================
--- /extensions/AMetaData/JpegMetaData/JpegMetaData.class.php	(revision 4997)
+++ /extensions/AMetaData/JpegMetaData/JpegMetaData.class.php	(revision 4998)
@@ -113,4 +113,5 @@
 
   require_once(JPEG_METADATA_DIR."Readers/JpegReader.class.php");
+  require_once(JPEG_METADATA_DIR."TagDefinitions/MagicTags.class.php");
 
   class JpegMetaData
@@ -123,7 +124,8 @@
     const KEY_EXIF_EXIF = "exif.exif";
     const KEY_EXIF_GPS  = "exif.gps";
-    const KEY_EXIF = "exif";
-    const KEY_IPTC = "iptc";
-    const KEY_XMP  = "xmp";
+    const KEY_EXIF  = "exif";
+    const KEY_IPTC  = "iptc";
+    const KEY_XMP   = "xmp";
+    const KEY_MAGIC = "magic";
 
     private $jpeg = null;
@@ -157,5 +159,5 @@
      * xmp                  |
      * maker                | maker => returns specifics tags from all the known
-     *                      |          makers
+     * magic                |          makers
      *                      |
      * ---------------------+---------------------------------------------------
@@ -180,5 +182,6 @@
         'iptc'  => true,
         'xmp'   => true,
-        'maker' => true
+        'maker' => true,
+        'magic' => true,
       );
 
@@ -211,4 +214,7 @@
         $list[]="xmp";
 
+      if($default['magic'])
+        $list[]="magic";
+
       foreach($list as $val)
       {
@@ -232,4 +238,8 @@
             $tmp=new XmpTags();
             $schema="xmp";
+            break;
+          case "magic":
+            $tmp=new MagicTags();
+            $schema="magic";
             break;
           case MAKER_PENTAX:
@@ -281,4 +291,6 @@
           }
       }
+
+      ksort($returned);
 
       return($returned);
@@ -332,5 +344,5 @@
      * iptc                 | If set to true, the function returns all the tags
      * xmp                  | known for the specified type tag
-     *                      | the exif parameter include the maker tags
+     * magic                | the exif parameter include the maker tags
      *                      |
      * ---------------------+---------------------------------------------------
@@ -404,4 +416,11 @@
           }
         }
+
+        if($this->options['magic'])
+        {
+          $this->processMagicTags();
+        }
+
+        ksort($this->tags);
       }
     }
@@ -468,7 +487,8 @@
         'filter' => self::TAGFILTER_ALL,
         'optimizeIptcDateTime' => false,
-        'exif' => true,
-        'iptc' => true,
-        'xmp'  => true
+        'exif'  => true,
+        'iptc'  => true,
+        'xmp'   => true,
+        'magic' => true
       );
 
@@ -552,4 +572,109 @@
     }
 
+    /**
+     * MagicTags are build with this function
+     */
+    private function processMagicTags()
+    {
+      $magicTags=new MagicTags();
+
+      foreach($magicTags->getTags() as $key => $val)
+      {
+        $tag=new Tag($key,0,$key);
+
+        for($i=0; $i<count($val['tagValues']); $i++)
+        {
+          $found=true;
+          preg_match_all('/{([a-z0-9:\.\s\/]*)(\[.*\])?}/i', $val['tagValues'][$i], $returned, PREG_PATTERN_ORDER);
+          foreach($returned[1] as $testKey)
+          {
+            $found=$found & array_key_exists($testKey, $this->tags);
+          }
+          if(count($returned[1])==0) $found=false;
+
+          if($found)
+          {
+            $returned=trim(preg_replace_callback(
+                '/{([a-z0-9:\.\s\/\[\]]*)}/i',
+                Array(&$this, "processMagicTagsCB"),
+                $val['tagValues'][$i]
+            ));
+
+            $tag->setValue($returned);
+            $tag->setLabel($returned);
+            $tag->setKnown(true);
+            $tag->setImplemented($val['implemented']);
+            $tag->setTranslatable($val['translatable']);
+
+            $i=count($val['tagValues']);
+          }
+        }
+
+        if($tag->isImplemented() and $found)
+        {
+          $this->tags["magic.".$key]=$tag;
+        }
+
+        unset($tag);
+      }
+      unset($magicTags);
+    }
+
+    /**
+     * this function is called by the processMagicTags to replace tagId by the
+     * tag values
+     *
+     * @param Array $matches : array[1] = the tagId
+     * @return String : the tag value
+     */
+    private function processMagicTagsCB($matches)
+    {
+      $label="";
+      preg_match_all('/([a-z0-9:\.\s\/]*)\[(.*)\]/i', $matches[1], $result, PREG_PATTERN_ORDER);
+      if(count($result[0])>0)
+      {
+
+        if(array_key_exists($result[1][0], $this->tags))
+        {
+          $tag=$this->tags[$result[1][0]]->getLabel();
+
+          preg_match_all('/([a-z0-9:\.\s\/]*)\[(.*)\]/i', $result[2][0], $result2, PREG_PATTERN_ORDER);
+
+          if(count($result2[0])>0)
+          {
+            if(array_key_exists($result2[2][0], $tag[$result2[1][0]] ))
+              $label=$tag[$result2[1][0]][$result2[2][0]];
+          }
+          else
+          {
+            if(array_key_exists($result[2][0], $tag))
+              $label=$tag[$result[2][0]];
+          }
+        }
+      }
+      else
+      {
+        if(array_key_exists($matches[1], $this->tags))
+        {
+          $label=$this->tags[$matches[1]]->getLabel();
+        }
+      }
+
+      if($label instanceof DateTime)
+        return($label->format("Y-m-d H:i:s"));
+
+      $label=XmpTags::getAltValue($label, L10n::getLanguage());
+
+      if(is_array($label))
+        return(implode(", ", $label));
+
+      return(trim($label));
+    }
+
+
+
+    /**
+     * used by the destructor to clean variables
+     */
     private function unsetAll()
     {
Index: /extensions/AMetaData/JpegMetaData/Readers/IfdReader.class.php
===================================================================
--- /extensions/AMetaData/JpegMetaData/Readers/IfdReader.class.php	(revision 4997)
+++ /extensions/AMetaData/JpegMetaData/Readers/IfdReader.class.php	(revision 4998)
@@ -496,13 +496,22 @@
           $returned=Array(
             "computed" => (isset($tag['tagValues.computed'][$values])?$tag['tagValues.computed'][$values]:"unknown"),
-            "detail" => Array() );
-          foreach($tag['tagValues.specialNames'] as $key => $value)
-          {
-            $filter = $values & $key;
-            if(isset($tag['tagValues.specialValues'][$key][$filter]))
-              $returned["detail"][]=$tag['tagValues.specialValues'][$key][$filter];
-            else
-              $returned["detail"][]="unknown";
-          }
+            "detail" => Array()
+          );
+
+          $value=$values & 0x0001;
+          $returned["detail"][]=$tag['tagValues.specialValues'][0x0001][$value];
+
+          $value=($values & 0x0006)>>1;
+          $returned["detail"][]=$tag['tagValues.specialValues'][0x0006][$value];
+
+          $value=($values & 0x0018)>>3;
+          $returned["detail"][]=$tag['tagValues.specialValues'][0x0018][$value];
+
+          $value=($values & 0x0020)>>5;
+          $returned["detail"][]=$tag['tagValues.specialValues'][0x0020][$value];
+
+          $value=($values & 0x0040)>>6;
+          $returned["detail"][]=$tag['tagValues.specialValues'][0x0040][$value];
+
           break;
         case 0x920A: // FocalLength, tag 0x920A
Index: /extensions/AMetaData/JpegMetaData/Readers/PentaxReader.class.php
===================================================================
--- /extensions/AMetaData/JpegMetaData/Readers/PentaxReader.class.php	(revision 4997)
+++ /extensions/AMetaData/JpegMetaData/Readers/PentaxReader.class.php	(revision 4998)
@@ -148,9 +148,9 @@
         case 0x000c: // "Flash",
           $tag=$this->tagDef->getTagById(0x000c);
-          $returned="";
+          $returned=Array();
           if(array_key_exists($values[0], $tag['tagValues.special'][0]))
-            $returned.=$tag['tagValues.special'][0][$values[0]];
+            $returned[]=$tag['tagValues.special'][0][$values[0]];
           if(array_key_exists($values[1], $tag['tagValues.special'][1]))
-            $returned.=";".$tag['tagValues.special'][1][$values[1]];
+            $returned[]=";".$tag['tagValues.special'][1][$values[1]];
           unset($tag);
           break;
Index: /extensions/AMetaData/JpegMetaData/TagDefinitions/IfdTags.class.php
===================================================================
--- /extensions/AMetaData/JpegMetaData/TagDefinitions/IfdTags.class.php	(revision 4997)
+++ /extensions/AMetaData/JpegMetaData/TagDefinitions/IfdTags.class.php	(revision 4998)
@@ -977,5 +977,5 @@
       // flash, tag 0x9209, see EXIF 2.2 documentation
       0x9209 => Array(
-        'tagName'     => "flash",
+        'tagName'     => "Flash",
         'schema'      => "exif",
         'translatable'=> true,
@@ -990,9 +990,9 @@
                 ),
         'tagValues.specialValues' => Array(
-          0x0000 => Array( // b00000001
+          0x0001 => Array( // b00000001 => 'fired'
                   0x00 => "flash did not fire",
                   0x01 => "flash fired"
                 ),
-          0x0006 => Array( // b00000110
+          0x0006 => Array( // b00000110 => 'return'
                   0x00 => "no strobe",                        // 00
                   0x01 => "reserved",                         // 01
@@ -1000,15 +1000,15 @@
                   0x03 => "strobe return light detected"      // 11
                 ),
-          0x0018 => Array( // b00011000
+          0x0018 => Array( // b00011000 => 'mode'
                   0x00 => "unknown",
                   0x01 => "compulsory flash firing",
-                  0x10 => "compulsory flash suppression",
-                  0x11 => "auto mode"
+                  0x02 => "compulsory flash suppression",
+                  0x03 => "auto mode"
                 ),
-          0x0020 => Array( // b00100000
+          0x0020 => Array( // b00100000 => 'function'
                   0x00 => "flash function present",
                   0x01 => "no flash function"
                 ),
-          0x0040 => Array( // b01000000
+          0x0040 => Array( // b01000000 => 'red-eye'
                   0x00 => "no red-eye reduction mode or unknown",
                   0x01 => "red-eye reduction supported"
Index: /extensions/AMetaData/JpegMetaData/TagDefinitions/MagicTags.class.php
===================================================================
--- /extensions/AMetaData/JpegMetaData/TagDefinitions/MagicTags.class.php	(revision 4998)
+++ /extensions/AMetaData/JpegMetaData/TagDefinitions/MagicTags.class.php	(revision 4998)
@@ -0,0 +1,312 @@
+<?php
+/*
+ * --:: JPEG MetaDatas ::-------------------------------------------------------
+ *
+ *  Author    : Grum
+ *   email    : grum at piwigo.org
+ *   website  : http://photos.grum.fr
+ *
+ *   << May the Little SpaceFrog be with you ! >>
+ *
+ *
+ * +-----------------------------------------------------------------------+
+ * | JpegMetaData - a PHP based Jpeg Metadata manager                      |
+ * +-----------------------------------------------------------------------+
+ * | Copyright(C) 2010  Grum - http://www.grum.fr                          |
+ * +-----------------------------------------------------------------------+
+ * | This program is free software; you can redistribute it and/or modify  |
+ * | it under the terms of the GNU General Public License as published by  |
+ * | the Free Software Foundation                                          |
+ * |                                                                       |
+ * | This program is distributed in the hope that it will be useful, but   |
+ * | WITHOUT ANY WARRANTY; without even the implied warranty of            |
+ * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
+ * | General Public License for more details.                              |
+ * |                                                                       |
+ * | You should have received a copy of the GNU General Public License     |
+ * | along with this program; if not, write to the Free Software           |
+ * | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
+ * | USA.                                                                  |
+ * +-----------------------------------------------------------------------+
+ *
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * The MagicTags is the definition of the computed JpegMetadata tags
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * .. Notes ..
+ *
+ * The MagicTags class is derived from the KnownTags class.
+ *
+ * ======> See KnownTags.class.php to know more about the tag definitions <=====
+ *
+ */
+
+  require_once(JPEG_METADATA_DIR."TagDefinitions/KnownTags.class.php");
+
+  /**
+   * Define the "magic" JpegMetadata computed tags
+   *
+   * all tag are defined by a list of metadata
+   *
+   * all metadata are searched in the given list order by their name : if a
+   * given metadata in is not found in the image, the next is searched.
+   *
+   * in most case, according with the Xmp specification, list are defined in
+   * this order :
+   *  - exif tags
+   *  - iptc tags
+   *  - xmp tags
+   *
+   * In some case, the Xmp metadata are in the first place of the list, because
+   * Xmp allows to UTF-8 string and we can consider that if there is exif & xmp
+   * data, the localized UTF-8 is most important
+   *
+   */
+  class MagicTags extends KnownTags
+  {
+    protected $label = "Magic JpegMetadata computed tags";
+    protected $tags = Array(
+
+      'Camera.Make' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues'    => Array(
+          "{exif.tiff.Make}",
+          "{xmp.tiff:Make}",
+        )
+      ),
+
+      'Camera.Model' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues'    => Array(
+          "{exif.tiff.Model}",
+          "{xmp.tiff:Model}",
+        )
+      ),
+
+
+      'ShotInfo.Aperture' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues'    => Array(
+          "{exif.exif.FNumber}",
+          "{xmp.exif:FNumber}",
+          "{exif.exif.ApertureValue}",
+          "{xmp.exif:ApertureValue}",
+        )
+      ),
+
+      'ShotInfo.Exposure' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues'    => Array(
+          "{exif.exif.ExposureTime}",
+          "{xmp.exif:ExposureTime}",
+          "{exif.exif.ShutterSpeedValue}",
+          "{xmp.exif:ShutterSpeedValue}",
+        )
+      ),
+
+      'ShotInfo.ISO' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues'    => Array(
+          "{exif.exif.ISOSpeedRatings}",
+          "{exif.Pentax.ISO}",
+          "{exif.Canon.CanonShotInfo.BaseISO}",
+          "{xmp.exif:ISOSpeedRatings}",
+        )
+      ),
+
+      'ShotInfo.FocalLength' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues'    => Array(
+          "{exif.exif.FocalLength}",
+          "{xmp.exif:FocalLength}",
+          "{exif.Pentax.FocalLength}",
+          "{exif.Canon.CanonCameraInfo.FocalLength}",
+        )
+      ),
+
+      'ShotInfo.FocalLengthIn35mm' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues'    => Array(
+          "{exif.exif.FocalLengthIn35mm}",
+          "{xmp.exif:FocalLengthIn35mm}",
+        )
+      ),
+
+      'ShotInfo.Lens' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues'    => Array(
+          "{exif.Pentax.LensType}",
+          "{exif.Nikon.Lens}",
+          "{exif.Canon.CanonCameraSettings.LensType}",
+          "{exif.Canon.CanonCameraInfo.LensType}",
+          "{xmp.aux:Lens}",
+          "{xmp.aux:LensID}", // work with the Xmp LensId is not the best way to
+                              // know the lens (all data needed to find the
+                              // exact lens are not available in xmp metadata)
+        )
+      ),
+
+      'ShotInfo.DateTime' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues'    => Array(
+          "{exif.exif.DateTimeOriginal}",
+          "{exif.exif.DateTimeDigitized}",
+          "{xmp.exif:DateTimeOriginal}",
+          "{xmp.exif:DateTimeDigitized}",
+        )
+      ),
+
+      'ShotInfo.Flash.Fired' => Array(
+        'implemented'  => true,
+        'translatable' => true,
+        'tagValues'    => Array(
+          "{exif.exif.Flash[detail[0]]}",
+          "{xmp.exif:Fired}",
+        )
+      ),
+
+      'ShotInfo.Flash.RedEyeMode' => Array(
+        'implemented'  => true,
+        'translatable' => true,
+        'tagValues'    => Array(
+          "{exif.exif.Flash[detail[4]]}",
+          "{xmp.exif:RedEyeMode}",
+        )
+      ),
+
+
+      'Image.Width' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues'    => Array(
+          "{exif.exif.PixelXDimension}",
+          "{exif.tiff.ImageWidth}",
+          "{xmp.exif:PixelXDimension}",
+          "{xmp.tiff:ImageWidth}",
+        )
+      ),
+
+      'Image.Height' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues'    => Array(
+          "{exif.exif.PixelYDimension}",
+          "{exif.tiff.ImageHeight}",
+          "{xmp.exif:PixelYDimension}",
+          "{xmp.tiff:ImageHeight}",
+        )
+      ),
+
+      'Image.Dimension' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues' => Array(
+          "{magic.Image.Width}x{magic.Image.Height}"
+        )
+      ),
+
+      'Author.ImageTitle' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues' => Array(
+          "{xmp.dc:title}",
+          "{exif.tiff.ImageDescription}",
+          "{iptc.Object Name}",
+        )
+      ),
+
+      'Author.Artist' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues' => Array(
+          "{xmp.dc:creator[values]}",
+          "{exif.tiff.Artist}",
+          "{iptc.Writer/Editor}",
+        )
+      ),
+
+      'Author.Copyright' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues' => Array(
+          "{xmp.dc:rights}",
+          "{exif.tiff.Copyright}",
+          "{iptc.Copyright Notice}"
+        )
+      ),
+
+      'Author.Comment' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues' => Array(
+          "{xmp.dc:description}",
+          "{iptc.Caption/Abstract}",
+          "{exif.exif.UserComment}",
+        )
+      ),
+
+      'Processing.PostProcessingSoftware' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues' => Array(
+          "{exif.tiff.ProcessingSoftware}",
+          "{exif.tiff.Software}",
+          "{xmp.tiff:Software}",
+          "{xmp.xmp:CreatorTool}",
+          "{iptc.Originating Program} {iptc.Program Version}",
+        )
+      ),
+
+      'Processing.Software' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues' => Array(
+          "{exif.tiff.Software}",
+          "{xmp.tiff:Software}",
+          "{xmp.dc:CreatorTool}",
+          "{exif.Canon.CanonFirmwareVersion}",
+        )
+      ),
+
+      'Processing.OriginalFileName' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues' => Array(
+          "{exif.tiff.DocumentName}",
+          "{xmp.crs:RawFileName}",
+        )
+      ),
+
+      'Processing.PostProcessingDateTime' => Array(
+        'implemented'  => true,
+        'translatable' => false,
+        'tagValues' => Array(
+          "{exif.tiff.DateTime}",
+          "{xmp.xmp:ModifyDate}",
+        )
+      ),
+
+    );
+
+
+    function __destruct()
+    {
+      parent::__destruct();
+    }
+
+  }
+
+
+?>
Index: /extensions/AMetaData/JpegMetaData/TagDefinitions/XmpTags.class.php
===================================================================
--- /extensions/AMetaData/JpegMetaData/TagDefinitions/XmpTags.class.php	(revision 4997)
+++ /extensions/AMetaData/JpegMetaData/TagDefinitions/XmpTags.class.php	(revision 4998)
@@ -48,4 +48,46 @@
   class XmpTags extends KnownTags
   {
+    /**
+     * this function extract from an Xmp Alt structure, the value in the given
+     * lang
+     *
+     * @param Array $tagValues :
+     * @param String $lang : the needed lang
+     * @return String : the value in the specified lang, or in the default lang
+     *                  if there is no specific value for the specified lang
+     */
+    static public function getAltValue($tagValues, $lang="x-default")
+    {
+      /*
+       * test if the $tagValues is valid, otherwise return the $tagValues as
+       * result
+       */
+      if(!is_array($tagValues)) return($tagValues);
+      if(!array_key_exists("type", $tagValues) or
+         !array_key_exists("values", $tagValues) )
+         return($tagValues);
+      if($tagValues['type']!="alt") return($tagValues);
+
+      $returned="";
+      foreach($tagValues['values'] as $key => $val)
+      {
+        if($val['type']['value']==$lang or
+           XmpTags::lang($val['type']['value'])==$lang or
+           $val['type']['value']=="x-default")
+          $returned=$val['value'];
+      }
+      return($returned);
+    }
+
+    /**
+     * this function tries to format the lang Id
+     * something like "fr-fr" is returned as "fr_FR"
+     */
+    static private function lang($lang)
+    {
+      $result=preg_match("/([a-z]*)([-|_])([a-z]*)/i", $lang, $arr);
+      return($arr[1]."_".strtoupper($arr[3]));
+    }
+
     const TYPE_SIMPLE = 0x00;
     const TYPE_SEQ = 0x01;
@@ -1308,5 +1350,6 @@
 /*
  * The Flash is a sequence of Flash structure
- * Not yet implemented
+ * Don't use the exif:Flash, but the associated tags :
+ *  exif:Fired, exif:Return, exif:Mode, exif:Function, exif:RedEyeMode
  */
       'exif:Flash' => Array(
@@ -1317,4 +1360,64 @@
         'schema'       => "exif",
       ),
+
+      'exif:Fired' => Array(
+        'implemented'  => true,
+        'translatable' => true,
+        'type'         => self::TYPE_SIMPLE,
+        'schema'       => "exif",
+        'tagValues' => Array(
+            'False' => "flash did not fire",
+            'True'  => "flash fired"
+        ),
+      ),
+
+      'exif:Return' => Array(
+        'implemented'  => true,
+        'translatable' => true,
+        'type'         => self::TYPE_SIMPLE,
+        'schema'       => "exif",
+        'tagValues' => Array(
+            0x00 => "no strobe",
+            0x01 => "reserved",
+            0x02 => "strobe return light not detected",
+            0x03 => "strobe return light detected"
+        ),
+      ),
+
+      'exif:Mode' => Array(
+        'implemented'  => true,
+        'translatable' => true,
+        'type'         => self::TYPE_SIMPLE,
+        'schema'       => "exif",
+        'tagValues' => Array(
+            0x00 => "unknown",
+            0x01 => "compulsory flash firing",
+            0x02 => "compulsory flash suppression",
+            0x03 => "auto mode"
+        ),
+      ),
+
+      'exif:Function' => Array(
+        'implemented'  => true,
+        'translatable' => true,
+        'type'         => self::TYPE_SIMPLE,
+        'schema'       => "exif",
+        'tagValues' => Array(
+            'False' => "flash function present",
+            'True'  => "no flash function"
+        ),
+      ),
+
+      'exif:RedEyeMode' => Array(
+        'implemented'  => true,
+        'translatable' => true,
+        'type'         => self::TYPE_SIMPLE,
+        'schema'       => "exif",
+        'tagValues' => Array(
+            'False' => "no red-eye reduction mode or unknown",
+            'True'  => "red-eye reduction supported"
+          ),
+      ),
+
       'exif:FocalLength' => Array(
         'exifTag'      => 0x920A,
