External Storage (public across apps) - java

I need to make a file in the Android External Storage area that can be accessed (read/write) by other apps.
I looked here but that says to pass it a directory type such as DIRECTORY_MUSIC, DIRECTORY_PICTURES etc.
But none of those types is what i want. So what I'm thinking is this:
File F = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "MyAppName" + File.separator + "MyFile");
Will this work or how can i ensure that a file will truly have public read/write access for other apps?
Also, I read somewhere that OutputStreams are only supposed to take a name with no path, and are always private, so how would i read/write ints to F?

Well, it seems to me that the statement for creating a new File you have there, would work. Although, why not try it out? Also, it is absolutely possible to write to a file and have it be accessible publicly, you do not need to do anything for this to happen, it will just happen by default. Reading/writing ints from/to the File can be done as usual, I recommend converting it to a String before writing.

It will works. You can ensure that a file truly have public access if you'll find it with some file manager and try to open it. In your example path to your file will be "%HOME_DIR%\MyAppName\MyFile". Also for creating file you could use FileOutputStream (not OutputStream), it takes File as parameter in constructor.

Files created in external storage are by default can be accessed by any other app (since the file is in external storage). The only thing you can control is the lifetime of the created file. As in whether the file should exist with your app only and deleted once the app is uninstalled or the file exists even after your app is removed.
If you want to create a file on your own path (not in DIRECTORY_PICTURE etc) inside your application then use getExternalFileDir() and pass null to it. See the link below for more details.
Saving file in external storage

Related

Write to ~/Library/ApplicationSupport/* with java?

I'm writing an Application for Mac in Java that needs to store a few preference files. By default, they seem to be storing to the User folder, but I'd like to store the files in the Library/ApplicationSupport folder, but I can't seem to figure out how to do that.
I've tried File file = new File("/Library/ApplicationSupport/AppName"); then file.mkdir() but it keeps returning false. I've tried adding ~ to the front of /Library/, and that didn't work either.
I've also tried just writing the file to the desired directory on a FileOutputStream, but no luck there either. I'm open to other ways of storing my preference files, I just don't want them stored in an obtrusive way to the user.
Thanks!
You can't write to /Library/ApplicationSupport because your user would not have the permission.
The plain Java io classes don't understand "~", so to write to ~/Library/ApplicationSupport, you need:
System.getProperty("user.home") + "/Library/ApplicationSupport"

Creating a file just to be uploaded into the online form

couldn't find relevant question on SO I'm asking a new one. I can create a file using FileWriter class, but it requires to specify the path for that file (physically creates the file). What I want to achieve is to create a file like in-memory, without specyfying the path or saving it on the disk and then upload it into the online form with selenium webdriver, is that somehow possible?
But there also is another problem, html fileUpload element will accept the path such as:
driver.findElement(By.id("Content_CV")).sendKeys("C:\\Users\\name\\Documents\\my_cv.pdf");
but will it accept the file itself? Probably not, so assuming that some of you knows how to create a file without saving it on the disk, would there be a way of providing path to that file anyway (given its virtual location)?
I'm trying to figure it out and I did some google research, yet here I am. Thanks for any attempt of help :)
If your question is just how to create a temporary file without caring about how to name it and where to create it without overwriting existing files, then you can simply use File.createTempFile. This will create an actual new temporary file on disk in the directory designated by the operating system for that purpose. You might also want to have a look at File.deleteOnExit.
If you are not looking for a java solution, you can simply create the file in a RAM drive
Software for this exist for all mayor operating systems.
Have a look at the wikipedia link above for more information.

Read a file from Amazon EBS

I want to download a file from one of the EBS volumes I created on Amazon Elastic block storage. Mostly it is advisable to used ServletContext#getResource() and its counterpart ServletContext#getResourceAsStream() as well advised here.
But in this case is the following code advisable
InputStream in = new FileInputStream(new File(FOLDER_PATH_ON_AMAZON_EBS + "/" + folder + "/" + fileName));
It's hard to tell what the question is here.
If you are asking whether it is better to use getServletContext() or new File(PATH_TO_EBS...) then it simply depends on what you are running. If you are running a standalone java application and requesting files via sockets, then you would use the latter (a FileInputStream over a file you know where to look). If you are running a web server (eg Tomcat) and will be using a web client to download the file, then you would typically use the getServletContext() since that is part of the web-server infrastructure.
Both ways let you get a handle on the file, but getServletContext() is going to refer to a location for your application under Tomcat's working area. Are you going to mount your EBS volume somewhere where you can easily reach it starting from Tomcat's working area.
If you are running a web server and it is allowing you to reach a file directly in your EBS volume with new FileInputStream(new File(MY_EBS_LOCATION + "/" + ...)) then use it by all means - clear and easy.
Having the file path in the properties file, and using the absolute path is better due the following reasons,
There are chances that the mountpoint of the ec2 volume changes, having that in the classpath and modifying that is comparatively harder than modifying the entry in the properties file.
Normally resources like property files are got using getResource(), if there is going to be other IO like storing photos, office docs then its wise to use absolute path for access.
It also depends on the usecase if the files(resource) is frequently used by the application, and the application only, then u can have that in classpath and pack it along with the archive.

java equivalent for mkstemp

Is there any way in Java to write out to a temporary file securely?
As far as I can tell, the only way to create a temporary file (createTempFile) does't actually open it at the same time, so there's a race condition between file open & file write. Am I missing something? I couldn't find the C source code behind createFileExclusively(String) in UnixFileSystem.java, but I doubt it can really do anything since the file open occurs in the Java code after the temp file is created (unless it tries to do something with file locks?).
The problem
Between when the temporary file is created & you open it, a malicious attacker could unlink that temporary file & put malicious stuff there. For example, an attacker could create a named pipe to read sensitive data. Or similarly if you eventually copy the file by reading it, then the named pipe could just ignore everything written & supply malicious content to be read.
I remember reading of numerous examples of temporary file attacks in the past 10+ years that exploit the race condition between when the name appears in the namespace and when the file is actually opened.
Hopefully a mitigating factor is that Java set's the umask correctly so a less-privileged user can't read/write to the file and typically the /tmp directory restricts permissions properly so that you can't perform an unlink attack.
Of course if you pass a custom directory for the temporary file that's owned by a less-privileged user who's compromised, the user could do an unlink attack against you. Hell, with inotify, it's probably even easier to exploit the race condition than just a brute force loop that does a directory listing.
http://kurt.seifried.org/2012/03/14/creating-temporary-files-securely/
Java
use java.io.File.createTempFile() – some interesting info at http://www.veracode.com/blog/2009/01/how-boring-flaws-become-interesting/
for directories there is a helpful posting at How to create a temporary directory/folder in Java?
Java 7
for files use java.io.File.createTempFile()
for directories use createTempDirectory()
http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html
Since Java 7 we have OpenOption.
An object that configures how to open or create a file.
Objects of this type are used by methods such as newOutputStream, newByteChannel, FileChannel.open, and AsynchronousFileChannel.open when opening or creating a file.
Of particular interest is StandardOpenOptions.CREATE_NEW.
Create a new file, failing if the file already exists. The check for the existence of the file and the creation of the file if it does not exist is atomic with respect to other file system operations.
So, you can do something like this:
FileChannel mkstemp() {
Path path = Files.createTempFile(null, null);
Files.delete(path);
return FileChannel.open(path, WRITE, CREATE_NEW);
}
Implementing the same template behaviour is left as exercise to the reader.
Keep in mind that on many systems, just because a file doesn't have a name doesn't at all mean it's inaccessible. For example, on Linux open file descriptors are available in /proc/<pid>/fd/<fdno>. So you should make sure that your use of temporary files is secure even if someone knows / has a reference to the open file.
You might get a more useful answer if you specify exactly what classes of attacks you are trying to prevent.
Secure against other ordinary userid's? Yes, on any properly functioning multi-user system.
Secure against the your own userid or the superuser? No.

getClassLoader().getResource(filepath) returns a null pointer

I'm using a method to generate XML files dynamically for a research project, they get put into a loader that reads from a file path, I don't have any control over how the loader handles things (otherwise I'd pass the internal XML representation instead of monkeying with temp files), I'm using this code to save the file:
File outputs = File.createTempFile("lvlFile", ".tmp.xml");
FileWriter fw = new FileWriter(outputs);
fw.write(el.asXML());
fw.close();
// filenames is my list of file paths which gets returned and passed around
filenames.add(outputs.getAbsolutePath());
Now, I'm sure that the file in question is written to directly. If I print outputs.getAbsolutePath() and navigate there via terminal to check the files, everything is generated and written properly, so everything is correct on the filesystem. However, this code:
URL url = this.getClass().getClassLoader().getResource(_levelFile);
Where _levelFile is one of my filenames generated above, causes url to be null. The path isn't getting corrupted or anything, printing verifies that _levelFile points to the correct path. The same code has succeeded for other files. Further, the bug doesn't seem related to whether or not I use getPath(), getCanonicalPath(), or getAbsolutePath(), further setting outputs.isReadable(true) doesn't do anything.
Any ideas? Please don't offer alternatives to the Url url = structure, I don't have any control over this code*, I'm obligated to change my code so that the url is set correctly.
(*) At least without SIGNIFICANT effort rewriting a large section of the framework I'm working with, even though the current code succeeds in all other cases.
Edit:
Again, I can't use an alternative to the URL code, it's part of a loader that I can't touch. Also, the loading fails even if I set the path of the temp file to the same directory that my successfully loaded files come from.
I assume that the ClassLoader will only look for resources within the class path - which probably doesn't include /tmp. I'm not sure if it actually supports absolute path names. It might just interpret them as relative to the root of the individual class path.
How about using _levelFile.toURI().toURL() instead?
Your are creating file in file system and then trying to read it as a resource. Resource is where JVM takes its classes, i.e. the classpath. So this operation will work only if your are writing file into your classpath.
And even if this is correct be careful: if for example you are running from eclipse your process will not probably "see" the new resource until you refresh your workspace.
Now my question is: Are your really sure that you want to read files as resources. It seems that your just should create new FileInputStream(_levelFile) and read from it.
Edit
#Anonymouse is right. You are creating temporary file using 2-arg version of createTempFile(), so your file is created in your temporary directory. The chance that it is into your classpath is very low... :)
So, if you want to read it then you have to get its path or just use it when creating your input stream:
File outputs = File.createTempFile("lvlFile", ".tmp.xml");
..........................
InputStream in = new FileInputStream(ouptuts);
// now read from this stream.

Categories

Resources