File Write - Unauthorized Access Exception - ios8

Trying to save a file locally from an app running in the iOS 8 Simulator and I'm continually getting access denied exceptions.
In previous apps I've used the following code to get a valid file path:
Environment.GetFolderPath(Environment.SpecialFolder.Personal)
or
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
But I've read that with iOS 8 this has now got to be written as:
NSFileManager.DefaultManager.GetUrls(NSSearchPathDirectory.DocumentDirectory,
NSSearchPathDomain.User)[0]
So I'm using the following code to generate a file path for a .txt file and receiving an access denied exception when trying to save with it:
public void SaveMyFile(string content)
{
NSUrl[] urls;
string filePath;
//
urls = NSFileManager.DefaultManager.GetUrls(NSSearchPathDirectory.DocumentDirectory,
NSSearchPathDomain.User);
filePath = Path.Combine(urls[0].Path, "MyApp", "myFile.txt");
File.WriteAllText(filePath, content);
}
So the file path that it gives me and also denies access to is /Users/Idox/Library/Developer/CoreSimulator/Devices/92498E38-7D50-4081-8A64-83061DC00A86/data/Containers/Data/Application/C35B3E98-C9E3-4ABA-AA7F-CD8419FA0EA5/Documents/MyApp/myFile.txt.
I'm wondering if there's some setting that needs to be toggled to give the app write access to this directory or if the directory itself is invalid.
I've also done a call to Directory.Exists(string path) to check if the directory is there, which it is.

You're missing the Path property on urls[0].Path
filePath = Path.Combine(urls[0].Path, "MyApp", "myFile.txt");

This was fixed in Xamarin.iOS 8.4, so if you're using a recent version of Xamarin you can use Environment.GetFolderPath without problems (which is useful if you want to share code across platforms).

Related

Xamarin Download file to - path access denied

We have an issue with downloading any type of file from our server to our phone.
The problem that we have is that we get an access denied error every time we try to save the said file to phone External Memory.
Access to the path "/storage/emulated/0/Download/Test.txt" is denied.
We have given it all the permissions that we found in:
https://developer.android.com/training/data-storage
for both Documents and other files and Media.
Does anyone have any idea why would this be happening? The 'downloading' the file is not the problem, but the saving part is.
After Android 6.0 , we need to request the permissions in runtime . In xamarin , you could use the plugin PermissionsPlugin to request runtime permission .
Usage
using Plugin.Permissions;
using Plugin.Permissions.Abstractions;
bool shouldRequest = await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Storage);
if(shouldRequest)
{
PermissionStatus status = await CrossPermissions.Current.RequestPermissionAsync<StoragePermission>();
if(status==PermissionStatus.Granted)
{
//do something you want
}
else
{
//...
}
}
For more details about the plugin you could check the github project site .

Cannot Create New Directory in MacOS app

I am working on a mac app. I have been struggling to create a directory in "Desktop" on Mac OS. I am working on High Sierra. It was working fine, but suddenly the app is unable to create a directory in Desktop. I get the following permission error. I am using Xcode 9.3 and swift 4.1.
Error Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file “TestDir” in the folder “Desktop”." UserInfo={NSFilePath=/Users/sj/Library/Containers/com.user.TestSync/Data/Desktop/TestDir, NSUnderlyingError=0x60400044cc60 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"
Here is my code:
class DBManager: NSObject {
static func getDirectoryPath() -> URL {
let homeDirectory = URL(fileURLWithPath: NSHomeDirectory())
let desktopPath = homeDirectory.appendingPathComponent("Desktop")
let databaseFolder = desktopPath.appendingPathComponent("TestDir")
return databaseFolder
}
static func createFolderIfNotExist() {
let databaseFolder = DBManager.getDirectoryPath()
if !FileManager().fileExists(atPath: databaseFolder.path) {
do {
try FileManager.default.createDirectory(atPath: databaseFolder.path, withIntermediateDirectories: true, attributes: nil)
} catch {
print(error)
}
}
}
}
The code works fine if I am to create a directory inside "Documents". But for some reason, I am not able to create inside Desktop even if I have provided read/write access for Desktop to everyone. I have also included the screenshot of the directory where I have to create one.
I tried to create a directory inside "Downloads" but ended with same permission issue. But, again I was successful to create directory inside "Library". So, it seems that the OS is not giving permission to create inside alias directory since both Desktop and Downloads are alias.
Any help is highly appreciated.
That is because your macOS Application is running in the "App Sandbox", check your "Capabilities" tab in the target settings.
~/Library/Containers/%BundleID%/Data/Desktop is a soft link to the user's desktop, and you have no write permissions (depending on your entitlements file not even read permissions).
Depending on your use case you can
disable the sandbox mode
let the user pick a folder by opening an "Open" dialog (then you can write to this)
enable read/write in some other protected user folder (like Downloads, etc.) or
create the TestDir directly in your home directory without using any soft linked folder
Besides what mentioned by #ChaosCoder, we also need set NSOpenPanel.canCreateDirectories to true:
panel.canCreateDirectories = true
Delete the App Sandbox data from your Capabilities.
Click on your project in your file navigator, then your project in the TARGETS tab, then make sure "Signing & Capabilities" is selected, then "ALL" then double click the "x" next to "App Sandbox".

Code a File Path that works in both OSX and Windows (dotnet core)

I have to save files in my dotnet core application. I originally developed in windows; but when I ported the code to try developing on a mac, the file path is no longer valid (i.e. "c:\content..."). Is there a way to reference a file path, in my code, that will work in both situations? We deploy to azure... so the windows file path must there too.
FileInfo fileInfo = new FileInfo("c:\\Content\\SalesOrderOutput\\" +
fileName.txt);
FileStream stream = fileInfo.OpenWrite();
Use Path.Combine method like this:
internal static readonly FileInfo Mp4WithAudio = new FileInfo(Path.Combine(Environment.CurrentDirectory, "Resources", "input.mp4"));
Code from https://github.com/tomaszzmuda/Xabe.FFmpeg/blob/c8cc4232b5afa2860ede3be63a680d754ed73002/Xabe.FFmpeg.Test/Resources.cs

mkdir error. permission denied. google api

I am attempting to use a service account with Google's API to add a calendar event using php. I have this working perfectly on a site already. When i moved it to another site on the same server, i suddenly began to receive the following error messages:
~PHP Warning: mkdir(): Permission denied in Google/Cache/File.php
~Uncaught exception 'Google_Cache_Exception' with message 'Could not create storage directory: in Google/Cache/File.php
The two environments are identical as far as i can tell
~Same server
~Same permissions on all files/folders
~Same credentials
~Both URLS authorized in Google's console
I checked with my server to see if something in the upvoted answer here could be the issue, but was assured that everything was set up correctly.
I've done a lot of searching and reading, but can't imagine what might be causing these errors when everything works perfectly from the other site.
Any help would be much appreciated!
In case anyone comes upon this: I solved this by following the advise given here:
A client error occurred: Could not create storage directory: /tmp/Google_Client/00
specifically, i manually added nested folders (google and cache) inside my tmp directory and then set the path to it for google using this code (from the link above):
$config = new Google_Config();
$config->setClassConfig('Google_Cache_File', array('directory' => '../../tmp/google/cache'));
// Here I set a relative folder to avoid pb on permissions to a folder like /tmp that is not permitted on my mutualised host
$client = new Google_Client($config);
Add this PHP code to your script:
$client = new Google_Client();
$client->setCache(new Google_Cache_File('/path/to/shared/cache'));
In case also that anyone needs to do this. I'm working with Codeigniter and recently moved to osx el capitan on mac from windows 7. My google cache folder had the admin permissions read and write but the error persists: mkdir permission denied, on google/cache/file.php
I looked at my code where I load the google api and added>
$config = new Google_Config();
$config->setClassConfig('Google_Cache_File', array('directory' => 'application/third_party/Google/src/Google/Cache/'));
$client = new Google_Client($config);
So with those line you set your cache folder.
Hope this helps in the future as It helped me.

Use relative path in Firefox extension

I develop Firefox extension with bundled executable file which should be run on browser startup.
To run process I need get nsIFile or nsILocalFile instance which points to executable file.
I know one solution how to get it using directory service:
var file = Components.classes["#mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties).get("ProfD", Components.interfaces.nsIFile);
file.append("extensions");
file.append("<extension id>");
file.append("<relative path>");
But this solution has two disadvantages:
It doesn't work in development mode, when instead of installed extension I have only text file with real extension path
I'm not sure that it will work on all Firefox configurations because of hardcoded "extensions" part of the path
So is there any nicer way to run executable file which comes with Firefox extension?
Thanks.
You are making way too many assumptions about the directory structure of the Firefox profile - don't. The Add-on Manager API lets you get the path of a file inside the extension, you should use it:
Components.utils.import("resource://gre/modules/AddonManager.jsm");
AddonManager.getAddonByID("<extension id>", function(addon)
{
var uri = addon.getResourceURI("<relative path>");
var file = uri.QueryInterface(Components.interfaces.nsIFileURL).file;
...
});
A restartless addon's startup function (in the bootstrap.js file) will receive, as its first parameter, the path where the addon is installed. You can then play various tricks to read files inside the .jar file, if any: see https://github.com/protz/GMail-Conversation-View/blob/master/bootstrap.js#L55 as an example.
In a non-restartless case, I must confess I don't have much of an idea :).
I found this thread looking for a way to reference a path to an image hosted in extension's directory from a content script. Here's a solution:
Include your files in web_accessible_resources in the extension's manifest.
"web_accessible_resources": [
"images/*"
]
Absolute paths to these resources contain randomly generated UUID, therefore we're using runtime.getUrl() giving it the path relative to manifest.json. Example:
let myImg = document.createElement('img');
myImg.src = browser.runtime.getURL("images/my-img.png")

Resources