Change User-Agent for AJAX calls from Delphi TWebBrowser - delphi

I have a Delphi application that loads the Google Maps JavaScript API in an embedded web browser. The page it loads looks like this:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<style>
#map {
height: 400px;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {});
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?v=3.29&key=~APIKEY~&callback=initMap">
</script>
</body>
</html>
I'm displaying the page like this in a TWebBrowser:
str := StringReplace(htmlBase, '~APIKEY~', cMapsAPIKey, []);
if not Assigned(WebBrowser.Document) then
WebBrowser.Navigate('about:blank', '1', '', '', 'User-Agent: Mozilla/5.0');
doc := WebBrowser.Document;
doc.Clear;
doc.Write(str);
doc.Close;
TWebBrowser.Navigate() will use the user agent string I've provided for the main page, but it uses this to load the scripts:
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3)
Starting with 3.29, the Google Maps JavaScript API seems to be checking the browser's user agent and displaying an error message: "You are using a browser that is not supported". This isn't an issue with 3.28 or below. The browser is supported (it's using IE 11), it's just sending the wrong user agent string.
On the JavaScript end, how can I override the user agent check without disabling warnings completely? And on the Delphi end, is there a way to change the user agent for AJAX calls?
Edit: Overriding TWebBrowser.Invoke() lets me change the user agent for all HTTP requests, but it looks like navigator.userAgent isn't being changed.

You appear to be using the VCL's TWebBrowser. Per Changing the UA (User Agent) of a TWebBrowser component, you can derive a new class from TWebBrowser to override its Invoke() method to return the desired UserAgent string when the DISPID_AMBIENT_USERAGENT property is requested. Then query the browser for its IOleControl interface and call its OnAmbientPropertyChange() method to signal to the browser that the DISPID_AMBIENT_USERAGENT property value has changed. The article has full code.
For good measure, in FMX's TWebBrowser, per Change User Agent for FireMonkey TWebBrowser, on Android you can use a helper class and RTTI trickery to access the browser's internal Java WebView object and call its WebSettings.setUserAgentString() method. Not sure about Windows, but on iOS you don't customize the user agent via the web browser itself (unless you hack the FMX framework to customize the requests it sends), you have to create a dictionary containing an item named UserAgent and register it with the global standardUserDefaults dictionary using its registerDefaults() method. How you do that in Delphi, I have no clue.

The problem why your Google Maps web page isn't loading fine in your TWebBrowser component is because it is working in Compatibility Mode. That is also the reason for mentioned User Agent string.
So why is this happening. Well TWebBrowser is just a wrapper for Internet Explorer browser API. And based on Microsoft decision any application that is using such API would be by default showing web pages in Compatibility mode.
You can disable this by using instructions here:
https://stackoverflow.com/a/25843958/3636228

Related

Using an MVC API with Windows Authentication from VBA

I have developed a MVC Application, which, for the purpose of this question only has one controller:
Public Function GetValue()
Return User.Identity.Name
End Function
The application is to be used on an Intranet network, therefore, I have set it to 'Windows Authentication'
The aim is to query this application, through VBA.
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
With objHTTP
.Open "GET", URL, False
.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.setRequestHeader "Content-type", "application/json"
.setRequestHeader "data-type", "json"
.send
.WaitForResponse
sResult = .ResponseText
End With
Debug.Print (sResult)
If I run the application locally (ie. debug on the computer that is running Excel), it works through Chrome (accessing localhost:xxxxx/api/name returns an xml file with my ActiveDirectory username).
The VBA routine works fine as well, and the Output window displays the XML I get in Chrome.
Now, if I publish the project to the IIS server, it still works through Chrome (accessing myserver/api/name returns an xml file with my ActiveDirectory username).
However, when I run the VBA module, it returns an Error 401:
Error:401 - Unauthorized: Access is denied due to invalid credentials.
The fact that it works in browsers leads me to believe that server-side configuration is OK, and that I need to tweak something in my VBA.
I have to admit that I am a bit clueless at this point...
Thank you for any leads you may give me :)
Thanks to #SWa comment, I solved this with a minor tweak to the function: Switching to WinHttpRequest and using setAutoLogonPolicy 0
Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
With objHTTP
.Open "GET", URL, False
.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.setRequestHeader "Content-type", "application/json"
.setRequestHeader "data-type", "json"
.setAutoLogonPolicy 0
.send
.WaitForResponse
sResult = .ResponseText
End With
Debug.Print (sResult)

Weird characters in URL

In my webserver when user requests URLs with weird characters, I remove these characters. And system logs these cases. When I check sanitized cases I found these. I'm curious that what would be the objective of these URLs ?
I check the IPs and these are real people and uses website as a normal person. But 1 time in their 20 URL requets of these people, URL has these weird characters at last.
http://example.com/#%EF%BF%BD%EF%BF%BD%02?o=3&g=&s=&z=%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%3E?, agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0,
http://example.com/%60E%EF%BF%BD%02?o=3&g=&s=&z=%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%3E?, agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
http://example.com/%60E%EF%BF%BD%02?o=3&g=&s=&z=%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%3E?, agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
http://example.com/p%EF%BF%BD%1D%01?o=3&g=&s=&z=%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%3E?, agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
http://example.com/%EF%BF%BDC%EF%BF%BD%02?o=3&g=&s=&z=%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%3E?, agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
http://example.com/%EF%BF%BDR%EF%BF%BD%02?o=3&g=&s=&z=%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD`%EF%BF%BD%EF%BF%BD%7F, agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36
http://example.com/%EF%BF%BDe%EF%BF%BDv8%01%EF%BF%BD?o=3&g=P%01%EF%BF%BD&s=&z=%EF%BF%BD%EF%BF%BD%15%01%EF%BF%BD%EF%BF%BD, agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36
http://en.wikipedia.org/wiki/Specials_(Unicode_block)
They are essentially malformed URLs. They can be generated from a specific malware that is trying to exploit web site vulnerabilities, from malfunctioning browser plugin or extension, or from a bug in a JS file (i.e. tracking with Google Analytics) in combination with a specific browser version/operating system. In any case, you can't actually control what requests will come from a client and there's nothing you can do to stop that so, if your generated HTML/JS code is correct, you have done your work.
If you like to correct those URLs for any reason, you can enable URL rewriting and set a rule with a regular expression filter to transform those URLs to valid URLs. Anyway, I don't suggest do that: the web server should respond with a error 404 page not found message, because that is the standard (it's a client error, after all), and this is in my opinion a faster and safer method than applying URL rewriting. (rewriting procedure may contains bugs, so someone can try to exploit that, etc, etc)
For sake of curiosity, you can easily decode those URLs with an online URL decoder of your choice (i.e. this), but essentially you will discover what you already know: there are a lot of UTF-8 replacement characters in those URLs.
In fact, %EF%BF%BD is the url-encoded version of the hex representation of the 3 bytes (EF BF BD) of the UTF-8 replacement character. You can see that character also as � or EF BF BD or FFFD or ï ¿ ½, and so on, depending of the representation method you choose.
Also, you can check by your own how the client handles that character. Go here:
http://www.cogsci.ed.ac.uk/~richard/utf-8.cgi?input=%EF%BF%BD&mode=char
press the GO button and, using your browser developer tools, check what really happens: the browser is actually encoding the unknown character with %EF%BF%BD before sending it to the web server.
These look like corrupted URLs being inserted by a piece of Malware/Adware called "Adpeak".
Here are some details on Adpeak:
How to remove AdPeak lqw.me script from my web pages?
Adpeak has a client side component that sticks the following tag into web pages:
<script type="text/javascript" id="2f2a695a6afce2c2d833c706cd677a8e" src="http://d.lqw.me/xuiow/?g=7FC3E74A-AFDA-0667-FB93-1C86261E6E1C&s=4150&z=1385998326"></script>
Adpeak also sometimes uses the host names "d.sitespeeds.com", "d.jazzedcdn.com", "d.deliversuper.com", "d.blazeapi.com", "d.quikcdn.com", probably others. Here are a few more examples:
<script type="text/javascript" id="2f2a695a6afce2c2d833c706cd677a8e" src="http://d.deliversuper.com/xuiow/?o=3&g=823F0056-D574-7451-58CF-01151D4A9833&s=7B0A8368-1A6F-48A5-B236-8BD61816B3F9&z=1399243226"></script>
<script type="text/javascript" id="2f2a695a6afce2c2d833c706cd677a8e" src="http://d.jazzedcdn.com/xuiow/?o=3&g=B43EA207-C6AC-E01B-7865-62634815F491&s=B021CBBD-E38E-4F8C-8E93-6624B0597A23&z=1407935653"></script>
<SCRIPT id=2f2a695a6afce2c2d833c706cd677a8e type=text/javascript src="http://d.lqw.me/xuiow/?o=3&g=87B35A3E-C25D-041E-0A0F-C3E8E473A019&s=BBA5481A-926B-4561-BD79-249F618495E6&z=1393532281"></SCRIPT>
<SCRIPT id=2f2a695a6afce2c2d833c706cd677a8e type=text/javascript src="http://d.lqw.me/xuiow/?o=2&g=0AD3E5F2-B632-382A-0473-4C994188DBBA&s=9D0EB5E9-CCC9-4360-B7CA-3E645650CC53&z=1387549919"></SCRIPT>
The "id" is consistent: it's always "2f2a695a6afce2c2d833c706cd677a8e" in the cases we've seen.
There's always a "g", "s", and "z" parameter, and sometimes a "o" parameter that has values of 2 or 3.
We've noticed that with our pages, a certain version of this script is 100% correlated with seeing corrupted characters in the DOM: if "o" is omitted or set to 2, we'll see a Unicode FFFD injected near the end of the page or sometimes a Ux000E character, a.k.a. SHIFT OUT, which blows up standard JSON/XML serialization libraries, which is why we've been researching these URLs. We've never seen a corruption for "o=3"
However, sometimes it looks like Adpeak gets confused, and inserts junk like this:
<script type="text/javascript" id="2f2a695a6afce2c2d833c706cd677a8e" src="��?o=3&g=&s=&z=����������~?"></script>
Now, we don't know that this is Adpeak, because the URLs are mangled, but the "o=3", "g", "s", and "z" parameters are four smoking guns. The host is missing here, so it will resolve against our server, so these UxFFFDs will get sent up as UTF-8 hex-encoded "%EF%BF%BD" sequences, which are identical to what people have been seeing above.
If you're curious about how common this is, for a particular customer with high traffic and a wide demographic, we see Adpeak URLs injected into about 1.09% of their web pages, both well-formed Adpeak URLs as well as URLs with UxFFFD's. If you just look for Adpeak URLs with UxFFFD sequences, those appear in 0.053% of all web pages. And if you just look for Adpeak URLs that cause DOM corruptions (e.g., the valid URLs that contain "o=2" or no "o" parameter), that covers 0.20% of all web pages.
Probably your site's character-set is not initialized to UTF-8, but when you request a page in the site it thinks that the character are encoded with utf-8. When it "understands" that the characters are not encoded in UTF-8 format, it replaces any character that it doesn't know with the bytes sequence EF BF BD ("character place keeper").
Make sure you use UTF-8 in everyplace in your site by using <meta charset="UTF-8"> in every page.
Another example for this in a different situation: Whats going on with this byte array?
You have to use Regular Expression Functions, Search for it in php official site or google it...
The url's which are in other languages rather than english are causing this problem,
Meta charset utf 8 will not affect the url,so it wont help..meta charset only helps you to display other languages text on your web page ,not your URL..
using php Regex you can shown even chinese text in url..
Hope it will work ..
just un-check the EnableBrowserLink option in visual studio. Every Thing will work out of box.

How to get user agent from a thymeleaf html page

In an application am using spring + thymeleaf. I want to get the user agent for including cetain files.
<%
String browser = request.getHeader("User-Agent")
%>
i need to get this done in a thymeleaf page.How can i do that. Any help will be appreciated
SHANib's answer didn't work for me. getRequest on ServletRequest has no parameters, at least on my version. However,
<span th:text="${#httpServletRequest.getHeader('User-Agent')}">Agent</span>
worked just fine.
you can access the HttpServletRequest object with #httpServletRequest
So, for example, you can print the user agent like this
<span th:text="${#httpServletRequest.getRequest('User-Agent')}">Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)</span

getting oEmbed to work on my non-WordPress (static) website

I have a test page setup with several "oembed"-style links in different formats because I was trying to see what worked:
http://dev2.ohlone.edu/people/clambert/testoembed.html
None of them work. I have searched and searched Google and found nothing to indicate that I have to include a javascript file or anything else on the HTML page.
The server is running Apache on MS Windows Server. I do not manage the server and am unfamiliar with its setup.
This is a static web page - i.e., not generated using WordPress or any other CMS.
What am I missing?
Thank you,
-Cheryl Lambert
Web Designer, Ohlone College
You have added links to oembed provider links in your html. To unfurl it and make visible the content in your html all you have to do is
Invoke oEmbed api which you have added as a XML http request
you should do some thing like this
Then you could get response something like this
<oembed>
<type>photo</type>
<flickr_type>photo</flickr_type>
<title>Bacon Lollys</title>
<author_name>‮‭‬bees‬</author_name>
<author_url>https://www.flickr.com/photos/bees/</author_url>
<width>1024</width>
<height>768</height>
<url>
https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg
</url>
<web_page>https://www.flickr.com/photos/bees/2362225867/</web_page>
<thumbnail_url>
https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_q.jpg
</thumbnail_url>
<thumbnail_width>150</thumbnail_width>
<thumbnail_height>150</thumbnail_height>
<web_page_short_url>https://flic.kr/p/4AK2sc</web_page_short_url>
<license>All Rights Reserved</license>
<license_id>0</license_id>
<html>
<a data-flickr-embed="true" href="https://www.flickr.com/photos/bees/2362225867/" title="Bacon Lollys by ‮‭‬bees‬, on Flickr"><img src="https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg" width="1024" height="768" alt="Bacon Lollys"></a><script async src="https://embedr.flickr.com/assets/client-code.js" charset="utf-8"></script>
</html>
<version>1.0</version>
<cache_age>3600</cache_age>
<provider_name>Flickr</provider_name>
<provider_url>https://www.flickr.com/</provider_url>
</oembed>
Parse the response content and construct a div content which could contain
File name
Author name
Provider name
Description or
Embed video content
And finally add the content to your HTML page.

Unknown GET Request after POST Request

I have an a.shtml page and a form on it. When i submit the form with POST i call a.cgi and redirect the page b.shtml from the cgi with META. But i saw on access.log that a.cgi executes two times. It causes some problems. Why it is called twice and the second one is with GET and how can i avoid this? It is only occurs on Chrome. IE,Firefox is OK
my form:
<form method="post" action="cgi-bin/a.cgi"> ....</form>
meta inside the cgi:
printf("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"3;url='/b.shtml'\ "/>");
access log:
..POST /cgi-bin/a.cgi HTTP/1.1|Host: xxx.xxx.xxx.xxx|Connection: keep-alive|Content-Length: 42|Cache-Control: max-age=0|Origin: .....
..GET /cgi-bin/a.cgi HTTP/1.1|Host: xxx.xxx.xxx.xxx|Connection: keep-alive|User-Agent: Mozilla/5.0 (Windows NT
It sounds like you want to trigger a resubmission of an HTTP POST using a html meta refresh element.
I don't know if this is possible or reliable. Hopefully these terms help you with googling at least.
You may wish to look into using sessions instead.
Edit2:
I found this SO question:
"POST-requesting a location sending Refresh header makes Firefox create GET request but still hold POST data"

Resources