简体   繁体   中英

Strange browser description PyQt

I was trying to get browser description using JavaScript, and got strange result:

productSub: 20100101 # When I open it with my Mozila FF browser
productSub: 20030107 # when I open it with PyQt4

vendorSub: # nothing in here with my Mozila FF
vendorSub: Apple Computer, Inc. # with PyQt4 ( even though I don't have anything to do with Apple)

This is HTML/JS:

<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<p id="myp">Hi</p>

<script>
    body = document.getElementsByTagName('body')[0];
    var nav_div = document.createElement('div');
    nav_div.id = 'nav_div';
    for (para in navigator) {
        var para_p = document.createElement('p');
        var context = document.createTextNode(para + ': ' + navigator[para]);
        para_p.appendChild(context);
        para_p.id = para;
        nav_div.appendChild(para_p);
    }
    body.appendChild(nav_div);
</script>
</body>
</html>

And here is the Python/PyQt4 code:

#! /usr/bin/env python2.7

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
import sys, signal


class MySettings(QWebPage):
    def userAgentForUrl(self, url):
        return 'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0'

class Opener(QWebView):
    def __init__(self):
        QWebView.__init__(self)
        url = QUrl('/home/john-the-ripper/JavaScript/w.html')
        self.setPage(MySettings())
        self.load(url)
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    opener = Opener()
    # press Ctrl + C for exit
    if signal.signal(signal.SIGINT, signal.SIG_DFL):
        sys.exit(app.exec_())
    app.exec_()

As you can see I have defined user agent the same as it is in my machine:

userAgent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0

Here is the result for PyQt4:

PyQt4中

And Here is the result for my native browser Mozila Fire Fox:

FF

So the questions are:

  1. Why productSub appers to be different, even though I have defined it in userAgentForUrl()
  2. Why when I open this page with PyQt4, vendorSub is Apple Computer, Inc.

A possible workaround is by redefining the navigator object. For a start, connect the javaScriptWindowObjectCleared signal from the page's main frame to a slot:

connect(myPage->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
  this, SLOT(tweakNavigatorObject()));

In your slot, execute some script ( QWebFrame::evaluateJavaScript ) which can totally redefine the object, eg

window.navigator = {
  appCodeName: 'Mozilla',
  appName: 'Netscape',
  vendor: 'My Company'
}

JFYI, this is the trick I have used in PhantomJS to provide the ability to manipulate the global object before the page's script gets executed, useful eg to manipulate Math.random behavior and to detect user agent sniffing .

Who says that the information in the navigator object is solely based on the UserAgent header? That header is only meant to be sent to servers when retrieving a URL. Yes, some values on the navigator object are taken from the current header, but, as you have found out, not all are, nor are they meant to.

In fact, only the appVersion and userAgent strings are taken from that header, everything else reflects the native browser instead.

The Qt browser is based on WebKit , which is a Apple project, hence the vendor string. You can see that when you run your navigator reflection code in Safari:

geolocation: [object Geolocation]
cookieEnabled: true
language: en-us
productSub: 20030107
product: Gecko
appCodeName: Mozilla
mimeTypes: [object MimeTypeArray]
vendorSub:
vendor: Apple Computer, Inc.
platform: MacIntel
appName: Netscape
appVersion: 5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17
userAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17
plugins: [object PluginArray]
onLine: true
javaEnabled: function javaEnabled() { [native code] }
getStorageUpdates: function getStorageUpdates() { [native code] }

Safari let's me switch the UserAgent header too, from the Developer menu. Switching it only changes the appVersion and userAgent strings too. Switching to Firefox 11.0 — Mac , for example, changes just those two variables to:

appVersion: 5.0 (Macintosh; Intel Mac OS X 10.7; rv:11.0) Gecko/20100101 Firefox/11.0
userAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:11.0) Gecko/20100101 Firefox/11.0

Another browser based on WebKit is Chrome, and it's navigator information is quite similar:

geolocation: [object Geolocation]
onLine: true
cookieEnabled: true
vendorSub:
vendor: Google Inc.
productSub: 20030107
product: Gecko
mimeTypes: [object MimeTypeArray]
plugins: [object PluginArray]
platform: MacIntel
userAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.101 Safari/537.11
language: en-US
appVersion: 5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.101 Safari/537.11
appName: Netscape
appCodeName: Mozilla
doNotTrack: null
javaEnabled: function javaEnabled() { [native code] }
getStorageUpdates: function getStorageUpdates() { [native code] }
webkitStartActivity: function webkitStartActivity() { [native code] }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM