Crosswalk CUSTOM append to user agent - mobile

My app requires custom user agent addition like "***; myAppUA".
For example, in webview I can do it:
String userAgent = settings.getUserAgentString();
userAgent += "; myAppUA";
settings.setUserAgentString(userAgent);
But I cannot find how to do it in Crosswalk.

I found patch here:
https://github.com/Reconers/cordova-plugin-crosswalk-webview/commit/f2b5d44b66a50b8fa4eeea9810c20cc29c601147
Now you can add in config.xml in app:
<preference name="AppendUserAgent" value="myAppUA" />

Related

Microsoft Android application is not matching the signature hash with the application reply URI

Goal: Use the MS Identity application that was created by Microsoft and try to tailor the application according to our needs.
Issue The android application is not matching the signature hash with the Applications' Reply URI.
Configuration Values
Signature Hash: ga0RGNYHvNM5d0SLGQfpQWAPGJ8=
Redirect URI: msauth://com.azuresamples.msalandroidapp/ga0RGNYHvNM5d0SLGQfpQWAPGJ8%3D
Android:host: com.azuresamples.msalandroidapp
Android Scheme: msauth
Logs and Screenshots
Logs show: The redirect URI in the configuration file doesn't match with the one generated with package name and signature hash.
Screenshot of the error in the Android Emulator
Methods Tried
Tried to fix this by changing the android:path value to /ga0RGNYHvNM5d0SLGQfpQWAPGJ8%3D however got this message from the UI:
Screenshot of the update android:path value
Tried to change the Reply URI directly from Azure Portal, but was not able to
Tried changing the Redirect URI in the android code to msauth://com.azuresamples.msalandroidapp/ga0RGNYHvNM5d0SLGQfpQWAPGJ8%3D but that gave the same error
The default library in the code was 1.2, changed it to 1.5+ in gradle and still it didnt work.
Configuration Files
auth_config_single_account.json
"client_id" : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"authorization_user_agent" : "DEFAULT",
"redirect_uri" : "msauth://com.azuresamples.msalandroidapp/ga0RGNYHvNM5d0SLGQfpQWAPGJ8%3D",
"account_mode" : "SINGLE",
"broker_redirect_uri_registered": true,
"authorities" : [
{
"type": "AAD",
"authority_url": "https://login.microsoftonline.com/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
]
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.azuresamples.msalandroidapp">
...
<intent-filter>
...
<data
android:host="com.azuresamples.msalandroidapp"
android:path="/ga0RGNYHvNM5d0SLGQfpQWAPGJ8="
android:scheme="msauth" />
</intent-filter>
...
</manifest>
Build-Gradle:app
...
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "androidx.appcompat:appcompat:$rootProject.ext.appCompatVersion"
implementation "com.google.android.material:material:$rootProject.ext.materialVersion"
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.android.volley:volley:1.1.1'
if (findProject(':msal') != null) {
// For developer team only.
localImplementation project(':msal')
externalImplementation 'com.microsoft.identity.client:msal:1.5.+'
}
else {
// Downloads and Builds MSAL from maven central.
implementation 'com.microsoft.identity.client:msal:1.5.+'
}
}
Update
Was trying to avoid this but I have updated my keystore using the debug.keystore that microsoft provides and it works, however this is not solution for production environments. What are the steps I need to take for this to work in the production environment.
Not sure if it will be a relevant answer, but will share my experience.
At some point I run into the same issue, dig into the library and figured out how hash is calculated there. It was something like this (I have translated it into kotlin):
try {
val info = packageManager.getPackageInfo(
packageName,
PackageManager.GET_SIGNATURES
)
for (signature in info.signatures) {
val md = MessageDigest.getInstance("SHA")
md.update(signature.toByteArray())
val hash = Base64.encodeToString(
md.digest(),
Base64.DEFAULT
)
Log.d("KeyHash", "KeyHash:$hash")
}
} catch (e: PackageManager.NameNotFoundException) {
Log.d("KeyHash", e.toString())
} catch (e: NoSuchAlgorithmException) {
}
The value calculated this way didn't match the value from running this command:
keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore | openssl sha1 -binary | openssl base64
But it was the one that msal library expects to get. Same happened on release signature. I haven't yet investigated the reason (maybe I did something wrong), but for now I'm using signature hash got from the first method, and it works fine.
This is Dome from the MSAL Android team.
If you want to use your own keystore, you will have to register your own application.
com.azuresamples.msalandroidapp was only registered with the signature hash of the provided debug.keystore.
Please let me know if you have any other question. You can also leave a question in our GitHub repository as well (we're constantly monitoring that one).
I tried with cmd and keytool but not get success. Please Try this code to generate key hash programmatically in you code.
String packageName = getApplicationContext().getPackageName();
try {
PackageInfo info = getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md;
md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
sha1Singature = new String(Base64.encode(md.digest(), 0));
//String something = new String(Base64.encodeBytes(md.digest()));
Log.e(AppConstants.TAG, sha1Singature);
}
} catch (PackageManager.NameNotFoundException e1) {
Log.e("name not found", e1.toString());
} catch (NoSuchAlgorithmException e) {
Log.e("no such an algorithm", e.toString());
} catch (Exception e) {
Log.e("exception", e.toString());
}
and then you set this Signature hash to Azure portal.

How to log as jsonPayload to stackdriver from google app engine using logback?

My spring boot app uses logback to log messages in json format. The app is configured to use consolelogappender (stdout).When the logs appear in stackdriver, they appear as textPayload instead of jsonPayload. Is it possible to write message to jsonPayload field in stackdriver using logback? If not, what are my options to log in json format?
Based on this Github Link it seems the issue all log entries are seen as textpayload. It has been added as a Feature Request but we do not have an ETA on when it will be available.
I'm not entirely sure if an alternative exist as Logback seems to be giving extensive log information, but if you are able to use the Stackdriver Logging Client instead, you could format the entry in order to get your object as a JsonPayLoad, although you will have specify most of the log categories yourself which can be an extra amount of work.
The easy way to do this, is to implements the transformation of TextPayload(JSON Format) to JSONPayload on the LoggingEnhacer
Check this answer How to use Stackdriver Structured Logging in App Engine Flex Java environment
It is possible via google-cloud-logging-logback library.
However, please note following (from https://cloud.google.com/logging/docs/structured-logging):
Note: message is saved as textPayload if it is the only field remaining
after the Logging agent moves the other special-purpose fields and
detect_json wasn't enabled; otherwise message remains in jsonPayload.
detect_json is not applicable to managed logging environments like
Google Kubernetes Engine.
To add more data to json add an enhancer. Example:
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.google.cloud.logging.LogEntry;
import com.google.cloud.logging.Payload;
import com.google.cloud.logging.logback.LoggingEventEnhancer;
import java.util.HashMap;
public class EventEnhancer implements LoggingEventEnhancer {
#Override
public void enhanceLogEntry(
LogEntry.Builder logEntry,
ILoggingEvent e
) {
HashMap<String, Object> map = new HashMap<>();
map.put("thread", e.getThreadName());
map.put("context", e.getLoggerContextVO().getName());
map.put("logger", e.getLoggerName());
Payload.JsonPayload payload = logEntry.build().getPayload();
map.putAll(payload.getDataAsMap());
logEntry.setPayload(
Payload.JsonPayload.of(map)
);
}
}
Configuration:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration scan="true">
<appender name="CLOUD" class="com.google.cloud.logging.logback.LoggingAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<log>application.log</log>
<redirectToStdout>true</redirectToStdout>
<resourceType>gae_app</resourceType>
<loggingEventEnhancer>EventEnhancer</loggingEventEnhancer>
<flushLevel>INFO</flushLevel>
</appender>
<root level="INFO">
<appender-ref ref="CLOUD"/>
</root>
</configuration>

Service Bus Connector and "raw" Text (Content-Type)

Ok.
I'm writing a POC (Proof of Concept) Logic App.
The logic app has a Service Bus connector wired to a queue.
I'm using peek/complete/abandon.
I wrote a client app (dotnet c# console app) that writes messages to the queue (nothing really to do with the logic app part).
I'm setting the Content Type to "text/plain".
string payLoad = #"{ ""myid"": ""1000"", ""mymessage"": ""1000 is great"" , ""myboolean"" : ""true"" }";
QueueClient queueClient = /* not seen here */;
brokeredMsg = new BrokeredMessage(payLoad) { ContentType = System.Net.Mime.MediaTypeNames.Text.Plain };
queueClient.Send(brokeredMsg);
Now I use Service Bus Explorer (4.0.104), and I see the message in the queue
The issue is that when my Logic App runs, its not seeing plain-text/json.
You can see it picked up the content-type.
But it garbly gooks the content itself.
Is there a way to get raw-text with this trigger?
Note, the documentation says:
let's look at the two Content-Types that don't require conversion or
casting that you can use in a logic app: application/json and
text/plain.
from :
https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-content-type
https://learn.microsoft.com/en-us/azure/connectors/connectors-create-api-servicebus
My C# console app packages.config (nothing to do with Logic Apps, but including for completeness)
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.WindowsAzure.ConfigurationManager" version="2.0.1.0" targetFramework="net45" />
<package id="WindowsAzure.ServiceBus" version="2.1.4.0" targetFramework="net45" />
</packages>
APPEND:
I needed to do two thing to get it to work
One:
I had to change the "sender" code slightly.
QueueClient queueClient = /* not seen here */;
string ct = System.Net.Mime.MediaTypeNames.Text.Plain;
/* see https://social.msdn.microsoft.com/Forums/en-US/8fbf2391-8440-46db-bb47-648daccf46fd/servicebus-output-json-is-being-wrapped-in-a-xml-header-in-logic-app?forum=azurelogicapps and https://abhishekrlal.com/2012/03/30/formatting-the-content-for-service-bus-messages/ */
string payLoad = #"{ ""myid"": ""1000"", ""mymessage"": ""1000 is great"" , ""myboolean"" : ""true"" }";
brokeredMsg = new BrokeredMessage(new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(Convert.ToString(payLoad))), true) { ContentType = ct };
queueClient.Send(brokeredMsg);
And I used the hint Derek Li gave me.
I've accepted his answer as the-answer, but PLEASE NOTE I had to do slightly more than he suggested. The code above has the urls for the reason I changed the sender code.
In a nutshell, the constructor for BrokeredMessage that I was using was choosing a specific serializer for me.
BrokeredMessage(Object)
Initializes a new instance of the BrokeredMessage class from a given object by
using DataContractSerializer with a binary XmlDictionaryWriter.
https://learn.microsoft.com/en-us/dotnet/api/microsoft.servicebus.messaging.brokeredmessage.-ctor?view=azureservicebus-4.1.1#Microsoft_ServiceBus_Messaging_BrokeredMessage__ctor
and after I figured out the answer, I found this SOF answer:
Azure Service Bus Serialization Type
You can use expression #base64ToString(triggerBody()?['ContentData'])" to convert it to string.

GWT Upload fails to App Engine

I want to provide a file upload to Google App Engine with the "GWT Upload" (https://code.google.com/p/gwtupload/). During the upload I get an error. As UploadAction servlet I use the build in: gwtupload.server.gae.AppEngineUploadAction
The servlet is configured in the web.xml in the following way:
<context-param>
<!-- max size of the upload request -->
<param-name>maxSize</param-name>
<param-value>3145728</param-value>
</context-param>
<context-param>
<!-- Useful in development mode to slow down the uploads in fast networks.
Put the number of milliseconds to sleep in each block received in the server.
false or 0, means don't use slow uploads -->
<param-name>slowUploads</param-name>
<param-value>200</param-value>
</context-param>
<servlet>
<servlet-name>uploadServlet</servlet-name>
<!-- This is the default servlet, it puts files in session -->
<servlet-class>gwtupload.server.gae.AppEngineUploadAction</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>uploadServlet</servlet-name>
<url-pattern>*.gupld</url-pattern>
</servlet-mapping>
During upload the progress bar progresses some percentages and then shows the following error:
But there are no more details in the logs.
The error message shows the class gwtupload.server.gae.MemCacheFileItemFactory$CacheableFileItem with the method setHeader(). That's strange because I can't find the method in that class. What's happening here?
Edit:
This is basically all the custom code i use. On the server side i use the build in gwtupload.server.gae.AppEngineUploadAction servlet.
package com.uploadtest.client;
import gwtupload.client.IUploadStatus.Status;
import gwtupload.client.IUploader;
import gwtupload.client.IUploader.UploadedInfo;
import gwtupload.client.MultiUploader;
import gwtupload.client.PreloadedImage;
import gwtupload.client.PreloadedImage.OnLoadPreloadedImageHandler;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.RootPanel;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class GWTUploadTest2 implements EntryPoint {
// A panel where the thumbnails of uploaded images will be shown
private FlowPanel panelImages = new FlowPanel();
public void onModuleLoad() {
// Attach the image viewer to the document
RootPanel.get("thumbnails").add(panelImages);
// Create a new uploader panel and attach it to the document
MultiUploader defaultUploader = new MultiUploader();
RootPanel.get("default").add(defaultUploader);
// Add a finish handler which will load the image once the upload finishes
defaultUploader.addOnFinishUploadHandler(onFinishUploaderHandler);
}
// Load the image in the document and in the case of success attach it to the viewer
private IUploader.OnFinishUploaderHandler onFinishUploaderHandler = new IUploader.OnFinishUploaderHandler() {
public void onFinish(IUploader uploader) {
if (uploader.getStatus() == Status.SUCCESS) {
new PreloadedImage(uploader.fileUrl(), showImage);
// The server sends useful information to the client by default
UploadedInfo info = uploader.getServerInfo();
System.out.println("File name " + info.name);
System.out.println("File content-type " + info.ctype);
System.out.println("File size " + info.size);
// You can send any customized message and parse it
System.out.println("Server message " + info.message);
}
}
};
// Attach an image to the pictures viewer
private OnLoadPreloadedImageHandler showImage = new OnLoadPreloadedImageHandler() {
public void onLoad(PreloadedImage image) {
image.setWidth("75px");
panelImages.add(image);
}
};
}
In addition to that i added the following jars to my clath path:
log4j-1.2.17.jar
gwtupload-gae-0.6.6.jar
gwtupload-0.6.6.jar
commons-fileupload-1.3.jar
commons-io-2.4.jar
Also zipped my whole sample project and uploaded it here:
https://skydrive.live.com/redir?resid=60B826E451F52B4D!118&authkey=!ALa1n2mL2sRR0wU
Edit 2:
Like Manolo pointed out: I was using "commons-fileupload-1.3.jar" instead of "commons-fileupload-1.2.1.jar". Changing the jar fixed my problem!
The problem is in the version of the commons-fileupload you are using, change it to the version 1.2.1, which is the one pointed in the gwtupload documentation.
It should work with 1.2.2 as well, but to use 1.3 requires new methods (setHeaders) which are not in the UploadListeners provided with gwtupload.
You should change in your project the target java (JDK compliance) to 1.6, since it is the last one supported in GWT to avoid problems, although it runs in 1.7.

Generate and download file with jboss seam

I need to add an 'export' function to an existing web app using seam. The purpose is to export search results to a csv file. I have no problem generating a csv, but I do not know how the send the csv back to the user.
I do not want to store the csv on the server because that would be waisted storage space. How could I achieve this in jboss seam?
Use the Document Store Servlet provided by Seam.
Almost copying and pasting from the reference doc, declare the servlet in web.xml like this:
<servlet>
<servlet-name>Document Store Servlet</servlet-name>
<servlet-class>org.jboss.seam.document.DocumentStoreServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Document Store Servlet</servlet-name>
<url-pattern>/seam/docstore/*</url-pattern>
</servlet-mapping>
Then create a export.xhtml file with only <s:resource> tag:
<s:resource xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
data="#{myComponent.csvData}"
contentType="application/vnd.ms-excel"
fileName="#{myComponent.csvFileName}"/>
Generate link for downloading the file in your page with <s:download>:
<s:download src="/csv/export.xhtml">
<h:outputText value="Download CSV"/>
<f:param name="param1" value="somevalue"/>
<f:param name="param2" value="someOtherValue"/>
</s:download>
Finally, implement getCsvData() and getCsvFileName() methods in your component:
// could be byte[], File or InputStream
public InputStream getCsvData() {
// generate data to be downloaded
}
public String getCsvFileName() {
return "myfile.csv";
}
Note that <s:download> propagates conversation (unless you set propagation=none). If you propagate the conversation context probably you won't need to pass any parameter. For large data set it may be preferable to not propagate the conversation and pass parameter to select the data in a request scoped component.
There's a couple of ways:
1) Check the Seam docs for info on using Seam-Excel to programmatically generate your file and then write it out using a mime-type set for CSV - this is all detailed in the docs.
However, I could not get this to work in the latest version of Seam, as it requires a response object, which used to be available from the Seam context but now only returns null.
2) Code the CSV file you want as an Excel xhtml template (see the Seam docs and example projects) and simply render this as normal using an tag.
I do this regularly and it works well, bar the restriction that you cannot supply a filename.
HTH.

Resources