HTTP uri in a GTK# FileChooserDialog - file

Can GTK#'s FileChooserDialog be used as a unified file/URI dialog? I'd like it to accept http/https/ftp URIs without "rewriting" them (prepending local directory).
Even if I set LocalOnly=false and paste a http://.... uri into the text box inside the filechooser, I cannot get the original entry. Local directory is always prepended to the text.

I've done some research, and I don't think it's possible. At least not with the direct native C GTK+ API, which is what I tested.
In my testing, I always either got the local directory's path prepended to the http:// URI I had entered in the dialog, or I got back (null). I did call the get_uri() method, not just get_filename().
I also took a quick look, as a reference, at the GIMP application's File menu. As you probably know, GIMP provides the G in GTK+, so it can sometimes be used as a reference for ideas on how to use the toolkit. GIMP does not try to support URIs entered in the file chooser dialog, instead it has a dedicated Open Location command, that opens a simple dialog with just a GtkEntry.

I think you need to set local-only to FALSE and then use the GIO get_file ()/get_files () calls which return a GFile* accessible through the GIO File API and therefore through gvfs.

I found a solution / hack after all (in C#):
private string _extractUri(Widget wi) {
if (wi is Entry)
return ((wi as Entry).Text);
else if (wi is Container) {
foreach (Widget w in (wi as Container).Children) {
string x = _extractUri(w);
if (x!=null)
return x;
}
}
return null;
}
I'm not sure if that's always safe, but it worked for the standard FileChooserDialog. It will return the original string from the input field - even if standard Uri / File results are mangled.

Related

Download arbitrary files to Android and iOS cache

I wrote the following method:
/**
* Downloads an arbitrary file to the cache asynchronously, if the current
* platform has a cache path, or to the app home; if the file was previously
* downloaded and if it's still available on the cache, it calls the
* onSuccess callback immediatly.More info:
* https://www.codenameone.com/blog/cache-sorted-properties-preferences-listener.html
*
* #param url The URL to download.
* #param extension you can leave it empty or null, however iOS cannot play
* videos without extension (https://stackoverflow.com/q/49919858)
* #param onSuccess Callback invoked on successful completion (on EDT by
* callSerially).
* #param onFail Callback invoked on failure (on EDT by callSerially).
*/
public static void downloadFileToCache(String url, String extension, SuccessCallback<String> onSuccess, Runnable onFail) {
FileSystemStorage fs = FileSystemStorage.getInstance();
if (extension == null) {
extension = "";
}
if (extension.startsWith(".")) {
extension = extension.substring(1);
}
String name = "cache_" + HashUtilities.sha256hash(url);
if (!extension.isEmpty()) {
name += "." + extension;
}
String filePath;
if (fs.hasCachesDir()) {
// this is supported by Android, iPhone and Javascript
filePath = fs.getCachesDir() + fs.getFileSystemSeparator() + name;
} else {
// The current platform doesn't have a cache path (for example the Simulator)
String homePath = fs.getAppHomePath();
filePath = homePath + fs.getFileSystemSeparator() + name;
}
// Was the file previously downloaded?
if (fs.exists(filePath)) {
CN.callSerially(() -> onSuccess.onSucess(filePath));
} else {
Util.downloadUrlToFileSystemInBackground(url, filePath, (evt) -> {
if (fs.exists(filePath)) {
CN.callSerially(() -> onSuccess.onSucess(filePath));
} else {
CN.callSerially(onFail);
}
});
}
}
It works. It's similar to some methods provided by the Util class, but with two main differences: the first is that the Util class provides methods only to download images to the cache, while I want to download arbitrary files; the second is that I can assume that the same url always returns the same file, so I don't need to download it again if it's still in the cache (while the Util methods always download the files when invoked).
However, I have some doubts.
My first question is about how caching works: currently I'm using this method to download images and videos to cache (in a chatting app), assuming that I don't need to care about when the files will be not more necessary, because the OS will delete them automatically. Is it so, right? Is it possible that the OS deletes files while I'm using them (for example immediately after storing them to the cache), or Android and iOS delete only older files?
I wrote this method to store arbitrary files. Is there any reasonable limit in MB to the file size that we can store in the cache?
Finally, I have a doubt about the callSerially that I used in the method. Previously I didn't use that, but I got odd results: my callbacks do UI manipulations and frequently (but not always) something went wrong. I solved all my callbacks problems adding the callSerially, so callSerially is the solution. But... why? The odd fact is that the ActionListener of Util.downloadUrlToFileSystemInBackground is called under the hood by the addResponseListener(callback) of a ConnectionRequest instance, so the callback is already invoked in the EDT (according to the javadoc). To be sure, I tested CN.isEdt() in the callbacks without adding the callSerially, and it returned true, so in theory callSerially is not necessary, but in practice it is. What's wrong in my reasoning?
Thank you for the explanations.
As far as I know the cache directory is just a directory that the OS is allowed to delete if it needs space. I don't think it will delete it for an active foreground application but that might vary.
There are no limits other than storage. But you still need to consider that the OS won't just clean that directory for you. It will only flush it when storage is very low and even then not always. So you still need to store data responsibly.
I think only the first callSeially has an impact. It defers the result to the next EDT loop instead of continuing in the existing thread.

Access Shared Preferences externally / Store a value into a new file and access it externally

I have the two following methods and I am using them to store a special value locally and be able to access it on application restart:
(Store value locally:)
private void SaveSet(string key, string value)
{
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
ISharedPreferencesEditor prefEditor = prefs.Edit();
prefEditor.PutString(key, value);
// editor.Commit(); // applies changes synchronously on older APIs
prefEditor.Apply(); // applies changes asynchronously on newer APIs
}
(Read it again:)
private string RetrieveSet(string key)
{
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
return prefs.GetString(key, null);
}
This works perfectly. Now is it possible to access and edit this Shared Preferences externally? Unfortunately, I cannot find any file when searching in folder
Phone\Android\data\com.<company_name>.<application_name>\files
nor anywhere else. I want / try to edit this value from my computer, after connecting the phone to it. Is this possible?
Alternatively: Can anyone maybe show me how to create a new file in the given path above, write/read it programmatically and how it stays there, even if application is closed / started again? So I can then edit this file with my computer anyhow?
I tried it with the following code, but unfortunately it doesn't work / no file is created or at least i cannot see it in the given path above:
//"This code snippet is one example of writing an integer to a UTF-8 text file to the internal storage directory of an application:"
public void SaveValueIntoNewFile(int value)
{
var backingFile = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "newFile.txt");
using (var writer = System.IO.File.CreateText(backingFile))
{
writer.WriteLine(value.ToString());
}
}
Would be very happy about every answer, thanks in advance and best regards
What you're looking for is where Android stores the Shared Preference file for applications that make use of it's default PreferenceManager.
I'd refer to this SO post which answers your question pretty well
SharedPreferences are stored in an xml file in the app data folder,
i.e.
/data/data/YOUR_PACKAGE_NAME/shared_prefs/YOUR_PREFS_NAME.xml
or the default preferences at:
/data/data/YOUR_PACKAGE_NAME/shared_prefs/YOUR_PACKAGE_NAME_preferences.xml
SharedPreferences added during runtime are not stored in the Eclipse
project.
Note: Accessing /data/data/ requires superuser
privileges
A simple method is to use Android Device Monotor,you can open it by clicking Tools--> android-->Android Device Monotor...
For example:
The path in my device is as follows:
/data/data/YOUR_PACKAGE_NAME/shared_prefs/YOUR_PACKAGE_NAME_preferences.xml
And we notice three buttons in the upper right corner of the picture.
The first one is used toPull a file from the device,the second one is used to Push a file onto the device,and the last one is used to delete the preferences.xml file.
So we can pull the preferences.xml file from current device to our computer and edit it as we want, and then push the updated preferences.xml to the folder again.Then we will get the value of preferences.xml file .

Download file with JSF

everyone!
I have a trouble. I tried to save excel file in jsf web application.
I generated file by my utils and trying to get "save" window, but I failed.
Here is my code:
<div>
<h:commandButton value="Apply" actionListener="#{hornPhonesBean.generateReport}"/>
</div>
and:
public void generateReport(ActionEvent event) {
System.out.println("GENERATE REPORT FROM = " + this.dateFrom + "; TO = " + this.dateTo);
try {
XSSFWorkbook workbook = (XSSFWorkbook) HornReportGenerator.getWorkbook(null, null);
String fileName = "1.xlsx";
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
// Some JSF component library or some Filter might have set some headers in the buffer beforehand. We want to get rid of them, else it may collide.
ec.responseReset();
// Check http://www.w3schools.com/media/media_mimeref.asp for all types. Use if necessary ExternalContext#getMimeType() for auto-detection based on filename.
ec.setResponseContentType("application/vnd.ms-excel");
// Set it with the file size. This header is optional. It will work if it's omitted, but the download progress will be unknown.
//ec.setResponseContentLength(contentLength);
// The Save As popup magic is done here. You can give it any file name you want, this only won't work in MSIE, it will use current request URL as file name instead.
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
OutputStream output = ec.getResponseOutputStream();
workbook.write(output);
output.flush();
output.close();
fc.responseComplete(); // Important! Otherwise JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
System.out.println("END");
} catch (Exception e) {
e.printStackTrace();
}
}
I read suggestions here and from another forums - everyone says I shouldnt use , but I didn't use it at all.
Then I thought that the problem could be in the
<ice:form>,
where I kept the
<h:commandButton>,
and I changed to
<h:form>,
but it didn't help.
Maybe the problem in the request - it has header Faces-Request partial/ajax. But I am not sure.
Please give me some ideas - I already spent 4 hours for this crazy jsf download issue)
Maybe the problem in the request - it has header Faces-Request partial/ajax. But I am not sure.
This suggests that the request is an ajax request. You can't download files by ajax. Ajax requests are processed by JavaScript which has for obvious security reasons no facilities to programmatically pop a Save As dialogue nor to access/manipulate client's disk file system.
Your code snippet does however not show that you're using ajax. Perhaps you oversimplified it too much or you're using ICEfaces which silently auto-enables ajax on all standard JSF command components.
In any case, you need to make sure that it's not sending an ajax request.
See also:
How to provide a file download from a JSF backing bean?
ICEfaces libary in classpath prevents Save As dialog from popping up on file download

Silverlight: Business Application Needs Access To Files To Print and Move

I have the following requirement for a business application:
(All of this could be on local or server)
Allow user to select folder location
Show contents of folder
Print selected items from folder (*.pdf)
Display which files have been printed
Potentially move printed files to new location (sub-folder of printed)
How can I make this happen in Silverlight?
Kind regards,
ribald
First of all, all but the last item can be done (the way you expect). Due to security protocols, silverlight cannot access the user's drive and manipulate it. The closest you can get is accessing silverlight's application storage which will be of no help to you whatsoever in this case. I will highlight how to do the first 4 items.
Allow user to select folder location & Show contents of folder
public void OnSelectPDF(object sender)
{
//create the open file dialog
OpenFileDialog ofg = new OpenFileDialog();
//filter to show only pdf files
ofg.Filter = "PDF Files|*.pdf";
ofg.ShowDialog();
byte[] _import_file = new byte[0];
//once a file is selected proceed
if (!object.ReferenceEquals(ofg.File, null))
{
try
{
fs = ofg.File.OpenRead();
_import_file = new byte[fs.Length];
fs.Read(_import_file, 0, (int)fs.Length);
}
catch (Exception ex)
{
}
finally
{
if (!object.ReferenceEquals(fs, null))
fs.Close();
}
//do stuff with file - such as upload the file to the server
};
}
If you noticed, in my example, once the file is retrieved, i suggest uploading it to a webserver or somewhere with temporary public access. I would recommend doing this via a web service. E.g
//configure the system file (customn class)
TSystemFile objFile = new TNetworkFile().Initialize();
//get the file description from the Open File Dialog (ofg)
objFile.Description = ofg.File.Extension.Contains(".") ? ofg.File.Extension : "." + ofg.File.Extension;
objFile.FileData = _import_file;
objFile.FileName = ofg.File.Name;
//upload the file
MasterService.ToolingInterface.UploadTemporaryFileAsync(objFile);
Once this file is uploaded, on the async result, most likely returning the temporary file name and upload location, I would foward the call to some javascript method in the browser for it to use the generic "download.aspx?fileName=givenFileName" technique to force a download on the users system which would take care of both saving to a new location and printing. Which is what your are seeking.
Example of the javascript technique (remember to include System.Windows.Browser):
public void OnInvokeDownload(string _destination)
{
//call the browser method/jquery method
//(I use constants to centralize the names of the respective browser methods)
try
{
HtmlWindow window = HtmlPage.Window;
//where BM_INVOKE_DOWNLOAD is something like "invokeDownload"
window.Invoke(Constants.TBrowserMethods.BM_INVOKE_DOWNLOAD, new object[] { _destination});
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); }
}
Ensure you have the javascript method existing either in an included javaScript file or in the same hosting page as your silverlight app. E.g:
function invokeDownload(_destination) {
//some fancy jquery or just the traditional document.location change here
//open a popup window to http://www.myurl.com/downloads/download.aspx? fileName=_destination
}
The code for download.aspx is outside the scope of my answer, as it varies per need and would just lengthen this post (A LOT MORE). But from what I've given, it will "work" for what you're looking for, but maybe not in exactly the way you expected. However, remember that this is primarily due to silverlight restrictions. What this approach does is rather than forcing you to need a pluging to view pdf files in your app, it allows the user computer to play it's part by using the existing adobe pdf reader. In silverlight, most printing, at least to my knowledge is done my using what you call and "ImageVisual" which is a UIElement. To print a pdf directly from silverlight, you need to either be viewing that PDF in a silverlight control, or ask a web service to render the PDF as an image and then place that image in a control. Only then could you print directly. I presented this approach as a lot more clean and direct approach.
One note - with the temp directory, i would recommend doing a clean up by some timespan of the files on the server side everytime a file is being added. Saves you the work of running some task periodically to check the folder and remove old files. ;)

How to register own protocol using the WebBrowser control?

In a WP7 Silverlight application with a WebBrowser control I want to use an own protocol like "myttp://" to deliver some local content. I can't use Navigate() to an IsolatedStrorage because some content will by created on demand. For the same reason NavigateToString() is also not usable for me.
I tried to register a WebRequestCreator descend for my MYTP protocol
myCreator = new MyRequestCreator();
WebRequest.RegisterPrefix("mytp://", myCreator);
but it isn't called from the browser control if I navigate to "mytp://test.html".
If I create a WebRequest via code
WebRequest request;
request = WebRequest.Create("mytp://test.html");`
everythings works fine.
Any suggestions what is wrong or how to do it?
The WebBrowser control will use the Windows Phone Internet Explorer Browser's HTTP stack to statisfy web requests. This HTTP stack is entirely separate from the Client HTTP stack being used by the application. Hence the browser does not see your protocol at all.
I agree with AnthonyWJones words, though I dont know, what exactly he meant by "Browser HTTP stack".
The standard Silverlight's "access to Browser's stack" (used to handle sessions etc) in form of System.Net.Browser.WebRequestCreator.BrowserHttp httprequest factory (versus the "normal/aside" System.Net.Browser.WebRequestCreator.ClientHttp factory) is actually available to the application code in WP7. It is hidden from the SDK, but available on the device and with small effort, the application can use it, for example, to have its emitted cookies in sync with the Browser's cache. For description, please see my humble other post
However, while using that factory and having all your session/cookies/userauth handling within those connections in sync with the WebBrowser, despite being very similar to the ClientHttp factory, you find (at least in 7.0 and 7.1 versions) that it is completely ignorant of any custom prefixes. Trying to open anything with this factory results in (WP7 v. Mango 7.1):
A first chance exception of type 'System.Net.ProtocolViolationException' occurred in System.Windows.dll
at System.Net.Browser.BrowserHttpWebRequest.InternalBeginGetRequestStream(AsyncCallback callback, Object state)
at System.Net.Browser.AsyncHelper.BeginOnUI(BeginMethod beginMethod, AsyncCallback callback, Object state)
at System.Net.Browser.BrowserHttpWebRequest.BeginGetRequestStream(AsyncCallback callback, Object state)
at MyApp.MyPage..ctor()
relevant code snippet of the MyPage:
public class WRC : IWebRequestCreate { public WebRequest Create(Uri uri) { return null;/*BREAKPOINT1*/ } }
WebRequest.RegisterPrefix("js://", new WRC()); // register the above handler
brwHttp = (IWebRequestCreate)typeof(System.Net.Browser.WebRequestCreator).GetProperty("BrowserHttp").GetValue(null, null);
var tmp = brwHttp.Create(new Uri("js://blah.blah.blah"));
var yyy = tmp.BeginGetResponse(callback, "wtf");
var response = tmp.EndGetResponse(yyy); /*BREAKPOINT2*/
var zzz = tmp.BeginGetRequestStream(callback, "wtf"); /*<---EXCEPTION*/
var stream = tmp.EndGetRequestStream(zzz); /*BREAKPOINT3*/
Execution results:
breakpoint1 never hit
breakpoint2 allows to see that "response" is NULL
breakpoint3 never hit due to the exception pasted above
My conclusion is, that the Silverlight Browser's stack is hardcoded to use some builtin set of prefixes, and all other prefixes are ignored/throw ProtocolViolation. My guess is, that in WP7 (7.0, 7.1) they are actually hardcoded to use http since my custom "js://" was passed to a BrowserHttpWebRequest.InternalBeginGetRequestStream as it's visible on the stacktrace :)
That confirms what Anthony had written - no way of having custom protocol handlers to work gracefully with the Silverlight's Browser Stack API.
However, I cannot agree with that the WebBrowser uses this connection factory. While is it true that the hidden factory is called BrowserHttp, and is true that it shares some per-user or per-session settings with the webbrowser, everything I try tens to indicate that the WebBrowser component uses yet completly other factory for its connections, and quite probably it is some native one. As an argument for that, I can only provide that I was able to successfully replace the original BrowserHttp factory with my simple custom implementation of it (both on the emulator and the phone), and with at least 6 webbrowsers in my current app, it wasn't used at all, not even once! (neither on the emulator, nor phone)

Resources