parse JSONP response (from express.js server) clientside using greasemonkey - javascript

We are working on a greasemonkeyscript to pull data from an express server cross-domain.
(We found code which is working for a normal html site here:
)
Can you get this to work for greasemonkey?
(maybe with unsafeWindow ?)
app.js:
var express = require("express");
var app = express();
var fs=require('fs');
var stringforfirefox = 'hi buddy!'
// in the express app for crossDomainServer.com
app.get('/getJSONPResponse', function(req, res) {
res.writeHead(200, {'Content-Type': 'application/javascript'});
res.end("__parseJSONPResponse(" + JSON.stringify( stringforfirefox) + ");");
});
app.listen(8001)
greasemonkeyscript:
// ==UserScript==
// #name greasemonkeytestscript
// #namespace http://www.example.com/
// #description jQuery test script
// #include *
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js
// ==/UserScript==
function __parseJSONPResponse(data) { alert(data); } // ??????????
document.onkeypress = function keypressed(e){
if (e.keyCode == 112) {
var script = document.createElement('script');
script.src = 'http://localhost:8001/getJSONPResponse';
document.body.appendChild(script); // triggers a GET request
alert(script);
}
}

I've never used Express before, but that app looks to be returning code like:
__parseJSONPResponse("\"hi buddy!\"");
which is placed into a <script> node in the target-page scope.
This means that the Greasemonkey script must also place the __parseJSONPResponse function in the target-page scope.
One way to do that is:
unsafeWindow.__parseJSONPResponse = function (data) {
alert (data);
}
However, it looks like you control the Express app. If that's true, then don't use JSONP for this kind of thing. Use GM_xmlhttpRequest().
app.js might become:
var express = require ("express");
var app = express ();
var fs = require ('fs');
var stringforfirefox = 'hi buddy!'
app.get ('/getJSONPResponse', function (req, res) {
res.send (JSON.stringify (stringforfirefox) );
} );
app.listen (8001)
And the GM script would be something like:
// ==UserScript==
// #name greasemonkeytestscript
// #namespace http://www.example.com/
// #description jQuery test script
// #include *
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// #grant GM_xmlhttpRequest
// ==/UserScript==
document.onkeypress = function keypressed (e){
if (e.keyCode == 112) {
GM_xmlhttpRequest ( {
method: 'GET',
url: 'http://localhost:8001/getJSONPResponse',
onload: function (respDetails) {
alert (respDetails.responseText);
}
} );
}
}

Related

Websocketsharp getting QueueUserWorkItemCallbackDefaultContext and System.ObjectDisposedException exception

I'm trying to get the captcha token from here using websocketsharp but I've got this error
29/08/2022 22:00:05|Error|QueueUserWorkItemCallbackDefaultContext.Execute|Operation is not supported on this platform.
29/08/2022 22:00:06|Fatal|<>c__DisplayClass48_0.<ReadBytesAsync>b__0|System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
at System.Net.Sockets.NetworkStream.<ThrowIfDisposed>g__ThrowObjectDisposedException|63_0()
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
at WebSocketSharp.Ext.<>c__DisplayClass48_0.<ReadBytesAsync>b__0(IAsyncResult ar)
Javascript code is loaded in TamperMonkey
Javascript:
// ==UserScript==
// #name Captcha Service
// #namespace mservice
// #version 1.0
// #description no description
// #author Moch
// #match https://www.habbo.com.br/api/public/captcha*
// #grant none
// ==/UserScript==
(function () {
'use strict';
var socket = new WebSocket("ws://127.0.0.1:8080");
socket.onopen = () => {
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has("token") && urlParams.get("token") !== "") {
socket.send(urlParams.get("token"));
}
}
})();
C#:
using WebSocketSharp;
using WebSocketSharp.Server;
public class Laputa : WebSocketBehavior
{
protected override void OnMessage(MessageEventArgs e)
{
Console.WriteLine(e.Data);
}
}
static void Main(string[] args)
{
var wssv = new WebSocketServer("ws://127.0.0.1:8080");
wssv.AddWebSocketService<Laputa>("/");
wssv.Start();
Console.ReadKey(true);
wssv.Stop();
}
I tried switching to WebSocketSharp-netstandard and WebScoketSharkFork but the same error appears.

Using google calender inside greasemonkey script

I am trying to use the google calender api inside a greasemonkey script. This is my code inspired from the google calender api tutorial:
// ==UserScript==
// #name Google Calender
// #namespace xyz
// #include *
// #version 1
// ==/UserScript==
var $ = unsafeWindow.jQuery;
API_js_callback = "https://apis.google.com/js/api.js";
var script = document.createElement('script');
script.src = API_js_callback;
var head = document.getElementsByTagName("head")[0];
(head || document.body).appendChild(script);
//this is not working
var gapi = unsafeWindow.gapi;
$(document).ready(function()
{
// Client ID and API key from the Developer Console
var CLIENT_ID = 'XXX';
// Array of API discovery doc URLs for APIs used by the quickstart
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];
// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
var SCOPES = "https://www.googleapis.com/auth/calendar.readonly";
handleClientLoad();
/**
* On load, called to load the auth2 library and API client library.
*/
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
/**
* Initializes the API client library and sets up sign-in state
* listeners.
*/
function initClient() {
.........
}
});
Inside the handleClientLoad method, I got the following exception:
Cannot read property 'load' of undefined
Any idea?
The gapi library is injected after the document loads, therefore it hasn't loaded yet when the document is ready. The gapi-related code need to be run on script load, for example:
GAPI_js_src = "https://apis.google.com/js/api.js";
var script = document.createElement('script');
script.src = GAPI_js_src;
var head = document.getElementsByTagName("head")[0];
(head || document.body).appendChild(script);
script.onload = (function() {
var gapi = unsafeWindow.gapi;
// Client ID and API key from the Developer Console
var CLIENT_ID = 'XXX';
// Array of API discovery doc URLs for APIs used by the quickstart
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];
// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
var SCOPES = "https://www.googleapis.com/auth/calendar.readonly";
handleClientLoad();
/**
* On load, called to load the auth2 library and API client library.
*/
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
/**
* Initializes the API client library and sets up sign-in state
* listeners.
*/
function initClient() {
.........
}
});

socketstream tutorials/authentication can't use Everyauth with the chat demo

https://socketstream.github.io/socketstream/docs/#/tutorials/authentication
when i put the codes in this section to the demo project(real time chat), the chat function doesn't work. can any one help me with this?
here's my code:
// ===================== SEPARATOR ============
var ss = require('socketstream');
var redirect = require('connect-redirection');
var everyauth = require('everyauth');
var http = require('http');
var conf = require('./conf/conf');
var auth_twitter = conf.oauth.twitter;
// Define a single-page client called 'main'
ss.client.define('main', {
view: 'app.html',
css: ['../node_modules/normalize.css/normalize.css', 'app.css'],
code: ['../node_modules/es6-shim/es6-shim.js', 'libs/jquery.min.js', 'app'],
tmpl: 'chat'
});
ss.http.middleware.prepend(redirect());
// Serve this client on the root URL
ss.http.route('/', function(req, res){
// if(!req.session.userId){ return res.redirect('/login'); }
res.serveClient('main');
});
// Use server-side compiled Hogan (Mustache) templates. Others engines available
ss.client.templateEngine.use(require('ss-hogan'));
// Minimize and pack assets if you type: SS_ENV=production node app.js
if (ss.env === 'production') ss.client.packAssets();
everyauth.twitter
.consumerKey(auth_twitter.KEY)
.consumerSecret(auth_twitter.SEC)
.findOrCreateUser( function (session, accessToken, accessTokenSecret, twitterUserMetadata) {
var userName = twitterUserMetadata.screen_name;
console.log('Twitter Username is', userName);
session.userId = userName;
session.save();
return true;
})
.redirectPath('/');
var bodyParser = require('body-parser');
//ss.http.middleware.prepend(bodyParser.urlencoded());
//ss.http.middleware.append(everyauth.middleware());
var server = http.Server(ss.http.middleware);
server.listen(3000);
ss.start(server);
After reading some doc, i tried this and it worked:
replace the last three lines codes:
var server = http.Server(ss.http.middleware);
server.listen(3000);
ss.start(server);
with this:
ss.start();

GM_xmlHttpRequest POST doesn't work in event listener

What I want is really simple: intercept the xmlHttpRequests sent by a page and send them to my local server to log it in a text file.
But obviously, Ajax calls don't work in event listeners... I found several solutions and tried, and tried, and tried... Spent my whole day searching for a solution. Here's the code:
var ajaxQueue = [];
var processAjaxQueue = function(){
if (ajaxQueue.length > 0) {
for (ajax in ajaxQueue) {
var obj = ajaxQueue[ajax];
setTimeOut(function(){GM_xmlhttpRequest(obj);},0);
}
ajaxQueue = [];
}
}
setInterval(function(){
processAjaxQueue();
}, 100);
function gmAjax(obj){
ajaxQueue.push(obj);
}
function envoiData(donnees)
{
setTimeout(function() {gmAjax({
method: "POST",
url: "http://127.0.0.1/log/index.php",
data: "prix="+donnees,
headers: {"Content-Type": "application/x-www-form-urlencoded"},
onload: function(reponse){alert('Chargé ! '+reponse.responseText);}
});}, 0);
}
(function(open) {
XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
this.addEventListener("readystatechange", function() {
console.log(this.readyState);
if(this.readyState == 4)
{
alert(this.responseText);
envoiData(this.responseText);
}
}, false);
open.call(this, method, url, async, user, pass);
};
})(XMLHttpRequest.prototype.open);
I really don't get what the problem is. The gmAjax idea comes from a site where the guy says that greasemonkey scripts execute and stop immediately, and therefore using addevent listener is impossible.
I have no error in the error console and my request works when outside the event listener.
Any help appreciated ^^
The original idea is correct.
However, you need to add a couple of things.
Add the #run-at document-start meta, so that the loggin started prior to any ajax requests are sent by the page.
You need to manipulate with XMLHttpRequest in the actual window scope (unsafeWindow) rather than in the sandbox.
So the resulting code is:
// ==UserScript==
// #run-at document-start
// #grant unsafeWindow
// ==/UserScript==
var unsafe = unsafeWindow;
... // keep your ajax queue code here
var oldOpen = unsafe.XMLHttpRequest.prototype.open;
unsafe.XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
this.addEventListener("readystatechange", function() {
if(this.readyState == 4)
{
alert(this.responseText);
envoiData(this.responseText);
}
}, false);
oldOpen.call(this, method, url, async, user, pass);
};

Adding #grant to a GM script breaks the overload of XMLHttpRequest.prototype.open?

I'm writing a Greasemonkey script where I want to overload the XMLHttpRequest.prototype.open function to hijack the Ajax calls on the page.
I'm using the following code:
// ==UserScript==
// #name name
// #namespace namespace
// #description desc
// #include https://url*
// #version 1.0
// ==/UserScript==
if (XMLHttpRequest.prototype) {
//New Firefox Versions
XMLHttpRequest.prototype.realOpen = XMLHttpRequest.prototype.open;
var myOpen = function(method, url, async, user, password) {
//call original
this.realOpen (method, url, async, user, password);
myCode();
}
//ensure all XMLHttpRequests use our custom open method
XMLHttpRequest.prototype.open = myOpen ;
}
This works well until I start using GM APIs. When I just add the following line to the meta section my code breaks, and myOpen is no longer called:
// #grant GM_getValue
This could be any GM API really, and my code breaks.
Everything else in my script works fine even with the GM APIs, it's just the overload of the XMLHttpRequest.prototype.open function that breaks.
I can kind of workaround it by using waitForKeyElements, however, I don't like it because it slows down the browser due to the interval it uses.
Any ideas why the GM APIs break the overload of the XMLHttpRequest.prototype.open call?
Many thanks,
Peter
The #grant directive switches Greasemonkey's sandbox back on -- which it must have to use any of the GM_ functions.
That prototype override would then only affect the script scope, and you want it to affect the page scope. To get around this, you need to inject the override. Like so:
function overrideXhrFunctions () {
if (XMLHttpRequest.prototype) {
//New Firefox Versions
XMLHttpRequest.prototype.realOpen = XMLHttpRequest.prototype.open;
var myOpen = function(method, url, async, user, password) {
//call original
this.realOpen (method, url, async, user, password);
myCode();
}
//ensure all XMLHttpRequests use our custom open method
XMLHttpRequest.prototype.open = myOpen ;
}
}
addJS_Node (null, null, overrideXhrFunctions) {
//-- addJS_Node is a standard(ish) function
function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
var D = document;
var scriptNode = D.createElement ('script');
if (runOnLoad) {
scriptNode.addEventListener ("load", runOnLoad, false);
}
scriptNode.type = "text/javascript";
if (text) scriptNode.textContent = text;
if (s_URL) scriptNode.src = s_URL;
if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()';
var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
targ.appendChild (scriptNode);
}
Note that mixing GM_ functions and injected code can get tricky. See "How to use GM_xmlhttpRequest in Injected Code?" for one way to do that.

Categories

Resources