Intermitent Base64 Task Conversion Errors - google-app-engine

I'm experiencing a really weird situation when passing on a POJO java object within the payload of a Pull Queue task using Gson. Without changing the code or the POJO being set within the payload of a task, this will randomly succeed or fail.
This is the code I'm using:
PullQueueTaskPayLoad tqp = new PullQueueTaskPayLoad("id","name");
tqp.uploadURL = taskPayLoad.uploadURL;
tqp.urls = taskPayLoad.urls;
tqp.sliceQueryParameter = taskPayLoad.sliceQueryParameter;
TaskOptions task = TaskOptions.Builder.withMethod(TaskOptions.Method.PULL);
task.payload(new Gson().toJson(tqp));
q.add(task);
Using an external queue consumer I then retrieve the POJO as follows:
Type GSON_TYPE = new TypeToken<PullQueueTaskPayLoad>() {}.getType();
byte[] b = new Base64().decodeBase64(leasedTask.getPayloadBase64().getBytes());
String payload = new String(b);
logger.info("About to convert payload: "+payload);
PullQueueTaskPayLoad taskpayload = new Gson().fromJson(payload, GSON_TYPE);
So from the debugging I did, the problem seems to be happening when I'm decoding the payload bytes. While encoding the same POJO (with different Ids) I randomly get 2 different decoded payload Strings as follows:
Correct decoding:
{"id":"1786024566","sliceQueryParameter": {"queryId":786024566,"sliceStart":-1,"sliceNumber":1,"params":{"DefaultAnnotation":{"http://www.slicepedia.org/ontology#hasNumberOfBulletPoints_SIGN":["\u003d"],"http://www.slicepedia.org/ontology#hasNumberOfBulletPoints":["0"],"http://www.slicepedia.org/ontology#hasNumberOfTokens":["80"],"http://www.slicepedia.org/ontology#hasNumberOfTokens_SIGN":["\u003e"]},"VG":{"http://www.slicepedia.org/ontology#hastense":["?"],"http://www.slicepedia.org/ontology#hasroot":["?"]}}},"uploadURL":"http://3.linguabox0412.appspot.com/_ah/upload/AMmfu6YRjxX23Ks-yh-9AZs4-3I1p6hxrFd6d4ptxSQegUkQHN7y4hNZwX6u7PufIHJbwtsHLXFZJ5P-vs90mslZEOMw0T-amN2qhEOAj_6YdwuY50FXMi8/ALBNUaYAAAAAT7Towgs4M00M5RLI8xnEOMdIxouZzuGu/","status":"IN_PROGRESS","action":"SLICE_SEARCH_AND_CREATE"}
Incorrect decoding:
{"id":"1-1968382407","sliceQueryParameter":{"queryId":-1968382407,"sliceStart":-1,"sliceNumber":1,"params":{"DefaultAnnotation":{"http://www.slicepedia.org/ontology#hasNumberOfBulletPoints_SIGN":["\u003d"],"http://www.slicepedia.org/ontology#hasNumberOfBulletPoints":["0"],"http://www.slicepedia.org/ontology#hasNumberOfTokens":["80"],"http://www.slicepedia.org/ontology#hasNumberOfTokens_SIGN":["\u003e"]},"VG":{"http://www.slicepedia.org/ontology#hastense":["?K??????˜?X?\YXK?ܙ?????H?\ܛ????Ȃ%?????'W??EU$?#?&?GG???2?Ɩ?wV&??C"?7?B?6??????W??B???gSe????'u?U'd?D??6?S??4UV?D?e7?%U?&%F%f?D?$???$&vu6?fF$????EG?v??6?6դvt?D???G??&D?fdֵ6%?甦??GD????F???$?V?CuF?$?F?F֤֧f?D??u?wt?4?C$?W?"?'7FGW2#?$???$?u$U52"?&7F???#?%4Ĕ4U?4T$4???E?5$TDR'
So the second string obviously fails when using Gson to convert it back to a POJO. But I dont' understand why this happens in only some cases and not others. For what I've seen, it seems to always happen after a ["?"] character string. I tried replacing and ? with other strings but it didn't change anything.

I think what is happening here is that the payload is webSafe-base64 encoded. In practice, this means swapping + and / and = for - and _ and .. Most base64 libraries have native support for decoding websafe base 64 strings.
Probably you are meeting one of these chars at a certain point, and that kills the decoding.
Here is some info on WebSafeBase64
Word of warning, though: the taskqueue implementation is actually sending padding equals (=) that you will have to convert manually before parsing.

Related

Byte Array To String Conversion Inconsistency

I am testing out AES encryption on android and i need to convert the encrypted text to a string so as to store it in my firebase database. I managed to do so sucessfully. The problem comes when I try to retrieve the string from the database and convert it back to a byte array for decryption.
The retreived string is identical to the string sent to the database but when i convert it to a byte array and compare the two values, they are different as seen in the code sample below. I even made sure to use the same Charset but this did not fix the issue.
val encryptedPair: Pair<ByteArray,ByteArray> = encrypt("text")
val enc: MutableMap<String, Any> = HashMap()
enc["ciphertext"] = encryptedPair.second.toString(Charsets.UTF_8).trim()
fireStoreDatabase.collection("enc").document("test").set(enc)
.addOnSuccessListener {
fireStoreDatabase.collection("enc").document("test").get()
.addOnSuccessListener { doc->
//The below if condition prints out encrytion method: diff
if(encryptedPair.second.contentEquals(doc.getString("password")!!.toByteArray(Charsets.UTF_8)))
Log.e("encryption method: ","same")
else
Log.e("encryption method: ","diff")
}
}
This difference leads to the decryption process failing. Note that when i try to encrypt and decrypt with the values locally, it works as expected. So i know the problem is with the byte array i get from firebase.
Any suggestions would be appreciated.
As Jon Skeet has suggested, using
val enc: MutableMap<String, Any> = HashMap()
enc["ciphertext"] = Blob.fromBytes(encryptedPair.second)
fireStoreDatabase.collection("enc").document("test").set(enc)
to save the data to firebase and then retrieving it with:
doc.getBlob("ciphertext")!!.toBytes())
worked as expected.

Byte array to Firestore

I have a byte array how do I store it in Firestore?
preferable to store as a File in Firestore Storage but storing them as custom object is fine too in Cloud Firestore.
I tried to make a file and use the function write Bytes() and on retrieving use read bytes but that is not able to work proper and causing some disruption as my byte array is a encrypted form of image which I need to store in Firestore. And Retrieve later and decrypt it.
Before I was trying to convert Byte Array to string but many people told that is no good practice as it will cause loss of data.
Than when I researched a bit few people recommended to use Blob and store the byte array but unfortunately I was unable to get the sample code for it.
val z = cipher.doFinal(byteArray)
val file = File.createTempFile("$name", null)
file.writeBytes(z)
Log.d("first","quick")
val storageReference = FirebaseStorage.getInstance()
.getReference("/image/0XhL4jD4XCemk38rcRkIEjJMgjh2/Aadhar/")
storageReference.putFile(Uri.fromFile(file))
.addOnSuccessListener {
Toast.makeText(context , "Success", Toast.LENGTH_SHORT).show()
}
Basically Z is the encrypted byte array that I somehow need to push to Firestore. I tried to make file and push in storage. Its Successfully completed.
But when I retrieve it back Something like below:-
val storageRef =
FirebaseStorage.getInstance().reference?.child("/image/0XhL4jD4XCemk38rcRkIEjJMgjh2/Aadhar/")
val localfile = File.createTempFile("temp", ".txt")
storageRef.getFile(localfile)
.addOnSuccessListener {
val bytes = localfile.readBytes()
var decryptedText: ByteArray = cipher.doFinal(bytes)
val configBmp = Bitmap.Config.valueOf(bitmap.config.name)
val bitmap_tmp = Bitmap.createBitmap(width, height, configBmp)
val buffer = ByteBuffer.wrap(decryptedText)
bitmap_tmp.copyPixelsFromBuffer(buffer)
img.setImageBitmap(bitmap_tmp)
}
The problem when I read bytes I got no clue what but something is going wrong there. I can be of sure that encryption and decryption both are working fine as I tested it Locally without pushing the byte array to Firestore and Just decrypt and it works perfectly good.
But when for the same byte array I try to store in file and push and retrieve later it doesn't works. The error I get is Illegal block size.
Simplified Question:-
Assume I have a byte array 'X'
How can I store it in Firestore [Cloud Firestore / Storage in form of files[preferred] with 0 loss of data and retrieve it back.
Help would be highly appreciated guys with a snippet of code to understand,
Thanks in adv.

Unable to translate bytes [...] at index ... from specified code page to Unicode when adding to index

I am using Newtonsoft.Json to create the JSON to update add items to an index, but I get the following error when I POST the request:
{"error":{"code":"","message":"The request is invalid.","innererror":{"message":"parameters : Unable to translate bytes [E3] at index 752 from specified code page to Unicode.\r\n","type":"","stacktrace":""}}}
I know the error occurs with some non letter characters in some of the strings in the data that I am serializing. The string data comes from SQL, so I'm guessing something is going on to do with encoding that I cannot figure out.
When I inspect the JSON string, and put it in manually construct a request with the same data in Fiddler it all works fine.
Does anyone have any idea what might be the problem, and how I can work around it?
I found my own solution after a bit more digging.
Adding "StringEscapeHandling.EscapeNonAscii" to the serialization options solves the problem:
jsonSettings = new JsonSerializerSettings
{
Formatting = Newtonsoft.Json.Formatting.Indented,
ContractResolver = new CamelCasePropertyNamesContractResolver(),
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
StringEscapeHandling = StringEscapeHandling.EscapeNonAscii
};

Simpleframework serialize elements name without conversion

I have to create XML from Java objects and I use the Simple framework.
My problem is I need to send some names in camel case:
#Element
String ChannelData
and the xml element produced is:
<channel-data>
Which is rejected by the receiver, it needs to be
<channelData>
I cannot find a way to configure this, I tried adding the name explicitly:
#Elenemt(name="channelData")
but without success.
Ok I solved it.
I actuallt initialized the Persister with the wrong format:
Format format = new Format(0, null, new HyphenStyle(), Verbosity.HIGH);
Instead of:
Format format = new Format(0, null, new CamelCaseStyle(), Verbosity.HIGH);

Hash-based logger for embedded application

Currently I am sending the UART the strings I want to log and reading it on the host with any terminal.
In order to reduce the logging time and hopefully the image size as well (my flash is tiny), I figured out that the strings are unused in the embedded system, so why storing them on the flash?
I want to implement a server, whom I can send a hashed-key of any string (for example - it's ROM address) and the string will be output to file or screen.
My questions are:
How to create the key2string converter out of the image file (the OS is CMX, but can be answered generally)
Is there a recomended way to generate image, that will know the strings addresses but will exclude them from ROM?
Is there a known generic (open-source or other) that implemented a similar logger?
Thanks
Rather than holding hard-coded strings, then trying to hash the answers and sent it via a UART, then somehow remove the strings from the resulting image, I suggest the following.
Just send an index for an error code. The PC side can look up that index and determine what the string is for that condition. If you want the device code to be more clear, the index can be an enumeration.
For example:
enum errorStrings
{
ES_valueOutOfLimits = 1,
ES_wowItsGettingWarm = 2,
ES_randomError = 3,
ES_passwordFailure = 4
};
So, if you were sending data to the UART via printf, you could do the following:
printf("%d\n",(int)ES_wowItsGettingWarm);
Then your PC software just needs to decode the "2" that comes across the UART back into a useful string of "Wow it's getting warm."
This keeps the firmware small, but you need to manually keep the file containing the enum and the file with the strings in sync.
My solution is sending file name and line (which should be 14-20 Byte) and having a source parser on the server side, which will generate map of the actual texts. This way the actual code will contain no "format" strings, but single "filename" string for each file. Furthermore, file names can be easily replaced with enum (unlike replacing every string in the code) to reduce the COMM throughput.
I hope the sample psaudo-code will help clarifying the idea:
/* target code */
#define PRINT(format,...) send(__FILE__,__LINE__,__VA_ARGS__)
...
/* host code (c++) */
void PrintComm(istream& in)
{
string fileName;
int line,nParams;
int* params;
in>>fileName>>line>>nParams;
if (nParams>0)
{
params = new int[nParams];
for (int i=0; i<nParams; ++i)
in>>params[i];
}
const char* format = FindFormat(fileName,line);
...
delete[] params;
}

Resources