I'm using Phonegap (Cordova) v1.9, and this app is solely for iPhone4+ use.
I've tried the two methods below, on their own and simultaneously.
Phonegap's deviceready event has been fired previous to this code.
I'm using the iPhone configuration utility to watch the console, but I'm not getting anything from the code below.
Also, I'm using Sencha Touch (v1.1) and jQuery. No conflicts noticed throughout the app.
Please help?
function onConfirmCallback(button){
console.log("onConfirmCallback");
console.log(button);
}
var toConfirm = navigator.notification.confirm("You don't have a pincode set.\nWould you like to set one now?", onConfirmCallback, "Pincode", "Yes,No");
toConfirm.onAlertDismissed = function(index, label){
console.log("onAlertDismissed");
console.log(index);
}
Have you tried looking for exceptions to see what might be happening?
try
{
var toConfirm = navigator.notification.confirm("You don't have a pincode set.\nWould you like to set one now?", onConfirmCallback, "Pincode", "Yes,No");
toConfirm.onAlertDismissed = function(index, label) {
console.log("onAlertDismissed");
console.log(index);
}
}
catch (ex)
{
console.log(ex.message);
}
Edit:
The example mentioned in the comment below (from https://groups.google.com/group/phonegap/browse_thread/thread/126f56f4e296e555) is for PhoneGap 0.9.2. I have not seen any examples for v1.3 where the confirm function returns an object as your using with 'toConfirm'. Maybe that is causing your problem. Have you tried the following (removing all other code to do with toConfirm to simplify the problem)?
navigator.notification.confirm("You don't have a pincode set.\nWould you like to set one now?", onConfirmCallback, "Pincode", "Yes,No");
http://docs.phonegap.com/en/1.3.0/phonegap_notification_notification.md.html#notification.confirm
Also, is there any reason your not using a newer version of PhoneGap (Cordova)?
Related
I'm trying to bypass a root detection mechanism on an android app using Frida, I've tried so many different scripts (frida code share) and different approaches (like hiding root) with no luck!
So I tried to locate the class and method responsible for checking if the device is rooted or not and changing it's return value.
This is my script :
setTimeout(function() { // avoid java.lang.ClassNotFoundException
Java.perform(function() {
var hook = Java.use("app.name.RootUtils");
console.log("info: hooking target class");
hook.isRooted.overload().implementation = function() {
console.log("info: entered target method");
return Java.use("java.lang.Boolean").$new(false);
}
});
},0);
If I inject this code normally it won't work because it looks like the isRooted method will get called before it
If I use spawn to run the app and change this method return value it fails with error :
frida.core.RPCException: Error: java.lang.ClassNotFoundException: Didn't find class ...
I've also tried spawning the app and then using objection to run "android root disable" but it will return this error :
frida.core.RPCException: TypeError: cannot read property 'getApplicationContext' of null
at getApplicationContext (src/android/lib/libjava.ts:21)
I'm not sure if this is a problem with Frida or my system or ...
I think if I was able to make my main code runs at exactly after the class gets loaded (like using a loop to check or using a hook) the problem would be fixed but I don't know how to write that kind of code in js for frida.
I'm on macOS 11.5.1 using python 3.9 and installed latest version of frida and objection
I've tested on one rooted phone with android 10 and an emulator with android 6
I was able to solve this issue with a simple yet not very technical solution.
I used a setInteval to run my hooking over and over until it gets to work, (as #Robert mentioned, I also needed to wrap hooking inside a try catch to prevent the code from stoping after first try)
This may not work for everyone but since it worked for me I will post the final code, may it helps someone else in the future :)
Java.perform(function() {
var it = setInterval(function(){
try{
var hook = Java.use("app.name.RootUtils");
console.log("info: hooking target class");
hook.isRooted.overload().implementation = function() {
console.log("info: entered target method");
clearInterval(it);
return Java.use("java.lang.Boolean").$new(false);
}
} catch(e) {
console.log("failed!");
}
},200); // runs every 200milisecods
});
PS : you may need to change interval time to match your app needs, it worked for me with 200 miliseconds.
Sometimes app would do encryptions in its class loader, you may need to replace Java.classFactory.loader with the app's customized class loader in order to make Java.use function properly.
Here's how it's done:
Java.perform(function() {
//get real classloader
//from http://www.lixiaopeng.top/article/63.html
var application = Java.use("android.app.Application");
var classloader;
application.attach.overload('android.content.Context')
.implementation = function(context) {
var result = this.attach(context); // run attach as it is
classloader = context.getClassLoader(); // get real classloader
Java.classFactory.loader = classloader;
return result;
}
//interesting classes
const interestingClassPath = "com.myApp.SometingInteresting";
interestingClass = Java.use(interestingClassPath);
//do whatever you like here
})
Class not found
How do you know the class is app.name.RootUtils have you decompiled to app using Jadx or apktool? How about the method where RootUtils.isRooted() is called? Is there any special code that loads the RootUtils class e.g. from a non-standard dex file included in the app? If the class is loaded from a special dex file you could hook this dex loading mechanism and first execute it and then install your hook for RootUtils.isRooted().
Alternatively assuming RootUtils.isRooted() is called only from one other method and does not use special code for loading the RootUtils class you could hook that method and use the this hook to install install your RootUtils.isRooted() hook.
Error handling
The correct way to handle errors in JavaScript is using try catch block, not the setTimeout function:
Java.perform(() => {
try {
var hook = Java.use("app.name.RootUtils");
...
} catch (e) {
console.log("Failed to hook root detection" + e);
}
}
Regarding your problems hooking the class
I'm using ExtJS 6.7 Modern toolkit and Ext.grid.Tree.selectOnExpander = false does not work properly when data for expandable node is loading from a remote server, i.e. node is selected when I click on the expander.
I expect that in this case the node will NOT be selected as in the case when the data is already loaded.
Check this fiddle as an illustration - try to expand node when it is loaded and when it is not loaded yet using expander.
So far I've tried to check fired events with Ext.util.Observable.capture and it seems like extra childtap event is triggired. I don't yet understand why. Seems like a bug for me.
Seems they forgot to implement the logic.
From the code I would sugget to use this snippet.
It extens the logic from Ext.dataview.List using the same style.
Sencha Fiddle: Fiddle
Ext.define('Portal.grid.Tree', {
override: 'Ext.grid.Tree',
shouldSelectItem: function(e) {
var me = this,
no = !me.callParent([e]),
cmp;
if (!no && !me.selectOnExpander) {
cmp = e.getTarget();
no = cmp.classList.contains('x-expander-el');
}
return !no;
}
});
The best solution I have found so far is to override Ext.grid.Tree onChildTap method (inherited from Ext.dataview.Abstract) like this:
Ext.define('Portal.grid.Tree', {
override: 'Ext.grid.Tree',
/** Override Ext.dataview.Abstract onChildTap method for correct processing selectOnExpander property **/
onChildTap: function(location) {
if (this.getSelectOnExpander() || location.event.target !== location.cell.expanderElement.dom) {
this.callParent(arguments);
}
},
});
I've been attempting to implement a ASP.NET MVC custom validation method. Tutorials I've used such as codeproject explain that you add data-val-customname to the element. Then jQuery.validate.unobtrusive.js then uses the third segment of the attribute
data-val-<customname>
as the name of the rule, as shown below.
$.validator.addMethod('customname', function(value, element, param) {
//... return true or false
});
However I just can't get the customname method to fire. By playing around I have been able to get the below code to work, but according to all the sources I've read Unobtrusive validation should not work like this.
$.validator.addMethod('data-val-customname', function(value, element, param) {
//... return true or false
});
I've posted an example of both methods
jsfiddle example
Any help would be much appreciated
I've updated my question hopefully to make clearer.
I have finally found got there in the end, but still feels like too much hard work and therefore I've probably got something wrong. Initial I was scuppered by a bug in Chrome Canary 62 which refused to allow the adding of a custom method.
My next issue was having to load jQuery, jQuery.validate and jQuery.validate.unobtrusive in the markup and then isolate javascript implementation in a ES6 class. I didn't want to add my adaptors before $().ready() because of my class structure and loading of the app file independent of jQuery. So I had to force $.validator.unobtrusive.parse(document);.
Despite this I was still having issues and finally debugged the source code and found that an existing validator information that is attached to the form was not merging with the updated parsed rules, and essentially ignoring any new adaptors added.
My final work around and admit feels like I've done too much, was to destroy the initial validation information before my forced re-parse.
Here is the working jsfiddle demo
Here is some simplified code
onJQueryReady() {
let formValidator = $.data(document.querySelector('form'), "validator" );
formValidator.destroy();
$.validator.unobtrusive.adapters.add("telephone", [], function (options) {
options.rules['telephone'] = {};
options.messages['telephone'] = options.message;
});
$.validator.unobtrusive.parse(document);
$.validator.addMethod("telephone", this.handleValidateTelephoneNumber);
}
I'm helping a friend with his site and after updating his WordPress installation to address the recent security issue, the JPlayer plugin that was handling audio on his site stopped working.
Chrome's console shows the error in the title, but I don't know JS well enough to be able to debug it properly. I'm pretty sure that the plugin itself is loaded correctly, along with JQuery, in the page header. I checked it against the plugin's instructions and it all appears fine.
I've also updated the plugin itself to ensure that it's not some compatibility issue.
I did not build his site, nor am I familiar with this particular plugin at all, I'm just trying to see if it's an easy fix or if I have to restore a backup.
I assume it has something to do with how his web designer (they had a falling out) implemented it in the main.js file, but that's about as far as I've gotten.
Help?
Really condensing and removing parts of main.js, it looks like
var $player = false,
$(document).ready(function() {
if(!$player) {
$("#jPlayer").jPlayer({
ready: function() {
$player = $(this); // IT'S BEING SET HERE !
PlaylistPlay(playlistObject,trackIndex);
}
});
} else {
PlaylistPlay(playlistObject,trackIndex);
}
});
function PlaylistPlay(lePID,trackIndex) {
playTrack(trackIndex);
}
function playTrack(index) {
$player.jPlayer("setMedia", {mp3: trackObject.mp3,oga: trackObject.oga}).jPlayer("play");
}
If you look closely at that, you'll see that there is a distinct possibility that PlaylistPlay can be called without $player being set to $(this), it's actually almost a certaintity, which means that $player is false, and doing
false.jPlayer(...
doesn't really work, see the console output that confirms the variable is false
The plugin is not initializing correctly. On $(document).ready() it's trying to initialize the plugin and it's reporting a Flash error.
Here's the significant part of the code:
$("#jPlayer").jPlayer({
...
error: function(event) {
var out = "<p id=\"noSolution\">Sorry, you need an HTML5 capable browser or flash to be able to listen to music on this website.<br /> Reason: ";
switch(event.jPlayer.error.type) {
case $.jPlayer.error.FLASH:
out += "A problem with the Flash insertion on the page.";
break;
...
}
}
...
});
Digging a bit deeper, I can trace this back to the vimeo.jplayer in the specific code block:
_flash_volume: function(a) {
try {
this._getMovie().fl_volume(a)
} catch (b) {
this._flashError(b)
}
}
That function is throwing an exception because this._getMovie() does not have a property named fl_volume.
The error you actually see is a side-effect of this failure. You could try removing the line: this._flashError(b) from the above statement and see if the error can be safely ignored.
When I run
window.onload = function () {
document.addEventListener("deviceready", getGeolocation);
}
function getGeolocation() {
navigator.geolocation.getCurrentPosition( successCallback, errorCallback, {maximumAge: 0});
}
or
function getGeolocation() {
watchGeoMarkerProcess = navigator.geolocation.watchPosition(updateCallback, errorCallback);
}
and then
function updateCallback(position) {
if (position.coords.accuracy < 100) {
navigator.geolocation.clearWatch(watchGeoMarkerProcess);
}
}
in my app on iOS 5 using phonegap it seems to get stuck, since the geolocation indicator-icon stays in the top bar and it never goes away, which I take to mean that the GPS doesn' get turned off. Also, sometimes I don't get any coords at all, throwing a time-out error.
I don't think there is anything wrong with the code since it works just fine as a webapp.
Any ideas?
navigator._geo is the 'real' implementation I believe. I've seen recent git commits where they are trying to over-ride navigator.geolocation but apparently failing on iOS. Looking at the phonegap source code gave me the idea to try the real call instead.
Here is the git commit:
http://mail-archives.apache.org/mod_mbox/incubator-callback-commits/201203.mbox/%3C20120307000809.B82AA5D82#tyr.zones.apache.org%3E
Here is another thread on the problem:
https://groups.google.com/forum/?fromgroups#!topic/phonegap/W32yYpV28W8
UPDATE: I have some measure of success now:
Edit your phonegap.js, comment out lines 3451-3453 which look like this:
__proxyObj(navigator.geolocation, navigator._geo,...
You will get an ugly permission alert.. but the location should work. The reasoning behind this change is that you will now use safari's location detection, not PhoneGaps.
UPDATE2: ..and the problem with PhoneGap turned out to be a conflict with another javascript library, in this case dragdealer.js. So double check for any suspicious variable names like "Location" or "Position" in any other javascript you are using. For some reason this conflict was not a problem on platforms other than iOS.
For what it's worth I have a same problem and these fixes did not work. But they may for you:
make sure you get the location after onDeviceReady() has been called
try using navigator._geo.getCurrentPosition
I had the same problem, although on Android.
Adding the enableHighAccuracy option caused it to start working:
navigator.geolocation.getCurrentPosition(onSuccess, onError, {enableHighAccuracy:true} );