-4

I have a problem that I cant find a clear answer on...

So I have this JavaScript code :

var asp = {
    alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
    lookup: null,
    ie: /MSIE/.test(navigator.userAgent),           // Checks the browser client
    ieo: /MSIE[67]/.test(navigator.userAgent),      // Checks The Browser Client
    encode: function(s) {
        var buffer = asp.toUtf8(s),
            position = -1,
            len = buffer.length,
            nan0, nan1, nan2, enc = [, , , ];
        if (asp.ie) {
            var result = [];
            while (++position < len) {
                nan0 = buffer[position];
                nan1 = buffer[++position];
                enc[0] = nan0 >> 2;
                enc[1] = ((nan0 & 3) << 4) | (nan1 >> 4);
                if (isNaN(nan1)) enc[2] = enc[3] = 64;
                else {
                    nan2 = buffer[++position];
                    enc[2] = ((nan1 & 15) << 2) | (nan2 >> 6);
                    enc[3] = (isNaN(nan2)) ? 64 : nan2 & 63
                }
                result.push(asp.alphabet.charAt(enc[0]), asp.alphabet.charAt(enc[1]), asp.alphabet.charAt(enc[2]), asp.alphabet.charAt(enc[3]))
            }
            return result.join('')
        } else {
            var result = '';
            while (++position < len) {
                nan0 = buffer[position];
                nan1 = buffer[++position];
                enc[0] = nan0 >> 2;
                enc[1] = ((nan0 & 3) << 4) | (nan1 >> 4);
                if (isNaN(nan1)) enc[2] = enc[3] = 64;
                else {
                    nan2 = buffer[++position];
                    enc[2] = ((nan1 & 15) << 2) | (nan2 >> 6);
                    enc[3] = (isNaN(nan2)) ? 64 : nan2 & 63
                }
                result += asp.alphabet[enc[0]] + asp.alphabet[enc[1]] + asp.alphabet[enc[2]] + asp.alphabet[enc[3]]
            }
            return result
        }
    },
    wrap: function(s) {
        if (s.length % 4) throw new Error("InvalidCharacterError: 'asp.wrap' failed: The string to be wrapd is not correctly encoded.");
        var buffer = asp.fromUtf8(s),
            position = 0,
            len = buffer.length;
        if (asp.ieo) {
            var result = [];
            while (position < len) {
                if (buffer[position] < 128) result.push(String.fromCharCode(buffer[position++]));
                else if (buffer[position] > 191 && buffer[position] < 224) result.push(String.fromCharCode(((buffer[position++] & 31) << 6) | (buffer[position++] & 63)));
                else result.push(String.fromCharCode(((buffer[position++] & 15) << 12) | ((buffer[position++] & 63) << 6) | (buffer[position++] & 63)))
            }
            return result.join('')
        } else {
            var result = '';
            while (position < len) {
                if (buffer[position] < 128) result += String.fromCharCode(buffer[position++]);
                else if (buffer[position] > 191 && buffer[position] < 224) result += String.fromCharCode(((buffer[position++] & 31) << 6) | (buffer[position++] & 63));
                else result += String.fromCharCode(((buffer[position++] & 15) << 12) | ((buffer[position++] & 63) << 6) | (buffer[position++] & 63))
            }
            return result
        }
    },
    toUtf8: function(s) {
        var position = -1,
            len = s.length,
            chr, buffer = [];
        if (/^[\x00-\x7f]*$/.test(s))
            while (++position < len) buffer.push(s.charCodeAt(position));
        else
            while (++position < len) {
                chr = s.charCodeAt(position);
                if (chr < 128) buffer.push(chr);
                else if (chr < 2048) buffer.push((chr >> 6) | 192, (chr & 63) | 128);
                else buffer.push((chr >> 12) | 224, ((chr >> 6) & 63) | 128, (chr & 63) | 128)
            }
        return buffer
    },
    fromUtf8: function(s) {
        var position = -1,
            len, buffer = [],
            enc = [, , , ];
        if (!asp.lookup) {
            len = asp.alphabet.length;
            asp.lookup = {};
            while (++position < len) asp.lookup[asp.alphabet.charAt(position)] = position;
            position = -1
        }
        len = s.length;
        while (++position < len) {
            enc[0] = asp.lookup[s.charAt(position)];
            enc[1] = asp.lookup[s.charAt(++position)];
            buffer.push((enc[0] << 2) | (enc[1] >> 4));
            enc[2] = asp.lookup[s.charAt(++position)];
            if (enc[2] == 64) break;
            buffer.push(((enc[1] & 15) << 4) | (enc[2] >> 2));
            enc[3] = asp.lookup[s.charAt(++position)];
            if (enc[3] == 64) break;
            buffer.push(((enc[2] & 3) << 6) | enc[3])
        }
        return buffer
    }
};

This is a local JavaScript file on my PC , And I need to be able to call a function from it from my Delphi Program ( And receive the output of the function as well )... What is the simplest way to achieve this? I found some source code on stack overflow, but the project was incomplete and I couldn't use the included scripts, An alternative would be to create an intermediary between the two ( Like a webpage perhaps? ) but I would preferably keep the solution as simple as possible, So if you guys can help me out with this , I would greatly appreciate it!

For the curious : the above script is a encryption and decryption algorithm EDIT: Its NOT an encryption algorithm, indead a simple base64 encoder, therefore this problem has been solved!

Thanks for taking the time to read this, Cheers for now!

8
  • 1
    I'd port the code to Delphi. That will result in far and away the cleanest code in the long run. Commented Mar 6, 2015 at 8:49
  • 1
    It's not hard to understand what it does. You just need a map between the bitwise operations of the two languages. Commented Mar 6, 2015 at 8:51
  • 2
    Encryption??!! If I have a closer look it's just a plain base64 encoder! (or am I wrong?) Commented Mar 6, 2015 at 9:59
  • 2
    @StijnSanders indeed - it seems lifted from somewhere... for example : stackoverflow.com/a/18519969/327083 Commented Mar 6, 2015 at 10:31
  • 2
    or perhaps this one stackoverflow.com/questions/5795263/binary-to-base64-delphi (plus an extra UTF8Encode ) Commented Mar 6, 2015 at 10:48

2 Answers 2

5

That code expects to be running in a browser environment, so to use it directly, you'll have to run it within a browser, perhaps a headless browser. Although it may be possible to remove the browser-specific parts of it, which seem mostly to be workarounds for Internet Explorer issues.

Rather than trying to use it directly, which will be quite complicated, I'd just translate it to Delphi.

Sign up to request clarification or add additional context in comments.

4 Comments

I considered this, however i am not quite familliar with javascript ( never liked the language as a whole ) but my project now forces me to deal with this script :/ , so porting the code to delphi wont really be feasible considering the time-constraints on the project ( i have to finish it before monday )
@KazutoKirigaya: I bet you can translate it to Delphi faster than you can get Delphi to successfullly call it as-is. And we're talking 3-4 dozen lines of code, Monday doesn't seem a hard deadline to meet.
@KazutoKirigaya Those are really your problems. TJ is just telling you what the best option is. If you can't take that option, then really that's a problem for you to come to terms with.
I realise this, and i do value his input greatly, I will do as he suggested, but would like to keep the discussion open incase there is someone with a better solution..
-3

For Running a JavaScript function you must use a WebBrowser component (Like TWebBrowser). But, by default TWebBrowser component is compatible with oldest versions of Internet Explorer. In the first step you must make compatibility for newest version. For doing that you must use this code(It is for IE10):

procedure TForm1.btnIE10EmulatorClick(Sender: TObject);var
  RegObj: TRegistry;
begin
  RegObj := TRegistry.Create;
  try
    RegObj.RootKey := HKEY_LOCAL_MACHINE;
    RegObj.Access := KEY_ALL_ACCESS;


    if (TOSVersion.Architecture = arIntelX64) then
    begin
      RegObj.OpenKey('\SOFTWARE\Wow6432Node\Microsoft\Internet ' +
        'Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION', True);
    end
    else if (TOSVersion.Architecture = arIntelX86) then
    begin
      RegObj.OpenKey('\SOFTWARE\Microsoft\Internet ' +
        'Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION', True);
    end;


    RegObj.WriteInteger(ExtractFileName(Application.ExeName), 10000 {compatibility with IE10}); // for other versions read msdn
  finally
    RegObj.Free;
  end;
end;

In second Step, Put a TWebBrowser component on your form.

In next step, add this function in your app:

procedure ExecuteJavaScript(document:IHTMLDocument2; Code: string);
var
  Window:IHTMLWindow2;
begin
  if not Assigned(Document) then Exit;
  Window:=Document.parentWindow;
  if not Assigned(Window) then Exit;
  try
    Window.execScript(Code,'JavaScript');
  except
    on E:Exception do raise Exception.Create('Javascript error '+E.Message+' in: '#13#10+Code);
  end;
end;

By this function you can run javascript function.

Example1 (running function without return value):

ExecuteJavaScript((WebBrowser1.Document as IHTMLDocument2), 'JsFunctionName();');

Example2 (javascript code returns value): If your JS code returns value, add this function to your delphi program:

function GetElementIdValue(WebBrowser:TWebBrowser; TagName,TagId,TagAttrib:String):String;
var
  Document: IHTMLDocument2;
  Body: IHTMLElement2;
  Tags: IHTMLElementCollection;
  Tag: IHTMLElement;
  I: Integer;
begin
  Result:='';
  if not Supports(WebBrowser.Document, IHTMLDocument2, Document) then
    raise Exception.Create('Invalid HTML document');
  if not Supports(Document.body, IHTMLElement2, Body) then
    raise Exception.Create('Can''t find <body> element');
  Tags := Body.getElementsByTagName(UpperCase(TagName));
  for I := 0 to Pred(Tags.length) do begin
    Tag:=Tags.item(I,EmptyParam) as IHTMLElement;
    if Tag.id=TagId then Result:=Tag.getAttribute(TagAttrib,0);
  end;
end;

and use this code for returning value:

procedure TForm1.Button3Click(Sender: TObject);
begin
  // eval demo cpde
  try
    ExecuteJavaScript(WebBrowser1,'DoEval("'+Edit1.Text+'");');
    ResultLabel.Caption := GetElementIdValue(WebBrowser1,'input','result','value'));
  except
    on E:Exception do ConsoleRed(E.Message);
  end;
end;

JavaScript code in this example is:

function DoEval(expr){
 // eval for delphi!
 document.getElementById('result').value=eval(expr);
}

For using this example your uses clouse must be like this:

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, OleCtrls, ExtCtrls, {REQUIRED UNITS} SHDocVw, MSHTML,
  ComCtrls {/REQUIRED UNITS};

10 Comments

Hmm, that btnIE10EmulatorClick function has many problems. For a start, the hard coding of Wow6432Node breaks the rules. You are meant to use the access flags to select alternate registry views. Furthermore, UAC is going to block such access unless you run the process elevated. Do you work on a machine with UAC disabled by any chance?
As for ExecuteJavaScript, what's missing here is how to feed input data in, and extract the result.
I am on the admin account of the pc, and i also have UAC turned off ( i hate the damn thing ) so yeah this would work, just need a way to feed in the input and extract the output
I hope you don't write code that is expected to run on any other machines. If you develop with UAC off then you can expect epic pain when the code leaves your machine. Setting those registry entries should be done outside your program. As a deployment step. And you really must stop hard coding Wow6432Node. The docs are clear. There's a proper way to do it. Why not avail yourself of it?
With it now established that the javascript function is simply a Base64 encode/decode, this is an absolutely ridiculous way to do it in Delphi. There are in-built functions to do this - one just has to use them.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.