How can Java and JavaScript work together? - javascript

I'll preface this by stating that I know Java is not JavaScript and vice versa.
I've got a project where I need to count occurrences of words for each of 1750 document names and document contents. I've got some awesome JavaScript from a colleague that does exactly what I want from a form input on a web page.
I want to use Java's FileReader, BufferedReader, walkFileTree, etc. to traverse the directories in which the documents live.
I'm not sure if this is the most efficient or effective approach, but both the Java and JavaScript parts of the code are working independently of one another now, and I'd like to see if I can get them to pass data between them before I start re-inventing the wheel.
Here's where I am so far. I'm stuck at the CLParse method & have inserted pseudocode:
public static void main(String... aArgs) throws FileNotFoundException {
File startingDirectory= new File("CGT");
List<File> files = FileListing.getFileListingNoSort(startingDirectory);
for(File file : files ) {
CLParse(file.toString());
} }
static private List<File> getFileListingNoSort(File aDirectory) throws FileNotFoundException {
List<File> result = new ArrayList<File>();
File[] filesAndDirs = aDirectory.listFiles();
List<File> filesDirs = Arrays.asList(filesAndDirs);
for(File file : filesDirs) {
result.add(file); //always add, even if directory
if ( ! file.isFile() ) {
List<File> deeperList = getFileListingNoSort(file);
result.addAll(deeperList);
} }
return result;
}
/* is something like this doable and how would I do it?
*/
public static void CLParse(String fn) {
pass fn to JavaScript counter
return an array of {word,occurences} for the string
write array to file
}
I'll be creating another set of methods to extract and pass the document CONTENTS as a string as well. I'd love to know if anyone has any practical experience passing values back and forth between Java and JavaScript, and advice on a good/better way to do it.

You got 2 Options to let them interact with each other, which i know:
1.Applet <-> javascript
2.Serlvet <-> javascript
With option 1, you have to build a Communication with a JSObject: JSObject
or you cann call the Applets Method instanstly with document.appletname.methodname();
with this you can even Parse same simply Formats to each other.
With Option 2 you have to build a communication with a Servlet.
in here you have to send an Ajax request to the the Servlet:
$.post('login',{name:"Peter", pw:"123456"},function()
{
//do whatever
})
JavaServlet class
the first comment, has to written as an Servlet in your web.xml, it´s the servlet pattern.
the second ones, are the parameters which can be read in the servlet. the function describes the stuff, which can be done in the request.
The differences between these two Options are:
1.the Applets runs on the users Computer, so you can access his files. But for this your applet has to be signed.
2.the Servlet runs on the Server. Here you have got full file access(if the system allows you too have it).

I would try to investigate Mozilla Rhino.
http://en.wikipedia.org/wiki/Rhino_%28JavaScript_engine%29

Check out Rhino https://developer.mozilla.org/en-US/docs/Rhino
You can create java objects and use them in javascript. Integration is straightforward

You can use AJAX to send and receive values to server. You can send parameters or JSON to server and get response.
You can use JSONP to serve the data, or if you have no control of the second server, use a reverse proxy to proxy requests to the second server through the first.

Related

How to avoid single route in Laravel for Server Sent Events

So I am trying to use Server Sent Events in my laravel app but the problem is that in SSE, you can only specify single URL as in:
var evtSource = new EventSource("sse.php");
The problem is that I want to send events from different parts/controllers of the entire application not just single sse.php file for example. Example:
// AuthController.php
public function postLogin(Request $request) {
// login logic
// SEND SSE EVENT ABOUT NEW USER LOGIN
}
// FooController.php
public function sendMessage() {
// SEND SSE EVENT ABOUT NEW MESSAGE
}
The only idea that comes to my mind is that from these controllers, create temporary files with event text and then read those text files in sse.php file, send events and then delete files. However, this doesn't look like perfect solution. Or maybe hook sse.php file with Laravel events mechanism somehow but that seems kinda advanced.
I also don't mind creating multiple event source objects with different php files like sse.php but problem is that those controllers methods don't necessarily just send events alone, they do other work as well. For example, I cannot use postLogin action directly in SSE object because it also performs the login logic not just sending event.
Has anyone had similar problem and how to tackle with it please ?
Never used SSE but, according to their docs, two solutions come to my mind:
1.Define multiple EventSource objects and handle them differently in your js:
var loginSource = new EventSource("{!! url("/loginsse") !!}");
var messageSource = new EventSource("{!! url("/messagesse") !!}");
2. Inside your sse.php file, check for updates from the others controller:
//sse.php called function
while(1) {
$login = AuthController::postLogin($request);
if ($login) return $login;
$msg = FooController::sendMessage();
if ($msg) return $msg;
// ...
}
You will need to make sendMessage() and postLogin(Request $request) static methods.
Consider also the adoption of some libraries to use SSE with laravel: a quick google search provided me several possibilities.
You could use Laravel's events and create a listener that would combine all the different events from your app into a single stream, and then you'd have a single controller that would emit that stream of events to the client. You could generate an event anywhere in your code and it would be streamed to the client. You'd need some sort of shared FIFO buffer to allow the communication between the listener and controller, listener would write to it, and controller would read it and send SSE. The simplest solution would be to use just a plain log file for this.
Also Laravel has built-in broadcasting feature using Laravel Echo, so maybe that could help? I'm not sure if Echo is using SSE (have zero experience with both), but it does pretty much the same thing...
Updated: Let me try to add an example:
1) First we need to create an event and a listener, e.g.:
php artisan make:event SendSSE
php artisan make:listener SendSSEListener --event=SendSSE
2) Your event class is just a wrapper around the data that you wish to pass to the listener. Add to SendSSE class as many properties as you need, but lets pass just a string message for this example:
public function __construct($msg)
{
$this->message = $msg;
}
public function getMessage()
{
return $this->message;
}
3) Now you can fire this event like this:
event(new \App\Events\SendSSE('Hello there'));
4) Your listener's handle() method will receive it and then you need to push it into a FIFO buffer that you'll use to communicate with the SSE controller. This can be as simple as writing to a file, and then reading from it in your controller, or you can use a DB or linux fifo pipe or shared memory or whatever you wish. I'll leave that part to you and presume that you have a service for it:
public function handle(\App\Events\SendSSE $event)
{
// let's presume you have a helper method that will pass
// the message to the SSE Controller
FifoBufferService::write($event->getMessage());
}
5) Finally, in your SSE Controller you should read the fifo buffer and when a new message comes pass it to the client:
while(1) {
// if this read doesn't block, than you'll probably need to sleep()
if ($new_msg = FifoBufferService::read()) {
$this->sendSSE($new_msg);
}
}

Send String to Node.js

I'm trying create a simple UI here on my iOS app to test a thing or two out but I'm having some issues here. My app is set up with a UITextField and UIButton. I'm trying to replace a string on my .js file which is saved on my virtual server. In my .js file I have below:
// Prepare a new notification
var notification = new apn.Notification();
// Display the following message (the actual notification text, supports emoji)
notification.alert = 'Hi James';
I basically would like to replace "Hi James" with whatever I typed in the UITextField in my Swift 3 project but not too sure where to start. This would be my first time sending data to .js file so anything would help. I'm thinking so far that it'd be something along the lines to below. Node.js would be similar to Javascript since it's cross platform.
func sendSomething(stringToSend : String) {
appController?.evaluateInJavaScriptContext({ (context) -> Void in
//Get a reference to the "myJSFunction" method that you've implemented in JavaScript
let myJSFunction = evaluation.objectForKeyedSubscript("myJSFunction")
//Call your JavaScript method with an array of arguments
myJSFunction.callWithArguments([stringToSend]) }, completion: { (evaluated) -> Void in
print("we have completed: \(evaluated)")
})
}
Found that on a relevant StackOverflow post so I feel like I'm getting close. Any assistant would be appreciated in advanced. Have a good one!
I recommend using the Node HTTP or ExpressJS server reading the POST fields and posting a document from your iOS app with the desired field
See
https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/

Security risks when evaluating user input as JavaScript in Java

I want to give the user the possibility of writing symbolic maths formulas which are later evaluated with certain values.
The user might - for example - want to enter some formula a * (b + 1) where a and b may be different upon each evaluation. My approach so far was using the built in JavaScript engine in Java but as I read through this tutorial on scripting, I realized that the engine is actually really powerful.
The formulas are stored in configuration files, so someone might send such a configuration file to another user, which would then be executed on their machine.
Unfortunately I don't know JavaScript, so I don't know if the user could actually inject any seriously malicious code.
The formula above would be stored as a JavaScriptFormulaProcessor object like this:
JavaScriptFormulaProcessor processor =
new JavaScriptFormulaProcessor("a * (b + 1)", "a", "b");
Initializing the engine:
public JavaScriptFormulaProcessor(String formula, String... variableNames) throws ScriptException {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
StringBuilder builder = new StringBuilder(variableNames[0]);
for (int i = 1; i < variableNames.length; i++) {
builder.append(", ").append(variableNames[i]);
}
String script = "function f("+builder.toString()+") { return "+formula+"}";
engine.eval(script);
invocable = (Invocable) engine;
}
Executing the function:
public void execute(Number[] functionInputs) throws ScriptException {
try {
Object result = invocable.invokeFunction("f", functionInputs);
// process result..
} catch (NoSuchMethodException e) {
throw new RuntimeException(e); // should actually never be thrown..
}
}
Does this code create an attack vector for my application? Bonus question: if yes, any better suggestions?
If formula is under the users' control, then this code is extremely vulnerable because Java methods can be accessed and run from within the ScriptEngine.
See also this question: Why can you execute Java-Code from a JS-ScriptEngine eval(String)?
As an example, consider this formula:
String formula = "(java.lang.Runtime.getRuntime().exec('some-malicious-script'), a+b)";
Apart from calculating the sum, this script would run java.lang.Runtime.getRuntime().exec().
You can run any static Java method this way.
I would say that this code is not safe as you allow JavaScript to be evaluated by the engine.
What I would do:
Send the config file to a server, where the receiver gets the config file from. Write a parser server side that only accepts valid formulas and discards anything that isn't, then store it somewhere (database / file / whatever). Then send a 100% safe package that you made yourself after parsing to the receiver. This way you assure that whatever the receiver gets is firstly validated by you.
NOTE: If you do this, you need to write some sort of converter in javascript that converts your package to the javascript - formulas in order for it to be evaluated by the code that you present in your question. You could choose to only validate server side, and then just send the user-made package originally sent to the receiver, though you'd allow yourself to make a mistake in validating causing the receiver to still run unsafe code.

Returning a value from Javascript to C++

I have tried searching for answers but nothing seems to have worked thus far. I have a GUI application that I am building for WinAPI, and I want to use a Javascript function that will check on the Youtube API for certain videos and such, but I haven't been able to call on any of the functions in Javascript.
The farthest I've seemed to be able to get is to add an HTML file to the external dependencies(.rc), and then the Javasctipt file from there, but I can't seem to be able to just call on the function.
Is there a better way of doing this than trying to interop Javasctipt and C++, or am I just going about calling the function wrong?
/* Pseudocode */
Javascript.js
void callAPI()
{
... Call on the Youtube API, check if there are new videos i'd like...
return boolIfUpdatedOrNot;
}
Source.cpp
... Some includes and such ...
WindowProc and such
{
Case Something:
... Call on the Javascript function ...
... Do something if returned true ...
... or return 0 if false ...
}
Do you really need Javascript to get the videos? If you don't need to authenticate, there is a simple data API that will return up to 50 videos specified by certain parameters such as playlist ID or search term. You can get the results in JSON or XML by using a simple HTTP GET request. I'm not familiar with doing this in WINAPI, but you could probably start here: http://msdn.microsoft.com/en-us/library/aa384110(v=vs.85).aspx
A simple example that will get the 10 most recent uploads from a channel with CHANNEL_NAME:
https://gdata.youtube.com/feeds/api/users/CHANNEL_NAME/uploads?max-results=10
To get this in JSON:
https://gdata.youtube.com/feeds/api/users/CHANNEL_NAME/uploads?v=2&max-results=10&alt=jsonc
You have to use the second version of the API to get it in JSON (hence the v=2 parameter). XML will probably be easier to parse in native C++ though, depending on whether you want to work with another library.
For more: https://gdata.youtube.com/demo/index.html

Obfuscating URL parameters to prevent users from changing them?

I am developing a fat client page based on Javascript that will allow users to carry out tasks outwith another web client application (Oracle Siebel).
The way the web page will be called from the browser will be by a simple window.open() call.
When this happens a URL will be passed which contains some parameters at the end which will change the functionality of the fat client page depending on what value they have.
e.g
userlevel=1 //normal user
userlevel=2 //advanced user
In an example full URL would be like so
www.mypage.com/index.htm?id=25215125%userlevel=2%context=full
However a user who wants to change their access only need to figure out that if they change their user level then they can change their access rights on this fat client page.
Yes, I know this is risky and before you ask why I am not using a server supported thin client with controls that cannot be altered by the user. I simply have to do it this way!
This system will be in a "trusted" environment and this users will have at best average IT skills.
So all I need to do is figure out a way to obfuscate/ scramble the URL parameters (if possible) and then decipher them at the fat client.
e.g.
www.mypage.com/index.htm?1sdf908ga90-821098650f8asdg098g0a98
I tested it out on the browser and no complaints so far so I guess I just need to develop a piece of logic to decipher it.
e.g. I could use MD5?
Any examples or ideas?
Thanks
Try Base64 encoding it. https://stackoverflow.com/a/4699739/1088652
That'll shorten it and obfuscate it, so that users can't just throw values in the URL.
Params integrity can be ensured with HMAC. You generate hash using secret key and all the params, you include this hash inside of URL, then at server side you generate hash using same params and compare values.
function generateSignature(array $params, $hmacKey)
{
// sort the array by key using SORT_STRING order
ksort($params, SORT_STRING);
$escapeFunc = function ($val) {
return str_replace(':', '\\:', str_replace('\\', '\\\\', $val));
};
// generate the signing data string
$signData = implode(':', array_map($escapeFunc, array_merge(array_keys($params), array_values($params))));
// base64-encode the binary result of the HMAC computation
$merchantSig = base64_encode(hash_hmac('sha256', $signData, pack("H*", $hmacKey), true));
return $merchantSig;
}

Categories

Resources