123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 2011 by the Free Pascal development team
- Mime Types Lookup/Management class.
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- 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.
- **********************************************************************}
- unit fpmimetypes;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils, contnrs;
- Type
- { TMimeType }
- TMimeType = Class(TObject)
- private
- FExtensions: String;
- FExtentions: String;
- FMimeType: String;
- Public
- Constructor Create(Const AMimeType,AExtensions : String);
- Procedure MergeExtensions(AExtensions : String);
- Property MimeType : String Read FMimeType Write FMimeType;
- Property Extensions : String Read FExtensions Write FExtentions;
- end;
- { TFPMimeTypes }
- TFPMimeTypes = Class(TComponent)
- Private
- FTypes : TFPHashList;
- FExtensions : TFPHashList;
- procedure ParseLine(ALine: String; out Mime, Extensions: String);
- Protected
- Function FindMimeByType(Const AMime : String) : TMimeType;
- Function FindMimeByExt(Const AExt : String) : TMimeType;
- Public
- Constructor Create(AOwner : TComponent); override;
- Destructor Destroy; override;
- // Extract an extension from an extension list as returned by GetMimeExtensions
- class function GetNextExtension(var E: String): string;
- // Load from stream
- procedure LoadFromStream(Const Stream : TStream); virtual;
- // Load from file
- procedure LoadFromFile(Const AFileName : string);
- // Add one type to the list. AMimeType is converted to lowercase,
- // AExtensions is a semicolon separated list of extensions. (no dot)
- Procedure AddType(Const AMimeType,AExtensions : String);
- // Get known extensions for a Mime Type. Empty if unknown. Case insensitive.
- Function GetMimeExtensions(Const AMimeType : String) : String;
- // Get mime type for an extension. Empty if unknown extension. Initial dot is stripped.
- Function GetMimeType(Const AExtension : String) : String;
- // Fill AList with known mime types. No particular order.
- Function GetKnownMimeTypes(AList : TStrings) : Integer;
- // Fill AList with known extensions types. No particular order.
- Function GetKnownExtensions(AList : TStrings) : Integer;
- end;
- Function MimeTypes : TFPMimeTypes;
- implementation
- { TFPMimeTypes }
- var
- FTypes : TFPMimeTypes;
- Class Function TFPMimeTypes.GetNextExtension(var E : String) : string;
- Var
- P : Integer;
- begin
- P:=Pos(';',E);
- If (P=0) then P:=Length(E)+1;
- Result:=Copy(E,1,P-1);
- Delete(E,1,P);
- end;
- Function MimeTypes : TFPMimeTypes;
- begin
- If (FTypes=Nil) then
- FTypes:=TFPMimeTypes.Create(Nil);
- Result:=FTypes;
- end;
- Procedure TFPMimeTypes.ParseLine(ALine : String; Out Mime,Extensions : String);
- COnst
- WhiteSpace = [' ',#9];
- Function GetNextWord(S : String; Var APos : Integer) : String;
- Var
- SPos : Integer;
- begin
- While (APos<=Length(S)) and (S[APos] in Whitespace) do
- Inc(APos);
- SPos:=APos;
- While (APos<=Length(S)) and not (S[APos] in Whitespace) do
- Inc(APos);
- Result:=Copy(S,SPos,APos-SPos);
- end;
- Var
- P : Integer;
- S : String;
- begin
- P:=1;
- Mime:=GetNextWord(ALine,p);
- Repeat
- S:=GetNextWord(ALine,P);
- if (length(S)>0) and (S[1]='.') then
- Delete(S,1,1);
- If (S<>'') then
- Extensions:=Extensions+S+';';// always add ;
- until (S='');
- end;
- function TFPMimeTypes.FindMimeByType(const AMime: String): TMimeType;
- Var
- I : integer;
- begin
- I:=FTypes.FindIndexOf(LowerCase(AMime));
- If (I<>-1) then
- Result:=TMimeType(FTypes.Items[I])
- else
- Result:=Nil;
- end;
- function TFPMimeTypes.FindMimeByExt(const AExt: String): TMimeType;
- Var
- I : integer;
- E : String;
- begin
- E:=LowerCase(AExt);
- If (E[1]='.') then
- Delete(E,1,1);
- I:=FExtensions.FindIndexOf(E);
- If (I<>-1) then
- Result:=TMimeType(FExtensions.Items[I])
- else
- Result:=Nil;
- end;
- constructor TFPMimeTypes.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FTypes:=TFPHashList.Create;
- FExtensions:=TFPHashList.Create;
- end;
- destructor TFPMimeTypes.Destroy;
- Var
- T : TMimeType;
- I : integer;
- begin
- For I:=FTypes.Count-1 downto 0 do
- begin
- T:=TMimeType(FTypes.Items[i]);
- FreeAndNil(T);
- end;
- FreeAndNil(FTypes);
- FreeAndNil(FExtensions);
- inherited Destroy;
- end;
- procedure TFPMimeTypes.LoadFromStream(const Stream: TStream);
- Var
- L : TStringList;
- S,M,E : String;
- I : Integer;
- begin
- L:=TStringList.Create;
- try
- L.LoadFromStream(Stream);
- For I:=0 to L.Count-1 do
- begin
- S:=Trim(L[I]);
- If (S<>'') and (S[1]<>'#') then
- begin
- ParseLine(S,M,E);
- If (M<>'') then
- AddType(M,E);
- end;
- end;
- finally
- L.Free;
- end;
- end;
- procedure TFPMimeTypes.LoadFromFile(const AFileName: string);
- Var
- F : TFileStream;
- begin
- F:=TFileStream.Create(AFileName,fmOpenRead);
- try
- LoadFromStream(F);
- finally
- F.Free;
- end;
- end;
- procedure TFPMimeTypes.AddType(const AMimeType, AExtensions: String);
- Var
- M,E,N : String;
- MT : TMimeType;
- I : Integer;
- begin
- M:=LowerCase(AMimeType);
- E:=LowerCase(AExtensions);
- I:=FTypes.FindINdexOf(AMimeType);
- if (i=-1) then
- begin
- MT:=TMimeType.Create(M,E);
- FTypes.Add(M,MT);
- end
- else
- begin
- MT:=TMimeType(FTypes.Items[i]);
- MT.MergeExtensions(AExtensions);
- end;
- repeat
- N:=GetNextExtension(E);
- If (N<>'') then
- begin
- I:=FExtensions.FindIndexOf(N);
- If (I=-1) then
- FExtensions.Add(N,MT);
- end;
- until (n='');
- end;
- function TFPMimeTypes.GetMimeExtensions(const AMimeType: String): String;
- Var
- T : TMimeType;
- begin
- T:=FindMimeByType(AMimeType);
- if Assigned(T) then
- Result:=T.Extensions;
- end;
- function TFPMimeTypes.GetMimeType(const AExtension: String): String;
- Var
- T : TMimeType;
- begin
- T:=FindMimeByExt(AExtension);
- if Assigned(T) then
- Result:=T.MimeType;
- end;
- function TFPMimeTypes.GetKnownMimeTypes(AList: TStrings): Integer;
- var
- i : Integer;
- begin
- AList.BeginUpdate;
- try
- AList.Clear;
- For I:=0 to FTypes.Count-1 do
- Alist.Add(FTypes.NameOfIndex(i));
- finally
- AList.EndUpdate;
- end;
- end;
- function TFPMimeTypes.GetKnownExtensions(AList: TStrings): Integer;
- var
- i : Integer;
- begin
- AList.BeginUpdate;
- try
- AList.Clear;
- For I:=0 to FExtensions.Count-1 do
- Alist.Add(FExtensions.NameOfIndex(i));
- finally
- AList.EndUpdate;
- end;
- end;
- { TMimeType }
- constructor TMimeType.Create(const AMimeType, AExtensions: String);
- begin
- FMimeType:=Lowercase(AMimeType);
- FExtensions:=Lowercase(AExtensions);
- end;
- procedure TMimeType.MergeExtensions(AExtensions: String);
- var
- E : String;
- begin
- Repeat
- E:=TFPMimeTypes.GetNextExtension(AExtensions);
- If (E<>'') then
- begin
- E:=E+';';
- If (Copy(Fextensions,1,Length(E))<>E) and (Pos(E,FExtensions)=0) then
- FExtensions:=Extensions+E;
- end;
- Until (E='')
- end;
- initialization
- finalization
- FreeAndNil(FTypes);
- end.
|