/StFLib/Src/HKStreamCol.pas

http://xplib.googlecode.com/ · Pascal · 369 lines · 294 code · 35 blank · 40 comment · 23 complexity · e70a3438c4b333856dfc57c54a213f28 MD5 · raw file

  1. {$IFDEF HKStreamCol}
  2. {$DEFINE DEBUG_UNIT}
  3. {$ENDIF}
  4. {$I StFLib.inc}
  5. unit HKStreamCol;
  6. {
  7. ----------------------------------------------------------------
  8. THKStreams v1.7 by Harry Kakoulidis 01/2002
  9. prog@xarka.com
  10. http://www.xarka.com/prog/
  11. This is Freeware. Please copy HKStrm17.zip unchanged.
  12. If you find bugs, have options etc. Please send at my e-mail.
  13. The use of this component is at your own risk.
  14. I do not take any responsibility for any damages.
  15. ----------------------------------------------------------------
  16. Update v1.7
  17. * Bug in RemoveStream procedure fixed by
  18. David Quinn (david@eternia.net)
  19. * Compiles with D6
  20. Update v1.6
  21. * Compability problem with Delphi 3
  22. pointed out by Glenn (buddyboy@idcomm.com)
  23. * Wrong password event idea by Lai xiaolong (laixl@mei29.scgb.com)
  24. * Bug with empty streams pointed
  25. out by Simon Horup, Crystal Art Software (info@casdk.com)
  26. * Bug with corrupted compressed files pointed out by
  27. Tsahi Chitin (TUtils@poboxes.com)
  28. ----------------------------------------------------------------
  29. }
  30. interface
  31. uses
  32. HKStreamRoutines, Windows, Messages, SysUtils, Classes, Graphics, Controls;
  33. type
  34. TGoodbytes = array[1..8] of byte;
  35. ECorruptFile = Class (Exception);
  36. const
  37. EncryptedByte: array[FALSE..TRUE] of Byte = (ord(' '), ord('*'));
  38. CompressedByte: array[FALSE..TRUE] of byte = (ord(' '), ord('&'));
  39. Goodbytes: TGoodbytes = (1, 2, 3, 4, 5, 6, 7, 8);
  40. type
  41. TOnAskForKey = function(sender : TObject) : string of object;
  42. THKStreams = Class (TComponent)
  43. private
  44. FCompressed, FEncrypted : Boolean;
  45. FKey : String;
  46. FOnAskForKey : TOnAskForKey;
  47. FOnCorrupt : TNotifyEvent;
  48. procedure WriteStr(S : String; Stream : TStream);
  49. function ReadStr(Stream : TStream) : string;
  50. procedure LoadFromStreamNor(ms : TStream);
  51. procedure SaveToStreamNor(ms : TStream);
  52. function CheckGood(ms : TStream) : boolean;
  53. procedure FoundCorrupt;
  54. public
  55. StreamList : TStringList;
  56. constructor Create(AOWner : TComponent); override;
  57. destructor Destroy; override;
  58. procedure LoadFromFile(const Filename : string);
  59. procedure SaveToFile(const Filename : string);
  60. procedure AddStream(const ID : string; Source : TStream);
  61. procedure RemoveStream(const ID : String);
  62. procedure LoadFromStream(ms : TStream);
  63. procedure SaveToStream(ms : TStream);
  64. procedure GetStream(const ID : string; Dest : TStream);
  65. procedure ClearStreams;
  66. published
  67. property Compressed : boolean read FCompressed write FCompressed;
  68. property Encrypted : boolean read FEncrypted write FEncrypted;
  69. property Key : string read FKey write FKey;
  70. property OnAskForKey : TOnAskForKey read FOnAskForKey write FOnAskForKey;
  71. property OnCorrupt : TNotifyEvent read FOnCorrupt write FOnCorrupt;
  72. end;
  73. procedure Register;
  74. implementation
  75. procedure Register;
  76. begin
  77. RegisterComponents('Super', [THKStreams]);
  78. end;
  79. { THKStreams }
  80. procedure THKStreams.AddStream(const ID : string; Source : TStream);
  81. var
  82. ms : TMemoryStream;
  83. begin
  84. if (length(id) > 0) and (assigned(source)) then begin
  85. ms := TmemoryStream.Create;
  86. ms.CopyFrom(source, 0);
  87. Streamlist.AddObject(ID, ms);
  88. end;
  89. end;
  90. procedure THKStreams.ClearStreams;
  91. var
  92. a : integer;
  93. begin
  94. with StreamList do begin
  95. for a := 0 to count - 1 do begin
  96. TMemoryStream(objects[a]).free;
  97. end;
  98. clear;
  99. end;
  100. end;
  101. constructor THKStreams.Create(AOWner : TComponent);
  102. begin
  103. inherited Create(AOwner);
  104. FCompressed := TRUE;
  105. FEncrypted := FALSE;
  106. StreamList := TStringList.create;
  107. StreamList.Sorted := TRUE;
  108. end;
  109. destructor THKStreams.Destroy;
  110. begin
  111. ClearStreams;
  112. StreamList.free;
  113. inherited Destroy;
  114. end;
  115. procedure THKStreams.GetStream(const ID : string; Dest : TStream);
  116. var
  117. i : integer;
  118. begin
  119. if (length(id) > 0) then begin
  120. i := Streamlist.IndexOf(ID);
  121. if i >= 0 then begin
  122. dest.CopyFrom(TMemoryStream(Streamlist.objects[i]), 0);
  123. end;
  124. dest.Position := 0;
  125. end;
  126. end;
  127. procedure THKStreams.LoadFromFile(const Filename : string);
  128. var
  129. fs : TFileStream;
  130. begin
  131. Fs := TFileStream.Create(FileName, fmOpenRead);
  132. try
  133. LoadFromStream(fs);
  134. finally
  135. FS.free;
  136. end;
  137. end;
  138. procedure THKStreams.FoundCorrupt;
  139. begin
  140. if assigned(FOnCorrupt) then begin
  141. FOnCorrupt(Self);
  142. end;
  143. raise ECorruptFile.Create('File is corrupt.');
  144. end;
  145. function THKStreams.CheckGood(ms : TStream) : boolean;
  146. var
  147. GoodTest : TGoodBytes;
  148. a : integer;
  149. begin
  150. ms.Position := 0;
  151. ms.read(GoodTest, sizeof(TGoodBytes));
  152. Result := TRUE;
  153. for a := 1 to sizeof(TGoodBytes) do begin
  154. if goodbytes[a] <> GoodTest[a] then begin
  155. FoundCorrupt;
  156. Result := FALSE;
  157. exit;
  158. end;
  159. end;
  160. end;
  161. procedure THKStreams.LoadFromStream(ms : TStream);
  162. var
  163. CMem, mem : TMemoryStream;
  164. e, c : byte;
  165. AKey : string;
  166. begin
  167. AKey := FKey;
  168. Cmem := TMemoryStream.create;
  169. mem := TMemoryStream.create;
  170. try
  171. ms.Position := 0;
  172. ms.read(c, sizeof(c));
  173. ms.read(e, sizeof(e));
  174. CMem.copyfrom(ms, ms.size - 2);
  175. CMEm.position := 0;
  176. if (e = EncryptedByte[TRUE]) then begin
  177. if not assigned(FOnAskForKey) then begin
  178. AKey := FKey;
  179. end else begin
  180. AKey := FOnAskForKey(Self);
  181. end;
  182. try
  183. DecryptStream(CMem, AKEy);
  184. except
  185. on Exception do begin
  186. foundcorrupt;
  187. end;
  188. end;
  189. end;
  190. if not (c = CompressedByte[TRUE]) then begin
  191. if not CheckGood(CMem) then begin
  192. exit;
  193. end;
  194. end;
  195. CMem.Position := 0;
  196. if (c = CompressedByte[TRUE]) then begin
  197. try
  198. LHAExpand(Cmem, Mem)
  199. except
  200. on Exception do begin
  201. FoundCorrupt;
  202. end;
  203. end;
  204. end else begin
  205. Mem.copyfrom(Cmem, 0);
  206. end;
  207. LoadFromStreamNor(Mem);
  208. finally
  209. CMem.Free;
  210. mem.free;
  211. end;
  212. FKey := AKey;
  213. FCompressed := (C = CompressedByte[TRUE]);
  214. FEncrypted := (e = EncryptedByte[TRUE]);
  215. end;
  216. procedure THKStreams.LoadFromStreamNor(ms : TStream);
  217. var
  218. Mem : TMemoryStream;
  219. Count, size, a : integer;
  220. ID : string;
  221. begin
  222. if not CheckGood(ms) then begin
  223. exit;
  224. end;
  225. ClearStreams;
  226. ms.Position := sizeof(TGoodBytes);
  227. ms.read(count, sizeof(count));
  228. for a := 0 to count - 1 do begin
  229. mem := TMemoryStream.create;
  230. ID := ReadStr(ms);
  231. ms.read(Size, sizeof(size));
  232. if size <> 0 then begin
  233. mem.CopyFrom(ms, size);
  234. end;
  235. Streamlist.AddObject(ID, mem);
  236. end;
  237. end;
  238. function THKStreams.ReadStr(Stream : TStream) : string;
  239. var
  240. i : word;
  241. s : string;
  242. begin
  243. stream.Read(i, sizeof(i));
  244. setlength(s, i);
  245. stream.Read(PChar(s)^, i);
  246. Result := s;
  247. end;
  248. procedure THKStreams.RemoveStream(const ID : String);
  249. var
  250. i : integer;
  251. begin
  252. if (length(id) > 0) then begin
  253. i := Streamlist.IndexOf(ID);
  254. if i >= 0 then begin {DTQ}
  255. TMemoryStream(Streamlist.objects[i]).free;
  256. Streamlist.Delete(i);
  257. end;
  258. end;
  259. end;
  260. procedure THKStreams.SaveToFile(const Filename : string);
  261. var
  262. fs : TFileStream;
  263. begin
  264. Fs := TFileStream.Create(FileName, fmCreate);
  265. try
  266. SaveToStream(fs);
  267. finally
  268. FS.free;
  269. end;
  270. end;
  271. procedure THKStreams.SaveToStream(ms : TStream);
  272. var
  273. mem, CMem : TMemoryStream;
  274. e, c : byte;
  275. begin
  276. CMem := TMemoryStream.Create;
  277. mem := TMemoryStream.Create;
  278. try
  279. SaveToStreamNor(mem);
  280. mem.position := 0;
  281. c := CompressedByte[FCompressed];
  282. e := EncryptedByte[FEncrypted and (FKey <> '')];
  283. ms.Write(c, sizeof(c));
  284. ms.write(e, sizeof(e));
  285. if FCompressed
  286. then begin
  287. LHACompress(mem, CMem);
  288. end else begin
  289. CMem.CopyFrom(mem, 0);
  290. end;
  291. if (FEncrypted) and (FKey <> '')
  292. then begin
  293. EncryptStream(CMem, Fkey);
  294. end;
  295. ms.CopyFrom(CMem, 0);
  296. finally
  297. mem.free;
  298. CMem.free;
  299. end;
  300. end;
  301. procedure THKStreams.SaveToStreamNor(ms : TStream);
  302. var
  303. Count, size, a : integer;
  304. begin
  305. ms.write(goodbytes, sizeof(Tgoodbytes));
  306. count := Streamlist.Count;
  307. ms.write(count, sizeof(count));
  308. for a := 0 to count - 1 do begin
  309. Writestr(Streamlist.strings[a], ms);
  310. size := TMemoryStream(Streamlist.Objects[a]).size;
  311. ms.Write(size, sizeof(size));
  312. ms.CopyFrom(TMemoryStream(StreamList.Objects[a]), 0);
  313. end;
  314. end;
  315. procedure THKStreams.WriteStr(S : String; Stream : TStream);
  316. var
  317. i : word;
  318. begin
  319. i := length(s);
  320. stream.Write(i, sizeof(i));
  321. stream.write(PChar(s)^, i);
  322. end;
  323. end.