Jump to content

wprins

uniGUI Subscriber
  • Posts

    151
  • Joined

  • Last visited

Everything posted by wprins

  1. Gerhard, sparkz thanks. I've not been on the forums much for the last 2 or so months. I eventually actually came up with a solution by myself about 2 months ago. It's not entirely unlike what you've (Gerhard) done, yours is a bit more succinct. I was planning on posting my solution at some point but have been either away or too busy. I'll still post it sometime as I avoid using AddJS which seems somehow slightly smelly to me and so may be of interest to others...(?) Edit: Gerhard, thanks again for your example. I did just have a quick look at what I did previously and I think your solution is perhaps preferable, nice and neat and to the point. Will try it out in due course. Nevertheless, for interest and in case anyone finds it useful or educational: Basically I used UniSession.CallbackURL() and UniSession.CallbackTarget() to generate a callback URL and target from within Delphi code. These are placed inside static HTML+JS page code placed a designtime (e.g. TUniHTMLFrame or TUniURLFrame content). At the bottom of the page I wrote some Javascript to retrieve the IP, after which I trigger a normal JS Form submit which fires the retrieved IP address off into the UniGui Session via UniFormAjaxEvent(). UniHTMLFrame1.HTML content: <div style="background-color:#ccc"> <br/><br/><br/><br/><br/> <form name="input" action="{URL_CALLBACK}" method="POST" target="{CALLBACK_TARGET}"> Username: <input type="text" name="user" value="Enter Text..."><br/> IP:<input type="text" name="ip" id="ip" value=""><br/> <input type="submit" value="Submit"> </form> <br/><br/><br/><br/><br/> </div> <script> var request = new XMLHttpRequest(); request.open('GET', 'https://jsonip.com', false); //synchronous request.send(null); if(request.status === 200) { data = JSON.parse(request.response); //console.log(data); //JQuery way: $("#ip").val(data.ip); document.forms["input"]["ip"].value = data.ip; //JQuery way: $("form#input").submit(); document.forms["input"].submit(); } </script> On Form create: procedure TMainForm.ReplaceTags; var S, Sc : string; begin S := UniSyntaxEdit1.Text; Sc := UniSession.CallbackUrl('mycallback', Self, []); S := StringReplace(S, '{URL_CALLBACK}', Sc, []); Sc := UniSession.CallbackTarget; S := StringReplace(S, '{CALLBACK_TARGET}', Sc, []); UniHTMLFrame1.HTML.Text := S; end; procedure TMainForm.UniFormCreate(Sender: TObject); begin UniSyntaxEdit1.Text:=UniHTMLFrame1.HTML.Text; ReplaceTags; end; Form Ajax event handler: procedure TMainForm.UniFormAjaxEvent(Sender: TComponent; EventName: string; Params: TUniStrings); begin if EventName = 'mycallback' then begin UniEdit1.Text := Params.Values['user']; UniEdit2.Text := Params.Values['ip']; UniMemo1.Text := Params.Text; end; end; (Again, this was based on and is a modified version of "HTTP Post Callback - HTMLFrame" demo project. I also similarly modified "HTTP Post Callback - URLFrame - Auto Target" which uses TUniURLFrame component instead of TUniHTMLFrame and does not require the "CALLBACK_TARGET" substitution.) Best regards.
  2. Hello, I've been away on holiday. Unfortunately I see no one's got any suggestions for my problem? So hence I post this additional response to bump it up a bit. As a reminder, my problem/question in short: What is the best way to call/run some Javascript in the browser and have something from it posted back to the corresponding UniGUI user session, and then from the UniGUI session update or set a cookie in the browser as a result? Walter
  3. Hello! Thanks for your response, but this does not help unfortunately. The properties you gave gives the "local network" IP address of the client machine on which the browser is running, which isn't usually the same as the apparent public IP address of that same machine. For example, if I run the uniGui server on my own machine and visit the server page with a browser, the above properties predictably return 127.0.0.1. If I visit my machine from another machine on the LAN, these properties give the the other machine's LAN IP address. So far so good. But of course, if my machine or the other machine, were to visit some other website out on the internet, then both my machine, and the other machine will appear to be originating from a third different IP address, e.g the public IP address of the router and/or proxy server through which the traffic is being routed from the machines out to the site being visited. Now if you think back to what I'm doing: The client browser is simultaneously showing a (local network) uniGUI server, *and* framing another site (out on the internet in this case). Therefore, to the UniGUI server the browser machine appears to have a local LAN IP, but to the site on the internet the browser looks like it has the public IP address where the traffic is coming from. Now for the framing to work, the uniGUI server has to know what the browser's apparent IP address is, and generate an access token using this information (amongst other things.) E.g. it doesn't use the the local LAN IP that is directly visible to the UniGUI server and is obviously not known by the remote site, but it has to use the IP address seen by the third party site. As I mentioned before, this can in fact be easily retrieved from the context of the client browser with a bit of Javascript, but I'm not sure how to get this back to the uniGUI server. That is, my key question is what the best way is to essentially get the browser to do a request to the internet (to establish its "public" IP) and then pass this to the user's UniGUI session, so it can generate the token to place in a TUniURLFrame. Thanks in advance! Walter
  4. Hi, Problem: I'm trying to determine the client's apparent IP address (their public IP) so it is known inside the user's uniGUI session. Background: This is needed to enable us to generate an access token for integrating with an external party/site, where the originating browsers IP address is also used in the token signature/hash calculation/verification process. Obviously determining the user's IP is something that needs to happen inside the browser itself, in order to get the apparent public IP address of the browser running the application. Now it turns out that from a web browser/JS perspective this is quite easy. In fact there are multiple services that has API's that enable one to retrieve your apparent public IP. (See here, for example.) So the obvious idea is to somehow have the browser perform this IP capture itself just prior to, or as part of Login and then pass it and store it as part of the user's session (MainModule). Now I've had a look at the "HTTP POST callback" examples which would've provided, it would seem,a way to achieve this, if our login page was in fact a TUniURLFrame. I could then write some Javascript code to GET from the above URL (on document ready/loaded etc, say) and then update the browser document accordingly to finagle things so that on submit/POST the IP would effectively get passed together with the other form variables. However, we currently use a typical uniGUI login form with edit boxes and so on for login, not a uniURLFrame. So I'm a little at a loss as to where/how to sneak the required JS into the page to fetch the IP and ensure that it gets passed to the uniGUI server session either immediately or on login. Question: Given the above, what's the best way for me to effectively get the browser to get the user's IP address using e.g. https://api.ipify.org/?format=json, and pass this back with the other login details on login to the uniGUI server session? Alternatively do you have any better ideas or have I missed some obvious solution to this problem? (Maybe perhaps using UniSession.AddJS() which has just occurred to me while writing this...?) Thanks so much in advance for any pointers/suggestions, Walter
  5. Thanks for the feedback, it helps to at least know what the cause of the issue is. I'll avoid messing with the virtualisation settings and bear in mind that doing so may affect the uniGUI installation. (Actually the fact that it was off was as a result of a BIOS upgrade some time ago, which as is usual, reset the BIOS settings to defaults. It wasn't until today that I actually needed to use Hyper-V again and then noticed that virtualisation support was in fact off in the BIOS and turned it back on. Perhaps it's worth mentioning this somewhere in the documentation somewhere.) Thanks again and have a great day, Walter
  6. Just to confirm, I uninstalled, reinstalled, and it's working now. Not the end of the world.
  7. Hello, Today I rebooted my PC due to installing newer IBM iSeries drivers on my PC and having to do the usual reboot song-and-dance, and to enable virtualization as I sometimes use Hyper-V (nothing directly related to uniGUI.) However, I now get the following trying to start Delphi: Apparently one of these actions (installing drivers, enabling hyper-v, rebooting) has caused the above. (I've had this once before, and didn't at that time know what triggered it either. It necessitated uninstalling and reinstalling uniGUI to fix as I recall. I'm assuming it's going to be the same this time.) I just wanted to note that somewhere your validation is being overzealous, and politely voice my displeasure at having to deal with this and suggest you look into why this happened to try and prevent it from occurring in future. (This type of thing, though rare, is rather irritating when it happens and wastes time and distracts from actual work.) Best wishes, Walter
  8. Right, I've come up with a solution myself. Posting this for the benefit of others who may want to do something similar in future. (Basically I've taken a slightly different (and likely more straightforward) tack in dealing with the HTML in the frame and avoided depending on document.ready() as trying to submit from within the document.ready() seemed to be causing the problem even though this works directly in a browser): Anyway, the HTML.Text is now as follows: <!doctype html> <html> <head> <meta charset="utf-8" /> <title>Gateway page</title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script> </head> <body> <div id="inputs" style="display: none"> <div id="lblreference">Reference to view:</div> <input type="text" name="reference" id="reference" value="" /> <form id="portal" method="post" name="portal"> <div id="lblgateway">Access token:</div><input type="text" name="gateway" id="gateway" value=""></input> <input type="submit" name="sub" id="sub" value="submit" /> </form> </div> </body> <script type="text/javascript"> var reference = "$reference$"; var token = "$token$"; //Set the above initial values into the form/fields with JQuery: $("#gateway").val(token); $("#reference").val(reference); //Setup a submit handler to check the values and abort if needed, //or modify the URL as required and then continue submission as normal: $("form#portal").submit( function (e) { if ($("#reference").val() == "") { alert("You must supply the reference to view."); $("#inputs").show(); return false; } if ($("#gateway").val() == "") { alert("You must supply the token to authorize viewing."); $("#inputs").show(); return false; } $("#portal").attr("action", "$portalurl$?$refparamname$="+$("#reference").val()); } ); //Try automatic submission at end of document load, here, now: $("form#portal").submit(); </script> </html> Then inside the Delphi code (just after TUniFrame construction, and during its subsequent setup) there is Delphi code like the following to substitute the parameter markers (delimited by $'s above) with their required values: UniURLFrame1.HTML.Text := StringReplace(UniURLFrame1.HTML.Text, '$reference$', IntToStr(LReference), [rfReplaceAll]); UniURLFrame1.HTML.Text := StringReplace(UniURLFrame1.HTML.Text, '$token$', LToken, [rfReplaceAll]); UniURLFrame1.HTML.Text := StringReplace(UniURLFrame1.HTML.Text, '$portalurl$', LPortalURL, [rfReplaceAll]); UniURLFrame1.HTML.Text := StringReplace(UniURLFrame1.HTML.Text, '$refparamname$', LRefURLParamName, [rfReplaceAll]); This has the desired result and immediately then posts the required values to the portal site and displays the results in the frame. I don't particularly like this string substitution based approach but it does work to accomplish the desired result. Comments/Improvements obviously welcome. Thanks Walter
  9. Hi, I'm trying to set up a TUniURLFrame (or TUniHTMLFrame perhaps) to allow me to basically do a POST to a specific URL, with specified form parameters, the key being that both the URL and the form (Post body) parameters are to be specified by the UniGUI application state and not necessarily entered by the user. That is to say, we thereby deliver a seamless integration with an external site within a UniGUI URLFrame (and within a browser IFrame.) There are obviously several ways to approach this, from the very dynamic (creating a form element at runtime to post with) or using JQuery Ajax call (say), to the more static option of creating a form in the HTML body and then doing the required URL and form parameter modifications in (say) the JS submit() event or the JS document.ready() event. Now from a simple web page I've managed to do this already, with HTML page as follows: <!doctype html> <html> <head> <meta charset="utf-8" /> <title>Gateway page</title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script> <script type="text/javascript"> $(document).ready( function () { var reference = ""; //329039512 var token = ""; //"0025215009068098f6b58417eaa9c325aa235cda7eda09e8e89490f" $("#gateway").val(token); $("#reference").val(reference); if (token != "") { $("#gateway").hide(); $("#lblgateway").hide(); } else { $("#gateway").show(); $("#lblgateway").show(); }; if (reference != "" && token != "") { $("#sub").hide(); $("form#portal").submit(); } else { $("#sub").show(); } $("form#portal").submit( function (e) { if ($("#reference").val() == "") { alert("You must supply the reference to view."); return false; } if ($("#gateway").val() == "") { alert("You must supply the token to authorize viewing."); return false; } $("#portal").attr("action", "https://some.site.com/gateway?reference="+$("#reference").val()); } ); } ); </script> </head> <body> <div id="lblreference">Reference to view:</div> <input type="text" name="reference" id="reference" value="" /> <div> <form id="portal" method="post" name="portal"> <div id="lblgateway">Access token:</div><input type="text" name="gateway" id="gateway" value=""></input> <input type="submit" name="sub" id="sub" value="submit" /> </form> </div> </body> </html> When you view this page in a browser it will determine what values are set and then automatically submit the page (e.g. via POST), updating the reference URL parameter as relevant (the "action") and setting the token value in the form parameters, thus performing a POST to the specified URL with the required URL and form param. (If the specified/hard coded values are left blank then it will wait for you to enter them manually and wait for you to click submit before performing the same.) This is great, however I'm trying to achieve the same in a seamless manner from a UniURLFrame and having trouble doing so. The goal is for the UniGUI application to supply the reference and access token (which it will obtain/calculate) and have the UniGUI frame then comply with the remote portal's API which (as above) demands that the reference parameter is passed via URL query string and the access token be passed via form parameter using a POST operation. Things I've tried: I've tried wholesale replacing the HTML of the UniURLFrame with the values embedded, using UniURLFrame.HTML.Clear() followed by UniURLFrame.HTML.Add() calls to essentially put the above HTML with the required valued in the HMTL. This fails and somehow ends up showing our UniGUI application login form in the UniURLFrame?!? Ive also tried setting the HTML as one big string (e.g. assigning to HTML.Text). This at least displays the form in the frame, but the document.ready() code does not fire and so the form parameter (token) and reference is empty. Moreover like before clicking submit results in the UniGUI login form appearing?! I've further tried various permutations of UniURLFrame.JSInterface.JSAdd() and UniURLFrame.JSInterface.JSCall, but couldn't figure out how and when these are supposed to be used. I've also tried these in UniURLFrame "OnFrameLoaded()" event handler but this never triggered(???) so I gave up on that. Ideally I'd like to set up the "static" content in the TUniURLFrame's HTML and then simply issue a call to a predefined JS method to achieve the setting and POSTing of the reference and the token (for example, see here or here). UniURLFrame.JSInterface.JSCall would seem like this should be the way to do this but as I say I've not been able to make this work. Nor have I been able to figure out how to do the "usual" UniSessoin.AddJS() way with the UniURLFrame as target instead. It's rather unobvious how these components are to be used and more generally how to interface between UniGUI server side and the JS in the browser. Some examples and documentation would be highly helpful. (I did check the demos as well but did not spot anything close to what I'm trying to do, apologies if I've missed something relevant!) Edit: To add, simply pasting the HTML code above into the HTML text (at design time) of the UniURLFrame, and then manually typing the reference and token parameters into the page and clicking submit works entirely as expected (apart from the fact that it's then a manual process which is precisely what I'm trying to avoid.) So my question is basically, how do I hook into this page and change the reference and token value from within the UniGUI application, such that the page code runs and seamlessly fetches the requested page without requiring the user to enter anything? Edit2: I've now tried modifying the HTML to insert the reference and token via string substitution and replacing the HTML.Text. This results in the URLFrame showing the application's login form in the frame again. I get the impression this is because I'm trying to submit the form from within the document.ready() code? I'll try to avoid doing this, but if not in the document ready, how do I trigger the submit from the UniURLFrame? Help?! Walter
  10. Relatedly, and perhaps an obvious question, but how do you trigger the opening of a URL on (say) button click into a new browser tab? Presumably doing this won't suffer from the above X-Frame-Options limitation, so in the meantime I'm considering doing this instead in our application. Would this be basically something like the following in the button click handler, or is there a better way? UniSession.AddJS('window.open(''https://www.google.co.uk'', ''_blank'');'); Edit: The above works as expected but is there a better way? Also for the benefit of others, one solution to this question is to install the "Ignore X-Frame headers" extension for Chrome that drops and thus effectively makes Chrome ignore the X-Frame-Options headers.
  11. Hi, I'm trying the URLFrame demo (and in our own application) where trying to fetch (for example) www.google.co.uk results in failure and the following error in the browser console: From what I've read ideally this restriction should be removed at the server end. But what if this is not an option? Is there any way to avoid this problem from the UniGUI side? Thanks in advance, Walter
  12. OK thanks. To add: I'm not actively working with uniGUI right at the moment (working on something else) so haven't looked into this further. That is, there's no immediate problem/rush. I'll reboot at some point and see what happens etc. Thanks for the responses. W
  13. Hi, This morning starting Delphi (Berlin 10.1) I am getting the abovementioned message starting up. What is it telling me? How do I fix it? </perplexed> http://i.imgur.com/kyVysIN.png W
  14. Argh! Ignore me, I'm an idiot. I've just reviewed my code again. I've added a check into TCRMServerModule.ControlPanelLogin(). My apologies!!!! (It's been a hard few weeks... )
  15. Sorry, I've not been clear. (Not related to Apache or third party web server.) If you run (for example) a standalone server, and you right-click the icon in the system tray, then click "Restore", then click "Manage", then click "Server monitor", I get a reddish screen with a login prompt for "Id" and "Password". At least, I get this on the server I'm working on. It may be I've cleared/set/reset/broken a setting something somewhere to cause this but I couldn't find anything obvious: http://i.imgur.com/YS0Grl0.png You can get to this same page by directly visiting http://<UniguiService>/server (which is what I was trying imply in my title.) (I've obviously modified the default port, as you can see)
  16. Hi, I recently noticed the /server page now asks for credentials (good) which I don't believe it did some time ago. However, I couldn't quickly find how to control this or what to use to authenticate myself (Id/Password)? Thanks, Walter
  17. Hi, My colleague is trying to update his build but has forgotten his password and lost his email, and there's no "I forgot my password" option on the portal login dialog. There also appears to be no way to get out of this dilemma in the customer portal from the my administrator view. (I thought about removing him and re-adding him afresh but it seems there's also no way of removing a team member entirely from from the customer portal once created.) Help would be appreciated.... Walter
  18. Thanks, apologies for not finding this myself.
  19. Sorry if this is a stupid question, but how would you actually send the file? In other words, what URL would you use to trigger the download/sending, and in what context? (I'm already sending files to the client but indirectly via the server module via assigning to the IdResponse.ContentStream. This works but is slightly awkward as it runs from the "server context" and so the process involves generating a custom URL that is then used in (for example) a link, and which is then recognized by the server module when passed back again. It would seem I'm missing or misunderstanding something obvious.
  20. Thanks for the suggestion. (Obviously not everyone will be happy with their spreadsheets being uploaded to Google, but it's an option certainly.)
  21. What is the use of UniSession.SendStream()? In what context might one use it? Likewise UniSession.SendFile()?
  22. I've come up with a somewhat less than ideal solution but in case anyone's interested: In part of the application where the file to download is identified (a click on a TUniTreeview node), I generate a GUID. Against the GUID I register the local (network) file path for the file to be served in a dictionary held on the server module. Then I setup the URL on the TUniURLFrame (or TUniLabel with the .TextConversion property set as txtHTML) as something like URL := '/guid?g='+GUIDToString(FileGUID); When the UniURLFrame is shown, or the user clicks (say) the HTML link in the label representing the file, the browser then fetches from the server with the above manufactured GUID based URL. Inside the ServerModule.HTTPCommand event handler I in turn check for document requests starting with '/guid'. If found the request is manually handled, something like this: if ARequestInfo.Document.StartsWith('/guid') then begin LGUIDStr := ARequestInfo.Params.Values['g']; if FGUIDCache.ContainsKey(LGUIDStr) then LFilename := FGUIDCache[LGUIDStr] else raise EProgrammerNotFound.Create('Failed to find '+LGUIDStr); if FileExists(LFileName) then LFileStream := TFileStream.Create(LFileName, fmOpenRead OR fmShareDenyNone) else raise EProgrammerNotFound.Create('Failed to find '+LFileName); AResponseInfo.CustomHeaders.Values['Content-Disposition'] := 'attachment; filename='+ExtractFileName(LFileName); AResponseInfo.ContentStream := LFileStream; //Freed by Indy? Handled := True; //LFileStream.Free; //Freed by Indy, I think. end; This has the result of prodding the browser into downloading the file. One concern I have with this is that it basically operates outside the user's session, so one needs to do something about authentication/authorisation since in principle anyone that can access the service can request the file without any blocks whatsoever, as it stands. This is why I was really wanting to do this from the user session {mainmodule} as then you know that the request is legit. It is of course unlikely that someone will guess the GUID, but still. The request ought to be rejected outright if not originating from the app itself. If UniGUI had support to identify requests originating from its own URLFrame components (via say, AccessHeader token) and/or to feed through those requests so that they could be processed/handled in the MainModule OnHandleRequest() that would be rather better than being forced to handle them indirectly in the main server thread/module... (If this is in fact possible and I've mised it please forgive my ignorance and point me in the right direction!)
  23. OK so this is not exactly a UniGUI question, but it might (I think) be interesting to other UniGUI users. Has anyone had the requirement to view Excel files in UniGUI application? If so what did you do? (I note that the Gnostice Stardocs option doesn't unfortunately support Excel spreadsheets so wouldn't help here.) The obvious idea is that Excel can render an Excel workbook to a quite passable HTML version of the workbook, so one might try using Office to convert the excel workbook and serve up (somehow) the result of the conversion. But I'm not really sure how happy I'd be with adding a dependency on Excel automation into a (multiuser UniGUI) service...
  24. wprins

    Newbie

    Our experience was much the same, except we bought it a few months earlier based on beta tests. I was a little taken aback when I found that the source did not in fact include *all* source code, but when I checked out the licensing I noticed this was the terms - my mistake Other than UniGUI, we have for similar reasons as you list above, never allowed any closed source components into our codebase. So I would be hugely appreciative and in favour of a way of obtaining full source code, to guarantee not getting get stuck in the future with infrastructure that you've got no way of upgrading or fixing.
×
×
  • Create New...