fpmimetypes.pp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2011 by the Free Pascal development team
  4. Mime Types Lookup/Management class.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit fpmimetypes;
  12. {$mode objfpc}{$H+}
  13. interface
  14. uses
  15. Classes, SysUtils, contnrs;
  16. Type
  17. { TMimeType }
  18. TMimeType = Class(TObject)
  19. private
  20. FExtensions: String;
  21. FExtentions: String;
  22. FMimeType: String;
  23. Public
  24. Constructor Create(Const AMimeType,AExtensions : String);
  25. Procedure MergeExtensions(AExtensions : String);
  26. Property MimeType : String Read FMimeType Write FMimeType;
  27. Property Extensions : String Read FExtensions Write FExtentions;
  28. end;
  29. { TFPMimeTypes }
  30. TFPMimeTypes = Class(TComponent)
  31. Private
  32. FTypes : TFPHashList;
  33. FExtensions : TFPHashList;
  34. procedure ParseLine(ALine: String; out Mime, Extensions: String);
  35. Protected
  36. Function FindMimeByType(Const AMime : String) : TMimeType;
  37. Function FindMimeByExt(Const AExt : String) : TMimeType;
  38. Public
  39. Constructor Create(AOwner : TComponent); override;
  40. Destructor Destroy; override;
  41. // Extract an extension from an extension list as returned by GetMimeExtensions
  42. class function GetNextExtension(var E: String): string;
  43. // Load from stream
  44. procedure LoadFromStream(Const Stream : TStream); virtual;
  45. // Load from file
  46. procedure LoadFromFile(Const AFileName : string);
  47. // Add one type to the list. AMimeType is converted to lowercase,
  48. // AExtensions is a semicolon separated list of extensions. (no dot)
  49. Procedure AddType(Const AMimeType,AExtensions : String);
  50. // Get known extensions for a Mime Type. Empty if unknown. Case insensitive.
  51. Function GetMimeExtensions(Const AMimeType : String) : String;
  52. // Get mime type for an extension. Empty if unknown extension. Initial dot is stripped.
  53. Function GetMimeType(Const AExtension : String) : String;
  54. // Fill AList with known mime types. No particular order.
  55. Function GetKnownMimeTypes(AList : TStrings) : Integer;
  56. // Fill AList with known extensions types. No particular order.
  57. Function GetKnownExtensions(AList : TStrings) : Integer;
  58. end;
  59. Function MimeTypes : TFPMimeTypes;
  60. implementation
  61. { TFPMimeTypes }
  62. var
  63. FTypes : TFPMimeTypes;
  64. Class Function TFPMimeTypes.GetNextExtension(var E : String) : string;
  65. Var
  66. P : Integer;
  67. begin
  68. P:=Pos(';',E);
  69. If (P=0) then P:=Length(E)+1;
  70. Result:=Copy(E,1,P-1);
  71. Delete(E,1,P);
  72. end;
  73. Function MimeTypes : TFPMimeTypes;
  74. begin
  75. If (FTypes=Nil) then
  76. FTypes:=TFPMimeTypes.Create(Nil);
  77. Result:=FTypes;
  78. end;
  79. Procedure TFPMimeTypes.ParseLine(ALine : String; Out Mime,Extensions : String);
  80. COnst
  81. WhiteSpace = [' ',#9];
  82. Function GetNextWord(S : String; Var APos : Integer) : String;
  83. Var
  84. SPos : Integer;
  85. begin
  86. While (APos<=Length(S)) and (S[APos] in Whitespace) do
  87. Inc(APos);
  88. SPos:=APos;
  89. While (APos<=Length(S)) and not (S[APos] in Whitespace) do
  90. Inc(APos);
  91. Result:=Copy(S,SPos,APos-SPos);
  92. end;
  93. Var
  94. P : Integer;
  95. S : String;
  96. begin
  97. P:=1;
  98. Mime:=GetNextWord(ALine,p);
  99. Repeat
  100. S:=GetNextWord(ALine,P);
  101. if (length(S)>0) and (S[1]='.') then
  102. Delete(S,1,1);
  103. If (S<>'') then
  104. Extensions:=Extensions+S+';';// always add ;
  105. until (S='');
  106. end;
  107. function TFPMimeTypes.FindMimeByType(const AMime: String): TMimeType;
  108. Var
  109. I : integer;
  110. begin
  111. I:=FTypes.FindIndexOf(LowerCase(AMime));
  112. If (I<>-1) then
  113. Result:=TMimeType(FTypes.Items[I])
  114. else
  115. Result:=Nil;
  116. end;
  117. function TFPMimeTypes.FindMimeByExt(const AExt: String): TMimeType;
  118. Var
  119. I : integer;
  120. E : String;
  121. begin
  122. E:=LowerCase(AExt);
  123. If (E[1]='.') then
  124. Delete(E,1,1);
  125. I:=FExtensions.FindIndexOf(E);
  126. If (I<>-1) then
  127. Result:=TMimeType(FExtensions.Items[I])
  128. else
  129. Result:=Nil;
  130. end;
  131. constructor TFPMimeTypes.Create(AOwner: TComponent);
  132. begin
  133. inherited Create(AOwner);
  134. FTypes:=TFPHashList.Create;
  135. FExtensions:=TFPHashList.Create;
  136. end;
  137. destructor TFPMimeTypes.Destroy;
  138. Var
  139. T : TMimeType;
  140. I : integer;
  141. begin
  142. For I:=FTypes.Count-1 downto 0 do
  143. begin
  144. T:=TMimeType(FTypes.Items[i]);
  145. FreeAndNil(T);
  146. end;
  147. FreeAndNil(FTypes);
  148. FreeAndNil(FExtensions);
  149. inherited Destroy;
  150. end;
  151. procedure TFPMimeTypes.LoadFromStream(const Stream: TStream);
  152. Var
  153. L : TStringList;
  154. S,M,E : String;
  155. I : Integer;
  156. begin
  157. L:=TStringList.Create;
  158. try
  159. L.LoadFromStream(Stream);
  160. For I:=0 to L.Count-1 do
  161. begin
  162. S:=Trim(L[I]);
  163. If (S<>'') and (S[1]<>'#') then
  164. begin
  165. ParseLine(S,M,E);
  166. If (M<>'') then
  167. AddType(M,E);
  168. end;
  169. end;
  170. finally
  171. L.Free;
  172. end;
  173. end;
  174. procedure TFPMimeTypes.LoadFromFile(const AFileName: string);
  175. Var
  176. F : TFileStream;
  177. begin
  178. F:=TFileStream.Create(AFileName,fmOpenRead);
  179. try
  180. LoadFromStream(F);
  181. finally
  182. F.Free;
  183. end;
  184. end;
  185. procedure TFPMimeTypes.AddType(const AMimeType, AExtensions: String);
  186. Var
  187. M,E,N : String;
  188. MT : TMimeType;
  189. I : Integer;
  190. begin
  191. M:=LowerCase(AMimeType);
  192. E:=LowerCase(AExtensions);
  193. I:=FTypes.FindINdexOf(AMimeType);
  194. if (i=-1) then
  195. begin
  196. MT:=TMimeType.Create(M,E);
  197. FTypes.Add(M,MT);
  198. end
  199. else
  200. begin
  201. MT:=TMimeType(FTypes.Items[i]);
  202. MT.MergeExtensions(AExtensions);
  203. end;
  204. repeat
  205. N:=GetNextExtension(E);
  206. If (N<>'') then
  207. begin
  208. I:=FExtensions.FindIndexOf(N);
  209. If (I=-1) then
  210. FExtensions.Add(N,MT);
  211. end;
  212. until (n='');
  213. end;
  214. function TFPMimeTypes.GetMimeExtensions(const AMimeType: String): String;
  215. Var
  216. T : TMimeType;
  217. begin
  218. T:=FindMimeByType(AMimeType);
  219. if Assigned(T) then
  220. Result:=T.Extensions;
  221. end;
  222. function TFPMimeTypes.GetMimeType(const AExtension: String): String;
  223. Var
  224. T : TMimeType;
  225. begin
  226. T:=FindMimeByExt(AExtension);
  227. if Assigned(T) then
  228. Result:=T.MimeType;
  229. end;
  230. function TFPMimeTypes.GetKnownMimeTypes(AList: TStrings): Integer;
  231. var
  232. i : Integer;
  233. begin
  234. AList.BeginUpdate;
  235. try
  236. AList.Clear;
  237. For I:=0 to FTypes.Count-1 do
  238. Alist.Add(FTypes.NameOfIndex(i));
  239. finally
  240. AList.EndUpdate;
  241. end;
  242. end;
  243. function TFPMimeTypes.GetKnownExtensions(AList: TStrings): Integer;
  244. var
  245. i : Integer;
  246. begin
  247. AList.BeginUpdate;
  248. try
  249. AList.Clear;
  250. For I:=0 to FExtensions.Count-1 do
  251. Alist.Add(FExtensions.NameOfIndex(i));
  252. finally
  253. AList.EndUpdate;
  254. end;
  255. end;
  256. { TMimeType }
  257. constructor TMimeType.Create(const AMimeType, AExtensions: String);
  258. begin
  259. FMimeType:=Lowercase(AMimeType);
  260. FExtensions:=Lowercase(AExtensions);
  261. end;
  262. procedure TMimeType.MergeExtensions(AExtensions: String);
  263. var
  264. E : String;
  265. begin
  266. Repeat
  267. E:=TFPMimeTypes.GetNextExtension(AExtensions);
  268. If (E<>'') then
  269. begin
  270. E:=E+';';
  271. If (Copy(Fextensions,1,Length(E))<>E) and (Pos(E,FExtensions)=0) then
  272. FExtensions:=Extensions+E;
  273. end;
  274. Until (E='')
  275. end;
  276. initialization
  277. finalization
  278. FreeAndNil(FTypes);
  279. end.