Beispiel #1
0
        /// <summary>
        /// 指定したパスの暗号化ファイルセットを開きます.
        /// </summary>
        /// <param name="foldernames">暗号化ファイルセットが存在するフォルダ.</param>
        /// <param name="filename">暗号化ファイルセットの名前.</param>
        /// <param name="key">暗号化ファイルセットに適用するキー.</param>
        /// <param name="createOption">trueに設定した場合,ファイルやフォルダが存在しない場合は新規作成されます.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="IOException"></exception>
        public static async Task <CryptoFileset> OpenOrCreateCryptoFilesetAsync(IEnumerable <string> foldernames, string filename, byte[] key, bool createOption)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (key.Length == 0)
            {
                throw new ArgumentException($"{nameof(key)} must have a element at least.");
            }
            var alreadyExisted = await ApplicationStorage.Exists(foldernames, filename);

            if (!alreadyExisted)
            {
                if (createOption)
                {
                    await ApplicationStorage.GetOrCreateFileAsync(foldernames, filename);
                }
                else
                {
                    throw new FileNotFoundException("The specified file does not exist.");
                }
            }
            var storage = await ApplicationStorage.GetOrCreateFileAsync(foldernames, filename);

            CryptoFileset cryptoFileset = new CryptoFileset()
            {
                targetFoldernames = foldernames,
                targetFilename    = filename,
                Key         = new byte[key.Length],
                originalKey = new byte[key.Length],
            };

            if (alreadyExisted)
            {
                try
                {
                    cryptoFileset.stream = await storage.OpenStreamForReadAsync();

                    //中身が空ならまだセーブしてない状態なので,読み込まずに終了
                    if (cryptoFileset.stream.Length == 0)
                    {
                        return(cryptoFileset);
                    }
                    //
                    var fileCount = cryptoFileset.ReadInt32();
                    while (cryptoFileset.files.Count < fileCount)
                    {
                        CodedFile file = new CodedFile()
                        {
                            //ファイル名のサイズを読み込む
                            NameSize = cryptoFileset.ReadInt32(),
                            //ファイルサイズを読み込む
                            OriginalSize = cryptoFileset.ReadInt32()
                        };
                        file.Size = file.OriginalSize;
                        //ファイル名を取得
                        file.Name = Encoding.Unicode.GetString(cryptoFileset.ReadBytes(file.NameSize), 0, file.NameSize);
                        //ファイルの中身は読み飛ばす。シークして次のファイルデータの先頭位置へ
                        cryptoFileset.stream.Seek(file.OriginalSize, SeekOrigin.Current);
                        //読み込んだ内容を追加
                        cryptoFileset.files.Add(file);
                    }
                }
                catch
                {
                    throw new IOException("Cannot read the file.");
                }
            }
            return(cryptoFileset);
        }