I am trying to implement a Firefox Extension which modify the POST request data.
Code follows, it fails where marked "Fails here!!!"
Any insight would be helpful.
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
var newData = "test 123";
function LOG(msg) {
var consoleService = Components.classes["#mozilla.org/consoleservice;1"]
.getService(Components.interfaces.nsIConsoleService);
consoleService.logStringMessage(msg);
}
function CMP() {
this.registered = false;
this.register();
}
CMP.prototype = {
register: function() {
if (this.registered == false) {
var observerService = Components.classes["#mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
observerService.addObserver(this, "http-on-modify-request", false);
this.registered = true;
}
},
observe: function(subject, topic, data)
{
LOG("Inside observe");
if (topic == "http-on-modify-request")
{
LOG("TOPIC is http-on-modify-request");
var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
if(httpChannel.requestMethod == "POST"){
LOG("Inside POST")
var uploadChannel = httpChannel.QueryInterface(Components.interfaces.nsIUploadChannel);
//var uploadChannelStream = uploadChannel.uploadStream;
Modify the data here. Here for testing i am passing "test 123" as new data
var newStringInputStream = Components.classes['#mozilla.org/io/string-input-stream;1'].createInstance(Components.interfaces.nsIStringInputStream);
newStringInputStream.setData(newData,newData.length);
LOG("set data in newStringInputStream!!");
uploadChannel.setUploadStream(newStringInputStream, "text/plain", -1 );// Fails here!!!
httpChannel.requestMethod = "POST";
LOG("upload DONE!!")
}
}
},
QueryInterface : function(aIID) {
if (aIID.equals(Components.interfaces.nsISupports) ||
aIID.equals(Components.interfaces.nsIObserver))
return this;
throw Components.results.NS_NOINTERFACE;
},
unregister: function() {
var observerService = Components.classes["#mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
observerService.removeObserver(this, "http-on-modify-request");
},
classID: Components.ID('{F799F47E-ABA5-4AF1-B8F2-BD74E3E5BCC0}'),
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIObserver])
};
if (XPCOMUtils.generateNSGetFactory)
{
var NSGetFactory = XPCOMUtils.generateNSGetFactory([CMP]);
}
Fixed it by changing by following in the above code. Main change was in setting modified data in httpChannel.uploadStream.
Hope this helps someone!
var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
if(httpChannel.requestMethod == "POST")
{
LOG("Inside POST")
var uploadChannel = httpChannel.QueryInterface(Components.interfaces.nsIUploadChannel);
var newStringInputStream = Components.classes['#mozilla.org/io/string-input-stream;1'].createInstance(Components.interfaces.nsIStringInputStream);
newStringInputStream.setData(newData,newData.length);
var uploadChannelStream = uploadChannel.uploadStream;
uploadChannelStream = uploadChannelStream.QueryInterface(Components.interfaces.nsISeekableStream).seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, 0);
httpChannel.uploadStream.QueryInterface(Components.interfaces.nsIMIMEInputStream);
httpChannel.uploadStream.setData(newStringInputStream);
LOG("Done POST")
}
Related
Can anyone help me with how to call the script include from the client script?
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
//Current assignment group
var assignment_group = newValue;
if(assignment_group){
var coe = '';
var ga = new GlideAjax('sn_hr_core.scriptIncludeNameUtils'); //Script include
ga.addParam('sysparm_name','MethodName'); //Method/Function
ga.addParam('assignment_group',assignment_group); //Parameter
ga.getXMLAnswer(function(response){
coe = response;
if(coe){
g_form.setValue('u_hr_coe', coe);
}
});
}
}
Script Include:
MethodName: function (assignment_group) {
var sys_id = this.getParameter('assignment_group') ? this.getParameter('assignment_group') : assignment_group; //Params
var result = '';
if(sys_id){
var grSysChoice = new GlideRecord('sys_choice');
grSysChoice.addEncodedQuery("element=assignment_group^name=sn_hr_core_case^dependent_value="+sys_id);
grSysChoice.orderBy('sequence');
grSysChoice.setLimit(1);
grSysChoice.query();
if(grSysChoice.next()) {
result = grSysChoice.getValue('value');
}
}
return result;
},
We need to use GlideAjax to call script include from client script.
var ga = new GlideAjax('sn_hr_core.scriptIncludeNameUtils'); //Script include
ga.addParam('sysparm_name','MethodName'); //Method/Function
ga.addParam('assignment_group',assignment_group); //Parameter
ga.getXMLAnswer(function(response){
coe = response;
if(coe){
g_form.setValue('u_hr_coe', coe);
}
});
Youtube video for Ref:
https://youtu.be/zNGdVSCGggE
Using ionic,
I am trying to create an image blob from URI and have tried several codes but failed.
Here is where I implement the imagepicker in ionic:
$cordovaImagePicker.getPictures(options)
.then(function (results) {
console.log(results[0]);
var datablob = $scope.dataURItoBlob(results[0]);
technique 1 (create the blob):
$scope.dataURItoBlob = function(dataURI) {
var binary = atob(dataURI.split(',')[1]);
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
return new Blob([new Uint8Array(array)], {
type: mimeString
});
}
technique 2 (create the blob):
$scope.dataURItoBlob = function(dataURI) {
var arr = dataURI.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
Both techniques does not work. Please help! thank you very much.
$cordovaImagePicker.getPictures(options)
.then(function (results) {
console.log(results[0]);
dataURItoBlob(results[0], function(url){
var datablob = url;
}, function(error){
console.error(error);
})
})
function dataURItoBlob(path, cb, error) {
resolveLocalFileSystemURL(path, function (fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function () {
if (typeof cb === 'function') {
cb(this.result)
}
};
reader.readAsDataURL(file);
}, function (err) {
if (typeof error === 'function') {
error(err)
}
});
});
}
Needs to cordova-plugin-file
const {Cc,Ci,Cr} = require("chrome");
function TracingListener() {
//this.receivedData = [];
}
function CCIN(cName, ifaceName) {
return Cc[cName].createInstance(Ci[ifaceName]);
}
function CCSV(cName, ifaceName){
if (Cc[cName])
// if fbs fails to load, the error can be _CC[cName] has no properties
return Cc[cName].getService(Ci[ifaceName]);
};
TracingListener.prototype =
{
originalListener: null,
receivedData: null, // array for incoming data.
onDataAvailable: function(request, context, inputStream, offset, count)
{
this.originalListener.onDataAvailable(request, context,inputStream, offset, count);
},
onStartRequest: function(request, context) {
this.receivedData = [];
this.originalListener.onStartRequest(request, context);
//thechannel.setRequestHeader("X-Hello", "World", false);
//this part of code will stop the request
/*request.QueryInterface(Ci.nsIHttpChannel);
var cookie=request.getRequestHeader("Cookie");
console.log("cookie="+cookie);*/
var postText = this.readPostTextFromRequest(request, context);
console.log("postText="+postText111);
},
onStopRequest: function(request, context, statusCode)
{
//this part of code will successfullly print the cookie
/*request.QueryInterface(Ci.nsIHttpChannel);
var cookie=request.getRequestHeader("Cookie");
console.log("cookie="+cookie);*/
this.originalListener.onStopRequest(request, context, statusCode);
},
QueryInterface: function (aIID) {
if (aIID.equals(Ci.nsIStreamListener) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_NOINTERFACE;
},
readPostTextFromRequest : function(request, context) {
try
{
var is = request.QueryInterface(Ci.nsIUploadChannel).uploadStream;
if (is)
{
var ss = is.QueryInterface(Ci.nsISeekableStream);
var prevOffset;
if (ss)
{
prevOffset = ss.tell();
ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
}
// Read data from the stream..
var charset = "UTF-8";
var text = this.readFromStream(is, charset, true);
// Seek locks the file so, seek to the beginning only if necko hasn't read it yet,
// since necko doesn't seek to 0 before reading (at lest not till 459384 is fixed).
if (ss && prevOffset == 0)
ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
return text;
}
else {
//dump("Failed to Query Interface for upload stream.\n");
}
}
catch(exc)
{
//dumpError(exc);
}
return null;
},
readFromStream : function(stream, charset, noClose) {
var sis = CCSV("#mozilla.org/binaryinputstream;1", "nsIBinaryInputStream");
sis.setInputStream(stream);
var segments = [];
for (var count = stream.available(); count; count = stream.available())
segments.push(sis.readBytes(count));
if (!noClose)
sis.close();
var text = segments.join("");
return text;
}
}
hRO = {
observe: function(request, aTopic, aData){
try {
if (aTopic == "http-on-examine-response") {
request.QueryInterface(Ci.nsIHttpChannel);
//if (request.originalURI && piratequesting.baseURL == request.originalURI.prePath && request.originalURI.path.indexOf("/index.php?ajax=") == 0) {
var newListener = new TracingListener();
request.QueryInterface(Ci.nsITraceableChannel);
newListener.originalListener = request.setNewListener(newListener);
//}
}
} catch (e) {
/*dump("\nhRO error: \n\tMessage: " + e.message + "\n\tFile: " + e.fileName + " line: " + e.lineNumber + "\n");*/
}
},
QueryInterface: function(aIID){
if (aIID.equals(Ci.nsIObserver) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_NOINTERFACE;
},
};
var observerService = Cc["#mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.addObserver(hRO,
"http-on-examine-response", false);
My question is: the same lines of code:
request.QueryInterface(Ci.nsIHttpChannel);
var cookie=request.getRequestHeader("Cookie");
console.log("cookie="+cookie);
performs different results in onStartRequest and onStopRequest, why?
I can read the cookie in onStopRequest but fails in onStartRequest. I don't think the request is not ready in onStartRequest because I can read the postText in onStartRequest.
I've written my first program with racer. It displays a simple text box manually bound to 'col.doc.prop' path. When I change the value, it does not apply to the store at server.
What causes my subscribed model not to get sync with server?
Server code:
var fs = require('fs');
var io = require('socket.io');
var racer = require('racer');
var mongo = require('racer-db-mongo');
racer.use(mongo);
racer.js({
entry: __dirname + '/client.js'
}, function(err, js) {
return fs.writeFileSync(__dirname + '/script.js', js);
});
var express = require('express');
var server = express.createServer();
server.use(express.static(__dirname));
server.get('/', function(req, res)
{
var model = store.createModel();
model.subscribe('col.doc', function(err, doc)
{
var prop = doc.get('prop');
if (!prop)
{
doc.set('prop', 123);
store.flush();
}
model.ref('_doc', doc);
model.bundle(function(bundle)
{
var client = require('fs').readFileSync('./client.html', 'utf-8');
client = client.replace('_init_', bundle.toString());
res.send(client);
});
});
});
var store = racer.createStore(
{
listen: server,
db:
{
type: 'Mongo',
uri: 'mongodb://localhost/racerdb'
}
});
store.set('col.doc.prop', 123);
store.flush();
server.listen(3001);
Client code:
useRacer = function()
{
var socket = io.connect('http://localhost:3001');
var racer = require('racer');
process.nextTick(function() {
racer.init(this.init, socket);
return delete this.init;
});
racer.on('ready', function(model)
{
addListener = document.addEventListener ? function(el, type, listener) {
return el.addEventListener(type, listener, false);
} : function(el, type, listener) {
return el.attachEvent('on' + type, function(e) {
return listener(e || event);
});
};
var element = document.getElementById('prop');
var listener = function()
{
var val = element.value;
model.set('col.doc.prop', val);
};
addListener(element, 'keyup', listener);
var upgrade = function(id, value)
{
if (model.connected)
{
var prop = model.get('col.doc.prop');
element.value = prop;
}
else
model.socket.socket.connect();
};
model.on('connectionStatus', upgrade);
model.on('set', 'con.*', upgrade);
});
};
The problem solved by changing some lines of the client code:
model.set('col.doc.prop', val) ==> model.set('_doc.prop', val)
model.get('col.doc.prop') ==> model.get('_doc.prop')
model.on('set', 'con.', upgrade) ==> model.on('set', '', upgrade)
I am getting this one error when I use the Mozilla validator:
This is the JS file:
const STATE_START = Components.interfaces.nsIWebProgressListener.STATE_START;
const STATE_STOP = Components.interfaces.nsIWebProgressListener.STATE_STOP;
// Version changes:
// It used to get the lists from a PHP file, but that was putting too much of a strain on the servers
// now it uses xml files.
// Randomizes the servers to load balance
// Mozilla editor suggested no synchronous file gets, so changed it to asynchronous
// Added one more server to help with the updates (Ilovemafiaafire.net)
// Edited some redirect code that some idiots were spreading FUD about.
var xmlDoc = null;
var quickFilter_100_count_redirect_url='http://www.mafiaafire.com/help_us.php';
var countXmlUrl = 0;
//var xmlUrl = 'http://elxotica.com/xml-update/xml-list.php';
var xmlUrl = new Array(4);
xmlUrl[0] = 'http://mafiaafire.com/xml-update/mf_xml_list.xml';
xmlUrl[1] = 'http://ifucksexygirls.com/xml-update/mf_xml_list.xml';
xmlUrl[2] = 'http://ezee.se/xml-update/mf_xml_list.xml';
xmlUrl[3] = 'http://ilovemafiaafire.net/mf_xml_list.xml';
xmlUrl.sort(function() {return 0.5 - Math.random()})
var realXmlUrl = xmlUrl[countXmlUrl];
var notificationUrl = 'http://mafiaafire.com/xml-update/click_here_for_details.php';
var root_node = null;
var second_node = null;
var timervar = null;
var mafiaafireFilterUrl = '';
//Calling the interface for preferences
var prefManager = Components.classes["#mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
var quickfilter_mafiaafire =
{
// get the domain name from the current url
get_domain_name:function()
{
var urlbar = window.content.location.href;
domain_name_parts = urlbar.match(/:\/\/(.[^/]+)/)[1].split('.');
if(domain_name_parts.length >= 3){
domain_name_parts[0] = '';
}
var dn = domain_name_parts.join('.');
if(dn.indexOf('.') == 0)
return dn.substr(1);
else
return dn;
},
// send ajax request to server for loading the xml
request_xml:function ()
{
//alert(countXmlUrl);
http_request = false;
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
if (!http_request)
{
return false;
}
http_request.onreadystatechange = this.response_xml;
http_request.open('GET', realXmlUrl, true);
http_request.send(null);
xmlDoc = http_request.responseXML;
},
// receive the ajax response
response_xml:function ()
{
if (http_request.readyState == 4)
{
if(http_request.status == 404 && countXmlUrl<=3)
{
countXmlUrl++;
//alert(xmlUrl[countXmlUrl]);
realXmlUrl = xmlUrl[countXmlUrl];
quickfilter_mafiaafire.request_xml();
}
if (http_request.status == 200)
{
xmlDoc = http_request.responseXML;
}
}
},
filterUrl:function()
{
var urlBar = window.content.location.href;
//check if url bar is blank or empty
if (urlBar == 'about:blank' || urlBar == '' || urlBar.indexOf('http')<0)
return false;
//1. get domain
processing_domain = this.get_domain_name();
//alert(processing_domain);
//Couldn't fetch the XML config, so returning gracefully
if(xmlDoc == null)
return false;
try
{
root_node = '';
// Parsing the xml
root_node = xmlDoc.getElementsByTagName('filter');
for(i=0;i<=root_node.length;i++)
{
second_node = '';
second_node = root_node[i];
if(second_node.getElementsByTagName('realdomain')[0].firstChild.nodeValue == processing_domain)
{
this.notificationBox();
mafiaafireFilterUrl = '';
mafiaafireFilterUrl = second_node.getElementsByTagName('filterdomain')[0].firstChild.nodeValue;
timervar = setTimeout("quickfilter_mafiaafire.redirectToAnotherUrl()",1500);
//window.content.location.href = second_node.getElementsByTagName('filterdomain')[0].firstChild.nodeValue;
//this.redirectToAnotherUrl(this.filterUrl);
//timervar = setInterval("quickfilter_mafiaafire.redirectToAnotherUrl(quickfilter_mafiaafire.filterUrl)",1000);
}
}
}
catch(e){
//alert(e.toString());
}
},
// This function is called for showing the notification
notificationBox:function()
{
try{
// Firefox default notification interface
var notificationBox = gBrowser.getNotificationBox();
notificationBox.removeAllNotifications(false);
notificationBox.appendNotification('You are being redirected', "", "chrome://quickfilter/content/filter.png", notificationBox.PRIORITY_INFO_HIGH, [{
accessKey: '',
label: ' click here for details',
callback: function() {
// Showing the notification Bar
window.content.location.href = notificationUrl;
}
}]);
}catch(e){}
},
redirectToAnotherUrl:function()
{
var qucikFilterRedirectCount = '';
//Read the value from preferrences
qucikFilterRedirectCount = prefManager.getCharPref("extensions.quickfilter_redirect_count");
//alert(qucikFilterRedirectCount);
if(qucikFilterRedirectCount % 15 == 0)
{
// Disable for now, can comment this entire section but this is the easier fix incase we decide to enable it later
//window.content.location.href = quickFilter_100_count_redirect_url+"?d="+mafiaafireFilterUrl;
window.content.location.href = mafiaafireFilterUrl;
}
else
{
window.content.location.href = mafiaafireFilterUrl;
}
qucikFilterRedirectCount = parseInt(qucikFilterRedirectCount)+1;
prefManager.setCharPref("extensions.quickfilter_redirect_count",qucikFilterRedirectCount);
}
}
var quickfilter_urlBarListener = {
QueryInterface: function(aIID)
{
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
//Called when the location of the window being watched changes
onLocationChange: function(aProgress, aRequest, aURI)
{
// This fires when the location bar changes; that is load event is confirmed
// or when the user switches tabs. If you use myListener for more than one tab/window,
// use aProgress.DOMWindow to obtain the tab/window which triggered the change.
quickfilter_mafiaafire.filterUrl();
},
//Notification indicating the state has changed for one of the requests associated with aWebProgress.
onStateChange: function(aProgress, aRequest, aFlag, aStatus)
{
if(aFlag & STATE_START)
{
// This fires when the load event is initiated
}
if(aFlag & STATE_STOP)
{
// This fires when the load finishes
}
},
//Notification that the progress has changed for one of the requests associated with aWebProgress
onProgressChange: function() {},
//Notification that the status of a request has changed. The status message is intended to be displayed to the user.
onStatusChange: function() {},
//Notification called for security progress
onSecurityChange: function() {},
onLinkIconAvailable: function() {}
};
var quickfilter_extension = {
init: function()
{
//Initiating the progressListerner
gBrowser.addProgressListener(quickfilter_urlBarListener, Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
//Load the block list xml form server
quickfilter_mafiaafire.request_xml();
},
uninit: function()
{
// Remove the progressListerner
gBrowser.removeProgressListener(quickfilter_urlBarListener);
}
};
// window.addEventListener("load", function () { TheGreatTest1.onFirefoxLoad(); }, false);
// this function is Called on window Onload event
window.addEventListener("load", function(e) {
quickfilter_extension.init();
}, false);
window.addEventListener("unload", function(e) {
quickfilter_extension.uninit();
}, false);
Can you tell me how to squash that error please?
It looks like the offending line is setTimeout("quickfilter_mafiaafire.redirectToAnotherUrl()",1500);
The setTimeout function can take a string (which then essentially gets eval'd) or a function (which gets called). Using a string is not recommended, for all the same reasons that using eval is not recommended. See https://developer.mozilla.org/en/DOM/window.setTimeout
In this case, the simplest fix would be to change it to setTimeout(function() { quickfilter_mafiaafire.redirectToAnotherUrl(); },1500);