NiceLabel Portal uses Microsoft Silverlight as its underlying technology. Because Silverlight is a browser-based plug-in, it has by default the lowest security privileges to ensure a safe browsing experience. This restriction introduces a number of challenges, especially when it comes to working with files. For example you do not have direct access to files on your drive from NiceLabel Portal. There is a solution though that might solve most of the problems.
Isolated storage is a great way to store data on the end user’s local computer. It’s flexible in that it works in all modes of Silverlight operation (in-browser, out-of-browser, elevated out-of-browser) and works as a virtual file system. Isolated storage is tied to individual user and lies outside of the browser cache. This means that even if a user clears browser history, files within isolated storage will remain intact.
To work with Isolated Storage in NiceLabel Portal you will have to use Python scripts. Here are scripts for some of the most common scenarios you might encounter when working with Isolated Storage.
Basics of Isolated Storage
The System.IO.IsolatedStorage namespace provides the functionality to work with a user’s isolated storage area. This area can be accessed through the IsolatedStorageFile class, which exposes two methods that retrieve an IsolatedStorageFile. These methods are GetUserStoreForApplication and GetUserStoreForSite. The GetUserStoreForApplication can be used to retrieve a user’s isolated storage for a specific Silverlight application, defined by the full URL to the .xap. The GetUserStoreForSite method gets a user’s isolated storage for the entire domain.
from System.IO.IsolatedStorage import * store = IsolatedStorageFile.GetUserStoreForApplication()
Once you’ve retrieved an IsolatedStorageFile, you can use it to manage a virtual file system, which gives you the ability to work with files and directories.
Checking if Isolated Storage is enabled
Before using Isolated Storage you should check if it is enabled because user can disable it in the “Microsoft Silverlight Configuration” dialog box under the “Application Storage” page). To configure the Silverlight plug-in (not just the Application Storage) a user can right-click the opened solution in the NiceLabel Portal or simply find Microsoft Silverlight in the Windows Start menu.
To programmatically check if Isolated Storage is enabled you can use the following code:
from System.IO.IsolatedStorage import * isEnabled = IsolatedStorageFile.IsEnabled if (isEnabled): # do something else: # display error message
Checking the Available Space
By default in-browser application gets 1 MB of free space. The IsolatedStorageFile class exposes two read-only properties that inform you of an isolated storage area’s memory situation. The first property, Quota, holds the total number of bytes allocated to the storage area. The other property, AvailableFreeSpace, represents the number of bytes remaining in the Isolated Storage.
from System.IO.IsolatedStorage import * store = IsolatedStorageFile.GetUserStoreForApplication() usedSize.Value = "Used size: " + str(store.UsedSize) + " bytes" quota.Value = "Quota: " + str(store.Quota) + " bytes" availableFreeSpace.Value = "Available free space: " + str(store.AvailableFreeSpace) + " bytes"
Requesting more space
To increase the Isolated Storage quota, you must call the IncreaseQuotaTo method from a user-initiated event, such as in an event handler for a button-click event. Unfortunately because of the way action execution is implemented in NiceLabel Portal you will not be able to increase the quota by a Python script even if you have the script defined on the “On click” event of the button object. You will have to write your own application that calls the above mentioned method or contact NiceLabel support for help.
Listing the contents of the virtual file system
The IsolatedStorageFile class provides two methods that enable you to retrieve the items within a storage area. The first method, GetDirectoryNames, enables you to get the names of the directories that match a certain pattern; the GetFileNames method allows you to search for files that match a particular filter. To perform the search just provide the path to the file or directory. If the directory or file name is found an array with one element will be returned. Otherwise, an empty set will be returned. Wildcard characters can also be used to match file names (the * character matches any number of characters, and the ? character matcher any single character.
from System.IO.IsolatedStorage import * store = IsolatedStorageFile.GetUserStoreForApplication() results1 = store.GetFileNames("*.txt"); results2 = store.GetFileNames("Folder/*"); results3 = store.GetFileNames("configfile*"); results4 = store.GetDirectoryNames("*"); # convert array of directory names into a string separated by commas if len(results4) > 0: all = ",".join(results)
Creating directories within Isolated Storage
The IsolatedStorageFile class has a method called CreateDirectory that enables you to create a directory within the isolated storage space.
from System.IO.IsolatedStorage import * store = IsolatedStorageFile.GetUserStoreForApplication() store.CreateDirectory("Folder1") store.CreateDirectory("Folder1/Sub/Leaf")
The first call to CreateDirectory is pretty simple; it creates a subdirectory under an existing
directory. The second call shows an additional feature. If you provide an absolute path to a subdirectory further down the line, all missing directories along the way will automatically be added. Once a directory exists, you can create files in it.
Checking if an item exists
from System.IO.IsolatedStorage import * store = IsolatedStorageFile.GetUserStoreForApplication() msg2.Value = str(store.FileExists(fileName.Value)) if store.FileExists(fileName.Value): msg.Value = "File already exists." else: msg.Value = "File does not exist!"
Removing items from Isolated Storage
from System.IO.IsolatedStorage import * store = IsolatedStorageFile.GetUserStoreForApplication() if store.FileExists(fileName.Value): store.DeleteFile(fileName.Value) if store.DirectoryExists(directoryName.Value): store.DeleteDirectory(directoryName.Value)
There are a few problems that you should be aware of when working with Isolated Storage.
- Administrators can set disk quota per user and assembly which means there is no guarantee on space available. So it is very important to add exception handling to your code.
- Computer can be locked down by administrative security policies preventing applications from writing to the Isolated Storage.
- Even though Isolated Storage is placed in a hidden folder it is possible, with a bit of effort, to find the folder. Therefore the data stored is not completely secure as users can change or remove files.
Isolated Storage Best Practices
When you use isolated storage, following these guidelines will help you avoid problems and make the most of the protection isolated storage provides.
- Wrap all calls to isolated storage within try/catch blocks to be resilient to potential IsolatedStorageExceptions, which can be thrown if isolated storage is disabled or if the store has been deleted.
- Keep isolated storage paths as small as possible to prevent the internal full path from reaching the 260-character limit.
- Encrypt sensitive data stored in isolated storage.
- Use IsolatedStorageSettings to store objects and simple settings in isolated storage.
from System.IO.IsolatedStorage import * # Write to application settings settings = IsolatedStorageSettings.ApplicationSettings settings.Add("FirstName", FirstName.Value) settings.Add("LastName", LastName.Value) # Read from application settings FirstName.Value = settings["FirstName"] LastName.Value = settings["LastName"] # Remove just first name from application settings settings.Remove("FirstName") # Clear all settings settings.Clear()
Please note that all code samples in this post will only work in NiceLabel Portal. Even though you will write them in NiceForm you will only be able to test them in NiceLabel Portal.
You can find all the samples in one sample NiceForm file (it is in a .zip file so you will have to uncompress it first).