You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pu...@apache.org on 2012/07/14 02:24:42 UTC

[33/46] rejigger to the new structure

http://git-wip-us.apache.org/repos/asf/incubator-cordova-wp7/blob/62d32605/templates/standalone/cordovalib/Commands/File.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/cordovalib/Commands/File.cs b/templates/standalone/cordovalib/Commands/File.cs
new file mode 100644
index 0000000..83492cf
--- /dev/null
+++ b/templates/standalone/cordovalib/Commands/File.cs
@@ -0,0 +1,1406 @@
+/*  
+	Licensed under the Apache License, Version 2.0 (the "License");
+	you may not use this file except in compliance with the License.
+	You may obtain a copy of the License at
+	
+	http://www.apache.org/licenses/LICENSE-2.0
+	
+	Unless required by applicable law or agreed to in writing, software
+	distributed under the License is distributed on an "AS IS" BASIS,
+	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+	See the License for the specific language governing permissions and
+	limitations under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.IsolatedStorage;
+using System.Runtime.Serialization;
+using System.Security;
+using System.Text;
+using System.Diagnostics;
+
+namespace WP7CordovaClassLib.Cordova.Commands
+{
+    /// <summary>
+    /// Provides access to isolated storage
+    /// </summary>
+    public class File : BaseCommand
+    {
+        // Error codes
+        public const int NOT_FOUND_ERR = 1;
+        public const int SECURITY_ERR = 2;
+        public const int ABORT_ERR = 3;
+        public const int NOT_READABLE_ERR = 4;
+        public const int ENCODING_ERR = 5;
+        public const int NO_MODIFICATION_ALLOWED_ERR = 6;
+        public const int INVALID_STATE_ERR = 7;
+        public const int SYNTAX_ERR = 8;
+        public const int INVALID_MODIFICATION_ERR = 9;
+        public const int QUOTA_EXCEEDED_ERR = 10;
+        public const int TYPE_MISMATCH_ERR = 11;
+        public const int PATH_EXISTS_ERR = 12;
+
+        // File system options
+        public const int TEMPORARY = 0;
+        public const int PERSISTENT = 1;
+        public const int RESOURCE = 2;
+        public const int APPLICATION = 3;
+
+        /// <summary>
+        /// Temporary directory name
+        /// </summary>
+        private readonly string TMP_DIRECTORY_NAME = "tmp";
+
+        /// <summary>
+        /// Represents error code for callback
+        /// </summary>
+        [DataContract]
+        public class ErrorCode
+        {
+            /// <summary>
+            /// Error code
+            /// </summary>
+            [DataMember(IsRequired = true, Name = "code")]
+            public int Code { get; set; }
+
+            /// <summary>
+            /// Creates ErrorCode object
+            /// </summary>
+            public ErrorCode(int code)
+            {
+                this.Code = code;
+            }
+        }
+
+        /// <summary>
+        /// Represents File action options.
+        /// </summary>
+        [DataContract]
+        public class FileOptions
+        {
+            /// <summary>
+            /// File path
+            /// </summary>
+            /// 
+            private string _fileName;
+            [DataMember(Name = "fileName")]
+            public string FilePath
+            {
+                get
+                {
+                    return this._fileName;
+                }
+
+                set
+                {
+                    int index = value.IndexOfAny(new char[] { '#', '?' });
+                    this._fileName = index > -1 ? value.Substring(0, index) : value;
+                }
+            }
+
+            /// <summary>
+            /// Full entryPath
+            /// </summary>
+            [DataMember(Name = "fullPath")]
+            public string FullPath { get; set; }
+
+            /// <summary>
+            /// Directory name
+            /// </summary>
+            [DataMember(Name = "dirName")]
+            public string DirectoryName { get; set; }
+
+            /// <summary>
+            /// Path to create file/directory
+            /// </summary>
+            [DataMember(Name = "path")]
+            public string Path { get; set; }
+
+            /// <summary>
+            /// The encoding to use to encode the file's content. Default is UTF8.
+            /// </summary>
+            [DataMember(Name = "encoding")]
+            public string Encoding { get; set; }
+
+            /// <summary>
+            /// Uri to get file
+            /// </summary>
+            /// 
+            private string _uri;
+            [DataMember(Name = "uri")]
+            public string Uri
+            {
+                get
+                {
+                    return this._uri;
+                }
+
+                set
+                {
+                    int index = value.IndexOfAny(new char[] { '#', '?' });
+                    this._uri = index > -1 ? value.Substring(0, index) : value;
+                }
+            }
+
+            /// <summary>
+            /// Size to truncate file
+            /// </summary>
+            [DataMember(Name = "size")]
+            public long Size { get; set; }
+
+            /// <summary>
+            /// Data to write in file
+            /// </summary>
+            [DataMember(Name = "data")]
+            public string Data { get; set; }
+
+            /// <summary>
+            /// Position the writing starts with
+            /// </summary>
+            [DataMember(Name = "position")]
+            public int Position { get; set; }
+
+            /// <summary>
+            /// Type of file system requested
+            /// </summary>
+            [DataMember(Name = "type")]
+            public int FileSystemType { get; set; }
+
+            /// <summary>
+            /// New file/directory name
+            /// </summary>
+            [DataMember(Name = "newName")]
+            public string NewName { get; set; }
+
+            /// <summary>
+            /// Destination directory to copy/move file/directory
+            /// </summary>
+            [DataMember(Name = "parent")]
+            public string Parent { get; set; }
+
+            /// <summary>
+            /// Options for getFile/getDirectory methods
+            /// </summary>
+            [DataMember(Name = "options")]
+            public CreatingOptions CreatingOpt { get; set; }
+
+            /// <summary>
+            /// Creates options object with default parameters
+            /// </summary>
+            public FileOptions()
+            {
+                this.SetDefaultValues(new StreamingContext());
+            }
+
+            /// <summary>
+            /// Initializes default values for class fields.
+            /// Implemented in separate method because default constructor is not invoked during deserialization.
+            /// </summary>
+            /// <param name="context"></param>
+            [OnDeserializing()]
+            public void SetDefaultValues(StreamingContext context)
+            {
+                this.Encoding = "UTF-8";
+                this.FilePath = "";
+                this.FileSystemType = -1;
+            }
+        }
+
+        /// <summary>
+        /// Stores image info
+        /// </summary>
+        [DataContract]
+        public class FileMetadata
+        {
+            [DataMember(Name = "fileName")]
+            public string FileName { get; set; }
+
+            [DataMember(Name = "fullPath")]
+            public string FullPath { get; set; }
+
+            [DataMember(Name = "type")]
+            public string Type { get; set; }
+
+            [DataMember(Name = "lastModifiedDate")]
+            public string LastModifiedDate { get; set; }
+
+            [DataMember(Name = "size")]
+            public long Size { get; set; }
+
+            public FileMetadata(string filePath)
+            {
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    if ((string.IsNullOrEmpty(filePath)) || (!isoFile.FileExists(filePath)))
+                    {
+                        throw new FileNotFoundException("File doesn't exist");
+                    }
+                    //TODO get file size the other way if possible                
+                    using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filePath, FileMode.Open, FileAccess.Read, isoFile))
+                    {
+                        this.Size = stream.Length;
+                    }
+                    this.FullPath = filePath;
+                    this.FileName = System.IO.Path.GetFileName(filePath);
+                    this.Type = MimeTypeMapper.GetMimeType(filePath);
+                    this.LastModifiedDate = isoFile.GetLastWriteTime(filePath).DateTime.ToString();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Represents file or directory modification metadata
+        /// </summary>
+        [DataContract]
+        public class ModificationMetadata
+        {
+            /// <summary>
+            /// Modification time
+            /// </summary>
+            [DataMember]
+            public string modificationTime { get; set; }
+        }
+
+        /// <summary>
+        /// Represents file or directory entry
+        /// </summary>
+        [DataContract]
+        public class FileEntry
+        {
+
+            /// <summary>
+            /// File type
+            /// </summary>
+            [DataMember(Name = "isFile")]
+            public bool IsFile { get; set; }
+
+            /// <summary>
+            /// Directory type
+            /// </summary>
+            [DataMember(Name = "isDirectory")]
+            public bool IsDirectory { get; set; }
+
+            /// <summary>
+            /// File/directory name
+            /// </summary>
+            [DataMember(Name = "name")]
+            public string Name { get; set; }
+
+            /// <summary>
+            /// Full path to file/directory
+            /// </summary>
+            [DataMember(Name = "fullPath")]
+            public string FullPath { get; set; }
+
+            public static FileEntry GetEntry(string filePath)
+            {
+                FileEntry entry = null;
+                try
+                {
+                    entry = new FileEntry(filePath);
+
+                }
+                catch (Exception)
+                {
+                    Debug.WriteLine("Exception in GetEntry for filePath :: " + filePath);
+                }
+                return entry;
+            }
+
+            /// <summary>
+            /// Creates object and sets necessary properties
+            /// </summary>
+            /// <param name="filePath"></param>
+            public FileEntry(string filePath)
+            {
+                if (string.IsNullOrEmpty(filePath))
+                {
+                    throw new ArgumentException();
+                }
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    this.IsFile = isoFile.FileExists(filePath);
+                    this.IsDirectory = isoFile.DirectoryExists(filePath);
+                    if (IsFile)
+                    {
+                        this.Name = Path.GetFileName(filePath);
+                    }
+                    else if (IsDirectory)
+                    {
+                        this.Name = this.GetDirectoryName(filePath);
+                        if (string.IsNullOrEmpty(Name))
+                        {
+                            this.Name = "/";
+                        }
+                    }
+                    else
+                    {
+                        throw new FileNotFoundException();
+                    }
+
+                    this.FullPath = new Uri(filePath).LocalPath;
+                }
+            }
+
+            /// <summary>
+            /// Extracts directory name from path string
+            /// Path should refer to a directory, for example \foo\ or /foo.
+            /// </summary>
+            /// <param name="path"></param>
+            /// <returns></returns>
+            private string GetDirectoryName(string path)
+            {
+                if (String.IsNullOrEmpty(path))
+                {
+                    return path;
+                }
+
+                string[] split = path.Split(new char[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
+                if (split.Length < 1)
+                {
+                    return null;
+                }
+                else
+                {
+                    return split[split.Length - 1];
+                }
+            }
+        }
+
+
+        /// <summary>
+        /// Represents info about requested file system
+        /// </summary>
+        [DataContract]
+        public class FileSystemInfo
+        {
+            /// <summary>
+            /// file system type
+            /// </summary>
+            [DataMember(Name = "name", IsRequired = true)]
+            public string Name { get; set; }
+
+            /// <summary>
+            /// Root directory entry
+            /// </summary>
+            [DataMember(Name = "root", EmitDefaultValue = false)]
+            public FileEntry Root { get; set; }
+
+            /// <summary>
+            /// Creates class instance
+            /// </summary>
+            /// <param name="name"></param>
+            /// <param name="rootEntry"> Root directory</param>
+            public FileSystemInfo(string name, FileEntry rootEntry = null)
+            {
+                Name = name;
+                Root = rootEntry;
+            }
+        }
+
+        [DataContract]
+        public class CreatingOptions
+        {
+            /// <summary>
+            /// Create file/directory if is doesn't exist
+            /// </summary>
+            [DataMember(Name = "create")]
+            public bool Create { get; set; }
+
+            /// <summary>
+            /// Generate an exception if create=true and file/directory already exists
+            /// </summary>
+            [DataMember(Name = "exclusive")]
+            public bool Exclusive { get; set; }
+
+
+        }
+
+        /// <summary>
+        /// File options
+        /// </summary>
+        private FileOptions fileOptions;
+
+        private bool LoadFileOptions(string options)
+        {
+            try
+            {
+                fileOptions = JSON.JsonHelper.Deserialize<FileOptions>(options);
+            }
+            catch (Exception)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                return false;
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Gets amount of free space available for Isolated Storage
+        /// </summary>
+        /// <param name="options">No options is needed for this method</param>
+        public void getFreeDiskSpace(string options)
+        {
+            try
+            {
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, isoFile.AvailableFreeSpace));
+                }
+            }
+            catch (IsolatedStorageException)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Check if file exists
+        /// </summary>
+        /// <param name="options">File path</param>
+        public void testFileExists(string options)
+        {
+            IsDirectoryOrFileExist(options, false);
+        }
+
+        /// <summary>
+        /// Check if directory exists
+        /// </summary>
+        /// <param name="options">directory name</param>
+        public void testDirectoryExists(string options)
+        {
+            IsDirectoryOrFileExist(options, true);
+        }
+
+        /// <summary>
+        /// Check if file or directory exist
+        /// </summary>
+        /// <param name="options">File path/Directory name</param>
+        /// <param name="isDirectory">Flag to recognize what we should check</param>
+        public void IsDirectoryOrFileExist(string options, bool isDirectory)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    bool isExist;
+                    if (isDirectory)
+                    {
+                        isExist = isoFile.DirectoryExists(fileOptions.DirectoryName);
+                    }
+                    else
+                    {
+                        isExist = isoFile.FileExists(fileOptions.FilePath);
+                    }
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, isExist));
+                }
+            }
+            catch (IsolatedStorageException) // default handler throws INVALID_MODIFICATION_ERR
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                }
+            }
+
+        }
+
+        public void readAsDataURL(string options)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+                string base64URL = null;
+
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    if (!isoFile.FileExists(fileOptions.FilePath))
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                        return;
+                    }
+                    string mimeType = MimeTypeMapper.GetMimeType(fileOptions.FilePath);
+
+                    using (IsolatedStorageFileStream stream = isoFile.OpenFile(fileOptions.FilePath, FileMode.Open, FileAccess.Read))
+                    {
+                        string base64String = GetFileContent(stream);
+                        base64URL = "data:" + mimeType + ";base64," + base64String;
+                    }
+                }
+
+                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, base64URL));
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                }
+            }
+        }
+
+        public void readAsText(string options)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+                string text;
+
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    if (!isoFile.FileExists(fileOptions.FilePath))
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                        return;
+                    }
+                    Encoding encoding = Encoding.GetEncoding(fileOptions.Encoding);
+
+                    using (TextReader reader = new StreamReader(isoFile.OpenFile(fileOptions.FilePath, FileMode.Open, FileAccess.Read), encoding))
+                    {
+                        text = reader.ReadToEnd();
+                    }
+                }
+
+                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, text));
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                }
+            }
+        }
+
+
+        public void truncate(string options)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+                long streamLength = 0;
+
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    if (!isoFile.FileExists(fileOptions.FilePath))
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                        return;
+                    }
+
+                    using (FileStream stream = new IsolatedStorageFileStream(fileOptions.FilePath, FileMode.Open, FileAccess.ReadWrite, isoFile))
+                    {
+                        if (0 <= fileOptions.Size && fileOptions.Size < stream.Length)
+                        {
+                            stream.SetLength(fileOptions.Size);
+                        }
+
+                        streamLength = stream.Length;
+                    }
+                }
+
+                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, streamLength));
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                }
+            }
+        }
+
+        public void write(string options)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+                if (string.IsNullOrEmpty(fileOptions.Data))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                    return;
+                }
+
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    // create the file if not exists
+                    if (!isoFile.FileExists(fileOptions.FilePath))
+                    {
+                        var file = isoFile.CreateFile(fileOptions.FilePath);
+                        file.Close();
+                    }
+
+                    using (FileStream stream = new IsolatedStorageFileStream(fileOptions.FilePath, FileMode.Open, FileAccess.ReadWrite, isoFile))
+                    {
+                        if (0 <= fileOptions.Position && fileOptions.Position < stream.Length)
+                        {
+                            stream.SetLength(fileOptions.Position);
+                        }
+                        using (BinaryWriter writer = new BinaryWriter(stream))
+                        {
+                            writer.Seek(0, SeekOrigin.End);
+                            writer.Write(fileOptions.Data.ToCharArray());
+                        }
+                    }
+                }
+
+                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, fileOptions.Data.Length));
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Look up metadata about this entry.
+        /// </summary>
+        /// <param name="options">filePath to entry</param>   
+        public void getMetadata(string options)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    if (isoFile.FileExists(fileOptions.FullPath))
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK,
+                            new ModificationMetadata() { modificationTime = isoFile.GetLastWriteTime(fileOptions.FullPath).DateTime.ToString() }));
+                    }
+                    else if (isoFile.DirectoryExists(fileOptions.FullPath))
+                    {
+                        string modTime = isoFile.GetLastWriteTime(fileOptions.FullPath).DateTime.ToString();
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new ModificationMetadata() { modificationTime = modTime }));
+                    }
+                    else
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    }
+
+                }
+            }
+            catch (IsolatedStorageException)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                }
+            }
+
+        }
+
+
+        /// <summary>
+        /// Returns a File that represents the current state of the file that this FileEntry represents.
+        /// </summary>
+        /// <param name="filePath">filePath to entry</param>
+        /// <returns></returns>
+        public void getFileMetadata(string options)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+                FileMetadata metaData = new FileMetadata(fileOptions.FullPath);
+                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, metaData));
+            }
+            catch (IsolatedStorageException)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Look up the parent DirectoryEntry containing this Entry. 
+        /// If this Entry is the root of IsolatedStorage, its parent is itself.
+        /// </summary>
+        /// <param name="options"></param>
+        public void getParent(string options)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+
+                if (string.IsNullOrEmpty(fileOptions.FullPath))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    return;
+                }
+
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    FileEntry entry;
+
+                    if (isoFile.FileExists(fileOptions.FullPath) || isoFile.DirectoryExists(fileOptions.FullPath))
+                    {
+                        string path = this.GetParentDirectory(fileOptions.FullPath);
+                        entry = FileEntry.GetEntry(path);
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry));
+                    }
+                    else
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    }
+
+                }
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                }
+            }
+        }
+
+        public void remove(string options)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    if (isoFile.FileExists(fileOptions.FullPath))
+                    {
+                        isoFile.DeleteFile(fileOptions.FullPath);
+                    }
+                    else
+                    {
+                        if (isoFile.DirectoryExists(fileOptions.FullPath))
+                        {
+                            isoFile.DeleteDirectory(fileOptions.FullPath);
+                        }
+                        else
+                        {
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                            return;
+                        }
+                    }
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
+                }
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                }
+            }
+        }
+
+        public void removeRecursively(string options)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            if (string.IsNullOrEmpty(fileOptions.FullPath))
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                return;
+            }
+            removeDirRecursively(fileOptions.FullPath);
+            DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
+        }
+
+        public void readEntries(string options)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+                if (string.IsNullOrEmpty(fileOptions.FullPath))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    return;
+                }
+
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    if (isoFile.DirectoryExists(fileOptions.FullPath))
+                    {
+                        string path = File.AddSlashToDirectory(fileOptions.FullPath);
+                        List<FileEntry> entries = new List<FileEntry>();
+                        string[] files = isoFile.GetFileNames(path + "*");
+                        string[] dirs = isoFile.GetDirectoryNames(path + "*");
+                        foreach (string file in files)
+                        {
+                            entries.Add(FileEntry.GetEntry(path + file));
+                        }
+                        foreach (string dir in dirs)
+                        {
+                            entries.Add(FileEntry.GetEntry(path + dir + "/"));
+                        }
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entries));
+                    }
+                    else
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    }
+                }
+            }
+            //catch (SecurityException)
+            //{
+            //    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR));
+            //}
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                }
+            }
+        }
+
+        public void requestFileSystem(string options)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+                if (fileOptions.Size != 0)
+                {
+                    using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                    {
+                        long availableSize = isoFile.AvailableFreeSpace;
+                        if (fileOptions.Size > availableSize)
+                        {
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, QUOTA_EXCEEDED_ERR));
+                            return;
+                        }
+                    }
+                }
+
+                if (fileOptions.FileSystemType == PERSISTENT)
+                {
+                    // TODO: this should be in it's own folder to prevent overwriting of the app assets, which are also in ISO
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("persistent", FileEntry.GetEntry("/"))));
+                }
+                else if (fileOptions.FileSystemType == TEMPORARY)
+                {
+                    using (IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForApplication())
+                    {
+                        if (!isoStorage.FileExists(TMP_DIRECTORY_NAME))
+                        {
+                            isoStorage.CreateDirectory(TMP_DIRECTORY_NAME);
+                        }
+                    }
+
+                    string tmpFolder = "/" + TMP_DIRECTORY_NAME + "/";
+
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("temporary", FileEntry.GetEntry(tmpFolder))));
+                }
+                else if (fileOptions.FileSystemType == RESOURCE)
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("resource")));
+                }
+                else if (fileOptions.FileSystemType == APPLICATION)
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("application")));
+                }
+                else
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                }
+
+            }
+            //catch (SecurityException)
+            //{
+            //    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR));
+            //}
+            //catch (FileNotFoundException)
+            //{
+            //    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+            //}
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                }
+            }
+        }
+
+        public void resolveLocalFileSystemURI(string options)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+                if (!Uri.IsWellFormedUriString(fileOptions.Uri, UriKind.Absolute))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR));
+                    return;
+                }
+
+                Uri fileUri = new Uri(Uri.UnescapeDataString(fileOptions.Uri));
+                string path = fileUri.LocalPath;
+
+                // TODO: research this :
+                //if (Uri.UriSchemeFile == fileUri.Scheme)
+                //{
+                //}
+
+                FileEntry uriEntry = FileEntry.GetEntry(path);
+                if (uriEntry != null)
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, uriEntry));
+                }
+                else
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                }
+            }
+            //catch (SecurityException)
+            //{
+            //    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR));
+            //}
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                }
+            }
+        }
+
+        public void copyTo(string options)
+        {
+            TransferTo(options, false);
+        }
+
+        public void moveTo(string options)
+        {
+            TransferTo(options, true);
+        }
+
+        public void getFile(string options)
+        {
+            GetFileOrDirectory(options, false);
+        }
+
+        public void getDirectory(string options)
+        {
+            GetFileOrDirectory(options, true);
+        }
+
+        #region internal functionality
+
+        /// <summary>
+        /// Retrieves the parent directory name of the specified path,
+        /// </summary>
+        /// <param name="path">Path</param>
+        /// <returns>Parent directory name</returns>
+        private string GetParentDirectory(string path)
+        {
+            if (String.IsNullOrEmpty(path) || path == "/")
+            {
+                return "/";
+            }
+
+            if (path.EndsWith(@"/") || path.EndsWith(@"\"))
+            {
+                return this.GetParentDirectory(Path.GetDirectoryName(path));
+            }
+
+            return Path.GetDirectoryName(path);
+        }
+
+        private void removeDirRecursively(string fullPath)
+        {
+            try
+            {
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    if (isoFile.DirectoryExists(fullPath))
+                    {
+                        string path = File.AddSlashToDirectory(fullPath);
+                        string[] files = isoFile.GetFileNames(path + "*");
+                        if (files.Length > 0)
+                        {
+                            foreach (string file in files)
+                            {
+                                isoFile.DeleteFile(path + file);
+                            }
+                        }
+                        string[] dirs = isoFile.GetDirectoryNames(path + "*");
+                        if (dirs.Length > 0)
+                        {
+                            foreach (string dir in dirs)
+                            {
+                                removeDirRecursively(path + dir + "/");
+                            }
+                        }
+                        isoFile.DeleteDirectory(Path.GetDirectoryName(path));
+                    }
+                    else
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                }
+            }
+        }
+
+        private void TransferTo(string options, bool move)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+
+            try
+            {
+                if ((fileOptions.Parent == null) || (string.IsNullOrEmpty(fileOptions.Parent)) || (string.IsNullOrEmpty(fileOptions.FullPath)))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    return;
+                }
+
+                string parentPath = File.AddSlashToDirectory(fileOptions.Parent);
+                string currentPath = fileOptions.FullPath;
+
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    bool isFileExist = isoFile.FileExists(currentPath);
+                    bool isDirectoryExist = isoFile.DirectoryExists(currentPath);
+                    bool isParentExist = isoFile.DirectoryExists(parentPath);
+
+                    if (((!isFileExist) && (!isDirectoryExist)) || (!isParentExist))
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                        return;
+                    }
+                    string newName;
+                    string newPath;
+                    if (isFileExist)
+                    {
+                        newName = (string.IsNullOrEmpty(fileOptions.NewName))
+                                    ? Path.GetFileName(currentPath)
+                                    : fileOptions.NewName;
+
+                        newPath = Path.Combine(parentPath, newName);
+
+                        // remove destination file if exists, in other case there will be exception
+                        if (!newPath.Equals(currentPath) && isoFile.FileExists(newPath))
+                        {
+                            isoFile.DeleteFile(newPath);
+                        }
+
+                        if (move)
+                        {
+                            isoFile.MoveFile(currentPath, newPath);
+                        }
+                        else
+                        {
+                            isoFile.CopyFile(currentPath, newPath, true);
+                        }
+                    }
+                    else
+                    {
+                        newName = (string.IsNullOrEmpty(fileOptions.NewName))
+                                    ? currentPath
+                                    : fileOptions.NewName;
+
+                        newPath = Path.Combine(parentPath, newName);
+
+                        if (move)
+                        {
+
+                            // remove destination directory if exists, in other case there will be exception
+                            // target directory should be empty
+                            if (!newPath.Equals(currentPath) && isoFile.DirectoryExists(newPath))
+                            {
+                                isoFile.DeleteDirectory(newPath);
+                            }
+
+                            isoFile.MoveDirectory(currentPath, newPath);
+                        }
+                        else
+                        {
+                            this.CopyDirectory(currentPath, newPath, isoFile);
+                        }
+                    }
+                    FileEntry entry = FileEntry.GetEntry(newPath);
+                    if (entry != null)
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry));
+                    }
+                    else
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    }
+                }
+
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                }
+            }
+        }
+
+        private bool HandleException(Exception ex)
+        {
+            bool handled = false;
+            if (ex is SecurityException)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR));
+                handled = true;
+            }
+            else if (ex is FileNotFoundException)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                handled = true;
+            }
+            else if (ex is ArgumentException)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR));
+                handled = true;
+            }
+            else if (ex is IsolatedStorageException)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_MODIFICATION_ERR));
+                handled = true;
+            }
+            else if (ex is DirectoryNotFoundException)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                handled = true;
+            }
+            return handled;
+        }
+
+        private void CopyDirectory(string sourceDir, string destDir, IsolatedStorageFile isoFile)
+        {
+            string path = File.AddSlashToDirectory(sourceDir);
+
+            if (!isoFile.DirectoryExists(destDir))
+            {
+                isoFile.CreateDirectory(destDir);
+            }
+            destDir = File.AddSlashToDirectory(destDir);
+            string[] files = isoFile.GetFileNames(path + "*");
+            if (files.Length > 0)
+            {
+                foreach (string file in files)
+                {
+                    isoFile.CopyFile(path + file, destDir + file);
+                }
+            }
+            string[] dirs = isoFile.GetDirectoryNames(path + "*");
+            if (dirs.Length > 0)
+            {
+                foreach (string dir in dirs)
+                {
+                    CopyDirectory(path + dir, destDir + dir, isoFile);
+                }
+            }
+        }
+
+        private void GetFileOrDirectory(string options, bool getDirectory)
+        {
+            if (!LoadFileOptions(options))
+            {
+                return;
+            }
+            if (fileOptions == null)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                return;
+            }
+
+            try
+            {
+                if ((string.IsNullOrEmpty(fileOptions.Path)) || (string.IsNullOrEmpty(fileOptions.FullPath)))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    return;
+                }
+
+                string path;
+
+                try
+                {
+                    path = Path.Combine(fileOptions.FullPath + "/", fileOptions.Path);
+                }
+                catch (Exception)
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR));
+                    return;
+                }
+
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    bool isFile = isoFile.FileExists(path);
+                    bool isDirectory = isoFile.DirectoryExists(path);
+                    bool create = (fileOptions.CreatingOpt == null) ? false : fileOptions.CreatingOpt.Create;
+                    bool exclusive = (fileOptions.CreatingOpt == null) ? false : fileOptions.CreatingOpt.Exclusive;
+                    if (create)
+                    {
+                        if (exclusive && (isoFile.FileExists(path) || isoFile.DirectoryExists(path)))
+                        {
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, PATH_EXISTS_ERR));
+                            return;
+                        }
+
+                        if ((getDirectory) && (!isDirectory))
+                        {
+                            isoFile.CreateDirectory(path);
+                        }
+                        else
+                        {
+                            if ((!getDirectory) && (!isFile))
+                            {
+
+                                IsolatedStorageFileStream fileStream = isoFile.CreateFile(path);
+                                fileStream.Close();
+                            }
+                        }
+
+                    }
+                    else
+                    {
+                        if ((!isFile) && (!isDirectory))
+                        {
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                            return;
+                        }
+                        if (((getDirectory) && (!isDirectory)) || ((!getDirectory) && (!isFile)))
+                        {
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, TYPE_MISMATCH_ERR));
+                            return;
+                        }
+                    }
+                    FileEntry entry = FileEntry.GetEntry(path);
+                    if (entry != null)
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry));
+                    }
+                    else
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                if (!this.HandleException(ex))
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                }
+            }
+        }
+
+        private static string AddSlashToDirectory(string dirPath)
+        {
+            if (dirPath.EndsWith("/"))
+            {
+                return dirPath;
+            }
+            else
+            {
+                return dirPath + "/";
+            }
+        }
+
+        /// <summary>
+        /// Returns file content in a form of base64 string
+        /// </summary>
+        /// <param name="stream">File stream</param>
+        /// <returns>Base64 representation of the file</returns>
+        private string GetFileContent(Stream stream)
+        {
+            int streamLength = (int)stream.Length;
+            byte[] fileData = new byte[streamLength + 1];
+            stream.Read(fileData, 0, streamLength);
+            stream.Close();
+            return Convert.ToBase64String(fileData);
+        }
+
+        #endregion
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-wp7/blob/62d32605/templates/standalone/cordovalib/Commands/FileTransfer.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/cordovalib/Commands/FileTransfer.cs b/templates/standalone/cordovalib/Commands/FileTransfer.cs
new file mode 100644
index 0000000..dbdc8ab
--- /dev/null
+++ b/templates/standalone/cordovalib/Commands/FileTransfer.cs
@@ -0,0 +1,521 @@
+/*  
+	Licensed under the Apache License, Version 2.0 (the "License");
+	you may not use this file except in compliance with the License.
+	You may obtain a copy of the License at
+	
+	http://www.apache.org/licenses/LICENSE-2.0
+	
+	Unless required by applicable law or agreed to in writing, software
+	distributed under the License is distributed on an "AS IS" BASIS,
+	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+	See the License for the specific language governing permissions and
+	limitations under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.IsolatedStorage;
+using System.Net;
+using System.Runtime.Serialization;
+using System.Windows;
+using System.Security;
+using System.Diagnostics;
+
+namespace WP7CordovaClassLib.Cordova.Commands
+{
+    public class FileTransfer : BaseCommand
+    {
+        public class DownloadRequestState
+        {
+            // This class stores the State of the request.
+            public HttpWebRequest request;
+            public DownloadOptions options;
+
+            public DownloadRequestState()
+            {
+                request = null;
+                options = null;
+            }
+        }
+
+        /// <summary>
+        /// Boundary symbol
+        /// </summary>       
+        private string Boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
+
+        // Error codes
+        public const int FileNotFoundError = 1;
+        public const int InvalidUrlError = 2;
+        public const int ConnectionError = 3;
+
+        /// <summary>
+        /// Options for downloading file
+        /// </summary>
+        [DataContract]
+        public class DownloadOptions
+        {
+            /// <summary>
+            /// File path to download to
+            /// </summary>
+            [DataMember(Name = "filePath", IsRequired = true)]
+            public string FilePath { get; set; }
+
+            /// <summary>
+            /// Server address to the file to download
+            /// </summary>
+            [DataMember(Name = "url", IsRequired = true)]
+            public string Url { get; set; }
+        }
+
+        /// <summary>
+        /// Options for uploading file
+        /// </summary>
+        [DataContract]
+        public class UploadOptions
+        {
+            /// <summary>
+            /// File path to upload
+            /// </summary>
+            [DataMember(Name = "filePath", IsRequired = true)]
+            public string FilePath { get; set; }
+
+            /// <summary>
+            /// Server address
+            /// </summary>
+            [DataMember(Name = "server", IsRequired = true)]
+            public string Server { get; set; }
+
+            /// <summary>
+            /// File key
+            /// </summary>
+            [DataMember(Name = "fileKey")]
+            public string FileKey { get; set; }
+
+            /// <summary>
+            /// File name on the server
+            /// </summary>
+            [DataMember(Name = "fileName")]
+            public string FileName { get; set; }
+
+            /// <summary>
+            /// File Mime type
+            /// </summary>
+            [DataMember(Name = "mimeType")]
+            public string MimeType { get; set; }
+
+
+            /// <summary>
+            /// Additional options
+            /// </summary>
+            [DataMember(Name = "params")]
+            public string Params { get; set; }
+
+            /// <summary>
+            /// Flag to recognize if we should trust every host (only in debug environments)
+            /// </summary>
+            [DataMember(Name = "debug")]
+            public bool Debug { get; set; }
+
+            /// <summary>
+            /// Creates options object with default parameters
+            /// </summary>
+            public UploadOptions()
+            {
+                this.SetDefaultValues(new StreamingContext());
+            }
+
+            /// <summary>
+            /// Initializes default values for class fields.
+            /// Implemented in separate method because default constructor is not invoked during deserialization.
+            /// </summary>
+            /// <param name="context"></param>
+            [OnDeserializing()]
+            public void SetDefaultValues(StreamingContext context)
+            {
+                this.FileKey = "file";
+                this.FileName = "image.jpg";
+                this.MimeType = "image/jpeg";
+            }
+
+        }
+
+        /// <summary>
+        /// Uploading response info
+        /// </summary>
+        [DataContract]
+        public class FileUploadResult
+        {
+            /// <summary>
+            /// Amount of sent bytes
+            /// </summary>
+            [DataMember(Name = "bytesSent")]
+            public long BytesSent { get; set; }
+
+            /// <summary>
+            /// Server response code
+            /// </summary>
+            [DataMember(Name = "responseCode")]
+            public long ResponseCode { get; set; }
+
+            /// <summary>
+            /// Server response
+            /// </summary>
+            [DataMember(Name = "response", EmitDefaultValue = false)]
+            public string Response { get; set; }
+
+            /// <summary>
+            /// Creates FileUploadResult object with response values
+            /// </summary>
+            /// <param name="bytesSent">Amount of sent bytes</param>
+            /// <param name="responseCode">Server response code</param>
+            /// <param name="response">Server response</param>
+            public FileUploadResult(long bytesSent, long responseCode, string response)
+            {
+                this.BytesSent = bytesSent;
+                this.ResponseCode = responseCode;
+                this.Response = response;
+            }
+        }
+
+        /// <summary>
+        /// Represents transfer error codes for callback
+        /// </summary>
+        [DataContract]
+        public class FileTransferError
+        {
+            /// <summary>
+            /// Error code
+            /// </summary>
+            [DataMember(Name = "code", IsRequired = true)]
+            public int Code { get; set; }
+
+            /// <summary>
+            /// The source URI
+            /// </summary>
+            [DataMember(Name = "source", IsRequired = true)]
+            public string Source { get; set; }
+
+            /// <summary>
+            /// The target URI
+            /// </summary>
+            [DataMember(Name = "target", IsRequired = true)]
+            public string Target { get; set; }
+
+            /// <summary>
+            /// The http status code response from the remote URI
+            /// </summary>
+            [DataMember(Name = "http_status", IsRequired = true)]
+            public int HttpStatus { get; set; }
+
+            /// <summary>
+            /// Creates FileTransferError object
+            /// </summary>
+            /// <param name="errorCode">Error code</param>
+            public FileTransferError(int errorCode)
+            {
+                this.Code = errorCode;
+                this.Source = null;
+                this.Target = null;
+                this.HttpStatus = 0;
+            }
+            public FileTransferError(int errorCode, string source, string target, int status)
+            {
+                this.Code = errorCode;
+                this.Source = source;
+                this.Target = target;
+                this.HttpStatus = status;
+            }
+        }
+
+        /// <summary>
+        /// Upload options
+        /// </summary>
+        private UploadOptions uploadOptions;
+
+        /// <summary>
+        /// Bytes sent
+        /// </summary>
+        private long bytesSent;
+
+        /// <summary>
+        /// sends a file to a server
+        /// </summary>
+        /// <param name="options">Upload options</param>
+        public void upload(string options)
+        {
+            Debug.WriteLine("options = " + options);
+            options = options.Replace("{}", "null");
+
+            try
+            {
+                try
+                {
+                    uploadOptions = JSON.JsonHelper.Deserialize<UploadOptions>(options);
+                }
+                catch (Exception)
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                    return;
+                }
+
+                Uri serverUri;
+                try
+                {
+                    serverUri = new Uri(uploadOptions.Server);
+                }
+                catch (Exception)
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, new FileTransferError(InvalidUrlError, uploadOptions.Server, null, 0)));
+                    return;
+                }
+                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(serverUri);
+                webRequest.ContentType = "multipart/form-data;boundary=" + Boundary;
+                webRequest.Method = "POST";
+                webRequest.BeginGetRequestStream(WriteCallback, webRequest);
+            }
+            catch (Exception)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, new FileTransferError(ConnectionError)));
+            }
+        }
+
+        public void download(string options)
+        {
+            DownloadOptions downloadOptions = null;
+            HttpWebRequest webRequest = null;
+
+            try
+            {
+                downloadOptions = JSON.JsonHelper.Deserialize<DownloadOptions>(options);
+            }
+            catch (Exception)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                return;
+            }
+
+            try
+            {
+                webRequest = (HttpWebRequest)WebRequest.Create(downloadOptions.Url);
+            }
+            catch (Exception)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, new FileTransferError(InvalidUrlError, downloadOptions.Url, null, 0)));
+                return;
+            }
+
+            if (downloadOptions != null && webRequest != null)
+            {
+                DownloadRequestState state = new DownloadRequestState();
+                state.options = downloadOptions;
+                state.request = webRequest;
+                webRequest.BeginGetResponse(new AsyncCallback(downloadCallback), state);
+            }
+
+
+
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="asynchronousResult"></param>
+        private void downloadCallback(IAsyncResult asynchronousResult)
+        {
+            DownloadRequestState reqState = (DownloadRequestState)asynchronousResult.AsyncState;
+            HttpWebRequest request = reqState.request;
+
+            try
+            {
+                HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
+
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    // create the file if not exists
+                    if (!isoFile.FileExists(reqState.options.FilePath))
+                    {
+                        var file = isoFile.CreateFile(reqState.options.FilePath);
+                        file.Close();
+                    }
+
+                    using (FileStream fileStream = new IsolatedStorageFileStream(reqState.options.FilePath, FileMode.Open, FileAccess.Write, isoFile))
+                    {
+                        long totalBytes = response.ContentLength;
+                        int bytesRead = 0;
+                        using (BinaryReader reader = new BinaryReader(response.GetResponseStream()))
+                        {
+
+                            using (BinaryWriter writer = new BinaryWriter(fileStream))
+                            {
+                                int BUFFER_SIZE = 1024;
+                                byte[] buffer;
+
+                                while (true)
+                                {
+                                    buffer = reader.ReadBytes(BUFFER_SIZE);
+                                    // fire a progress event ?
+                                    bytesRead += buffer.Length;
+                                    if (buffer.Length > 0)
+                                    {
+                                        writer.Write(buffer);
+                                    }
+                                    else
+                                    {
+                                        writer.Close();
+                                        reader.Close();
+                                        fileStream.Close();
+                                        break;
+                                    }
+                                }
+                            }
+
+                        }
+
+
+                    }
+                }
+                WP7CordovaClassLib.Cordova.Commands.File.FileEntry entry = new WP7CordovaClassLib.Cordova.Commands.File.FileEntry(reqState.options.FilePath);
+                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry));
+            }
+            catch (IsolatedStorageException)
+            {
+                // Trying to write the file somewhere within the IsoStorage.
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, new FileTransferError(FileNotFoundError)));
+            }
+            catch (SecurityException)
+            {
+                // Trying to write the file somewhere not allowed.
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, new FileTransferError(FileNotFoundError)));
+            }
+            catch (WebException webex)
+            {
+                // TODO: probably need better work here to properly respond with all http status codes back to JS
+                // Right now am jumping through hoops just to detect 404.
+                if ((webex.Status == WebExceptionStatus.ProtocolError && ((HttpWebResponse)webex.Response).StatusCode == HttpStatusCode.NotFound) || webex.Status == WebExceptionStatus.UnknownError)
+                {
+                    // Weird MSFT detection of 404... seriously... just give us the f(*&#$@ status code as a number ffs!!!
+                    // "Numbers for HTTP status codes? Nah.... let's create our own set of enums/structs to abstract that stuff away."
+                    // FACEPALM
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, new FileTransferError(ConnectionError, null, null, 404)));
+                }
+                else
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, new FileTransferError(ConnectionError)));
+                }
+            }
+            catch (Exception)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, new FileTransferError(FileNotFoundError)));
+            }
+        }
+
+
+
+        /// <summary>
+        /// Read file from Isolated Storage and sends it to server
+        /// </summary>
+        /// <param name="asynchronousResult"></param>
+        private void WriteCallback(IAsyncResult asynchronousResult)
+        {
+            try
+            {
+                HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
+                using (Stream requestStream = (webRequest.EndGetRequestStream(asynchronousResult)))
+                {
+                    string lineStart = "--";
+                    string lineEnd = Environment.NewLine;
+                    byte[] boundaryBytes = System.Text.Encoding.UTF8.GetBytes(lineStart + Boundary + lineEnd);
+                    string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"" + lineEnd + lineEnd + "{1}" + lineEnd;
+
+                    if (uploadOptions.Params != null)
+                    {
+
+                        string[] arrParams = uploadOptions.Params.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries);
+
+                        foreach (string param in arrParams)
+                        {
+                            string[] split = param.Split('=');
+                            string key = split[0];
+                            string val = split[1];
+                            requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
+                            string formItem = string.Format(formdataTemplate, key, val);
+                            byte[] formItemBytes = System.Text.Encoding.UTF8.GetBytes(formItem);
+                            requestStream.Write(formItemBytes, 0, formItemBytes.Length);
+                        }
+                        requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
+                    }
+                    using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                    {
+                        if (!isoFile.FileExists(uploadOptions.FilePath))
+                        {
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, new FileTransferError(FileNotFoundError, uploadOptions.Server, uploadOptions.FilePath, 0)));
+                            return;
+                        }
+
+                        using (FileStream fileStream = new IsolatedStorageFileStream(uploadOptions.FilePath, FileMode.Open, isoFile))
+                        {
+                            string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" + lineEnd + "Content-Type: {2}" + lineEnd + lineEnd;
+                            string header = string.Format(headerTemplate, uploadOptions.FileKey, uploadOptions.FileName, uploadOptions.MimeType);
+                            byte[] headerBytes = System.Text.Encoding.UTF8.GetBytes(header);
+                            requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
+                            requestStream.Write(headerBytes, 0, headerBytes.Length);
+                            byte[] buffer = new byte[4096];
+                            int bytesRead = 0;
+
+                            while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
+                            {
+                                requestStream.Write(buffer, 0, bytesRead);
+                                bytesSent += bytesRead;
+                            }
+                        }
+                        byte[] endRequest = System.Text.Encoding.UTF8.GetBytes(lineEnd + lineStart + Boundary + lineStart + lineEnd);
+                        requestStream.Write(endRequest, 0, endRequest.Length);
+                    }
+                }
+                webRequest.BeginGetResponse(ReadCallback, webRequest);
+            }
+            catch (Exception)
+            {
+                Deployment.Current.Dispatcher.BeginInvoke(() =>
+                {
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, new FileTransferError(ConnectionError)));
+                });
+            }
+        }
+
+        /// <summary>
+        /// Reads response into FileUploadResult
+        /// </summary>
+        /// <param name="asynchronousResult"></param>
+        private void ReadCallback(IAsyncResult asynchronousResult)
+        {
+            try
+            {
+                HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
+                using (HttpWebResponse response = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult))
+                {
+                    using (Stream streamResponse = response.GetResponseStream())
+                    {
+                        using (StreamReader streamReader = new StreamReader(streamResponse))
+                        {
+                            string responseString = streamReader.ReadToEnd();
+                            Deployment.Current.Dispatcher.BeginInvoke(() =>
+                            {
+                                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileUploadResult(bytesSent, (long)response.StatusCode, responseString)));
+                            });
+                        }
+                    }
+                }
+            }
+            catch (Exception)
+            {
+                Deployment.Current.Dispatcher.BeginInvoke(() =>
+                {
+                    FileTransferError transferError = new FileTransferError(ConnectionError, uploadOptions.Server, uploadOptions.FilePath, 403);
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, transferError));
+                });
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-wp7/blob/62d32605/templates/standalone/cordovalib/Commands/GeoLocation.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/cordovalib/Commands/GeoLocation.cs b/templates/standalone/cordovalib/Commands/GeoLocation.cs
new file mode 100644
index 0000000..49a4787
--- /dev/null
+++ b/templates/standalone/cordovalib/Commands/GeoLocation.cs
@@ -0,0 +1,34 @@
+/*  
+	Licensed under the Apache License, Version 2.0 (the "License");
+	you may not use this file except in compliance with the License.
+	You may obtain a copy of the License at
+	
+	http://www.apache.org/licenses/LICENSE-2.0
+	
+	Unless required by applicable law or agreed to in writing, software
+	distributed under the License is distributed on an "AS IS" BASIS,
+	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+	See the License for the specific language governing permissions and
+	limitations under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Threading;
+using System.Device.Location;
+
+namespace WP7CordovaClassLib.Cordova.Commands
+{
+    /// <summary>
+    /// This is a command stub, the browser provides the correct implementation.  We use this to trigger the static analyzer that we require this permission 
+    /// </summary>
+    public class GeoLocation
+    {
+        /* Unreachable code, by design -jm */
+        private void triggerGeoInclusion()
+        {
+            new GeoCoordinateWatcher();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-wp7/blob/62d32605/templates/standalone/cordovalib/Commands/ImageExifHelper.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/cordovalib/Commands/ImageExifHelper.cs b/templates/standalone/cordovalib/Commands/ImageExifHelper.cs
new file mode 100644
index 0000000..626726b
--- /dev/null
+++ b/templates/standalone/cordovalib/Commands/ImageExifHelper.cs
@@ -0,0 +1,222 @@
+/*  
+	Licensed under the Apache License, Version 2.0 (the "License");
+	you may not use this file except in compliance with the License.
+	You may obtain a copy of the License at
+	
+	http://www.apache.org/licenses/LICENSE-2.0
+	
+	Unless required by applicable law or agreed to in writing, software
+	distributed under the License is distributed on an "AS IS" BASIS,
+	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+	See the License for the specific language governing permissions and
+	limitations under the License.
+ * 
+ * Portions of this code are based on Simon McKenzie's ExifLib 
+ * http://www.codeproject.com/Articles/36342/ExifLib-A-Fast-Exif-Data-Extractor-for-NET-2-0
+*/
+
+
+
+using System;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+using System.IO;
+using System.Windows.Media.Imaging;
+using System.Diagnostics;
+
+namespace WP7CordovaClassLib.Cordova.Commands
+{
+    public class ImageExifOrientation
+    {
+        public const int Portrait = 1;
+        public const int PortraitUpsideDown = 3;
+        public const int LandscapeLeft = 6;
+        public const int LandscapeRight = 8;
+    }
+
+    public class ImageExifHelper
+    {
+
+        public static Stream RotateStream(Stream stream, int angle)
+        {
+            stream.Position = 0;
+            if (angle % 90 != 0 || angle < 0)
+            {
+                throw new ArgumentException();
+            }
+            if (angle % 360 == 0)
+            {
+                return stream;
+            }
+
+            angle = angle % 360;
+
+            BitmapImage bitmap = new BitmapImage();
+            bitmap.SetSource(stream);
+            WriteableBitmap wbSource = new WriteableBitmap(bitmap);
+
+            WriteableBitmap wbTarget = null;
+
+            int srcPixelWidth = wbSource.PixelWidth;
+            int srcPixelHeight = wbSource.PixelHeight;
+
+            if (angle % 180 == 0)
+            {
+                wbTarget = new WriteableBitmap(srcPixelWidth, srcPixelHeight);
+            }
+            else
+            {
+                wbTarget = new WriteableBitmap(srcPixelHeight, srcPixelWidth);
+            }
+
+            int destPixelWidth = wbTarget.PixelWidth;
+            int[] srcPxls = wbSource.Pixels;
+            int[] destPxls = wbTarget.Pixels;
+
+            // this ugly if/else is to avoid a conditional check for every pixel
+            if (angle == 90)
+            {
+                for (int x = 0; x < srcPixelWidth; x++)
+                {
+                    for (int y = 0; y < srcPixelHeight; y++)
+                    {
+                        destPxls[(srcPixelHeight - y - 1) + (x * destPixelWidth)] = srcPxls[x + y * srcPixelWidth];
+                    }
+                }
+            }
+            else if (angle == 180)
+            {
+                for (int x = 0; x < srcPixelWidth; x++)
+                {
+                    for (int y = 0; y < srcPixelHeight; y++)
+                    {
+                        destPxls[(srcPixelWidth - x - 1) + (srcPixelHeight - y - 1) * srcPixelWidth] = srcPxls[x + y * srcPixelWidth];
+                    }
+                }
+            }
+            else if (angle == 270)
+            {
+                for (int x = 0; x < srcPixelWidth; x++)
+                {
+                    for (int y = 0; y < srcPixelHeight; y++)
+                    {
+                        destPxls[y + (srcPixelWidth - x - 1) * destPixelWidth] = srcPxls[x + y * srcPixelWidth];
+                    }
+                }
+            }
+
+            MemoryStream targetStream = new MemoryStream();
+            wbTarget.SaveJpeg(targetStream, destPixelWidth, wbTarget.PixelHeight, 0, 100);
+            return targetStream;
+        }
+
+        public static int getImageOrientationFromStream(Stream imgStream)
+        {
+
+            // 0xFFD8 : jpgHeader
+            // 0xFFE1 :
+            // 0x???? : length of exif data
+            // 0x????, 0x???? : Chars 'E','x','i','f'
+            // 0x0000 : 2 empty bytes
+            // <== mark beginning of tags SIZE:ID:VALUE
+            // 0x???? : 'II' or 'MM' for Intel or Motorola ( always getting II on my WP7 devices ), determins littleEndian-ness
+            // 0x002A : marker value
+            // 0x???? : offset to the Image File Data
+
+            // XXXX possible space before actual tag data ... we skip to mark + offset
+
+            // 0x???? number of exif tags present
+
+            // make sure we are at the begining
+            imgStream.Seek(0, SeekOrigin.Begin);
+            BinaryReader reader = new BinaryReader(imgStream);
+
+            byte[] jpgHdr = reader.ReadBytes(2); // always (0xFFD8)
+
+            byte start = reader.ReadByte(); // 0xFF
+            byte index = reader.ReadByte(); // 0xE1
+
+            while (start == 0xFF && index != 0xE1) // This never seems to happen, todo: optimize
+            {
+                // Get the data length
+                ushort dLen = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
+                // skip along
+                reader.BaseStream.Seek(dLen - 2, SeekOrigin.Current);
+                start = reader.ReadByte();
+                index = reader.ReadByte();
+            }
+
+            // It's only success if we found the 0xFFE1 marker
+            if (start != 0xFF || index != 0xE1)
+            {
+                //   throw new Exception("Could not find Exif data block");
+                Debug.WriteLine("Did not find EXIF data");
+                return 0;
+            }
+
+            // read 2 byte length of EXIF data
+            ushort exifLen = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
+            String exif = ""; // build the string
+            for (var n = 0; n < 4; n++)
+            {
+                exif += reader.ReadChar();
+            }
+            if (exif != "Exif")
+            {
+                // did not find exif data ...
+                Debug.WriteLine("Did not find EXIF data");
+                return 0;
+            }
+
+            // read 2 empty bytes
+            //ushort emptyBytes = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
+            reader.ReadBytes(2);
+
+            long headerMark = reader.BaseStream.Position; // where are we now <==
+
+            //bool isLEndian = (reader.ReadChar() + "" + reader.ReadChar()) == "II";
+            reader.ReadBytes(2); // 'II' or 'MM', but we don't care
+
+            if (0x002A != BitConverter.ToUInt16(reader.ReadBytes(2), 0))
+            {
+                Debug.WriteLine("Error in data != 0x002A");
+                return 0;
+            }
+
+            // Get the offset to the IFD (image file directory)
+            ushort imgOffset = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
+
+            imgStream.Position = headerMark + imgOffset;
+            ushort tagCount = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
+            for (ushort x = 0; x < tagCount; x++)
+            {
+                // Orientation = 0x112, aka 274
+                if (0x112 == BitConverter.ToUInt16(reader.ReadBytes(2), 0))
+                {
+                    ushort dType = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
+                    // don't care ..
+                    uint comps = reader.ReadUInt32();
+                    byte[] tagData = reader.ReadBytes(4);
+                    int orientation = (int)tagData[0];
+                    Debug.WriteLine("orientation = " + orientation.ToString());
+                    return orientation;
+                    // 6 means rotate clockwise 90 deg
+                    // 8 means rotate counter-clockwise 90 deg
+                    // 1 means all is good
+                    // 3 means flip vertical
+                }
+                // skip to the next item, 12 bytes each
+                reader.BaseStream.Seek(10, SeekOrigin.Current);
+            }
+            return 0;
+        }
+
+    }
+}