Frida (android) - why java.lang.StringBuilder append is not hooked - frida

I'm studying frida.
As an example, I simply created a string through the StringBuilder and append it.
I hooked "append" using "frida".
But it doesn't work.
String val;
val = "Log Data....";
StringBuilder log = new StringBuilder("LOG : ").append(val);
log.append("[[");
log.append("]]");
Java.perform(function () {
var StringBuilder = Java.use('java.lang.StringBuilder');
var ctor = StringBuilder.$init.overload('java.lang.String');
ctor.implementation = function (arg) {
var log_arg = '';
var result = ctor.call(this, arg);
if (arg !== null) {
log_arg = arg.toString();
}
console.log('new StringBuilder("' + log_arg + '");');
return result;
};
var append = StringBuilder.append.overload('java.lang.String');
append.implementation = function (arg) {
var result = append.call(this, arg);
var log_arg = '';
if (result !== null) {
log_arg = result.toString();
}
console.log('StringBuilder.append1(); => ' + log_arg);
return result;
};
});
Result :
new StringBuilder("LOG : ");
" Log Data....[[]] " - I can't see the message.... Probably not hooking.

Your hook to append isn't hooking the instance that was initialized.
var ctor = StringBuilder.$init.overload('java.lang.String');
This is where you initialize and allocate, so you need to make the call here.
Something more like
var append = ctor.implementation = function(arg)...
should work. But because StringBuilder has a ton of overloads to cover a ton of data types and it can get called a ton of times, it's much easier to simply hook its toString method so that you don't have to do any casting or write a ton of overloads.
const StringBuilder = Java.use('java.lang.StringBuilder');
StringBuilder.toString.implementation = function () {
var res = this.toString();
var tmp = "";
if (res !== null){
tmp = res.toString().replace("/n", "");
console.log(tmp);
}
return res;
};
should hook the actual string that it will output.

Related

Xamarin.ios: Detail command is null because it shows before function

I'm building an iOS app with Xamarin.ios MvvmCross. And I have a function that puts a random id in a text file every day. So I get a recipe of the day.
The problem is that the code for the Detail command function (for the button) runs before the function that stores everything in the text file. So the detail command returns null and nothing happens when I push the button. The second time I run the code it does what it should do because there's already an id stored in the text file.
The view:
public override void ViewDidLoad()
{
base.ViewDidLoad();
MvxFluentBindingDescriptionSet<TabHomeView, TabHomeViewModel> set = new MvxFluentBindingDescriptionSet<TabHomeView, TabHomeViewModel>(this);
set.Bind(MorningImage).For(img => img.Image).To(res => res.MorningContent.picture).WithConversion<StringToImageConverter>();
set.Bind(MorningJuiceName).To(vm => vm.MorningContent.name);
set.Bind(MorningBtn)
.To(vm => vm.NavigateToMorningJuice);
set.Apply();
}
The function to put a random id in the text file:
public async void GetAfternoonJuice()
{
Recipes = await _recipeService.GetRecipes();
int counter = Recipes.Count;
Random rnd = new Random();
int RandomNumber = rnd.Next(1, counter);
string rndNumToStr = RandomNumber.ToString();
DateTime dateAndTime = DateTime.Now;
string day = dateAndTime.ToString("dd/MM/yyyy");
string folderValue = (day + "," + rndNumToStr);
var _folderName = "TextFilesFolder2";
var _fileName = "AfternoonJuice";
if (!_fileStore.FolderExists(_folderName))
_fileStore.EnsureFolderExists(_folderName);
//Content van de file uitlezen
string value = string.Empty;
_fileStore.TryReadTextFile(_folderName + "/" + _fileName, out (value));
string CheckFileContent = value;
string[] TextFileList;
//Als er niets in zit, default data in steken
if (CheckFileContent == null)
{
_fileStore.WriteFile(_folderName + "/" + _fileName, "00/00/00,0");
string d = "00/00/00,0";
TextFileList = d.Split(',');
}
else
{
TextFileList = CheckFileContent.Split(',');
}
if (TextFileList[0] != day)
{
//File verwijderen om overbodige data te verwijderen.
_fileStore.DeleteFile(_folderName + "/" + _fileName);
//File aanmaken.
if (!_fileStore.FolderExists(_folderName))
_fileStore.EnsureFolderExists(_folderName);
_fileStore.WriteFile(_folderName + "/" + _fileName, folderValue);
string NewValue = string.Empty;
_fileStore.TryReadTextFile(_folderName + "/" + _fileName, out (NewValue));
string NValue = NewValue;
List<string> NewTextFileList = new List<string>(
NValue.Split(new string[] { "," }, StringSplitOptions.None));
int numVall = Int32.Parse(NewTextFileList[1]);
int NewRandomValue = numVall;
AfternoonContent = await _recipeService.GetRecipeById(NewRandomValue);
RaisePropertyChanged(() => AfternoonContent);
}
else
{
int numVall = Int32.Parse(TextFileList[1]);
int NewRandomValue = numVall;
AfternoonContent = await _recipeService.GetRecipeById(NewRandomValue);
RaisePropertyChanged(() => AfternoonContent);
}
}
The detail command:
public MvxCommand<Recipe> NavigateToAfternoonJuice
{
get
{
var _folderName = "TextFilesFolder2";
var _fileName = "AfternoonJuice";
string value = string.Empty;
_fileStore.TryReadTextFile(_folderName + "/" + _fileName, out (value));
string fV = value;
List<string> TextFileList = new List<string>(
fV.Split(new string[] { "," }, StringSplitOptions.None));
int numVall = Int32.Parse(TextFileList[1]);
int NewRandomValue = numVall;
return new MvxCommand<Recipe>(SelectedRecipe =>
{
ShowViewModel<DetailJuiceListViewModel>(new { RecipeId = NewRandomValue });
});
}
}
Some of code in your public property NavigateToAfternoonJuice runs before your command is executed. It will be run, when the binding occurs and not when the command actually executes the body.
You probably want to modify your command to something as follows instead.
private MvxCommand<Recipe> _navigateToAfternoonJuice;
public MvxCommand<Recipe> NavigateToAfternoonJuice
{
get
{
if (_navigateToAfternoonJuice == null)
_navigateToAfternoonJuice = new MvxCommand<Recipe>(DoNavigateToAfternoonJuice);
return _navigateToAfternoonJuice;
}
}
private void DoNavigateToAfternoonJuice(Reciepe selectedRecipe)
{
var _folderName = "TextFilesFolder2";
var _fileName = "AfternoonJuice";
string value = string.Empty;
_fileStore.TryReadTextFile(_folderName + "/" + _fileName, out (value));
string fV = value;
List<string> TextFileList = new List<string>(
fV.Split(new string[] { "," }, StringSplitOptions.None));
int numVall = Int32.Parse(TextFileList[1]);
int NewRandomValue = numVall;
ShowViewModel<DetailJuiceListViewModel>(new { RecipeId = NewRandomValue });
}
This will make the text file to be read when the command executes.

Using dart to create a javascript library

The problem
I'm currently working on a JavaScript library, and in order to reduce the amount of bugs I thought that my library might benefit from using Dart's static typing mechanism. First, because my lib wasn't doing any interop neither with HTML nor with other JavaScript libraries, only pure javascript object manipulation stuff. However I didn't find any info on the net showing how it is possible to build a JS library using dart. So I've tried to do that myself, created initial dart file:
library Repo;
class Type {
final String name;
final TypeCategory category;
Type(String name, TypeCategory category) : name = name, category = category {
category.types[name] = this;
}
}
class TypeCategory {
final String name;
final Map<String, Type> types = new Map();
TypeCategory(this.name);
}
class Branch {
}
class Descriptor {
}
class TableDescriptor extends Descriptor {
TableDescriptor.ctor() {
}
}
class Repo {
Descriptor descriptor(String name) {
}
Branch branch(String name) {
}
void Merge() {
}
}
main() {
return Repo;
}
Compiled it to JavaScript using dart2js to see how I'm doing:
// Generated by dart2js, the Dart to JavaScript compiler version: 1.3.6.
// The code supports the following hooks:
// dartPrint(message):
// if this function is defined it is called instead of the Dart [print]
// method.
//
// dartMainRunner(main, args):
// if this function is defined, the Dart [main] method will not be invoked
// directly. Instead, a closure that will invoke [main], and its arguments
// [args] is passed to [dartMainRunner].
(function($) {
function dart(){ this.x = 0 }var A = new dart;
delete A.x;
var B = new dart;
delete B.x;
var C = new dart;
delete C.x;
var D = new dart;
delete D.x;
var E = new dart;
delete E.x;
var F = new dart;
delete F.x;
var G = new dart;
delete G.x;
var H = new dart;
delete H.x;
var J = new dart;
delete J.x;
var K = new dart;
delete K.x;
var L = new dart;
delete L.x;
var M = new dart;
delete M.x;
var N = new dart;
delete N.x;
var O = new dart;
delete O.x;
var P = new dart;
delete P.x;
var Q = new dart;
delete Q.x;
var R = new dart;
delete R.x;
var S = new dart;
delete S.x;
var T = new dart;
delete T.x;
var U = new dart;
delete U.x;
var V = new dart;
delete V.x;
var W = new dart;
delete W.x;
var X = new dart;
delete X.x;
var Y = new dart;
delete Y.x;
var Z = new dart;
delete Z.x;
function Isolate() {}
init();
$ = Isolate.$isolateProperties;
var $$ = {};
(function (reflectionData) {
"use strict";
function map(x){x={x:x};delete x.x;return x}
function processStatics(descriptor) {
for (var property in descriptor) {
if (!hasOwnProperty.call(descriptor, property)) continue;
if (property === "^") continue;
var element = descriptor[property];
var firstChar = property.substring(0, 1);
var previousProperty;
if (firstChar === "+") {
mangledGlobalNames[previousProperty] = property.substring(1);
var flag = descriptor[property];
if (flag > 0) descriptor[previousProperty].$reflectable = flag;
if (element && element.length) init.typeInformation[previousProperty] = element;
} else if (firstChar === "#") {
property = property.substring(1);
$[property]["#"] = element;
} else if (firstChar === "*") {
globalObject[previousProperty].$defaultValues = element;
var optionalMethods = descriptor.$methodsWithOptionalArguments;
if (!optionalMethods) {
descriptor.$methodsWithOptionalArguments = optionalMethods = {}
}
optionalMethods[property] = previousProperty;
} else if (typeof element === "function") {
globalObject[previousProperty = property] = element;
functions.push(property);
init.globalFunctions[property] = element;
} else if (element.constructor === Array) {
addStubs(globalObject, element, property, true, descriptor, functions);
} else {
previousProperty = property;
var newDesc = {};
var previousProp;
for (var prop in element) {
if (!hasOwnProperty.call(element, prop)) continue;
firstChar = prop.substring(0, 1);
if (prop === "static") {
processStatics(init.statics[property] = element[prop]);
} else if (firstChar === "+") {
mangledNames[previousProp] = prop.substring(1);
var flag = element[prop];
if (flag > 0) element[previousProp].$reflectable = flag;
} else if (firstChar === "#" && prop !== "#") {
newDesc[prop.substring(1)]["#"] = element[prop];
} else if (firstChar === "*") {
newDesc[previousProp].$defaultValues = element[prop];
var optionalMethods = newDesc.$methodsWithOptionalArguments;
if (!optionalMethods) {
newDesc.$methodsWithOptionalArguments = optionalMethods={}
}
optionalMethods[prop] = previousProp;
} else {
var elem = element[prop];
if (prop !== "^" && elem != null && elem.constructor === Array && prop !== "<>") {
addStubs(newDesc, elem, prop, false, element, []);
} else {
newDesc[previousProp = prop] = elem;
}
}
}
$$[property] = [globalObject, newDesc];
classes.push(property);
}
}
}
function addStubs(descriptor, array, name, isStatic, originalDescriptor, functions) {
var f, funcs = [originalDescriptor[name] = descriptor[name] = f = array[0]];
f.$stubName = name;
functions.push(name);
for (var index = 0; index < array.length; index += 2) {
f = array[index + 1];
if (typeof f != "function") break;
f.$stubName = array[index + 2];
funcs.push(f);
if (f.$stubName) {
originalDescriptor[f.$stubName] = descriptor[f.$stubName] = f;
functions.push(f.$stubName);
}
}
for (var i = 0; i < funcs.length; index++, i++) {
funcs[i].$callName = array[index + 1];
}
var getterStubName = array[++index];
array = array.slice(++index);
var requiredParameterInfo = array[0];
var requiredParameterCount = requiredParameterInfo >> 1;
var isAccessor = (requiredParameterInfo & 1) === 1;
var isSetter = requiredParameterInfo === 3;
var isGetter = requiredParameterInfo === 1;
var optionalParameterInfo = array[1];
var optionalParameterCount = optionalParameterInfo >> 1;
var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1;
var isIntercepted = requiredParameterCount + optionalParameterCount != funcs[0].length;
var functionTypeIndex = array[2];
var unmangledNameIndex = 2 * optionalParameterCount + requiredParameterCount + 3;
var isReflectable = array.length > unmangledNameIndex;
if (getterStubName) {
f = tearOff(funcs, array, isStatic, name, isIntercepted);
f.getterStub = true;
if (isStatic) init.globalFunctions[name] = f;
originalDescriptor[getterStubName] = descriptor[getterStubName] = f;
funcs.push(f);
if (getterStubName) functions.push(getterStubName);
f.$stubName = getterStubName;
f.$callName = null;
if (isIntercepted) init.interceptedNames[getterStubName] = true;
}
if (isReflectable) {
for (var i = 0; i < funcs.length; i++) {
funcs[i].$reflectable = 1;
funcs[i].$reflectionInfo = array;
}
var mangledNames = isStatic ? init.mangledGlobalNames : init.mangledNames;
var unmangledName = array[unmangledNameIndex];
var reflectionName = unmangledName;
if (getterStubName) mangledNames[getterStubName] = reflectionName;
if (isSetter) {
reflectionName += "=";
} else if (!isGetter) {
reflectionName += ":" + requiredParameterCount + ":" + optionalParameterCount;
}
mangledNames[name] = reflectionName;
funcs[0].$reflectionName = reflectionName;
funcs[0].$metadataIndex = unmangledNameIndex + 1;
if (optionalParameterCount) descriptor[unmangledName + "*"] = funcs[0];
}
}
function tearOffGetterNoCsp(funcs, reflectionInfo, name, isIntercepted) {
return isIntercepted
? new Function("funcs", "reflectionInfo", "name", "H", "c",
"return function tearOff_" + name + (functionCounter++)+ "(x) {" +
"if (c === null) c = H.closureFromTearOff(" +
"this, funcs, reflectionInfo, false, [x], name);" +
"return new c(this, funcs[0], x, name);" +
"}")(funcs, reflectionInfo, name, H, null)
: new Function("funcs", "reflectionInfo", "name", "H", "c",
"return function tearOff_" + name + (functionCounter++)+ "() {" +
"if (c === null) c = H.closureFromTearOff(" +
"this, funcs, reflectionInfo, false, [], name);" +
"return new c(this, funcs[0], null, name);" +
"}")(funcs, reflectionInfo, name, H, null)
}
function tearOffGetterCsp(funcs, reflectionInfo, name, isIntercepted) {
var cache = null;
return isIntercepted
? function(x) {
if (cache === null) cache = H.closureFromTearOff(this, funcs, reflectionInfo, false, [x], name);
return new cache(this, funcs[0], x, name)
}
: function() {
if (cache === null) cache = H.closureFromTearOff(this, funcs, reflectionInfo, false, [], name);
return new cache(this, funcs[0], null, name)
}
}
function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) {
var cache;
return isStatic
? function() {
if (cache === void 0) cache = H.closureFromTearOff(this, funcs, reflectionInfo, true, [], name).prototype;
return cache;
}
: tearOffGetter(funcs, reflectionInfo, name, isIntercepted);
}
var functionCounter = 0;
var tearOffGetter = (typeof dart_precompiled == "function")
? tearOffGetterCsp : tearOffGetterNoCsp;
if (!init.libraries) init.libraries = [];
if (!init.mangledNames) init.mangledNames = map();
if (!init.mangledGlobalNames) init.mangledGlobalNames = map();
if (!init.statics) init.statics = map();
if (!init.typeInformation) init.typeInformation = map();
if (!init.globalFunctions) init.globalFunctions = map();
if (!init.interceptedNames) init.interceptedNames = map();
var libraries = init.libraries;
var mangledNames = init.mangledNames;
var mangledGlobalNames = init.mangledGlobalNames;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var length = reflectionData.length;
for (var i = 0; i < length; i++) {
var data = reflectionData[i];
var name = data[0];
var uri = data[1];
var metadata = data[2];
var globalObject = data[3];
var descriptor = data[4];
var isRoot = !!data[5];
var fields = descriptor && descriptor["^"];
var classes = [];
var functions = [];
processStatics(descriptor);
libraries.push([name, uri, classes, functions, metadata, fields, isRoot,
globalObject]);
}
})
([
["Repo", "repo.dart", , F, {
"^": "",
main: function() {
return C.Type_Jeh;
}
},
1],
["_js_helper", "dart:_js_helper", , H, {
"^": "",
createRuntimeType: function($name) {
return new H.TypeImpl($name, null);
},
TypeImpl: {
"^": "Object;_typeName,_unmangledName"
}
}],
["dart.core", "dart:core", , P, {
"^": "",
Null: {
"^": "Object;"
},
Object: {
"^": ";"
}
}],
]);
Isolate.$finishClasses($$, $, null);
$$ = null;
// Runtime type support
// getInterceptor methods
C.Type_Jeh = H.createRuntimeType('Repo');
$.libraries_to_load = {};
$.Closure_functionCounter = 0;
$.BoundClosure_selfFieldNameCache = null;
$.BoundClosure_receiverFieldNameCache = null;
init.functionAliases = {};
;
init.metadata = [];
$ = null;
Isolate = Isolate.$finishIsolateConstructor(Isolate);
$ = new Isolate();
function convertToFastObject(properties) {
function MyClass() {};
MyClass.prototype = properties;
new MyClass();
return properties;
}
A = convertToFastObject(A);
B = convertToFastObject(B);
C = convertToFastObject(C);
D = convertToFastObject(D);
E = convertToFastObject(E);
F = convertToFastObject(F);
G = convertToFastObject(G);
H = convertToFastObject(H);
J = convertToFastObject(J);
K = convertToFastObject(K);
L = convertToFastObject(L);
M = convertToFastObject(M);
N = convertToFastObject(N);
O = convertToFastObject(O);
P = convertToFastObject(P);
Q = convertToFastObject(Q);
R = convertToFastObject(R);
S = convertToFastObject(S);
T = convertToFastObject(T);
U = convertToFastObject(U);
V = convertToFastObject(V);
W = convertToFastObject(W);
X = convertToFastObject(X);
Y = convertToFastObject(Y);
Z = convertToFastObject(Z);
// BEGIN invoke [main].
;(function (callback) {
if (typeof document === "undefined") {
callback(null);
return;
}
if (document.currentScript) {
callback(document.currentScript);
return;
}
var scripts = document.scripts;
function onLoad(event) {
for (var i = 0; i < scripts.length; ++i) {
scripts[i].removeEventListener("load", onLoad, false);
}
callback(event.target);
}
for (var i = 0; i < scripts.length; ++i) {
scripts[i].addEventListener("load", onLoad, false);
}
})(function(currentScript) {
init.currentScript = currentScript;
if (typeof dartMainRunner === "function") {
dartMainRunner(F.main, []);
} else {
F.main([]);
}
});
// END invoke [main].
function init() {
Isolate.$isolateProperties = {};
function generateAccessor(fieldDescriptor, accessors, cls) {
var fieldInformation = fieldDescriptor.split("-");
var field = fieldInformation[0];
var len = field.length;
var code = field.charCodeAt(len - 1);
var reflectable;
if (fieldInformation.length > 1)
reflectable = true;
else
reflectable = false;
code = code >= 60 && code <= 64 ? code - 59 : code >= 123 && code <= 126 ? code - 117 : code >= 37 && code <= 43 ? code - 27 : 0;
if (code) {
var getterCode = code & 3;
var setterCode = code >> 2;
var accessorName = field = field.substring(0, len - 1);
var divider = field.indexOf(":");
if (divider > 0) {
accessorName = field.substring(0, divider);
field = field.substring(divider + 1);
}
if (getterCode) {
var args = getterCode & 2 ? "receiver" : "";
var receiver = getterCode & 1 ? "this" : "receiver";
var body = "return " + receiver + "." + field;
var property = cls + ".prototype.get$" + accessorName + "=";
var fn = "function(" + args + "){" + body + "}";
if (reflectable)
accessors.push(property + "$reflectable(" + fn + ");\n");
else
accessors.push(property + fn + ";\n");
}
if (setterCode) {
var args = setterCode & 2 ? "receiver, value" : "value";
var receiver = setterCode & 1 ? "this" : "receiver";
var body = receiver + "." + field + " = value";
var property = cls + ".prototype.set$" + accessorName + "=";
var fn = "function(" + args + "){" + body + "}";
if (reflectable)
accessors.push(property + "$reflectable(" + fn + ");\n");
else
accessors.push(property + fn + ";\n");
}
}
return field;
}
Isolate.$isolateProperties.$generateAccessor = generateAccessor;
function defineClass(name, cls, fields) {
var accessors = [];
var str = "function " + cls + "(";
var body = "";
for (var i = 0; i < fields.length; i++) {
if (i != 0)
str += ", ";
var field = generateAccessor(fields[i], accessors, cls);
var parameter = "parameter_" + field;
str += parameter;
body += "this." + field + " = " + parameter + ";\n";
}
str += ") {\n" + body + "}\n";
str += cls + ".builtin$cls=\"" + name + "\";\n";
str += "$desc=$collectedClasses." + cls + ";\n";
str += "if($desc instanceof Array) $desc = $desc[1];\n";
str += cls + ".prototype = $desc;\n";
if (typeof defineClass.name != "string") {
str += cls + ".name=\"" + cls + "\";\n";
}
str += accessors.join("");
return str;
}
var inheritFrom = function() {
function tmp() {
}
var hasOwnProperty = Object.prototype.hasOwnProperty;
return function(constructor, superConstructor) {
tmp.prototype = superConstructor.prototype;
var object = new tmp();
var properties = constructor.prototype;
for (var member in properties)
if (hasOwnProperty.call(properties, member))
object[member] = properties[member];
object.constructor = constructor;
constructor.prototype = object;
return object;
};
}();
Isolate.$finishClasses = function(collectedClasses, isolateProperties, existingIsolateProperties) {
var pendingClasses = {};
if (!init.allClasses)
init.allClasses = {};
var allClasses = init.allClasses;
var hasOwnProperty = Object.prototype.hasOwnProperty;
if (typeof dart_precompiled == "function") {
var constructors = dart_precompiled(collectedClasses);
} else {
var combinedConstructorFunction = "function $reflectable(fn){fn.$reflectable=1;return fn};\n" + "var $desc;\n";
var constructorsList = [];
}
for (var cls in collectedClasses) {
if (hasOwnProperty.call(collectedClasses, cls)) {
var desc = collectedClasses[cls];
if (desc instanceof Array)
desc = desc[1];
var classData = desc["^"], supr, name = cls, fields = classData;
if (typeof classData == "string") {
var split = classData.split("/");
if (split.length == 2) {
name = split[0];
fields = split[1];
}
}
var s = fields.split(";");
fields = s[1] == "" ? [] : s[1].split(",");
supr = s[0];
split = supr.split(":");
if (split.length == 2) {
supr = split[0];
var functionSignature = split[1];
if (functionSignature)
desc.$signature = function(s) {
return function() {
return init.metadata[s];
};
}(functionSignature);
}
if (typeof dart_precompiled != "function") {
combinedConstructorFunction += defineClass(name, cls, fields);
constructorsList.push(cls);
}
if (supr)
pendingClasses[cls] = supr;
}
}
if (typeof dart_precompiled != "function") {
combinedConstructorFunction += "return [\n " + constructorsList.join(",\n ") + "\n]";
var constructors = new Function("$collectedClasses", combinedConstructorFunction)(collectedClasses);
combinedConstructorFunction = null;
}
for (var i = 0; i < constructors.length; i++) {
var constructor = constructors[i];
var cls = constructor.name;
var desc = collectedClasses[cls];
var globalObject = isolateProperties;
if (desc instanceof Array) {
globalObject = desc[0] || isolateProperties;
desc = desc[1];
}
allClasses[cls] = constructor;
globalObject[cls] = constructor;
}
constructors = null;
var finishedClasses = {};
init.interceptorsByTag = Object.create(null);
init.leafTags = {};
function finishClass(cls) {
var hasOwnProperty = Object.prototype.hasOwnProperty;
if (hasOwnProperty.call(finishedClasses, cls))
return;
finishedClasses[cls] = true;
var superclass = pendingClasses[cls];
if (!superclass || typeof superclass != "string")
return;
finishClass(superclass);
var constructor = allClasses[cls];
var superConstructor = allClasses[superclass];
if (!superConstructor)
superConstructor = existingIsolateProperties[superclass];
var prototype = inheritFrom(constructor, superConstructor);
}
for (var cls in pendingClasses)
finishClass(cls);
};
Isolate.$lazy = function(prototype, staticName, fieldName, getterName, lazyValue) {
var sentinelUndefined = {};
var sentinelInProgress = {};
prototype[fieldName] = sentinelUndefined;
prototype[getterName] = function() {
var result = $[fieldName];
try {
if (result === sentinelUndefined) {
$[fieldName] = sentinelInProgress;
try {
result = $[fieldName] = lazyValue();
} finally {
if (result === sentinelUndefined) {
if ($[fieldName] === sentinelInProgress) {
$[fieldName] = null;
}
}
}
} else {
if (result === sentinelInProgress)
H.throwCyclicInit(staticName);
}
return result;
} finally {
$[getterName] = function() {
return this[fieldName];
};
}
};
};
Isolate.$finishIsolateConstructor = function(oldIsolate) {
var isolateProperties = oldIsolate.$isolateProperties;
function Isolate() {
var hasOwnProperty = Object.prototype.hasOwnProperty;
for (var staticName in isolateProperties)
if (hasOwnProperty.call(isolateProperties, staticName))
this[staticName] = isolateProperties[staticName];
function ForceEfficientMap() {
}
ForceEfficientMap.prototype = this;
new ForceEfficientMap();
}
Isolate.prototype = oldIsolate.prototype;
Isolate.prototype.constructor = Isolate;
Isolate.$isolateProperties = isolateProperties;
Isolate.$finishClasses = oldIsolate.$finishClasses;
return Isolate;
};
}
})()
//# sourceMappingURL=out.js.map
//# sourceMappingURL=out.js.map
And that's it, I've thrown away Dart because I didn't knew what to do with generated JS file, also I was frightened of potentially high amount of time required for keeping the resulting library interface clean and similar to one I'm using with JavaScript.
The question(s)
How do I expose class definitions created in Dart and later use them in JavaScript?
Do you think it's worth it going into Dart when nearly all potential library users will be using JS version instead? (Using dart is already not good for me due to difference in community sizes, this means that less people will find it easy to contribute to my library)
In your opinion, what should I do?
Even though Dart supports this use case, if you target JavaScript developers I would stick with JavaScript.
#AlexandreArdhuin shows in his answer to Expose Dart functions to javascript how you can make a Dart function available to JavaScript.
Under the dart-js-interop are many examples how to do function calls and pass data between Dart and JavaScript.
Wrap dart class into custom element, the Dart object auto expose to javascript.
Assume we have 2 Dart Classes, SlickGrid Class contains Column class in Dart
class SlickGrid{
List<Column> columns;
}
class Column{}
class GridWrap extends HtmlElement {
ShadowRoot shadowRoot;
SlickGrid grid; // here is your cool object
}
compile to javascript, and register custom element, then open javascript console,
//this is SlickGrid object
var grid= document.querySelector('cj-grid').grid;
// this is dart Column Object
var column = grid.columns.$index(0,0);
// call toString function in dart object that produce json string...
column.toString$0()

Silverlight 3 File Dialog Box

Ok - I have a WCF Service which reads an excel file from a certain location and strips the data into an object. What I need is the ability to allow users of my program to Upload an excel sheet to the file location that my Service uses.
Alternitivley I could pass the Uploaded excel sheet to the service directly.
Can anyone help with this. My service code is:
public List<ImportFile> ImportExcelData(string FileName)
{
//string dataSource = Location + FileName;
string dataSource = Location;
string conStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + dataSource.ToString() + ";Extended Properties=Excel 8.0;";
var con = new OleDbConnection(conStr);
con.Open();
var data = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
var sheetName = data.Rows[0]["TABLE_NAME"].ToString();
OleDbCommand cmd = new OleDbCommand("SELECT * FROM [" + sheetName + "] WHERE Status = '4'", con);
OleDbDataAdapter oleda = new OleDbDataAdapter();
oleda.SelectCommand = cmd;
DataSet ds = new DataSet();
oleda.Fill(ds, "Employees");
DataTable dt = ds.Tables[0];
var _impFiles = new List<ImportFile>();
foreach (DataRow row in dt.Rows)
{
var _import = new ImportFile();
_import.PurchaseOrder = row[4].ToString();
try
{
var ord = row[8].ToString();
DateTime dati = Convert.ToDateTime(ord);
_import.ShipDate = dati;
}
catch (Exception)
{
_import.ShipDate = null;
}
ImportFile additionalData = new ImportFile();
additionalData = GetAdditionalData(_import.PurchaseOrder);
_import.NavOrderNo = additionalData.NavOrderNo;
_import.IsInstall = additionalData.IsInstall;
_import.SalesOrderId = additionalData.SalesOrderId;
_import.ActivityID = additionalData.ActivityID;
_import.Subject = additionalData.Subject ;
_import.IsMatched = (_import.ShipDate != null & _import.NavOrderNo != "" & _import.NavOrderNo != null & _import.ShipDate > DateTime.Parse("01/01/1999") ? true : false);
_import.UpdatedShipToField = false;
_import.UpdatedShipToFieldFailed = false;
_import.CreateNote = false;
_import.CreateNoteFailed = false;
_import.CompleteTask = false;
_import.CompleteTaskFailed = false;
_import.FullyCompleted = 0;
_import.NotCompleted = false;
_impFiles.Add(_import);
}
oleda.Dispose();
con.Close();
//File.Delete(dataSource);
return _impFiles;
}
You will want to modify your service to accept a Stream instead of a filename, then you can save if off to a file (or parse it directly from the Stream, although I don't know how to do that).
Then in your Silverlight app you could do something like this:
private void Button_Click(object sender, RoutedEventArgs ev)
{
var dialog = new OpenFileDialog();
dialog.Filter = "Excel Files (*.xls;*.xlsx;*.xlsm)|*.xls;*.xlsx;*.xlsm|All Files (*.*)|*.*";
if (dialog.ShowDialog() == true)
{
var fileStream = dialog.File.OpenRead();
var proxy = new WcfService();
proxy.ImportExcelDataCompleted += (s, e) =>
{
MessageBox.Show("Import Data is at e.Result");
// don't forget to close the stream
fileStream.Close();
};
proxy.ImportExcelDataAsync(fileStream);
}
}
You could also have your WCF service accept a byte[] and do something like this.
private void Button_Click(object sender, RoutedEventArgs ev)
{
var dialog = new OpenFileDialog();
dialog.Filter = "Excel Files (*.xls;*.xlsx;*.xlsm)|*.xls;*.xlsx;*.xlsm|All Files (*.*)|*.*";
if (dialog.ShowDialog() == true)
{
var length = dialog.File.Length;
var fileContents = new byte[length];
using (var fileStream = dialog.File.OpenRead())
{
if (length > Int32.MaxValue)
{
throw new Exception("Are you sure you want to load > 2GB into memory. There may be better options");
}
fileStream.Read(fileContents, 0, (int)length);
}
var proxy = new WcfService();
proxy.ImportExcelDataCompleted += (s, e) =>
{
MessageBox.Show("Import Data is at e.Result");
// no need to close any streams this way
};
proxy.ImportExcelDataAsync(fileContents);
}
}
Update
Your service could look like this:
public List<ImportFile> ImportExcelData(Stream uploadedFile)
{
var tempFile = HttpContext.Current.Server.MapPath("~/uploadedFiles/" + Path.GetRandomFileName());
try
{
using (var tempStream = File.OpenWrite(tempFile))
{
uploadedFile.CopyTo(tempStream);
}
//string dataSource = Location + FileName;
string dataSource = tempFile;
string conStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + dataSource.ToString() +
";Extended Properties=Excel 8.0;";
var con = new OleDbConnection(conStr);
con.Open();
}
finally
{
if (File.Exists(tempFile))
File.Delete(tempFile);
}
}
Thanks Bendewey that was great. Had to amend it slightly -
My Service:
var tempFile = #"c:\temp\" + Path.GetRandomFileName();
try
{
int length = 256;
int bytesRead = 0;
Byte[] buffer = new Byte[length];
// write the required bytes
using (FileStream fs = new FileStream(tempFile, FileMode.Create))
{
do
{
bytesRead = uploadedFile.Read(buffer, 0, length);
fs.Write(buffer, 0, bytesRead);
}
while (bytesRead == length);
}
uploadedFile.Dispose();
string conStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + dataSource.ToString() + ";Extended Properties=Excel 8.0;";
var con = new OleDbConnection(conStr);
Thanks Again for your help

Adobe Air how to check if URL is online\gives any response exists?

I have url I want to check if it is live. I want to get bool value. How to do such thing?
You can use an URLLoader and listen for the events to check if it loads, and if not what might be the problem. Would be handy to use the AIRMonitor first to make sure the client's computer is online in the first place.
Here is a class I started to write to illustrate the idea:
package
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.HTTPStatusEvent;
import flash.events.IEventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
/**
* ...
* #author George Profenza
*/
public class URLChecker extends EventDispatcher
{
private var _url:String;
private var _request:URLRequest;
private var _loader:URLLoader;
private var _isLive:Boolean;
private var _liveStatuses:Array;
private var _completeEvent:Event;
private var _dispatched:Boolean;
private var _log:String = '';
public function URLChecker(target:IEventDispatcher = null)
{
super(target);
init();
}
private function init():void
{
_loader = new URLLoader();
_loader.addEventListener(Event.COMPLETE, _completeHandler);
_loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, _httpStatusHandler);
_loader.addEventListener(IOErrorEvent.IO_ERROR, _ioErrorEventHandler);
_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _securityErrorHandler);
_completeEvent = new Event(Event.COMPLETE, false, true);
_liveStatuses = [];//add other acceptable http statuses here
}
public function check(url:String = 'http://stackoverflow.com'):void {
_dispatched = false;
_url = url;
_request = new URLRequest(url);
_loader.load(_request);
_log += 'load for ' + _url + ' started : ' + new Date() + '\n';
}
private function _completeHandler(e:Event):void
{
_log += e.toString() + ' at ' + new Date();
_isLive = true;
if (!_dispatched) {
dispatchEvent(_completeEvent);
_dispatched = true;
}
}
private function _httpStatusHandler(e:HTTPStatusEvent):void
{
/* comment this in when you're sure what statuses you're after
var statusesLen:int = _liveStatuses.length;
for (var i:int = statusesLen; i > 0; i--) {
if (e.status == _liveStatuses[i]) {
_isLive = true;
dispatchEvent(_completeEvent);
}
}
*/
//200 range
_log += e.toString() + ' at ' + new Date();
if (e.status >= 200 && e.status < 300) _isLive = true;
else _isLive = false;
if (!_dispatched) {
dispatchEvent(_completeEvent);
_dispatched = true;
}
}
private function _ioErrorEventHandler(e:IOErrorEvent):void
{
_log += e.toString() + ' at ' + new Date();
_isLive = false;
if (!_dispatched) {
dispatchEvent(_completeEvent);
_dispatched = true;
}
}
private function _securityErrorHandler(e:SecurityErrorEvent):void
{
_log += e.toString() + ' at ' + new Date();
_isLive = false;
if (!_dispatched) {
dispatchEvent(_completeEvent);
_dispatched = true;
}
}
public function get isLive():Boolean { return _isLive; }
public function get log():String { return _log; }
}
}
and here's a basic usage example:
var urlChecker:URLChecker = new URLChecker();
urlChecker.addEventListener(Event.COMPLETE, urlChecked);
urlChecker.check('wrong_place.url');
function urlChecked(event:Event):void {
trace('is Live: ' + event.target.isLive);
trace('log: ' + event.target.log);
}
The idea is simple:
1. You create a checked
2. Listen for the COMPLETE event(triggered when it has a result
3. In the handler check if it's live and what it logged.
In the HTTP specs, 200 area seems ok, but depending on what you load, you might need
to adjust the class. Also you need to handle security/cross domain issue better, but at least it's a start.
HTH
An important consideration that George's answer left out is the URLRequestMethod. If one were trying to verify the existence of rather large files (e.g, media files) and not just a webpage, you'd want to make sure to set the method property on the URLRequest to URLRequestMethod.HEAD.
As stated in the HTTP1.1 Protocol:
The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response.
Hence, if you really only want to verify the existence of the URL, this is the way to go.
For those who need the code spelled out:
var _request:URLRequest = URLRequest(url);
_request.method = URLRequestMethod.HEAD; // bandwidth :)
Otherwise, George's answer is a good reference point.
NB: This particular URLRequestMethod is only available in AIR.

An observer for page loads in a custom xul:browser

In my firefox extension I'm creating a xul:browser element. I want to have an observer that intercepts any url changes within the embedded browser and opens the url in a new browser tab (in the main browser). I'd also like new windows spawned by the xul:browser window to open in a tab instead of a new browser window.
I've created an observer which works, but I don't yet know how to apply that observer only to the xul:browser element.
function myFunction(){
var container = jQuery("#container")[0];
var new_browser_element = document.createElement('browser');
container.appendChild(new_browser_element);
var observerService = Components.classes["#mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
observerService.addObserver(myObserver, "http-on-modify-request", false);
}
var myObserver = {
observe: function(aSubject, aTopic, aData){
if (aTopic != 'http-on-modify-request'){
aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
// alert(aSubject.URI.spec);
// Now open url in new tab
}
},
QueryInterface: function(iid){
if (!iid.equals(Components.interfaces.nsISupports) &&
!iid.equals(Components.interfaces.nsIObserver))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
}
};
You could try:
var myObserver = {
observe: function(aSubject, aTopic, aData){
if (aTopic == 'http-on-modify-request')
{
aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
var url = aSubject.URI.spec;
var postData ;
if (aSubject.requestMethod.toLowerCase() == "post")
{
var postText = this.readPostTextFromRequest(request);
if (postText)
{
var dataString = parseQuery(postText);
postData = postDataFromString(dataString);
}
}
var oHttp = aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
var interfaceRequestor = oHttp.notificationCallbacks.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
var DOMWindow = interfaceRequestor.getInterface(Components.interfaces.nsIDOMWindow);
//check if it is one of your mini browser windows
if (jQuery(DOMWindow).hasClass('mini_browser'))
{
openInTab(url, postData);
var request = aSubject.QueryInterface(Components.interfaces.nsIRequest);
request.cancel(Components.results.NS_BINDING_ABORTED);
}
}
},
QueryInterface: function(iid){
if (!iid.equals(Components.interfaces.nsISupports) &&
!iid.equals(Components.interfaces.nsIObserver))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
},
readPostTextFromRequest : function(request) {
var is = request.QueryInterface(Components.interfaces.nsIUploadChannel).uploadStream;
if (is)
{
var ss = is.QueryInterface(Components.interfaces.nsISeekableStream);
var prevOffset;
if (ss)
{
prevOffset = ss.tell();
ss.seek(Components.interfaces.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(Components.interfaces.nsISeekableStream.NS_SEEK_SET, 0);
return text;
}
else {
dump("Failed to Query Interface for upload stream.\n");
}
}
return null;
},
readFromStream : function(stream, charset, noClose)
{
var sis = Components.classes["#mozilla.org/binaryinputstream;1"]
.getService(Components.interfaces.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;
}
};
function openInTab(url, postData)
{
var wm = Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var recentWindow = wm.getMostRecentWindow("navigator:browser");
if (recentWindow)
{
// Use an existing browser window, open tab and "select" it
recentWindow.gBrowser.selectedTab = recentWindow.gBrowser.addTab(url, null, null, postData);
}
}
function parseQuery() {
var qry = this;
var rex = /[?&]?([^=]+)(?:=([^&#]*))?/g;
var qmatch, key;
var paramValues = {};
// parse querystring storing key/values in the ParamValues associative array
while (qmatch = rex.exec(qry)) {
key = decodeURIComponent(qmatch[1]);// get decoded key
val = decodeURIComponent(qmatch[2]);// get decoded value
paramValues[key] = val;
}
return paramValues;
}
function postDataFromString(dataString)
{
// POST method requests must wrap the encoded text in a MIME
// stream
var stringStream = Components.classes["#mozilla.org/io/string-input-stream;1"]
.createInstance(Components.interfaces.nsIStringInputStream);
if ("data" in stringStream) // Gecko 1.9 or newer
stringStream.data = dataString;
else // 1.8 or older
stringStream.setData(dataString, dataString.length);
var postData = Components.classes["#mozilla.org/network/mime-input-stream;1"].
createInstance(Components.interfaces.nsIMIMEInputStream);
postData.addHeader("Content-Type", "application/x-www-form-urlencoded");
postData.addContentLength = true;
postData.setData(stringStream);
return postData;
}
I'll update this to fill in the blanks in a bit.
edit: see http://forums.mozillazine.org/viewtopic.php?p=2772951#p2772951 for how to get the source window of a request.
Request cancellation code from http://zenit.senecac.on.ca/wiki/index.php/Support_For_OpenID.
see http://mxr.mozilla.org/mozilla-central/source/netwerk/base/public/nsIRequest.idl for details on nsIRequest.
See http://forums.mozillazine.org/viewtopic.php?p=2404533#p2404533 and https://developer.mozilla.org/en/XUL/Method/addTab for the definition of addTab.
parseQuery comes from http://blog.strictly-software.com/2008/10/using-javascript-to-parse-querystring.html.
See https://developer.mozilla.org/en/Code_snippets/Post_data_to_window#Preprocessing_POST_data for how to process post data in a form suitable for addTab.
ReadPostFromText and ReadTextFromStream both come from firebug (though slightly modified)

Resources