How to use shell-script as a Chrome host application for native messages

How do you handle the Native Messaging API API with a bash script?

I managed to do this using python with in this example

Of course, I can call bash from python code using subprocess , but is it possible to skip python and process the message in bash directly?

the problematic part reads the serialized JSON message into a variable. The message is serialized using JSON, UTF-8 encoding and precedes the 32-bit message length in its own byte order via stdin.

echo $* only outputs: chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/

Also something like

 read echo $REPLY 

nothing output. No sign of a JSON message. For this, Python uses struct.unpack . Can this be done in bash ?

+6
source share
1 answer

I suggest not using (bash) shell scripts as your own messaging server, because bash is too limited to be useful.

read without any parameters reads an entire line before terminating, while its own messaging protocol indicates that the first four bytes determine the length of the next message (in native byte order).

Bash is a terrible binary data processing tool. An improved version of your read command will specify the -n N option to stop reading after N characters (note: not bytes) and -r to remove some processing. For instance. The following will store the first four characters in a variable named var_prefix :

 IFS= read -rn 4 var_prefix 

Even if you assume that this stores the first four bytes in a variable (it is not!), Then you need to convert the bytes to an integer. Did I mention that bash automatically discards all NUL bytes? These features make bash completely useless for being a fully capable embedded messaging server.

You can deal with this shortcoming by ignoring the first few bytes and start analyzing the result when you find the symbol { , the beginning of the request in JSON format. After that, you should read all the input data until the end of the input is found. You need a JSON parser that stops reading input when it encounters the end of a JSON string. Good luck writing this.

Creating output is simpler, just use echo -n or printf .

Here is a minimal example assuming input ends with } , reads it (without processing), and responds to the result. Although this demo works, I highly recommend not using bash, but a richer (scripting) language like Python or C ++.

 #!/bin/bash # Loop forever, to deal with chrome.runtime.connectNative while IFS= read -r -n1 c; do # Read the first message # Assuming that the message ALWAYS ends with a }, # with no }s in the string. Adopt this piece of code if needed. if [ "$c" != '}' ] ; then continue fi message='{"message": "Hello world!"}' # Calculate the byte size of the string. # NOTE: This assumes that byte length is identical to the string length! # Do not use multibyte (unicode) characters, escape them instead, eg # message='"Some unicode character:\u1234"' messagelen=${#message} # Convert to an integer in native byte order. # If you see an error message in Chrome stdout with # "Native Messaging host tried sending a message that is ... bytes long.", # then just swap the order, ie messagelen1 <-> messagelen4 and # messagelen2 <-> messagelen3 messagelen1=$(( ($messagelen ) & 0xFF )) messagelen2=$(( ($messagelen >> 8) & 0xFF )) messagelen3=$(( ($messagelen >> 16) & 0xFF )) messagelen4=$(( ($messagelen >> 24) & 0xFF )) # Print the message byte length followed by the actual message. printf "$(printf '\\x%x\\x%x\\x%x\\x%x' \ $messagelen1 $messagelen2 $messagelen3 $messagelen4)%s" "$message" done 
+6
source

Source: https://habr.com/ru/post/972261/


All Articles