&ANALYZE-SUSPEND _VERSION-NUMBER UIB_v9r12
&ANALYZE-RESUME
&ANALYZE-SUSPEND _UIB-CODE-BLOCK _CUSTOM _DEFINITIONS Procedure 
/*---------------------------------------------------------------------
    Copyright (C) 2001 Lemur Computing Ltd. All rights reserved.
    This program is freeware provided for general distribution without 
    warranty of any kind providing this copyright notice and explanatory 
    text is left intact.  
    ---------------------------------------------------------------------
    
    File        : MD5.p
    Purpose     : MD5 Encrypting Algorithm

    Syntax      : FUNCTION encryptString RETURNS CHARACTER
                    ( INPUT str AS CHAR ) 

    Description : 

    Author(s)   : Lee Bourne
    Created     : 26th November 2001
    Notes       : A Progress implementation of the RSA Data Security, Inc. 
                  MD5 Message Digest Algorithm, as defined in RFC 1321.
                  
                  Email lee@lemurcomputing.co.uk for details
                  
                  See http://pajhome.org.uk/crypt/md5/index.html for details
                  of the JavaScript implementation and details of the
                  security limitations of this method.
                      
  ----------------------------------------------------------------------*/

/* ***************************  Definitions  ************************** */


DEFINE VARIABLE hex_chr AS CHARACTER NO-UNDO INIT "0123456789abcdef".

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME


&ANALYZE-SUSPEND _UIB-PREPROCESSOR-BLOCK 

/* ********************  Preprocessor Definitions  ******************** */

&Scoped-define PROCEDURE-TYPE Procedure
&Scoped-define DB-AWARE no



/* _UIB-PREPROCESSOR-BLOCK-END */
&ANALYZE-RESUME


/* ************************  Function Prototypes ********************** */

&IF DEFINED(EXCLUDE-binaryAdd) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD binaryAdd Procedure 
FUNCTION binaryAdd RETURNS INTEGER
  ( INPUT px AS INT,
    INPUT py AS INT )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-binaryAnd) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD binaryAnd Procedure 
FUNCTION binaryAnd RETURNS INTEGER
  (
    INPUT intOperand1 AS INTEGER, 
    INPUT intOperand2 AS INTEGER) FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-binaryNot) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD binaryNot Procedure 
FUNCTION binaryNot RETURNS INTEGER
  ( INPUT piValue AS INT )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-binaryOr) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD binaryOr Procedure 
FUNCTION binaryOr RETURNS INTEGER
  ( INPUT intOperand1 AS INTEGER, 
    INPUT intOperand2 AS INTEGER) FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-binaryXOr) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD binaryXOr Procedure 
FUNCTION binaryXOr RETURNS INTEGER
    ( INPUT iParam1 AS INTEGER, 
      INPUT iParam2 AS INTEGER) FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-encryptString) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD encryptString Procedure 
FUNCTION encryptString RETURNS CHARACTER
  ( INPUT str AS CHAR )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-intToUnsignedInt) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD intToUnsignedInt Procedure 
FUNCTION intToUnsignedInt RETURNS DECIMAL
    (INPUT intOperand AS INTEGER) FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_cmn) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD md5_cmn Procedure 
FUNCTION md5_cmn RETURNS INTEGER
  ( INPUT pq AS INT, 
    INPUT pa AS INT,
    INPUT pb AS INT, 
    INPUT px AS INT, 
    INPUT ps AS INT,
    INPUT pt AS INT)  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_ff) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD md5_ff Procedure 
FUNCTION md5_ff RETURNS INTEGER
  ( INPUT pa AS INT,
    INPUT pb AS INT, 
    INPUT pc AS INT, 
    INPUT pd AS INT, 
    INPUT px AS INT, 
    INPUT ps AS INT,
    INPUT pt AS INT )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_gg) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD md5_gg Procedure 
FUNCTION md5_gg RETURNS INTEGER
  ( INPUT pa AS INT, 
    INPUT pb AS INT, 
    INPUT pc AS INT, 
    INPUT pd AS INT, 
    INPUT px AS INT, 
    INPUT ps AS INT, 
    INPUT pt AS INT )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_hh) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD md5_hh Procedure 
FUNCTION md5_hh RETURNS INTEGER
  ( INPUT pa AS INT, 
    INPUT pb AS INT, 
    INPUT pc AS INT, 
    INPUT pd AS INT, 
    INPUT px AS INT, 
    INPUT ps AS INT, 
    INPUT pt AS INT )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_ii) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD md5_ii Procedure 
FUNCTION md5_ii RETURNS INTEGER
  ( INPUT pa AS INT, 
    INPUT pb AS INT, 
    INPUT pc AS INT, 
    INPUT pd AS INT, 
    INPUT px AS INT, 
    INPUT ps AS INT, 
    INPUT pt AS INT )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_rhex) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD md5_rhex Procedure 
FUNCTION md5_rhex RETURNS CHARACTER
  ( INPUT num AS INTEGER )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_rol) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD md5_rol Procedure 
FUNCTION md5_rol RETURNS INTEGER
  ( INPUT num AS INTEGER,
    INPUT cnt AS INTEGER )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_str2blks) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD md5_str2blks Procedure 
FUNCTION md5_str2blks RETURNS CHARACTER
  ( INPUT str AS CHAR )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-shiftLeft) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD shiftLeft Procedure 
FUNCTION shiftLeft RETURNS INTEGER
  ( INPUT piInput    AS INT,
    INPUT piNumShift AS INT )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-shiftRight) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD shiftRight Procedure 
FUNCTION shiftRight RETURNS INTEGER
  ( INPUT piInput    AS INT,
    INPUT piNumShift AS INT )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-shiftRightZero) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD shiftRightZero Procedure 
FUNCTION shiftRightZero RETURNS INTEGER
  ( INPUT piInput    AS INT,
    INPUT piNumShift AS INT )  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-unsignedIntToInt) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD unsignedIntToInt Procedure 
FUNCTION unsignedIntToInt RETURNS INTEGER
    (INPUT decOperand AS DECIMAL)  FORWARD.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF


/* *********************** Procedure Settings ************************ */

&ANALYZE-SUSPEND _PROCEDURE-SETTINGS
/* Settings for THIS-PROCEDURE
   Type: Procedure
   Allow: 
   Frames: 0
   Add Fields to: Neither
   Other Settings: CODE-ONLY COMPILE
 */
&ANALYZE-RESUME _END-PROCEDURE-SETTINGS

/* *************************  Create Window  ************************** */

&ANALYZE-SUSPEND _CREATE-WINDOW
/* DESIGN Window definition (used by the UIB) 
  CREATE WINDOW Procedure ASSIGN
         HEIGHT             = 15
         WIDTH              = 60.
/* END WINDOW DEFINITION */
                                                                        */
&ANALYZE-RESUME

 


&ANALYZE-SUSPEND _UIB-CODE-BLOCK _CUSTOM _MAIN-BLOCK Procedure 


/* ***************************  Main Block  *************************** */

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME


/* ************************  Function Implementations ***************** */

&IF DEFINED(EXCLUDE-binaryAdd) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION binaryAdd Procedure 
FUNCTION binaryAdd RETURNS INTEGER
  ( INPUT px AS INT,
    INPUT py AS INT ) :

DEF VAR lsw AS INT NO-UNDO.
DEF VAR msw AS INT NO-UNDO.

    lsw = binaryAnd(px, 65535) + binaryAnd(py, 65535).
    msw = shiftRight(px, 16) + shiftRight(py, 16) + shiftRight(lsw, 16).
  
    RETURN binaryOr(shiftLeft(msw, 16), binaryAnd(lsw, 65535)).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-binaryAnd) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION binaryAnd Procedure 
FUNCTION binaryAnd RETURNS INTEGER
  (
    INPUT intOperand1 AS INTEGER, 
    INPUT intOperand2 AS INTEGER):

DEFINE VARIABLE decValue    AS DECIMAL NO-UNDO INITIAL 0.
DEFINE VARIABLE decLoop     AS DECIMAL NO-UNDO.
DEFINE VARIABLE decOperand1 AS DECIMAL NO-UNDO.
DEFINE VARIABLE decOperand2 AS DECIMAL NO-UNDO.
    
    ASSIGN decLoop     = EXP(2, 31)
           decOperand1 = IntToUnsignedInt(intOperand1)
           decOperand2 = IntToUnsignedInt(intOperand2).
    DO WHILE decLoop > 0.5:
        ASSIGN decValue = decValue + decLoop
               WHEN decOperand1 >= decLoop AND decOperand2 >= decLoop
               decOperand1 = decOperand1 - decLoop
               WHEN decOperand1 >= decLoop
               decOperand2 = decOperand2 - decLoop
                WHEN decOperand2 >= decLoop
               decLoop = decLoop / 2.
    END.

    RETURN UnsignedIntToInt(decValue).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-binaryNot) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION binaryNot Procedure 
FUNCTION binaryNot RETURNS INTEGER
  ( INPUT piValue AS INT ) :
/*------------------------------------------------------------------------------
  Purpose:  
    Notes:  
------------------------------------------------------------------------------*/

  RETURN ((piValue * -1) - 1).   /* Function return value. */

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-binaryOr) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION binaryOr Procedure 
FUNCTION binaryOr RETURNS INTEGER
  ( INPUT intOperand1 AS INTEGER, 
    INPUT intOperand2 AS INTEGER):

DEFINE VARIABLE decValue    AS DECIMAL NO-UNDO INITIAL 0.
DEFINE VARIABLE decLoop     AS DECIMAL NO-UNDO.
DEFINE VARIABLE decOperand1 AS DECIMAL NO-UNDO.
DEFINE VARIABLE decOperand2 AS DECIMAL NO-UNDO.
    
    ASSIGN decLoop     = EXP(2, 31)
           decOperand1 = intToUnsignedInt(intOperand1)
           decOperand2 = intToUnsignedInt(intOperand2).
    DO WHILE decLoop > 0.5:
        ASSIGN decValue = decValue + decLoop
               WHEN decOperand1 >= decLoop OR decOperand2 >= decLoop
               decOperand1 = decOperand1 - decLoop
               WHEN decOperand1 >= decLoop
               decOperand2 = decOperand2 - decLoop
               WHEN decOperand2 >= decLoop
               decLoop = decLoop / 2.
    END.
    
    RETURN unsignedIntToInt(decValue).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-binaryXOr) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION binaryXOr Procedure 
FUNCTION binaryXOr RETURNS INTEGER
    ( INPUT iParam1 AS INTEGER, 
      INPUT iParam2 AS INTEGER):
/*------------------------------------------------------------------------------
  Purpose:  
    Notes:  
------------------------------------------------------------------------------*/

    RETURN binaryOr(binaryAnd(binaryNot(iParam1), iParam2), binaryAnd(iParam1, binaryNot(iParam2))).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-encryptString) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION encryptString Procedure 
FUNCTION encryptString RETURNS CHARACTER
  ( INPUT str AS CHAR ) :
/*
 * Take a string and return the hex representation of its MD5.
 */

DEF VAR mx   AS CHAR NO-UNDO INIT "".
DEF VAR ia   AS INT  NO-UNDO.
DEF VAR ib   AS INT  NO-UNDO.
DEF VAR ic   AS INT  NO-UNDO.
DEF VAR id   AS INT  NO-UNDO.
DEF VAR iBlk AS INT  NO-UNDO.
DEF VAR olda AS INT  NO-UNDO.
DEF VAR oldb AS INT  NO-UNDO.
DEF VAR oldc AS INT  NO-UNDO.
DEF VAR oldd AS INT  NO-UNDO.

    mx = md5_str2blks(str).
    ia =  1732584193.
    ib = -271733879.
    ic = -1732584194.
    id =  271733878.
    
    REPEAT iBlk = 1 TO NUM-ENTRIES(mx) BY 16:
        olda = ia.
        oldb = ib.
        oldc = ic.
        oldd = id.
        
        ia = md5_ff(ia, ib, ic, id, INT(ENTRY(iBlk +  0, mx)), 7 , -680876936).
        id = md5_ff(id, ia, ib, ic, INT(ENTRY(iBlk +  1, mx)), 12, -389564586).
        ic = md5_ff(ic, id, ia, ib, INT(ENTRY(iBlk +  2, mx)), 17,  606105819).
        ib = md5_ff(ib, ic, id, ia, INT(ENTRY(iBlk +  3, mx)), 22, -1044525330).
        ia = md5_ff(ia, ib, ic, id, INT(ENTRY(iBlk +  4, mx)), 7 , -176418897).
        id = md5_ff(id, ia, ib, ic, INT(ENTRY(iBlk +  5, mx)), 12,  1200080426).
        ic = md5_ff(ic, id, ia, ib, INT(ENTRY(iBlk +  6, mx)), 17, -1473231341).
        ib = md5_ff(ib, ic, id, ia, INT(ENTRY(iBlk +  7, mx)), 22, -45705983).
        ia = md5_ff(ia, ib, ic, id, INT(ENTRY(iBlk +  8, mx)), 7 ,  1770035416).
        id = md5_ff(id, ia, ib, ic, INT(ENTRY(iBlk +  9, mx)), 12, -1958414417).
        ic = md5_ff(ic, id, ia, ib, INT(ENTRY(iBlk + 10, mx)), 17, -42063).
        ib = md5_ff(ib, ic, id, ia, INT(ENTRY(iBlk + 11, mx)), 22, -1990404162).
        ia = md5_ff(ia, ib, ic, id, INT(ENTRY(iBlk + 12, mx)), 7 ,  1804603682).
        id = md5_ff(id, ia, ib, ic, INT(ENTRY(iBlk + 13, mx)), 12, -40341101).
        ic = md5_ff(ic, id, ia, ib, INT(ENTRY(iBlk + 14, mx)), 17, -1502002290).
        ib = md5_ff(ib, ic, id, ia, INT(ENTRY(iBlk + 15, mx)), 22,  1236535329).
        
        ia = md5_gg(ia, ib, ic, id, INT(ENTRY(iBlk +  1, mx)), 5 , -165796510).
        id = md5_gg(id, ia, ib, ic, INT(ENTRY(iBlk +  6, mx)), 9 , -1069501632).
        ic = md5_gg(ic, id, ia, ib, INT(ENTRY(iBlk + 11, mx)), 14,  643717713).
        ib = md5_gg(ib, ic, id, ia, INT(ENTRY(iBlk +  0, mx)), 20, -373897302).
        ia = md5_gg(ia, ib, ic, id, INT(ENTRY(iBlk +  5, mx)), 5 , -701558691).
        id = md5_gg(id, ia, ib, ic, INT(ENTRY(iBlk + 10, mx)), 9 ,  38016083).
        ic = md5_gg(ic, id, ia, ib, INT(ENTRY(iBlk + 15, mx)), 14, -660478335).
        ib = md5_gg(ib, ic, id, ia, INT(ENTRY(iBlk +  4, mx)), 20, -405537848).
        ia = md5_gg(ia, ib, ic, id, INT(ENTRY(iBlk +  9, mx)), 5 ,  568446438).
        id = md5_gg(id, ia, ib, ic, INT(ENTRY(iBlk + 14, mx)), 9 , -1019803690).
        ic = md5_gg(ic, id, ia, ib, INT(ENTRY(iBlk +  3, mx)), 14, -187363961).
        ib = md5_gg(ib, ic, id, ia, INT(ENTRY(iBlk +  8, mx)), 20,  1163531501).
        ia = md5_gg(ia, ib, ic, id, INT(ENTRY(iBlk + 13, mx)), 5 , -1444681467).
        id = md5_gg(id, ia, ib, ic, INT(ENTRY(iBlk +  2, mx)), 9 , -51403784).
        ic = md5_gg(ic, id, ia, ib, INT(ENTRY(iBlk +  7, mx)), 14,  1735328473).
        ib = md5_gg(ib, ic, id, ia, INT(ENTRY(iBlk + 12, mx)), 20, -1926607734).
        
        ia = md5_hh(ia, ib, ic, id, INT(ENTRY(iBlk +  5, mx)), 4 , -378558).
        id = md5_hh(id, ia, ib, ic, INT(ENTRY(iBlk +  8, mx)), 11, -2022574463).
        ic = md5_hh(ic, id, ia, ib, INT(ENTRY(iBlk + 11, mx)), 16,  1839030562).
        ib = md5_hh(ib, ic, id, ia, INT(ENTRY(iBlk + 14, mx)), 23, -35309556).
        ia = md5_hh(ia, ib, ic, id, INT(ENTRY(iBlk +  1, mx)), 4 , -1530992060).
        id = md5_hh(id, ia, ib, ic, INT(ENTRY(iBlk +  4, mx)), 11,  1272893353).
        ic = md5_hh(ic, id, ia, ib, INT(ENTRY(iBlk +  7, mx)), 16, -155497632).
        ib = md5_hh(ib, ic, id, ia, INT(ENTRY(iBlk + 10, mx)), 23, -1094730640).
        ia = md5_hh(ia, ib, ic, id, INT(ENTRY(iBlk + 13, mx)), 4 ,  681279174).
        id = md5_hh(id, ia, ib, ic, INT(ENTRY(iBlk +  0, mx)), 11, -358537222).
        ic = md5_hh(ic, id, ia, ib, INT(ENTRY(iBlk +  3, mx)), 16, -722521979).
        ib = md5_hh(ib, ic, id, ia, INT(ENTRY(iBlk +  6, mx)), 23,  76029189).
        ia = md5_hh(ia, ib, ic, id, INT(ENTRY(iBlk +  9, mx)), 4 , -640364487).
        id = md5_hh(id, ia, ib, ic, INT(ENTRY(iBlk + 12, mx)), 11, -421815835).
        ic = md5_hh(ic, id, ia, ib, INT(ENTRY(iBlk + 15, mx)), 16,  530742520).
        ib = md5_hh(ib, ic, id, ia, INT(ENTRY(iBlk +  2, mx)), 23, -995338651).
                                                         
        ia = md5_ii(ia, ib, ic, id, INT(ENTRY(iBlk +  0, mx)), 6 , -198630844).
        id = md5_ii(id, ia, ib, ic, INT(ENTRY(iBlk +  7, mx)), 10,  1126891415).
        ic = md5_ii(ic, id, ia, ib, INT(ENTRY(iBlk + 14, mx)), 15, -1416354905).
        ib = md5_ii(ib, ic, id, ia, INT(ENTRY(iBlk +  5, mx)), 21, -57434055).
        ia = md5_ii(ia, ib, ic, id, INT(ENTRY(iBlk + 12, mx)), 6 ,  1700485571).
        id = md5_ii(id, ia, ib, ic, INT(ENTRY(iBlk +  3, mx)), 10, -1894986606).
        ic = md5_ii(ic, id, ia, ib, INT(ENTRY(iBlk + 10, mx)), 15, -1051523).
        ib = md5_ii(ib, ic, id, ia, INT(ENTRY(iBlk +  1, mx)), 21, -2054922799).
        ia = md5_ii(ia, ib, ic, id, INT(ENTRY(iBlk +  8, mx)), 6 ,  1873313359).
        id = md5_ii(id, ia, ib, ic, INT(ENTRY(iBlk + 15, mx)), 10, -30611744).
        ic = md5_ii(ic, id, ia, ib, INT(ENTRY(iBlk +  6, mx)), 15, -1560198380).
        ib = md5_ii(ib, ic, id, ia, INT(ENTRY(iBlk + 13, mx)), 21,  1309151649).
        ia = md5_ii(ia, ib, ic, id, INT(ENTRY(iBlk +  4, mx)), 6 , -145523070).
        id = md5_ii(id, ia, ib, ic, INT(ENTRY(iBlk + 11, mx)), 10, -1120210379).
        ic = md5_ii(ic, id, ia, ib, INT(ENTRY(iBlk +  2, mx)), 15,  718787259).
        ib = md5_ii(ib, ic, id, ia, INT(ENTRY(iBlk +  9, mx)), 21, -343485551).
        
        ia = binaryAdd(ia, olda).
        ib = binaryAdd(ib, oldb).
        ic = binaryAdd(ic, oldc).
        id = binaryAdd(id, oldd).
    END.

    RETURN md5_rhex(ia) + md5_rhex(ib) + md5_rhex(ic) + md5_rhex(id). 

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-intToUnsignedInt) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION intToUnsignedInt Procedure 
FUNCTION intToUnsignedInt RETURNS DECIMAL
    (INPUT intOperand AS INTEGER):
    
DEFINE VARIABLE decUnsignedInt AS DECIMAL NO-UNDO.
    
    ASSIGN decUnsignedInt = intOperand.
    IF intOperand < 0 THEN
        ASSIGN decUnsignedInt = EXP(2, 32) + decUnsignedInt.

    RETURN decUnsignedInt.

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_cmn) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION md5_cmn Procedure 
FUNCTION md5_cmn RETURNS INTEGER
  ( INPUT pq AS INT, 
    INPUT pa AS INT,
    INPUT pb AS INT, 
    INPUT px AS INT, 
    INPUT ps AS INT,
    INPUT pt AS INT) :
/*------------------------------------------------------------------------------
  Purpose:  
    Notes:  
------------------------------------------------------------------------------*/
    RETURN binaryAdd(md5_rol(binaryAdd(binaryAdd(pa, pq), binaryAdd(px, pt)), ps), pb).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_ff) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION md5_ff Procedure 
FUNCTION md5_ff RETURNS INTEGER
  ( INPUT pa AS INT,
    INPUT pb AS INT, 
    INPUT pc AS INT, 
    INPUT pd AS INT, 
    INPUT px AS INT, 
    INPUT ps AS INT,
    INPUT pt AS INT ) :
/*------------------------------------------------------------------------------
  Purpose:  
    Notes:  
------------------------------------------------------------------------------*/

  RETURN md5_cmn(binaryOr(binaryAnd(pb, pc), binaryAnd(binaryNot(pb), pd)), pa, pb, px, ps, pt).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_gg) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION md5_gg Procedure 
FUNCTION md5_gg RETURNS INTEGER
  ( INPUT pa AS INT, 
    INPUT pb AS INT, 
    INPUT pc AS INT, 
    INPUT pd AS INT, 
    INPUT px AS INT, 
    INPUT ps AS INT, 
    INPUT pt AS INT ) :
/*------------------------------------------------------------------------------
  Purpose:  
    Notes:  
------------------------------------------------------------------------------*/

    RETURN md5_cmn(binaryOr(binaryAnd(pb, pd), binaryAnd(pc, binaryNot(pd))), pa, pb, px, ps, pt).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_hh) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION md5_hh Procedure 
FUNCTION md5_hh RETURNS INTEGER
  ( INPUT pa AS INT, 
    INPUT pb AS INT, 
    INPUT pc AS INT, 
    INPUT pd AS INT, 
    INPUT px AS INT, 
    INPUT ps AS INT, 
    INPUT pt AS INT ) :
/*------------------------------------------------------------------------------
  Purpose:  
    Notes:  
------------------------------------------------------------------------------*/

    RETURN md5_cmn(binaryXOr(binaryXOr(pb, pc), pd), pa, pb, px, ps, pt).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_ii) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION md5_ii Procedure 
FUNCTION md5_ii RETURNS INTEGER
  ( INPUT pa AS INT, 
    INPUT pb AS INT, 
    INPUT pc AS INT, 
    INPUT pd AS INT, 
    INPUT px AS INT, 
    INPUT ps AS INT, 
    INPUT pt AS INT ) :
/*------------------------------------------------------------------------------
  Purpose:  
    Notes:  
------------------------------------------------------------------------------*/

    RETURN md5_cmn(binaryXOr(pc, binaryOr(pb, binaryNot(pd))), pa, pb, px, ps, pt).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_rhex) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION md5_rhex Procedure 
FUNCTION md5_rhex RETURNS CHARACTER
  ( INPUT num AS INTEGER ) :
/*
 * Convert a 32-bit number to a hex string with ls-byte first
 */

DEF VAR str AS CHAR NO-UNDO INIT "".
DEF VAR j AS INT NO-UNDO.


    REPEAT j = 0 TO 3:
        str = str + SUBSTRING(hex_chr, binaryAnd(shiftRight(num, (j * 8) + 4), 15) + 1, 1)
                  + SUBSTRING(hex_chr, binaryAnd(shiftRight(num, (j * 8)), 15) + 1, 1).
    END.
    
    RETURN str.

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_rol) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION md5_rol Procedure 
FUNCTION md5_rol RETURNS INTEGER
  ( INPUT num AS INTEGER,
    INPUT cnt AS INTEGER ) :
/*
 * Bitwise rotate a 32-bit number to the left
 */

   RETURN binaryOr(shiftLeft(num, cnt), shiftRightZero(num, (32 - cnt))).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-md5_str2blks) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION md5_str2blks Procedure 
FUNCTION md5_str2blks RETURNS CHARACTER
  ( INPUT str AS CHAR ) :
/*
 * Convert a string to a sequence of 16-word blocks, stored as an array.
 * Append padding bits and the length, as described in the MD5 standard.
 */
DEF VAR nblk   AS INT NO-UNDO.
DEF VAR blks   AS CHAR NO-UNDO INIT "".
DEF VAR iBlock AS INT NO-UNDO.

    nblk = shiftRight((LENGTH(str) + 8), 6) + 1.
    blks = "0".
    REPEAT iBlock = 2 TO (nblk * 16):
        blks = blks + "," + "0".
    END.
    REPEAT iBlock = 0 TO LENGTH(str) - 1:
        ENTRY(shiftRight(iBlock, 2) + 1, blks) = 
            STRING(binaryOr(INT(ENTRY(shiftRight(iBlock, 2) + 1, blks)), 
                            shiftLeft(ASC(SUBSTRING(str, iBlock + 1, 1)),
                                      ((iBlock MOD 4) * 8)))).

    END.
    ENTRY(shiftRight(iBlock, 2) + 1, blks) = 
        STRING(binaryOr(INT(ENTRY(shiftRight(iBlock, 2) + 1, blks)), 
                        shiftLeft(128, ((iBlock MOD 4) * 8)))).
    ENTRY(nblk * 16 - 1, blks) = STRING(LENGTH(str) * 8).

    RETURN blks.

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-shiftLeft) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION shiftLeft Procedure 
FUNCTION shiftLeft RETURNS INTEGER
  ( INPUT piInput    AS INT,
    INPUT piNumShift AS INT ) :
/*------------------------------------------------------------------------------
  Purpose:  
    Notes:  
------------------------------------------------------------------------------*/
DEF VAR dInput  AS DECIMAL.
DEF VAR iNum    AS INT.

    dInput  = intToUnsignedInt(piInput).

    REPEAT iNum = 1 TO piNumShift:
        IF (dInput > EXP(2, 31)) THEN
            dInput = dInput - EXP(2, 31).
        dInput = dInput * 2.
    END.

    RETURN unsignedIntToInt(dInput).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-shiftRight) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION shiftRight Procedure 
FUNCTION shiftRight RETURNS INTEGER
  ( INPUT piInput    AS INT,
    INPUT piNumShift AS INT ) :
/*------------------------------------------------------------------------------
Purpose:  
  Notes:  
------------------------------------------------------------------------------*/
DEF VAR dInput  AS DECIMAL.
DEF VAR iNum    AS INT.
DEF VAR bSigned AS LOGICAL.

    dInput  = DECIMAL(ABSOLUTE(piInput)).
    bSigned = (piInput < 0).
        
    REPEAT iNum = 1 TO piNumShift:
        dInput = dInput / 2.
        IF (bSigned) THEN
            dInput = INTEGER(dInput).
        ELSE
            dInput = TRUNCATE(dInput,0).
    END.
    
    IF (bSigned) THEN
        dInput = dInput * -1.

    RETURN INTEGER(dInput).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-shiftRightZero) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION shiftRightZero Procedure 
FUNCTION shiftRightZero RETURNS INTEGER
  ( INPUT piInput    AS INT,
    INPUT piNumShift AS INT ) :
/*------------------------------------------------------------------------------
Purpose:  
  Notes:  
------------------------------------------------------------------------------*/
DEF VAR dInput  AS DECIMAL.
DEF VAR iNum    AS INT.
DEF VAR iSigned AS INT.

    dInput  = intToUnsignedInt(piInput).
    
    REPEAT iNum = 1 TO piNumShift:
        dInput = dInput / 2.
        dInput = TRUNCATE(dInput,0).
    END.
    
    RETURN unsignedIntToInt(dInput).

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

&IF DEFINED(EXCLUDE-unsignedIntToInt) = 0 &THEN

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION unsignedIntToInt Procedure 
FUNCTION unsignedIntToInt RETURNS INTEGER
    (INPUT decOperand AS DECIMAL) :
    
DEFINE VARIABLE intSignedInt AS INTEGER NO-UNDO.
    
    IF decOperand < EXP(2, 31) THEN
        ASSIGN intSignedInt = decOperand.
    ELSE
        ASSIGN intSignedInt = decOperand - EXP(2, 32).
    RETURN intSignedInt.

END FUNCTION.

/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

&ENDIF

