visitor (0 QPoints)
  • FR
  • EN
  • NL
  • DE
  • ES
315 experts, 1193 registered users, 1659 questions already answered
European Experts Exchange, the very best site for high-quality IT solutions

New Improved Search!

 


05/10/2011 1h30 : Steve Jobs is dead, the father of Apple ][ is gone, we are all orphaned.

Languages :: Pascal :: Innerfuse Pascal MD5 implementation.


By: mrguide U.S.A.  Date: 08/06/2003 00:00:00  English  Points: 300 Status: Answered
Quality : Excellent
Hello,

At this moment I am writing a server application for Windows. This server uses authentication and thus has a file in which it registers all it's users. This file is a Windows INI file that contains a section for every user. The user's password is saved as an attribute to a user's section. At this moment the password isn't encrypted and thus saved as plain text.

To deploy this application I've used Inno Setup to create an installer. Because I wanted to let the user add an Administrator user to the server at install-time I moved to My Inno Setup Extensions and wrote code to write info about this initial Administrator user to the INI file at install-time. This code is written for the Innerfuse Pascal Interpreter integrated into My Inno Setup Extensions.

Now because of security reasons I would like to use md5-encryption for saving the user's passwords. In the application server (a delphi program) I already have managed to do so. But for the installation script I haven't managed to find or port an existing script for calculating MD5 hashes out of passwords.

I have tried to port existing delphi and turbo pascal implementations of this code (which can be found everywhere on the web) but I couldn't succeed because Innerfuse Pascal has a very limited (or incompatible) syntax and set of data types.

My question is: Can anyone give me some Innerfuse Pascal Script code to calculate a MD5 hash (as specified in RFC 1321) out of a password string?

Maybe these links can get you started:
The official MD5 standard: <A HREF="http://www.rfc-editor.org/rfc/rfc1321.txt">http://www.rfc-editor.org/rfc/rfc1321.txt</a>
Good document on calculating MD5 hashes: <A HREF="http://www.opengroup.org/onlinepubs/9668899/chap2.htm#tagcjh_05_04">http://www.opengroup.org/onlinepubs/9668899/chap2.htm#tagcjh_05_04</a>
My Inno Setup Extensions homepage: <A HREF="http://www.wintax.nl/isx/">http://www.wintax.nl/isx/</a>
Innerfuse Pascal script: <A HREF="http://www.carlo-kok.com/ifps3.php">http://www.carlo-kok.com/ifps3.php</a>
A bunch of MD5 hashing implementations in other pascal-like languages:
- <A HREF="http://www.fichtner.net/delphi/md5.delphi.phtml">http://www.fichtner.net/delphi/md5.delphi.phtml</a>
- <A HREF="http://pascal.sources.ru/crypt/md5asm32.htm">http://pascal.sources.ru/crypt/md5asm32.htm</a>
- <A HREF="http://www.fortunecity.com/skyscraper/true/882/DelphiComponents.htm">http://www.fortunecity.com/skyscraper/true/882/DelphiComponents.htm</a>

I would be very thankful if anyone could help me on this. This is why I am offering 200 points.

Thanks in advance,

MrGuide
By: Okey Date: 08/06/2003 03:42:00 English  Type : Comment
Post a 20 points question with link to these question here in better categories!
Sorry but why innerfuse pascal?
I don't understand but what can't be done with pascal?
By: mrguide Date: 08/06/2003 03:55:00 English  Type : Comment
In reply to Okey:

I think the pascal section here is perfectly suitable for a question like this. The question concerns only, and nothing more than, the pascal programming aspects of an MD5 implementation. I know for sure that when i ask this question in the security section of experts-exchange, people will tell me this isn't about security but about the implementation of a security algorithm. That is why i chose this section to post my question in. Only if nobody in this section knows the answer to this question (what seems very unexpectable to me), I will ask it in other questions.

Then.. why Innerfuse Pascal. Because I want to implement the MD5 hashing into My Inno Setup Extensions. My Inno Setup Extensions offers the ability to embed Innerfuse Pascal script into the setup scripts. This is why I ask for Innerfuse Pascal Script code. If I needed standard Borland Turbo Pascal or Borland Delphi code to calculate an MD5 hash, that wouldn't be a problem; there are lots of MD5 calculations units around on the internet.


By: Okey Date: 08/06/2003 04:01:00 English  Type : Comment
Hmmmhhhh I'm very sory but I can't help you,
but I thought more about Web ... section!
By: VGR Date: 08/06/2003 04:11:00 English  Type : Comment
mrguide, what are the differences between Innerfuse Pascal scripting and standard Pascal or Turbo Pascal ? Couldn't standard Pascal code do the trick ? A MD5 is only a digest on 32 bits, after all...
By: mrguide Date: 08/06/2003 17:24:00 English  Type : Comment
In reply to Okey:

Please try to provide me with an useful answer and do not start wasting your time in posting comments that don't matter here. By the way... this question has absolutely nothing to do with the web. It is about implementing a cryptographic algorithm in a specific programming language.

In reply to VGR:

The main aspects in which Innerfuse Pascal and the other well-known pascal variants differ are:
- syntax (many turbo pascal language constructions aren't allowed in Innerfuse Pascal)
- available functions (Innerfuse implements only a small subset of Turbo Pascal's functionality. Besides that the function and procedure names can also have different names than the ones in Turbo Pascal).
- the idea behind the language: Turbo Pascal and many others are meant to develop stand-alone applications. Innerfuse Pascal is meant to extend an application through a scripting language that is inspired upon the other pascal languages.

The reason why I want a Innerfuse pascal implementations is because I am bound to it. The only way I can extend the installer for my application is to extend it with Innerfuse Pascal. Just because Innerfuse Pascal is the only scripting language my Setup Compiler (My Inno Setup Extensions) offers.

The reason why I am unable to implement such a script in Innerfuse pascal is because I am not able to port the existing implementations (see the links in my question on top of this page for some of them) to Innerfuse Pascal. I simply don't have the knowledge to port that code since it uses pointers, weird typecasts and other tricks that only die-hard programmers know how to handle with.
By: VGR Date: 08/06/2003 17:34:00 English  Type : Comment
ok, then I may help you [die hard grin]

I'll try to see what is the syntax of innerfuse pascal, and then try to port one of the MD5 t-pascal implementations to it.

I don't guarantee anything at this stage. More news later.
By: VGR Date: 08/06/2003 17:36:00 English  Type : Comment
from <A HREF="http://www.carlo-kok.com/ifps3.php">http://www.carlo-kok.com/ifps3.php</a> I deduce "most" of Delphi/ObjectPascal/Turbo-Pascal should work right out.
By: VGR Date: 08/06/2003 17:38:00 English  Type : Comment
ok, I saw that roughly only pointers seem to be lacking from Innerfuse Pascal.

So can you tell me what's wrong with this unit ?

// tabs = 2
// -----------------------------------------------------------------------------------------------
//
// MD5 Message-Digest for Delphi 4
//
// Delphi 4 Unit implementing the
// RSA Data Security, Inc. MD5 Message-Digest Algorithm
//
// Implementation of Ronald L. Rivest's RFC 1321
//
// Copyright © 1997-1999 Medienagentur Fichtner & Meyer
// Written by Matthias Fichtner
//
// -----------------------------------------------------------------------------------------------
// See RFC 1321 for RSA Data Security's copyright and license notice!
// -----------------------------------------------------------------------------------------------
//
// 14-Jun-97 mf Implemented MD5 according to RFC 1321 RFC 1321
// 16-Jun-97 mf Initial release of the compiled unit (no source code) RFC 1321
// 28-Feb-99 mf Added MD5Match function for comparing two digests RFC 1321
// 13-Sep-99 mf Reworked the entire unit RFC 1321
// 17-Sep-99 mf Reworked the "Test Driver" project RFC 1321
// 19-Sep-99 mf Release of sources for MD5 unit and "Test Driver" project RFC 1321
//
// -----------------------------------------------------------------------------------------------
// The latest release of md5.pas will always be available from
// the distribution site at: <A HREF="http://www.fichtner.net/delphi/md5/">http://www.fichtner.net/delphi/md5/</a>
// -----------------------------------------------------------------------------------------------
// Please send questions, bug reports and suggestions
// regarding this code to: mfichtner@fichtner-meyer.com
// -----------------------------------------------------------------------------------------------
// This code is provided "as is" without express or
// implied warranty of any kind. Use it at your own risk.
// -----------------------------------------------------------------------------------------------

unit md5;

// -----------------------------------------------------------------------------------------------
INTERFACE
// -----------------------------------------------------------------------------------------------

uses
Windows;

type
MD5Count = array[0..1] of DWORD;
MD5State = array[0..3] of DWORD;
MD5Block = array[0..15] of DWORD;
MD5CBits = array[0..7] of byte;
MD5Digest = array[0..15] of byte;
MD5Buffer = array[0..63] of byte;
MD5Context = record
State: MD5State;
Count: MD5Count;
Buffer: MD5Buffer;
end;

procedure MD5Init(var Context: MD5Context);
procedure MD5Update(var Context: MD5Context; Input: pChar; Length: longword);
procedure MD5Final(var Context: MD5Context; var Digest: MD5Digest);

function MD5String(M: string): MD5Digest;
function MD5File(N: string): MD5Digest;
function MD5Print(D: MD5Digest): string;

function MD5Match(D1, D2: MD5Digest): boolean;

// -----------------------------------------------------------------------------------------------
IMPLEMENTATION
// -----------------------------------------------------------------------------------------------

var
PADDING: MD5Buffer = (
$80, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00
);

function F(x, y, z: DWORD): DWORD;
begin
Result := (x and y) or ((not x) and z);
end;

function G(x, y, z: DWORD): DWORD;
begin
Result := (x and z) or (y and (not z));
end;

function H(x, y, z: DWORD): DWORD;
begin
Result := x xor y xor z;
end;

function I(x, y, z: DWORD): DWORD;
begin
Result := y xor (x or (not z));
end;

procedure rot(var x: DWORD; n: BYTE);
begin
x := (x shl n) or (x shr (32 - n));
end;

procedure FF(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
inc(a, F(b, c, d) + x + ac);
rot(a, s);
inc(a, b);
end;

procedure GG(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
inc(a, G(b, c, d) + x + ac);
rot(a, s);
inc(a, b);
end;

procedure HH(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
inc(a, H(b, c, d) + x + ac);
rot(a, s);
inc(a, b);
end;

procedure II(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
inc(a, I(b, c, d) + x + ac);
rot(a, s);
inc(a, b);
end;

// -----------------------------------------------------------------------------------------------

// Encode Count bytes at Source into (Count / 4) DWORDs at Target
procedure Encode(Source, Target: pointer; Count: longword);
var
S: PByte;
T: PDWORD;
I: longword;
begin
S := Source;
T := Target;
for I := 1 to Count div 4 do begin
T^ := S^;
inc(S);
T^ := T^ or (S^ shl 8);
inc(S);
T^ := T^ or (S^ shl 16);
inc(S);
T^ := T^ or (S^ shl 24);
inc(S);
inc(T);
end;
end;

// Decode Count DWORDs at Source into (Count * 4) Bytes at Target
procedure Decode(Source, Target: pointer; Count: longword);
var
S: PDWORD;
T: PByte;
I: longword;
begin
S := Source;
T := Target;
for I := 1 to Count do begin
T^ := S^ and $ff;
inc(T);
T^ := (S^ shr 8) and $ff;
inc(T);
T^ := (S^ shr 16) and $ff;
inc(T);
T^ := (S^ shr 24) and $ff;
inc(T);
inc(S);
end;
end;

// Transform State according to first 64 bytes at Buffer
procedure Transform(Buffer: pointer; var State: MD5State);
var
a, b, c, d: DWORD;
Block: MD5Block;
begin
Encode(Buffer, @Block, 64);
a := State[0];
b := State[1];
c := State[2];
d := State[3];
FF (a, b, c, d, Block[ 0], 7, $d76aa478);
FF (d, a, b, c, Block[ 1], 12, $e8c7b756);
FF (c, d, a, b, Block[ 2], 17, $242070db);
FF (b, c, d, a, Block[ 3], 22, $c1bdceee);
FF (a, b, c, d, Block[ 4], 7, $f57c0faf);
FF (d, a, b, c, Block[ 5], 12, $4787c62a);
FF (c, d, a, b, Block[ 6], 17, $a8304613);
FF (b, c, d, a, Block[ 7], 22, $fd469501);
FF (a, b, c, d, Block[ 8], 7, $698098d8);
FF (d, a, b, c, Block[ 9], 12, $8b44f7af);
FF (c, d, a, b, Block[10], 17, $ffff5bb1);
FF (b, c, d, a, Block[11], 22, $895cd7be);
FF (a, b, c, d, Block[12], 7, $6b901122);
FF (d, a, b, c, Block[13], 12, $fd987193);
FF (c, d, a, b, Block[14], 17, $a679438e);
FF (b, c, d, a, Block[15], 22, $49b40821);
GG (a, b, c, d, Block[ 1], 5, $f61e2562);
GG (d, a, b, c, Block[ 6], 9, $c040b340);
GG (c, d, a, b, Block[11], 14, $265e5a51);
GG (b, c, d, a, Block[ 0], 20, $e9b6c7aa);
GG (a, b, c, d, Block[ 5], 5, $d62f105d);
GG (d, a, b, c, Block[10], 9, $2441453);
GG (c, d, a, b, Block[15], 14, $d8a1e681);
GG (b, c, d, a, Block[ 4], 20, $e7d3fbc8);
GG (a, b, c, d, Block[ 9], 5, $21e1cde6);
GG (d, a, b, c, Block[14], 9, $c33707d6);
GG (c, d, a, b, Block[ 3], 14, $f4d50d87);
GG (b, c, d, a, Block[ 8], 20, $455a14ed);
GG (a, b, c, d, Block[13], 5, $a9e3e905);
GG (d, a, b, c, Block[ 2], 9, $fcefa3f8);
GG (c, d, a, b, Block[ 7], 14, $676f02d9);
GG (b, c, d, a, Block[12], 20, $8d2a4c8a);
HH (a, b, c, d, Block[ 5], 4, $fffa3942);
HH (d, a, b, c, Block[ 8], 11, $8771f681);
HH (c, d, a, b, Block[11], 16, $6d9d6122);
HH (b, c, d, a, Block[14], 23, $fde5380c);
HH (a, b, c, d, Block[ 1], 4, $a4beea44);
HH (d, a, b, c, Block[ 4], 11, $4bdecfa9);
HH (c, d, a, b, Block[ 7], 16, $f6bb4b60);
HH (b, c, d, a, Block[10], 23, $bebfbc70);
HH (a, b, c, d, Block[13], 4, $289b7ec6);
HH (d, a, b, c, Block[ 0], 11, $eaa127fa);
HH (c, d, a, b, Block[ 3], 16, $d4ef3085);
HH (b, c, d, a, Block[ 6], 23, $4881d05);
HH (a, b, c, d, Block[ 9], 4, $d9d4d039);
HH (d, a, b, c, Block[12], 11, $e6db99e5);
HH (c, d, a, b, Block[15], 16, $1fa27cf8);
HH (b, c, d, a, Block[ 2], 23, $c4ac5665);
II (a, b, c, d, Block[ 0], 6, $f4292244);
II (d, a, b, c, Block[ 7], 10, $432aff97);
II (c, d, a, b, Block[14], 15, $ab9423a7);
II (b, c, d, a, Block[ 5], 21, $fc93a039);
II (a, b, c, d, Block[12], 6, $655b59c3);
II (d, a, b, c, Block[ 3], 10, $8f0ccc92);
II (c, d, a, b, Block[10], 15, $ffeff47d);
II (b, c, d, a, Block[ 1], 21, $85845dd1);
II (a, b, c, d, Block[ 8], 6, $6fa87e4f);
II (d, a, b, c, Block[15], 10, $fe2ce6e0);
II (c, d, a, b, Block[ 6], 15, $a3014314);
II (b, c, d, a, Block[13], 21, $4e0811a1);
II (a, b, c, d, Block[ 4], 6, $f7537e82);
II (d, a, b, c, Block[11], 10, $bd3af235);
II (c, d, a, b, Block[ 2], 15, $2ad7d2bb);
II (b, c, d, a, Block[ 9], 21, $eb86d391);
inc(State[0], a);
inc(State[1], b);
inc(State[2], c);
inc(State[3], d);
end;

// -----------------------------------------------------------------------------------------------

// Initialize given Context
procedure MD5Init(var Context: MD5Context);
begin
with Context do begin
State[0] := $67452301;
State[1] := $efcdab89;
State[2] := $98badcfe;
State[3] := $10325476;
Count[0] := 0;
Count[1] := 0;
ZeroMemory(@Buffer, SizeOf(MD5Buffer));
end;
end;

// Update given Context to include Length bytes of Input
procedure MD5Update(var Context: MD5Context; Input: pChar; Length: longword);
var
Index: longword;
PartLen: longword;
I: longword;
begin
with Context do begin
Index := (Count[0] shr 3) and $3f;
inc(Count[0], Length shl 3);
if Count[0] < (Length shl 3) then inc(Count[1]);
inc(Count[1], Length shr 29);
end;
PartLen := 64 - Index;
if Length >= PartLen then begin
CopyMemory(@Context.Buffer[Index], Input, PartLen);
Transform(@Context.Buffer, Context.State);
I := PartLen;
while I + 63 < Length do begin
Transform(@Input, Context.State);
inc(I, 64);
end;
Index := 0;
end else I := 0;
CopyMemory(@Context.Buffer[Index], @Input, Length - I);
end;

// Finalize given Context, create Digest and zeroize Context
procedure MD5Final(var Context: MD5Context; var Digest: MD5Digest);
var
Bits: MD5CBits;
Index: longword;
PadLen: longword;
begin
Decode(@Context.Count, @Bits, 2);
Index := (Context.Count[0] shr 3) and $3f;
if Index < 56 then PadLen := 56 - Index else PadLen := 120 - Index;
MD5Update(Context, @PADDING, PadLen);
MD5Update(Context, @Bits, 8);
Decode(@Context.State, @Digest, 4);
ZeroMemory(@Context, SizeOf(MD5Context));
end;

// -----------------------------------------------------------------------------------------------

// Create digest of given Message
function MD5String(M: string): MD5Digest;
var
Context: MD5Context;
begin
MD5Init(Context);
MD5Update(Context, pChar(M), length(M));
MD5Final(Context, Result);
end;

// Create digest of file with given Name
function MD5File(N: string): MD5Digest;
var
FileHandle: THandle;
MapHandle: THandle;
ViewPointer: pointer;
Context: MD5Context;
begin
MD5Init(Context);
FileHandle := CreateFile(pChar(N), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
if FileHandle <> INVALID_HANDLE_VALUE then try
MapHandle := CreateFileMapping(FileHandle, nil, PAGE_READONLY, 0, 0, nil);
if MapHandle <> 0 then try
ViewPointer := MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);
if ViewPointer <> nil then try
MD5Update(Context, ViewPointer, GetFileSize(FileHandle, nil));
finally
UnmapViewOfFile(ViewPointer);
end;
finally
CloseHandle(MapHandle);
end;
finally
CloseHandle(FileHandle);
end;
MD5Final(Context, Result);
end;

// Create hex representation of given Digest
function MD5Print(D: MD5Digest): string;
var
I: byte;
const
Digits: array[0..15] of char =
('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
begin
Result := '';
for I := 0 to 15 do Result := Result + Digits[(D shr 4) and $0f] + Digits[D and $0f];
end;

// -----------------------------------------------------------------------------------------------

// Compare two Digests
function MD5Match(D1, D2: MD5Digest): boolean;
var
I: byte;
begin
I := 0;
Result := TRUE;
while Result and (I < 16) do begin
Result := D1 = D2;
inc(I);
end;
end;

end.


By: VGR Date: 08/06/2003 17:42:00 English  Type : Comment
Innerfuse Pascal Script 3 (short IFPS3) is a script engine written in Delphi. IFPS allowes you to use most of Object Pascal language within your Delphi projects at runtime. It's a set of units that can be compiled into your exe file so there is no need to distribute any external files. It has the following features:

Variables, Constants
Standard statements: Begin/End, If/Then/Else, For/To/Downto/Do, Case x Of, Repeat/Until, While, uses, Exit, Continue, Break
Functions (Declared inside or outside script)
Standard types: Byte, Shortint, Char, Word, SmallInt, Cardinal, Longint, Integer, String, Real, Double, Single, Extended, Boolean, Array, Record, Enumerations
Importing Delphi functions and classes.
Assigning script functions to Delphi events.
Compiling to a file and running later

If it knows "uses" and is able to "import Delphi functions"... "Uses Windows;" and the use of DWORD should work.

I guess your scripting Pascal will choke on the pointers. It would be fine if I knew where to start for adaptation, for example if your ? (compiler ? IDE?) produced a list of syntax errors, like Delphi does
By: VGR Date: 08/06/2003 17:45:00 English  Type : Comment
also : does it know the type LongWord ?
By: mrguide Date: 08/06/2003 17:59:00 English  Type : Comment
First of all I will answer your questions:
- No, Innerfuse Pascal does not know the uses clause (or at least not when running in My Inno Setup Extensions)
- Yes, you can try to copy delphi functions into your Innerfuse Pascal script but you cannot reference it by a uses statement. When copying delphi functions it is very likely that you have to change it's source extensively before Innerfuse Pascal accepts it
- No, Innerfuse Pascal does not support the DWORD data type
- Yes, Innerfuse Pascal supports the longword data type


I will summarize the things I had to delete from your source before it compiled without errors:
- the line with the unit keyword; Innerfuse Pascal script doesn't work unit-oriented (or at least not when running in My Inno Setup Extensions)
- the line with the interface keyword; simply not supported
- the line with uses; same reason
- the type definitions containing this syntax:
typedef = array[beginindex .. endindex] of typedef
^these have to change into: typedef = array of typedef and later be set with SetArrayLength
- everything that depends on DWORD; it's not a supported data type
- the procedure and function definitions before the implementation line. pre-definitions of procedures/functions aren't part of the Innerfuse Pascal structure
- the implementation line itself
- the definition of PADDING; when declaring a variable in a var section you cannot directly assign a value to it
- all procedures containing the data type 'pointer'
- all with-do constructions; not supported
- the calls to CopyMemory in the MD5Update function
- the call to transform because I had to delete it since it contained an argument of the pointer data type
- the Inc(x,y) instructions; not supported
- the calls to Decode in MD5Final because I had to delete Decode since it contained pointer arguments
- the call to ZeroMemory in MD5Final; not supported
- the calls to MD5Update in MD5Final; some of the given arguments aren't recognized
- the call to MD5Init in MD5string because I had to delete MD5Init since it contained an unrecognized data type
- the complete MD5File function since it uses incompatible data type and i do not need to encode files. I only want to calculate the hash out of a single string
- the const declaration in MD5Print; you cannot declare constants inside a function/procedure. Besides that the digits constant is constructed using the 'array[beginindex .. endindex] of datatype' construction which is illegal in Innerfuse Pascal
- the for loop inside MD5Print that uses the digits constant; the constant was deleted
- the Inc instruction in MD5Match; Inc is not supported
- the end. line; that isn't needed in Innerfuse Pascal
- the variable declaration 'bits' in MD5Final; it wasn't used anymore
- the variable declaration 'I' in MD5Print; it wasn't used anymore


Now I reached the point of compilation :) But not the one of satisfaction :( To help you porting/fixing the code, I'll provide the remaining source code:

;--start of testscript.iss---------------------------------------------------------

[Setup]
; These setup parameters are used to stop Inno Setup from showing any of its
; wizard-style interface elements that are part of an installation
AppName=test
AppVerName=test
CreateAppDir=false
UsePreviousAppDir=false
UsePreviousGroup=false
AlwaysShowComponentsList=false
ShowComponentSizes=false
FlatComponentsList=false
UsePreviousSetupType=false
UsePreviousTasks=false
UsePreviousUserInfo=false
DisableStartupPrompt=true
OutputBaseFileName=UninstallService
OutputDir=.

[Code]
type
MD5CBits = array of byte;
MD5Digest = array of byte;
MD5Buffer = array of byte;
MD5Context = record
Buffer: MD5Buffer;
end;

procedure MD5Update(var Context: MD5Context; Input: pChar; Length: longword);
var
Index: longword;
PartLen: longword;
I: longword;
begin
PartLen := 64 - Index;
if Length >= PartLen then begin
I := PartLen;
while I + 63 < Length do begin
end;
Index := 0;
end else I := 0;
end;

procedure MD5Final(var Context: MD5Context; var Digest: MD5Digest);
var
Index: longword;
PadLen: longword;
begin
Index := (Context.Buffer[0] shr 3) and $3f;
if Index < 56 then PadLen := 56 - Index else PadLen := 120 - Index;
end;

function MD5String(M: string): MD5Digest;
var
Context: MD5Context;
begin
MD5Update(Context, pChar(M), length(M));
MD5Final(Context, Result);
end;

function MD5Print(D: MD5Digest): string;
begin
Result := '';
end;

function MD5Match(D1, D2: MD5Digest): boolean;
var
I: byte;
begin
I := 0;
Result := TRUE;
while Result and (I < 16) do begin
Result := D1 = D2;
end;
end;

function InitializeSetup(): boolean;
begin
// This is a sort of 'main' function that will be called when the installer
// is started. You can insert code to do things here.

// This 'should' popup a message with the MD5 hash of the text 'Hash me' :)
MsgBox(MD5Print(MD5String('Hash me')), mbInformation, MB_OK);

// Now return false so the installer won't continue after executing this
// function. This makes this installer script perfect for testing Innerfuse
// pascal scripts
Result := false
end;

//--end of testscript.iss------------------------------------------------------


You can copy-paste everything between 'start op testscript.iss' and 'end of testscript.iss' and save it as plain text in testscript.iss. Then you can download My Inno Setup Extensions ( <A HREF="http://www.xs4all.nl/~mlaan2/isx/Isxsetup.exe">http://www.xs4all.nl/~mlaan2/isx/Isxsetup.exe</a> ) and open testscript.iss using this program. It should compile fine but show an error when running. After all the MD5String function doesn't work properly anymore. If you need more information... just ask.
By: VGR Date: 09/06/2003 05:25:00 English  Type : Comment
padding is not a variables assigned a value (bad) but an typed constant (ie, an initialized variable :D )

i guess you saw that DWORD is in fact LongWord.

transforming a unit structure in plain include file format was my inyenyion (no more implementation, interface, interface declarations, implicit signatures in implementation, etc)

the with..do was also easy to make disappear

i think we can make it ;-)
By: VGR Date: 09/06/2003 05:51:00 English  Type : Comment
I started porting. No guarantee, but I'll try, at least :D

I'll follow your instructions and transform the code accordingly (no more pointers etc)

-so you have access to windows API functions like ZeroMemory() ?
-do you have the address operator (@) ?
By: mrguide Date: 09/06/2003 17:51:00 English  Type : Comment
Well in Innerfuse Pascal you can access Windows API functions through dll functions. To use these you must declare them like:

function StartNTService(hService :HANDLE;dwNumServiceArgs : cardinal;lpServiceArgVectors : cardinal) : boolean;
external 'StartServiceA@advapi32.dll stdcall';

And for the adress operator... I guess Innerfuse doesn't allow memory-level operations. I've tried to find something about pointers and memory adresses in Innerfuse Pascal, but I couldn't find anything.

By: VGR Date: 11/06/2003 18:38:00 English  Type : Comment
I'm almost done with it

I encounter a known compiler bug :
for longword values :
Inc(a,b) is ok whereas a:=a+b throws an "integer overflow" exception

should finish in some minutes
By: VGR Date: 11/06/2003 20:33:00 English  Type : Answer
DONE !

I had to set those options to cope with the (normal) integer overflow. Basically, I turned off range checking and overflow checking. I hope you can also do it.
{$A+,B-,C+,D+,E-,F-,G+,H+,I+,J+,K-,L+,M-,N+,O-,P+,Q-,R-,S-,T-,U-,V+,W-,X+,Y+,Z1}

Here is the basic Uses clause I had to use. I guess you'll have to use SysUtils.StrPCopy with your Innerfuse way of defining an external function
uses Windows in 'H:\Borland\Delphi4\Source\Rtl\Win\windows.pas',
SysUtils; // for StrPCopy

Now the code :

First a caveat : I leave one piece of work to you, as you're the best placed to do so : the transformation of all array declarations to innerfuse's open array + SetLength() calls.
I'm not experienced in this.

------- code that should at least compile on Innerfuse Pascal ----
type
DWORD = LongWord;
MD5Count = array[0..1] of DWORD;
MD5State = array[0..3] of DWORD;
MD5Block = array[0..15] of DWORD;
MD5CBits = array[0..7] of byte;
MD5Digest = array[0..15] of byte;
MD5Buffer = array[0..63] of byte;
MD5Context = record
State: MD5State;
Count: MD5Count;
Buffer: MD5Buffer;
end;

var PADDING: MD5Buffer;

//VGR09062003 ADDed this
Type typbuf = array[0..79] Of Byte;
pChar = ^typbuf;
//--------------------------- my routines
Procedure ZeroMemory(Var par; siz : Integer);
type TBytes = array[0..MaxInt - 1] of Byte;
Var i : DWORD;
Begin
for i:=0 to siz-1 Do TBytes(par):=0;
End; // ZeroMemory
Procedure CopyMemory(Var res : MD5Buffer;Index : LongWord; Input : typbuf; deb, PartLen : LongWord);
Var i : DWORD;
Begin
If PartLen>0 Then For i:=deb to PartLen-1 Do res[Index+i]:= Input;
End; // CopyMemory
Procedure CopyMemoryBuf(Var res : MD5Buffer;Index : LongWord; Input : MD5Buffer; deb, PartLen : LongWord);
Var i : DWORD;
Begin
If PartLen>0 Then For i:=deb to PartLen-1 Do res[Index+i]:= Input;
End; // CopyMemoryBuf
Procedure CopyMemoryBits(Var res : MD5Buffer;Index : LongWord; Input : MD5CBits; deb, PartLen : LongWord);
Var i : DWORD;
Begin
If PartLen>0 Then For i:=deb to PartLen-1 Do res[Index+i]:= Input;
End; // CopyMemoryBits
procedure Decode2(Var Source : MD5State; Var Target : MD5Digest; Count: longword);
var
S: DWORD;
T: Byte;
I: longword;
begin
S := 0;
T := 0;
for I := 1 to Count do begin
S:=DWORD(Source[I-1]);
Target[T] := S and $ff;
T:=T+1;
Target[T] := (S shr 8) and $ff;
T:=T+1;
Target[T] := (S shr 16) and $ff;
T:=T+1;
Target[T] := (S shr 24) and $ff;
T:=T+1;
end;
end;
procedure EncodeCBuf(Source : MD5Buffer; Var Target: MD5Block; Count: longword);
var
S: Byte;
T: DWORD;
I: longword;
begin
S := 0;
T := 0;
for I := 1 to Count div 4 do begin
T := Source[S];
S:=S+1;
T := T or (Source[S] shl 8);
S:=S+1;
T := T or (Source[S] shl 16);
S:=S+1;
T := T or (Source[S] shl 24);
S:=S+1;
Target[I-1]:=T;
//DEL T:=T+SizeOf(DWORD);
end;
end;
procedure EncodeBits(Source : MD5CBits; Var Target: MD5Block; Count: longword);
var
S: Byte;
T: DWORD;
I: longword;
begin
S := 0;
T := 0;
for I := 1 to Count div 4 do begin
T := Source[S];
S:=S+1;
T := T or (Source[S] shl 8);
S:=S+1;
T := T or (Source[S] shl 16);
S:=S+1;
T := T or (Source[S] shl 24);
S:=S+1;
Target:=T;
//DEL T:=T+SizeOf(DWORD);
end;
end;
//EoAdd
//--------------------------- MD5 routines
function F(x, y, z: DWORD): DWORD;
begin
F := (x and y) or ((not x) and z);
end;

function G(x, y, z: DWORD): DWORD;
begin
G := (x and z) or (y and (not z));
end;

function H(x, y, z: DWORD): DWORD;
begin
H := x xor y xor z;
end;

function I(x, y, z: DWORD): DWORD;
begin
I := y xor (x or (not z));
end;

procedure rot(var x: DWORD; n: BYTE);
begin
x := (x shl n) or (x shr (32 - n));
end;

procedure FF(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
a:=a+F(b, c, d) + x + ac;
rot(a, s);
a:=a+b;
end;

procedure GG(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
a:=a+ G(b, c, d) + x + ac;
rot(a, s);
a:=a+ b;
end;

procedure HH(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
a:=a+ H(b, c, d) + x + ac;
rot(a, s);
a:=a+ b;
end;

procedure II(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
a:=a+ I(b, c, d) + x + ac;
rot(a, s);
a:=a+ b;
end;

// -----------------------------------------------------------------------------------------------

// Encode Count bytes at Source into (Count / 4) DWORDs at Target
procedure Encode(Source : typbuf; Var Target: MD5Block; Count: longword);
var
S: Byte;
T: DWORD;
I: longword;
begin
S := 0;
T := 0;
for I := 1 to Count div 4 do begin
T := Source[S];
S:=S+1;
T := T or (Source[S] shl 8);
S:=S+1;
T := T or (Source[S] shl 16);
S:=S+1;
T := T or (Source[S] shl 24);
S:=S+1;
Target:=T;
//DEL T:=T+SizeOf(DWORD);
end;
end;

// Decode Count DWORDs at Source into (Count * 4) Bytes at Target
procedure Decode(Var Source : MD5Count; Var Target : MD5CBits; Count: longword);
var
S: DWORD;
T: Byte;
I: longword;
begin
S := 0;
T := 0;
for I := 1 to Count do begin
S:=DWORD(Source[I-1]);
Target[T] := S and $ff;
T:=T+1;
Target[T] := (S shr 8) and $ff;
T:=T+1;
Target[T] := (S shr 16) and $ff;
T:=T+1;
Target[T] := (S shr 24) and $ff;
T:=T+1;
//useless now inc(S);
end;
end;

// Transform State according to first 64 bytes at Buffer
procedure Transform(Var Buffer : typbuf; start : LongWord; var State: MD5State);
var
a, b, c, d: DWORD;
Block: MD5Block;
begin
Encode(Buffer, Block, 64);
a := State[0];
b := State[1];
c := State[2];
d := State[3];
FF (a, b, c, d, Block[ 0], 7, $d76aa478);
FF (d, a, b, c, Block[ 1], 12, $e8c7b756);
FF (c, d, a, b, Block[ 2], 17, $242070db);
FF (b, c, d, a, Block[ 3], 22, $c1bdceee);
FF (a, b, c, d, Block[ 4], 7, $f57c0faf);
FF (d, a, b, c, Block[ 5], 12, $4787c62a);
FF (c, d, a, b, Block[ 6], 17, $a8304613);
FF (b, c, d, a, Block[ 7], 22, $fd469501);
FF (a, b, c, d, Block[ 8], 7, $698098d8);
FF (d, a, b, c, Block[ 9], 12, $8b44f7af);
FF (c, d, a, b, Block[10], 17, $ffff5bb1);
FF (b, c, d, a, Block[11], 22, $895cd7be);
FF (a, b, c, d, Block[12], 7, $6b901122);
FF (d, a, b, c, Block[13], 12, $fd987193);
FF (c, d, a, b, Block[14], 17, $a679438e);
FF (b, c, d, a, Block[15], 22, $49b40821);
GG (a, b, c, d, Block[ 1], 5, $f61e2562);
GG (d, a, b, c, Block[ 6], 9, $c040b340);
GG (c, d, a, b, Block[11], 14, $265e5a51);
GG (b, c, d, a, Block[ 0], 20, $e9b6c7aa);
GG (a, b, c, d, Block[ 5], 5, $d62f105d);
GG (d, a, b, c, Block[10], 9, $2441453);
GG (c, d, a, b, Block[15], 14, $d8a1e681);
GG (b, c, d, a, Block[ 4], 20, $e7d3fbc8);
GG (a, b, c, d, Block[ 9], 5, $21e1cde6);
GG (d, a, b, c, Block[14], 9, $c33707d6);
GG (c, d, a, b, Block[ 3], 14, $f4d50d87);
GG (b, c, d, a, Block[ 8], 20, $455a14ed);
GG (a, b, c, d, Block[13], 5, $a9e3e905);
GG (d, a, b, c, Block[ 2], 9, $fcefa3f8);
GG (c, d, a, b, Block[ 7], 14, $676f02d9);
GG (b, c, d, a, Block[12], 20, $8d2a4c8a);
HH (a, b, c, d, Block[ 5], 4, $fffa3942);
HH (d, a, b, c, Block[ 8], 11, $8771f681);
HH (c, d, a, b, Block[11], 16, $6d9d6122);
HH (b, c, d, a, Block[14], 23, $fde5380c);
HH (a, b, c, d, Block[ 1], 4, $a4beea44);
HH (d, a, b, c, Block[ 4], 11, $4bdecfa9);
HH (c, d, a, b, Block[ 7], 16, $f6bb4b60);
HH (b, c, d, a, Block[10], 23, $bebfbc70);
HH (a, b, c, d, Block[13], 4, $289b7ec6);
HH (d, a, b, c, Block[ 0], 11, $eaa127fa);
HH (c, d, a, b, Block[ 3], 16, $d4ef3085);
HH (b, c, d, a, Block[ 6], 23, $4881d05);
HH (a, b, c, d, Block[ 9], 4, $d9d4d039);
HH (d, a, b, c, Block[12], 11, $e6db99e5);
HH (c, d, a, b, Block[15], 16, $1fa27cf8);
HH (b, c, d, a, Block[ 2], 23, $c4ac5665);
II (a, b, c, d, Block[ 0], 6, $f4292244);
II (d, a, b, c, Block[ 7], 10, $432aff97);
II (c, d, a, b, Block[14], 15, $ab9423a7);
II (b, c, d, a, Block[ 5], 21, $fc93a039);
II (a, b, c, d, Block[12], 6, $655b59c3);
II (d, a, b, c, Block[ 3], 10, $8f0ccc92);
II (c, d, a, b, Block[10], 15, $ffeff47d);
II (b, c, d, a, Block[ 1], 21, $85845dd1);
II (a, b, c, d, Block[ 8], 6, $6fa87e4f);
II (d, a, b, c, Block[15], 10, $fe2ce6e0);
II (c, d, a, b, Block[ 6], 15, $a3014314);
II (b, c, d, a, Block[13], 21, $4e0811a1);
II (a, b, c, d, Block[ 4], 6, $f7537e82);
II (d, a, b, c, Block[11], 10, $bd3af235);
II (c, d, a, b, Block[ 2], 15, $2ad7d2bb);
II (b, c, d, a, Block[ 9], 21, $eb86d391);
State[0]:=State[0]+ a;
State[1]:=State[1]+ b;
State[2]:=State[2]+ c;
State[3]:=State[3]+ d;
end;

procedure TransformCBuf(Var Buffer : MD5Buffer; start : LongWord; var State: MD5State);
var
a, b, c, d: DWORD;
Block: MD5Block;
begin
EncodeCBuf(Buffer, Block, 64);
a := State[0];
b := State[1];
c := State[2];
d := State[3];
FF (a, b, c, d, Block[ 0], 7, $d76aa478);
FF (d, a, b, c, Block[ 1], 12, $e8c7b756);
FF (c, d, a, b, Block[ 2], 17, $242070db);
FF (b, c, d, a, Block[ 3], 22, $c1bdceee);
FF (a, b, c, d, Block[ 4], 7, $f57c0faf);
FF (d, a, b, c, Block[ 5], 12, $4787c62a);
FF (c, d, a, b, Block[ 6], 17, $a8304613);
FF (b, c, d, a, Block[ 7], 22, $fd469501);
FF (a, b, c, d, Block[ 8], 7, $698098d8);
FF (d, a, b, c, Block[ 9], 12, $8b44f7af);
FF (c, d, a, b, Block[10], 17, $ffff5bb1);
FF (b, c, d, a, Block[11], 22, $895cd7be);
FF (a, b, c, d, Block[12], 7, $6b901122);
FF (d, a, b, c, Block[13], 12, $fd987193);
FF (c, d, a, b, Block[14], 17, $a679438e);
FF (b, c, d, a, Block[15], 22, $49b40821);
GG (a, b, c, d, Block[ 1], 5, $f61e2562);
GG (d, a, b, c, Block[ 6], 9, $c040b340);
GG (c, d, a, b, Block[11], 14, $265e5a51);
GG (b, c, d, a, Block[ 0], 20, $e9b6c7aa);
GG (a, b, c, d, Block[ 5], 5, $d62f105d);
GG (d, a, b, c, Block[10], 9, $2441453);
GG (c, d, a, b, Block[15], 14, $d8a1e681);
GG (b, c, d, a, Block[ 4], 20, $e7d3fbc8);
GG (a, b, c, d, Block[ 9], 5, $21e1cde6);
GG (d, a, b, c, Block[14], 9, $c33707d6);
GG (c, d, a, b, Block[ 3], 14, $f4d50d87);
GG (b, c, d, a, Block[ 8], 20, $455a14ed);
GG (a, b, c, d, Block[13], 5, $a9e3e905);
GG (d, a, b, c, Block[ 2], 9, $fcefa3f8);
GG (c, d, a, b, Block[ 7], 14, $676f02d9);
GG (b, c, d, a, Block[12], 20, $8d2a4c8a);
HH (a, b, c, d, Block[ 5], 4, $fffa3942);
HH (d, a, b, c, Block[ 8], 11, $8771f681);
HH (c, d, a, b, Block[11], 16, $6d9d6122);
HH (b, c, d, a, Block[14], 23, $fde5380c);
HH (a, b, c, d, Block[ 1], 4, $a4beea44);
HH (d, a, b, c, Block[ 4], 11, $4bdecfa9);
HH (c, d, a, b, Block[ 7], 16, $f6bb4b60);
HH (b, c, d, a, Block[10], 23, $bebfbc70);
HH (a, b, c, d, Block[13], 4, $289b7ec6);
HH (d, a, b, c, Block[ 0], 11, $eaa127fa);
HH (c, d, a, b, Block[ 3], 16, $d4ef3085);
HH (b, c, d, a, Block[ 6], 23, $4881d05);
HH (a, b, c, d, Block[ 9], 4, $d9d4d039);
HH (d, a, b, c, Block[12], 11, $e6db99e5);
HH (c, d, a, b, Block[15], 16, $1fa27cf8);
HH (b, c, d, a, Block[ 2], 23, $c4ac5665);
II (a, b, c, d, Block[ 0], 6, $f4292244);
II (d, a, b, c, Block[ 7], 10, $432aff97);
II (c, d, a, b, Block[14], 15, $ab9423a7);
II (b, c, d, a, Block[ 5], 21, $fc93a039);
II (a, b, c, d, Block[12], 6, $655b59c3);
II (d, a, b, c, Block[ 3], 10, $8f0ccc92);
II (c, d, a, b, Block[10], 15, $ffeff47d);
II (b, c, d, a, Block[ 1], 21, $85845dd1);
II (a, b, c, d, Block[ 8], 6, $6fa87e4f);
II (d, a, b, c, Block[15], 10, $fe2ce6e0);
II (c, d, a, b, Block[ 6], 15, $a3014314);
II (b, c, d, a, Block[13], 21, $4e0811a1);
II (a, b, c, d, Block[ 4], 6, $f7537e82);
II (d, a, b, c, Block[11], 10, $bd3af235);
II (c, d, a, b, Block[ 2], 15, $2ad7d2bb);
II (b, c, d, a, Block[ 9], 21, $eb86d391);
State[0]:=State[0]+ a;
State[1]:=State[1]+ b;
State[2]:=State[2]+ c;
State[3]:=State[3]+ d;
end;

procedure TransformBits(Var Buffer : MD5CBits; start : LongWord; var State: MD5State);
var
a, b, c, d: DWORD;
Block: MD5Block;
begin
EncodeBits(Buffer, Block, 64);
a := State[0];
b := State[1];
c := State[2];
d := State[3];
FF (a, b, c, d, Block[ 0], 7, $d76aa478);
FF (d, a, b, c, Block[ 1], 12, $e8c7b756);
FF (c, d, a, b, Block[ 2], 17, $242070db);
FF (b, c, d, a, Block[ 3], 22, $c1bdceee);
FF (a, b, c, d, Block[ 4], 7, $f57c0faf);
FF (d, a, b, c, Block[ 5], 12, $4787c62a);
FF (c, d, a, b, Block[ 6], 17, $a8304613);
FF (b, c, d, a, Block[ 7], 22, $fd469501);
FF (a, b, c, d, Block[ 8], 7, $698098d8);
FF (d, a, b, c, Block[ 9], 12, $8b44f7af);
FF (c, d, a, b, Block[10], 17, $ffff5bb1);
FF (b, c, d, a, Block[11], 22, $895cd7be);
FF (a, b, c, d, Block[12], 7, $6b901122);
FF (d, a, b, c, Block[13], 12, $fd987193);
FF (c, d, a, b, Block[14], 17, $a679438e);
FF (b, c, d, a, Block[15], 22, $49b40821);
GG (a, b, c, d, Block[ 1], 5, $f61e2562);
GG (d, a, b, c, Block[ 6], 9, $c040b340);
GG (c, d, a, b, Block[11], 14, $265e5a51);
GG (b, c, d, a, Block[ 0], 20, $e9b6c7aa);
GG (a, b, c, d, Block[ 5], 5, $d62f105d);
GG (d, a, b, c, Block[10], 9, $2441453);
GG (c, d, a, b, Block[15], 14, $d8a1e681);
GG (b, c, d, a, Block[ 4], 20, $e7d3fbc8);
GG (a, b, c, d, Block[ 9], 5, $21e1cde6);
GG (d, a, b, c, Block[14], 9, $c33707d6);
GG (c, d, a, b, Block[ 3], 14, $f4d50d87);
GG (b, c, d, a, Block[ 8], 20, $455a14ed);
GG (a, b, c, d, Block[13], 5, $a9e3e905);
GG (d, a, b, c, Block[ 2], 9, $fcefa3f8);
GG (c, d, a, b, Block[ 7], 14, $676f02d9);
GG (b, c, d, a, Block[12], 20, $8d2a4c8a);
HH (a, b, c, d, Block[ 5], 4, $fffa3942);
HH (d, a, b, c, Block[ 8], 11, $8771f681);
HH (c, d, a, b, Block[11], 16, $6d9d6122);
HH (b, c, d, a, Block[14], 23, $fde5380c);
HH (a, b, c, d, Block[ 1], 4, $a4beea44);
HH (d, a, b, c, Block[ 4], 11, $4bdecfa9);
HH (c, d, a, b, Block[ 7], 16, $f6bb4b60);
HH (b, c, d, a, Block[10], 23, $bebfbc70);
HH (a, b, c, d, Block[13], 4, $289b7ec6);
HH (d, a, b, c, Block[ 0], 11, $eaa127fa);
HH (c, d, a, b, Block[ 3], 16, $d4ef3085);
HH (b, c, d, a, Block[ 6], 23, $4881d05);
HH (a, b, c, d, Block[ 9], 4, $d9d4d039);
HH (d, a, b, c, Block[12], 11, $e6db99e5);
HH (c, d, a, b, Block[15], 16, $1fa27cf8);
HH (b, c, d, a, Block[ 2], 23, $c4ac5665);
II (a, b, c, d, Block[ 0], 6, $f4292244);
II (d, a, b, c, Block[ 7], 10, $432aff97);
II (c, d, a, b, Block[14], 15, $ab9423a7);
II (b, c, d, a, Block[ 5], 21, $fc93a039);
II (a, b, c, d, Block[12], 6, $655b59c3);
II (d, a, b, c, Block[ 3], 10, $8f0ccc92);
II (c, d, a, b, Block[10], 15, $ffeff47d);
II (b, c, d, a, Block[ 1], 21, $85845dd1);
II (a, b, c, d, Block[ 8], 6, $6fa87e4f);
II (d, a, b, c, Block[15], 10, $fe2ce6e0);
II (c, d, a, b, Block[ 6], 15, $a3014314);
II (b, c, d, a, Block[13], 21, $4e0811a1);
II (a, b, c, d, Block[ 4], 6, $f7537e82);
II (d, a, b, c, Block[11], 10, $bd3af235);
II (c, d, a, b, Block[ 2], 15, $2ad7d2bb);
II (b, c, d, a, Block[ 9], 21, $eb86d391);
State[0]:=State[0]+ a;
State[1]:=State[1]+ b;
State[2]:=State[2]+ c;
State[3]:=State[3]+ d;
end;

// -----------------------------------------------------------------------------------------------
// Initialize given Context
procedure MD5Init(var Context: MD5Context);
Var i : Byte;
begin
//VGR09062003 ADDed this
PADDING[0]:=$80;
for i:=1 to 63 Do PADDING:=$00;
//EoAdd
Context.State[0] := $67452301;
Context.State[1] := $efcdab89;
Context.State[2] := $98badcfe;
Context.State[3] := $10325476;
Context.Count[0] := 0;
Context.Count[1] := 0;
ZeroMemory(Context.Buffer,SizeOf(MD5Buffer));
end;

// Update given Context to include Length bytes of Input
procedure MD5UpdateMD5(var Context: MD5Context; Input : MD5Buffer; Length: longword);
var
Index: longword;
PartLen: longword;
I: longword;
begin
Index := (Context.Count[0] shr 3) and $3f;
Context.Count[0]:=Context.Count[0]+ Length shl 3;
if Context.Count[0] < (Length shl 3) then Context.Count[1]:=Context.Count[1]+1;
Context.Count[1]:=Context.Count[1]+ Length shr 29;
PartLen := 64 - Index;
if Length >= PartLen then begin
CopyMemoryBuf(Context.Buffer,Index, Input,0, PartLen);
TransformCBuf(Context.Buffer,0, Context.State);
I := PartLen;
while I + 63 < Length do begin
TransformCBuf(Input,I, Context.State);
I:=I+ 64;
end;
Index := 0;
end else I := 0;
CopyMemoryBuf(Context.Buffer,Index, Input,I, Length - I);
end;
procedure MD5UpdateBits(var Context: MD5Context; Input : MD5CBits; Length: longword);
var
Index: longword;
PartLen: longword;
I: longword;
begin
Index := (Context.Count[0] shr 3) and $3f;
Context.Count[0]:=Context.Count[0]+ Length shl 3;
if Context.Count[0] < (Length shl 3) then Context.Count[1]:=Context.Count[1]+1;
Context.Count[1]:=Context.Count[1]+ Length shr 29;
PartLen := 64 - Index;
if Length >= PartLen then begin
CopyMemoryBits(Context.Buffer,Index, Input,0, PartLen);
TransformCBuf(Context.Buffer,0, Context.State);
I := PartLen;
while I + 63 < Length do begin
TransformBits(Input,I, Context.State);
I:=I+ 64;
end;
Index := 0;
end else I := 0;
CopyMemoryBits(Context.Buffer,Index, Input,I, Length - I);
end;

procedure MD5Update(var Context: MD5Context; Input : typbuf; Length: longword);
var
Index: longword;
PartLen: longword;
I: longword;
std : typbuf;
begin
std:=Input;
Index := (Context.Count[0] shr 3) and $3f;
Context.Count[0]:=Context.Count[0]+ Length shl 3;
if Context.Count[0] < (Length shl 3) then Context.Count[1]:=Context.Count[1]+1;
Context.Count[1]:=Context.Count[1]+ Length shr 29;
PartLen := 64 - Index;
if Length >= PartLen then begin
CopyMemory(Context.Buffer,Index, std,0, PartLen);
TransformCBuf(Context.Buffer,0, Context.State);
I := PartLen;
while I + 63 < Length do begin
Transform(std,I, Context.State);
I:=I+ 64;
end;
Index := 0;
end else I := 0;
CopyMemory(Context.Buffer,Index, std,I, Length - I);
end;

// Finalize given Context, create Digest and zeroize Context
procedure MD5Final(var Context: MD5Context; var Digest: MD5Digest);
var
Bits: MD5CBits;
Index: longword;
PadLen: longword;
begin
Decode(Context.Count, Bits, 2);
Index := (Context.Count[0] shr 3) and $3f;
if Index < 56 then PadLen := 56 - Index else PadLen := 120 - Index;
MD5UpdateMD5(Context, PADDING, PadLen);
MD5UpdateBits(Context, Bits, 8);
Decode2(Context.State, Digest, 4);
ZeroMemory(Context, SizeOf(MD5Context));
end;

// Create digest of given Message
function MD5String(M: string): MD5Digest;
var
Context: MD5Context;
Mbuf : typbuf;
i : Byte;
Res : MD5Digest;
begin
for i:=1 to Length(M) Do Mbuf[i-1]:=Ord(M); Mbuf:=$0;
MD5Init(Context);
MD5Update(Context, Mbuf, length(M));
MD5Final(Context, Res);
MD5String:=Res; // cleaner
end;

// Create hex representation of given Digest
const Digits: array[0..15] of char =
('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');

function MD5Print(D: MD5Digest): string;
var
I: byte;
begin
Result := '';
for I := 0 to 15 do Result := Result + Digits[(D shr 4) and $0f] + Digits[D and $0f];
MD5Print:=Result; // cleaner
end;

Var thestring : String;
function InitializeSetup(): boolean;
begin
// This is a sort of 'main' function that will be called when the installer
// is started. You can insert code to do things here.

// This 'should' popup a message with the MD5 hash of the text 'Hash me' :)
thestring:=MD5Print(MD5String('Hash me'));
// MsgBox(thestring, mbInformation, MB_OK);

// Now return false so the installer won't continue after executing this
// function. This makes this installer script perfect for testing Innerfuse
// pascal scripts
Result := false
end;

------- end of code ----

By: mrguide Date: 11/06/2003 21:51:00 English  Type : Comment
ah, nice work VGR! But..... it doesn't compile yet. I've tried a few things but I can't get it to work.

I think, correct me if I'm wrong, you're still compiling your code in some other pascal IDE. In my opinion you really need to run the My Inno Setup Extensions environment. This is the only way you can compile and test this code to suit my needs.

Please download the My Inno Setup Extensions environment and make it work in there. Only if you can reach that goal I will be fully satisfied.

Because I think this problem is something more difficult than I estimated when asking my question, I will increase the points by 100.

By: VGR Date: 11/06/2003 22:08:00 English  Type : Comment
1) have you modified the array[...] definitions first ?

2) yes, compiles as console on Delphi

3) I followed line by line your instructions and deleted all mentioned incompatibilities, and it wasn't easy at all (especially when you've no Pointer and no @ddress operator... in a code full of them)

4) I would prefer you to show the current list of problems [not counting the array defs]
By: weckert Date: 24/06/2003 12:27:00 English  Type : Comment
I have never used Inno Setup, but was wondering. Could you write a small Delphi application that asks for the admin's password and update the file? Tehn in Inno Setup call that program and wait for it to end before continuing?

If you have problems then could create a Delphi DLL that performs that task and have your setup script call that? This has the added bonus of keeping your source code your source code.

WEckert

Do register to be able to answer

EContact
browser fav
page generated in 383.950000 milliseconds

Why Google AdSense ads ?

compteur
 Ranking-Hits PageRank for this page