2005-06-19 Alexander Olk <xenomorph2@onlinehome.de>
authorAlexander Olk <aolk@mono-cvs.ximian.com>
Sun, 19 Jun 2005 11:58:51 +0000 (11:58 -0000)
committerAlexander Olk <aolk@mono-cvs.ximian.com>
Sun, 19 Jun 2005 11:58:51 +0000 (11:58 -0000)
* Mime.cs:
- added inodes.
- return application/x-zerosize for files with size zero
  (if no extension pattern matches).
- check matches collection for strings too.
- return only the first mime type if the name value
  collection has more than one mime type.

svn path=/trunk/mcs/; revision=46214

mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Mime.cs

index 5377a1ac6e1e052fa89175939465112e3c6acda2..e11847d7519f406a0f46a986699527ffc7273a2d 100644 (file)
@@ -1,3 +1,13 @@
+2005-06-19  Alexander Olk  <xenomorph2@onlinehome.de>
+
+       * Mime.cs:
+       - added inodes.
+       - return application/x-zerosize for files with size zero
+         (if no extension pattern matches).
+       - check matches collection for strings too.
+       - return only the first mime type if the name value
+         collection has more than one mime type.
+
 2005-06-18  Jonathan Chambers <jonathan.chambers@ansys.com>
        
        * PropertyGrid.cs: Cleaned up some TODOs
index e1e8c2037af002ba55456c6899074864968f378b..d90b92a82647f6ba394a9816add96336369cb2ae 100644 (file)
@@ -29,6 +29,7 @@ using System.IO;
 using System.Collections;
 using System.Collections.Specialized;
 using System.Text.RegularExpressions;
+using System.Text;
 
 // Usage:
 // - for files:
@@ -47,172 +48,15 @@ using System.Text.RegularExpressions;
 
 // TODO:
 // - optimize
-// - some stuff returns more then one mime type (means result string has more then one mime type) -> fix me
 // - little/big endian stuff for TypeHostXX
-// - inode/... ?
 // - async callback ?!?
 // - freedesktop org file extensions can have regular expressions also, resolve them too
 // - sort match collections by magic priority ( higher = first )
 // - MimeGenerated: use indexes to point to mime type name strings instead of repeating the name string each time (in match, subclass, etc.) !?!
-// - shrink mime_file_cache after some time ?!?
-// - buffer is currently hard coded to 8192, value should be determined by MimeGenerated
+// - buffer is currently hard coded to size 8192, value should be determined by MimeGenerated
 
 namespace System.Windows.Forms
 {
-       internal class MimeType
-       {
-               private string comment;
-               private Hashtable commentsLanguage = new Hashtable();
-               
-               public string Comment
-               {
-                       get {
-                               return comment;
-                       }
-                       set {
-                               comment = value;
-                       }
-               }
-               
-               public Hashtable CommentsLanguage
-               {
-                       get {
-                               return commentsLanguage;
-                       }
-                       set {
-                               commentsLanguage = value;
-                       }
-               }
-               public string GetCommentForLanguage( string language )
-               {
-                       return commentsLanguage[ language ] as string;
-               }
-       }
-       
-       internal enum MatchTypes
-       {
-               TypeString,
-               TypeHost16,
-               TypeHost32,
-               TypeBig16,
-               TypeBig32,
-               TypeLittle16,
-               TypeLittle32,
-               TypeByte
-       }
-       
-       internal class Match
-       {
-               string mimeType;
-               byte[] byteValue;
-               byte[] mask = null;
-               int priority;
-               int offset;
-               int offsetLength;
-               int wordSize = 1;
-               MatchTypes matchType;
-               ArrayList matches = new ArrayList();
-               
-               public string MimeType
-               {
-                       set {
-                               mimeType = value;
-                       }
-                       
-                       get {
-                               return mimeType;
-                       }
-               }
-               
-               public byte[] ByteValue
-               {
-                       set {
-                               byteValue = value;
-                       }
-                       
-                       get {
-                               return byteValue;
-                       }
-               }
-               
-               public byte[] Mask
-               {
-                       set {
-                               mask = value;
-                       }
-                       
-                       get {
-                               return mask;
-                       }
-               }
-               
-               public int Priority
-               {
-                       set {
-                               priority = value;
-                       }
-                       
-                       get {
-                               return priority;
-                       }
-               }
-               
-               public ArrayList Matches
-               {
-                       set {
-                               matches = value;
-                       }
-                       
-                       get {
-                               return matches;
-                       }
-               }
-               
-               public int Offset
-               {
-                       set {
-                               offset = value;
-                       }
-                       
-                       get {
-                               return offset;
-                       }
-               }
-               
-               public int OffsetLength
-               {
-                       set {
-                               offsetLength = value;
-                       }
-                       
-                       get {
-                               return offsetLength;
-                       }
-               }
-               
-               public int WordSize
-               {
-                       set {
-                               wordSize = value;
-                       }
-                       
-                       get {
-                               return wordSize;
-                       }
-               }
-               
-               public MatchTypes MatchType
-               {
-                       set {
-                               matchType = value;
-                       }
-                       
-                       get {
-                               return matchType;
-                       }
-               }
-       }
-       
        public class Mime
        {
                public static Mime Instance = new Mime();
@@ -226,13 +70,20 @@ namespace System.Windows.Forms
                
                private const string octet_stream = "application/octet-stream";
                private const string text_plain = "text/plain";
+               private const string zero_file = "application/x-zerosize";
                
                private StringDictionary mime_file_cache = new StringDictionary();
                
+               private const int mime_file_cache_max_size = 5000;
+               
                private string search_string;
                
                private static object lock_object = new Object();
                
+               private int platform = (int) Environment.OSVersion.Platform;
+               
+               private bool is_zero_file = false;
+               
                public Mime( )
                {
                        MimeGenerated.Init( );
@@ -261,7 +112,6 @@ namespace System.Windows.Forms
                        return Instance.global_result;
                }
                
-               // not tested
                public static string GetMimeTypeForString( string input )
                {
                        lock ( lock_object )
@@ -302,12 +152,28 @@ namespace System.Windows.Forms
                        }
                        
                        current_file_name = filename;
-                       global_result = octet_stream;
+                       is_zero_file = false;
                        
-                       GoByFileName( );
+                       if ( !CheckForInode( ) )
+                       {
+                               global_result = octet_stream;
+                               
+                               GoByFileName( );
+                       }
                        
                        if ( !mime_file_cache.ContainsKey( current_file_name ) )
                                mime_file_cache.Add( current_file_name, global_result );
+                       
+                       // not tested
+                       if ( mime_file_cache.Count > mime_file_cache_max_size )
+                       {
+                               IEnumerator enumerator = mime_file_cache.GetEnumerator( );
+                               
+                               for ( int i = 0; i < mime_file_cache_max_size - 1000; i++ )
+                               {
+                                       mime_file_cache.Remove( enumerator.Current.ToString( ) );
+                               }
+                       }
                }
                
                private void StartDataLookup( byte[] data )
@@ -344,6 +210,63 @@ namespace System.Windows.Forms
                                return;
                }
                
+               private bool CheckForInode( )
+               {
+                       if ( ( platform == 4 ) || ( platform == 128 ) )
+                       {
+                               // *nix platform
+                               Mono.Unix.UnixFileInfo ufi = new Mono.Unix.UnixFileInfo( current_file_name );
+                               
+                               if ( ufi.IsFile )
+                               {
+                                       return false;
+                               }
+                               else
+                               if ( ufi.IsDirectory )
+                               {
+                                       global_result = "inode/directory";
+                                       return true;
+                               }
+                               else
+                               if ( ufi.IsBlockDevice )
+                               {
+                                       global_result = "inode/blockdevice";
+                                       return true;
+                               }
+                               else
+                               if ( ufi.IsSocket )
+                               {
+                                       global_result = "inode/socket";
+                                       return true;
+                               }
+                               else
+                               if ( ufi.IsSymbolicLink )
+                               {
+                                       global_result = "inode/symlink";
+                                       return true;
+                               }
+                               else
+                               if ( ufi.IsCharacterDevice )
+                               {
+                                       global_result = "inode/chardevice";
+                                       return true;
+                               }
+                               else
+                               if ( ufi.IsFIFO )
+                               {
+                                       global_result = "inode/fifo";
+                                       return true;
+                               }
+                       }
+                       else
+                       {
+                               // TODO!!!!
+                               // windows platform
+                       }
+                       
+                       return false;
+               }
+               
                private void GoByFileName( )
                {
                        // check if we can open the file
@@ -356,14 +279,24 @@ namespace System.Windows.Forms
                                return;
                        }
                        
-                       // check for matches with a priority >= 80
-                       if ( CheckMatch80Plus( ) )
-                               return;
+                       if ( !is_zero_file )
+                       {
+                               // check for matches with a priority >= 80
+                               if ( CheckMatch80Plus( ) )
+                                       return;
+                       }
                        
                        // check global patterns, aka file extensions...
+                       // this should be done for zero size files also,
+                       // for example zero size file trash.ccc~ should return
+                       // application/x-trash instead of application/x-zerosize
                        if ( CheckGlobalPatterns( ) )
                                return;
                        
+                       // if file size is zero, no other checks are needed
+                       if ( is_zero_file )
+                               return;
+                       
                        // ok, still nothing matches then try matches with a priority < 80
                        if ( CheckMatchBelow80( ) )
                                return;
@@ -387,6 +320,16 @@ namespace System.Windows.Forms
                        return false;
                }
                
+               private void CheckGlobalResult( )
+               {
+                       int comma_index = global_result.IndexOf( "," );
+                       
+                       if ( comma_index != -1 )
+                       {
+                               global_result = global_result.Substring( 0, comma_index );
+                       }
+               }
+               
                private bool CheckGlobalPatterns( )
                {
                        string filename = Path.GetFileName( current_file_name );
@@ -404,6 +347,7 @@ namespace System.Windows.Forms
                                        if ( key.Equals( filename ) )
                                        {
                                                global_result = MimeGenerated.GlobalLiterals[ i ];
+                                               CheckGlobalResult( );
                                                return true;
                                        }
                                }
@@ -412,6 +356,7 @@ namespace System.Windows.Forms
                                        if ( Regex.IsMatch( filename, key ) )
                                        {
                                                global_result = MimeGenerated.GlobalLiterals[ i ];
+                                               CheckGlobalResult( );
                                                return true;
                                        }
                                }
@@ -428,6 +373,7 @@ namespace System.Windows.Forms
                                        if ( filename.EndsWith( key ) )
                                        {
                                                global_result = MimeGenerated.GlobalPatternsLong[ i ];
+                                               CheckGlobalResult( );
                                                return true;
                                        }
                                        else
@@ -435,6 +381,7 @@ namespace System.Windows.Forms
                                                if ( filename_lower.EndsWith( key ) )
                                                {
                                                        global_result = MimeGenerated.GlobalPatternsLong[ i ];
+                                                       CheckGlobalResult( );
                                                        return true;
                                                }
                                        }
@@ -450,6 +397,7 @@ namespace System.Windows.Forms
                                        
                                        if ( global_result != null )
                                        {
+                                               CheckGlobalResult( );
                                                return true;
                                        }
                                        
@@ -459,6 +407,7 @@ namespace System.Windows.Forms
                                        
                                        if ( global_result != null )
                                        {
+                                               CheckGlobalResult( );
                                                return true;
                                        }
                                }
@@ -475,6 +424,7 @@ namespace System.Windows.Forms
                                        if ( filename.EndsWith( key.Replace( "*", "" ) ) )
                                        {
                                                global_result = MimeGenerated.GlobalSufPref[ i ];
+                                               CheckGlobalResult( );
                                                return true;
                                        }
                                }
@@ -483,6 +433,7 @@ namespace System.Windows.Forms
                                        if ( filename.StartsWith( key.Replace( "*", "" ) ) )
                                        {
                                                global_result = MimeGenerated.GlobalSufPref[ i ];
+                                               CheckGlobalResult( );
                                                return true;
                                        }
                                }
@@ -531,7 +482,7 @@ namespace System.Windows.Forms
                        //  using a simple brute force search algorithm
                        // compare each (masked) value from the buffer with the (masked) value from the match
                        // TODO:
-                       // - to find some more speed, maybe use unsafe code
+                       // - to find some more speed, maybe we should use unsafe code
                        // - check if buffer[0] and buffer[lastmatchbyte] match ByteValue[0] and ByteValue[lastmatchbyte] in a match
                        
                        for ( int offset_counter = 0; offset_counter < match.OffsetLength; offset_counter++ )
@@ -643,10 +594,17 @@ namespace System.Windows.Forms
                                
                                file_stream = new FileStream( current_file_name, FileMode.Open, FileAccess.Read ); // FileShare ??? use BinaryReader ???
                                
-                               file_stream.Read( buffer, 0, buffer.Length );
+                               if ( file_stream.Length == 0 )
+                               {
+                                       global_result = zero_file;
+                                       is_zero_file = true;
+                               }
+                               else
+                               {
+                                       file_stream.Read( buffer, 0, buffer.Length );
+                               }
                                
                                file_stream.Close( );
-                               
                        }
                        catch (Exception e)
                        {
@@ -676,10 +634,182 @@ namespace System.Windows.Forms
                                return true;
                        }
                        
-                       // TODO: conver string to byte array and check matches also.
+                       // convert string to byte array
+                       byte[] string_byte = ( new ASCIIEncoding( ) ).GetBytes( search_string );
+                       
+                       System.Array.Clear( buffer, 0, buffer.Length );
+                       
+                       if ( string_byte.Length > buffer.Length )
+                       {
+                               System.Array.Copy( string_byte, buffer, buffer.Length );
+                       }
+                       else
+                       {
+                               System.Array.Copy( string_byte, buffer, string_byte.Length );
+                       }
+                       
+                       if ( CheckMatch80Plus( ) )
+                               return true;
+                       
+                       if ( CheckMatchBelow80( ) )
+                               return true;
                        
                        return false;
                }
        }
+       
+       internal class MimeType
+       {
+               private string comment;
+               private Hashtable commentsLanguage = new Hashtable();
+               
+               public string Comment
+               {
+                       get {
+                               return comment;
+                       }
+                       set {
+                               comment = value;
+                       }
+               }
+               
+               public Hashtable CommentsLanguage
+               {
+                       get {
+                               return commentsLanguage;
+                       }
+                       set {
+                               commentsLanguage = value;
+                       }
+               }
+               public string GetCommentForLanguage( string language )
+               {
+                       return commentsLanguage[ language ] as string;
+               }
+       }
+       
+       internal enum MatchTypes
+       {
+               TypeString,
+               TypeHost16,
+               TypeHost32,
+               TypeBig16,
+               TypeBig32,
+               TypeLittle16,
+               TypeLittle32,
+               TypeByte
+       }
+       
+       internal class Match
+       {
+               string mimeType;
+               byte[] byteValue;
+               byte[] mask = null;
+               int priority;
+               int offset;
+               int offsetLength;
+               int wordSize = 1;
+               MatchTypes matchType;
+               ArrayList matches = new ArrayList();
+               
+               public string MimeType
+               {
+                       set {
+                               mimeType = value;
+                       }
+                       
+                       get {
+                               return mimeType;
+                       }
+               }
+               
+               public byte[] ByteValue
+               {
+                       set {
+                               byteValue = value;
+                       }
+                       
+                       get {
+                               return byteValue;
+                       }
+               }
+               
+               public byte[] Mask
+               {
+                       set {
+                               mask = value;
+                       }
+                       
+                       get {
+                               return mask;
+                       }
+               }
+               
+               public int Priority
+               {
+                       set {
+                               priority = value;
+                       }
+                       
+                       get {
+                               return priority;
+                       }
+               }
+               
+               public ArrayList Matches
+               {
+                       set {
+                               matches = value;
+                       }
+                       
+                       get {
+                               return matches;
+                       }
+               }
+               
+               public int Offset
+               {
+                       set {
+                               offset = value;
+                       }
+                       
+                       get {
+                               return offset;
+                       }
+               }
+               
+               public int OffsetLength
+               {
+                       set {
+                               offsetLength = value;
+                       }
+                       
+                       get {
+                               return offsetLength;
+                       }
+               }
+               
+               public int WordSize
+               {
+                       set {
+                               wordSize = value;
+                       }
+                       
+                       get {
+                               return wordSize;
+                       }
+               }
+               
+               public MatchTypes MatchType
+               {
+                       set {
+                               matchType = value;
+                       }
+                       
+                       get {
+                               return matchType;
+                       }
+               }
+       }
 }