Exemple #1
0
        static private void AddNewDriveItem(FileMetadata_Info newdata)
        {
            ItemInfo value;

            if (newdata == null)
            {
                return;
            }
            if (newdata.status == "AVAILABLE")
            {
                // exist item
                if (DriveTree.TryGetValue(newdata.id, out value))
                {
                    if (value.info != null)
                    {
                        foreach (var p in value.info.parents)
                        {
                            ItemInfo value2;
                            if (DriveTree.TryGetValue(p, out value2))
                            {
                                ItemInfo outvalue;
                                while (!value2.children.TryRemove(value.info.id, out outvalue))
                                {
                                    if (!value2.children.TryGetValue(value.info.id, out outvalue))
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    value.info = newdata;
                }
                else
                {
                    DriveTree[newdata.id] = new ItemInfo(newdata);
                }
                foreach (var p in newdata.parents)
                {
                    if (DriveTree.TryGetValue(p, out value))
                    {
                        value.children[newdata.id] = DriveTree[newdata.id];
                    }
                    else
                    {
                        DriveTree[p] = new ItemInfo(null);
                        DriveTree[p].children[newdata.id] = DriveTree[newdata.id];
                    }
                }
                if (newdata.isRoot ?? false)
                {
                    root_id = newdata.id;
                }
            }
            else if (newdata.status == "TRASH" || newdata.status == "PURGED")
            {
                // deleted item
                DeleteDriveItem(newdata);
            }
        }
        public AmazonDriveSeekableStream(AmazonDrive Drive, FileMetadata_Info downitem) : base()
        {
            this.Drive = Drive;
            targetItem = downitem;
            FileSize   = targetItem.OrignalLength ?? 0;

            if (FileSize <= 0)
            {
                return;
            }

            slots = new SlotMaster(Drive, downitem, cts.Token);

            _Position = 0;

            if (downitem.contentProperties?.size > ConfigAPI.FilenameChangeTrickSize && !Regex.IsMatch(downitem.name, "^[\x20-\x7e]*$"))
            {
                OrgFilename = downitem.name;
                Config.Log.LogOut("AmazonDriveSeekableStream : <BIG FILE> temporary filename change");
                Config.Log.LogOut("AmazonDriveSeekableStream : orgnal name : " + OrgFilename);
                Drive.renameItem(downitem.id, ConfigAPI.temporaryFilename + downitem.id).Wait();
            }

            lastslot  = ((downitem.OrignalLength ?? 0) - 1) / AmazonDriveStreamConfig.slotsize;
            lockslot1 = AmazonDriveStreamConfig.lockslotfirstnum;
            lockslot2 = lastslot - AmazonDriveStreamConfig.lockslotlastnum;
            if (lockslot2 < lockslot1)
            {
                lockslot2 = lockslot1;
            }
            slots.CreateTask(0);
            slots.CreateTask(lockslot2);
            slots.CreateTask(lockslot1);
            slots.CreateTask(lockslot1 + AmazonDriveStreamConfig.preforwardnum);
        }
 public SlotTask(AmazonDrive Drive, FileMetadata_Info targetItem, CancellationToken ct = default(CancellationToken))
 {
     cts             = CancellationTokenSource.CreateLinkedTokenSource(ct, Internal_cts.Token);
     this.Drive      = Drive;
     this.targetItem = targetItem;
     lastslot        = ((targetItem.OrignalLength ?? 0) - 1) / AmazonDriveStreamConfig.slotsize;
 }
Exemple #4
0
        public static async Task <bool> EncryptFilename(string uploadfilename, string enckey, string checkpoint, CancellationToken ct = default(CancellationToken))
        {
            int retry = 30;

            while (--retry > 0)
            {
                var child = (await GetChanges(checkpoint, ct).ConfigureAwait(false)).Where(x => x.name.Contains(uploadfilename)).LastOrDefault();
                if (child?.status == "AVAILABLE")
                {
                    Config.Log.LogOut("EncryptFilename");
                    using (var ms = new MemoryStream())
                    {
                        byte[] plain = Encoding.UTF8.GetBytes(enckey);
                        ms.Write(plain, 0, plain.Length);
                        ms.Position = 0;
                        using (var enc = new CryptCTR.AES256CTR_CryptStream(ms, child.id))
                        {
                            byte[] buf = new byte[ms.Length];
                            enc.Read(buf, 0, buf.Length);
                            string cryptname = "";
                            foreach (var c in buf)
                            {
                                cryptname += (char)('\u2800' + c);
                            }
                            int retry2 = 30;
                            FileMetadata_Info reItem = null;
                            while (--retry2 > 0)
                            {
                                try
                                {
                                    if (reItem == null)
                                    {
                                        reItem = await Drive.renameItem(id : child.id, newname : cryptname, ct : ct).ConfigureAwait(false);
                                    }
                                }
                                catch { }
                                var child2 = (await GetChanges(checkpoint: ChangeCheckpoint, ct: ct).ConfigureAwait(false)).Where(x => x.name.Contains(cryptname)).LastOrDefault();
                                if (reItem != null && child2?.status == "AVAILABLE")
                                {
                                    AmazonDriveTree[reItem.id].IsEncrypted = CryptMethods.Method1_CTR;
                                    AmazonDriveTree[reItem.id].ReloadCryptedMethod1();
                                    break;
                                }
                                await Task.Delay(2000).ConfigureAwait(false);
                            }
                            return(true);
                        }
                    }
                }
                await Task.Delay(2000).ConfigureAwait(false);
            }
            return(false);
        }
Exemple #5
0
 public static string DecryptFilename(FileMetadata_Info downloaditem)
 {
     using (var ms = new MemoryStream())
     {
         string cryptname = downloaditem?.name;
         if (string.IsNullOrEmpty(cryptname))
         {
             return(null);
         }
         byte[] buf = new byte[cryptname.Length];
         int    i   = 0;
         foreach (var c in cryptname)
         {
             if (c < '\u2800' || c > '\u28ff')
             {
                 return(null);
             }
             buf[i++] = (byte)(c - '\u2800');
         }
         ms.Write(buf, 0, i);
         ms.Position = 0;
         using (var dec = new CryptCTR.AES256CTR_CryptStream(ms, downloaditem.id))
         {
             byte[] plain = new byte[i];
             dec.Read(plain, 0, plain.Length);
             var plainname = Encoding.UTF8.GetString(plain);
             if (plainname.IndexOfAny(Path.GetInvalidFileNameChars()) < 0)
             {
                 if (Regex.IsMatch(plainname ?? "", ".*?\\.[a-z0-9]{8}$"))
                 {
                     return(plainname);
                 }
                 else
                 {
                     return(null);
                 }
             }
             else
             {
                 return(null);
             }
         }
     }
 }
Exemple #6
0
        static private void DeleteDriveItem(FileMetadata_Info deldata)
        {
            ItemInfo value;

            if (deldata == null)
            {
                return;
            }
            if (DriveTree.TryGetValue(deldata.id, out value))
            {
                var children = value.children.Values.ToArray();
                foreach (var child in children)
                {
                    DeleteDriveItem(child.info);
                }
                ItemInfo outitem;
                while (!DriveTree.TryRemove(deldata.id, out outitem))
                {
                    if (!DriveTree.TryGetValue(deldata.id, out outitem))
                    {
                        break;
                    }
                }
            }
            foreach (var p in deldata.parents)
            {
                if (DriveTree.TryGetValue(p, out value))
                {
                    ItemInfo outvalue;
                    while (!value.children.TryRemove(deldata.id, out outvalue))
                    {
                        if (!value.children.TryGetValue(deldata.id, out outvalue))
                        {
                            break;
                        }
                    }
                }
            }
        }
Exemple #7
0
        static string FindItemsID(string[] path_str, FileMetadata_Info root = null)
        {
            if (path_str.Length == 0)
            {
                return(root?.id);
            }
            while (path_str.Length > 0 && string.IsNullOrEmpty(path_str.First()))
            {
                path_str = path_str.Skip(1).ToArray();
            }
            if (path_str.Length == 0)
            {
                return(root?.id);
            }

            if (root == null)
            {
                root = DriveData.AmazonDriveTree[DriveData.AmazonDriveRootID].info;
            }

            var children = DriveData.AmazonDriveTree[root.id].children.Select(x => x.Value);

            foreach (var c in children)
            {
                if (c.DisplayName == path_str[0])
                {
                    if (c.info.kind == "FOLDER")
                    {
                        return(FindItemsID(path_str.Skip(1).ToArray(), c.info));
                    }
                    else
                    {
                        return(null);
                    }
                }
            }
            return(null);
        }
Exemple #8
0
 public RemoteItemInfo(FileMetadata_Info info, string path, string name)
 {
     this.info = info;
     this.path = path;
     this.name = name;
 }
Exemple #9
0
        static FileMetadata_Info[] FindItems(string[] path_str, bool recursive = false, FileMetadata_Info root = null)
        {
            List <FileMetadata_Info> ret = new List <FileMetadata_Info>();

            if (root == null)
            {
                root = DriveData.AmazonDriveTree[DriveData.AmazonDriveRootID].info;
            }
            if (!(path_str?.Length > 0))
            {
                ret.Add(root);
                return(ret.ToArray());
            }
            while (path_str.Length > 0 && string.IsNullOrEmpty(path_str.First()))
            {
                path_str = path_str.Skip(1).ToArray();
            }
            if (path_str.Length == 0)
            {
                ret.Add(root);
                return(ret.ToArray());
            }

            var children = DriveData.AmazonDriveTree[root.id].children.Select(x => x.Value);

            foreach (var c in children)
            {
                if (c.DisplayName == path_str[0]
                    ||
                    ((path_str[0].Contains('*') || path_str[0].Contains('?')) &&
                     Regex.IsMatch(c.DisplayName, Regex.Escape(path_str[0]).Replace("\\*", ".*").Replace("\\?", "."))))
                {
                    if (c.info.kind == "FOLDER")
                    {
                        ret.AddRange(FindItems((recursive && path_str[0] == "*") ? path_str : path_str.Skip(1).ToArray(), recursive, c.info));
                    }
                    else
                    {
                        if (path_str[0] == c.DisplayName
                            ||
                            (((path_str[0].Contains('*') || path_str[0].Contains('?')) &&
                              Regex.IsMatch(c.DisplayName, Regex.Escape(path_str[0]).Replace("\\*", ".*").Replace("\\?", ".")))))
                        {
                            ret.Add(c.info);
                        }
                    }
                }
            }
            if (recursive)
            {
                ret.Sort((x, y) => (DriveData.GetFullPathfromId(x.id)).CompareTo(DriveData.GetFullPathfromId(y.id)));
                return(ret.ToArray());
            }
            else
            {
                ret.Sort((x, y) => x.name.CompareTo(y.name));
                return(ret.ToArray());
            }
        }
        public SlotMaster(AmazonDrive Drive, FileMetadata_Info downitem, CancellationToken ct = default(CancellationToken))
        {
            cts        = CancellationTokenSource.CreateLinkedTokenSource(cts_internal.Token, ct);
            this.Drive = Drive;
            targetItem = downitem;
            lastslot   = ((downitem.OrignalLength ?? 0) - 1) / AmazonDriveStreamConfig.slotsize;
            lockslot1  = AmazonDriveStreamConfig.lockslotfirstnum;
            lockslot2  = lastslot - AmazonDriveStreamConfig.lockslotlastnum;
            if (lockslot2 < lockslot1)
            {
                lockslot2 = lockslot1;
            }
            int extraslot = 0;

            Task.Run(() =>
            {
                foreach (var newitem in SlotBuffer.GetConsumingEnumerable(cts.Token))
                {
                    try
                    {
                        slot.GetOrAdd(newitem.Key, newitem.Value);

                        while (slot.Count > AmazonDriveStreamConfig.slotbacklog + extraslot)
                        {
                            Task.Delay(100, cts.Token).Wait(cts.Token);
                        }
                        if (cts.Token.IsCancellationRequested)
                        {
                            return;
                        }
                    }
                    catch { }
                }
            }, cts.Token);
            Task.Run(() =>
            {
                while (!cts.Token.IsCancellationRequested)
                {
                    try
                    {
                        const int slotnumc = AmazonDriveStreamConfig.slotbacklog;
                        // slotが多すぎるのでいらないものから消す
                        if (slot.Count > slotnumc)
                        {
                            var pos = slot
                                      .OrderByDescending(x => x.Value.Age)
                                      .OrderBy(x => x.Value.ReadAge)
                                      .First().Key;

                            var s = StartLock;
                            if (s != null)
                            {
                                pos = s.Value;
                            }

                            //Config.Log.LogOut(string.Format("AmazonDriveStream : Removing slots current pos {0}", pos));

                            var deleteitem = slot
                                             .Where(x => !(x.Key >= StartLock && x.Key <= EndLock))
                                             .Where(x => x.Key > lockslot1 && x.Key < lockslot2);

                            deleteitem = deleteitem
                                         .Where(x => x.Key <pos - AmazonDriveStreamConfig.slotkeepold || x.Key> pos + AmazonDriveStreamConfig.slotbacklog * 2)
                                         .OrderByDescending(x => x.Value.ReadAge)
                                         .Take(slot.Count - slotnumc).ToArray();
                            foreach (var item in deleteitem)
                            {
                                MemoryStreamSlot o;
                                if (slot.TryRemove(item.Key, out o))
                                {
                                    //Config.Log.LogOut(string.Format("AmazonDriveStream : Remove slot {0} pos {1:#,0} len {2:#,0}", item.Key, o.Offset, o.Length));
                                    if (!(item.Key >= StartLock && item.Key <= EndLock))
                                    {
                                        o.Dispose();
                                    }
                                    else
                                    {
                                        slot.GetOrAdd(item.Key, o);
                                    }
                                }
                            }
                            extraslot = slot.Count - slotnumc;
                        }
                        // 終了したタスクを除去する
                        if (Tasks.Any(x => x.Done))
                        {
                            var deleteitem = Tasks.Where(x => x.Done).ToArray();
                            foreach (var item in deleteitem)
                            {
                                SlotTask o;
                                if (Tasks.TryTake(out o))
                                {
                                    //Config.Log.LogOut(string.Format("AmazonDriveStream : Remove end Task slot {0}", o.ReadingSlotno));
                                    o.Dispose();
                                }
                            }
                        }
                        // 走りすぎているスレットを消す
                        if (accesslog.Count() > 0)
                        {
                            var min_point = accesslog.OrderByDescending(x => x.Value).Take(1).Min(x => x.Key);
                            var max_point = min_point + AmazonDriveStreamConfig.slotbacklog;
                            min_point     = Math.Max(min_point - AmazonDriveStreamConfig.slotnearby * 2, 0);
                            max_point     = Math.Min(max_point + AmazonDriveStreamConfig.slotnearby * 2, lastslot);
                            //Config.Log.LogOut(string.Format("AmazonDriveStream : min_point {0}", min_point));
                            //Config.Log.LogOut(string.Format("AmazonDriveStream : max_point {0}", max_point));
                            if (min_point < lockslot2 && Tasks.Any(x => x.ReadingSlotno < min_point && x.ReadingSlotno > lockslot1))
                            {
                                var deleteitem = Tasks.Where(x => x.ReadingSlotno <min_point && x.ReadingSlotno> lockslot1).ToList();
                                SlotTask o;
                                while (deleteitem.Count > 0 && Tasks.TryTake(out o))
                                {
                                    if (deleteitem.Contains(o))
                                    {
                                        //Config.Log.LogOut(string.Format("AmazonDriveStream : Remove1 Task slot {0} too far({1})", o.ReadingSlotno, min_point));
                                        deleteitem.Remove(o);
                                        o.Dispose();
                                    }
                                    else
                                    {
                                        Tasks.Add(o);
                                    }
                                }
                            }
                            if (Tasks.Count == 1)
                            {
                                Tasks.First().leadThread = true;
                            }
                            else
                            {
                                foreach (var item in Tasks)
                                {
                                    item.leadThread = false;
                                }
                            }
                            if (max_point > lockslot1 && Tasks.Any(x => x.ReadingSlotno > max_point && x.ReadingSlotno < lockslot2))
                            {
                                var deleteitem = Tasks.Where(x => x.ReadingSlotno > max_point && x.ReadingSlotno < lockslot2).ToList();
                                SlotTask o;
                                while (deleteitem.Count > 0 && Tasks.TryTake(out o))
                                {
                                    if (deleteitem.Contains(o))
                                    {
                                        if (o.leadThread)
                                        {
                                            //Config.Log.LogOut(string.Format("AmazonDriveStream : LeadThread Task slot {0} too far({1})", o.ReadingSlotno, min_point));
                                            deleteitem.Remove(o);
                                            Tasks.Add(o);
                                        }
                                        else
                                        {
                                            //Config.Log.LogOut(string.Format("AmazonDriveStream : Remove2 Task slot {0} too far({1})", o.ReadingSlotno, min_point));
                                            deleteitem.Remove(o);
                                            o.Dispose();
                                        }
                                    }
                                    else
                                    {
                                        Tasks.Add(o);
                                    }
                                }
                            }
                        }
                    }
                    catch { }
                    //Config.Log.LogOut(string.Format("AmazonDriveStream : Tasks {0} slots {1}", Tasks.Count, slot.Count));
                    //Config.Log.LogOut(string.Format("AmazonDriveStream : slot {0}", string.Join(",",Tasks.Select(x=>x.ReadingSlotno.ToString()))));
                    Task.Delay(500, cts.Token).Wait(cts.Token);
                }
            }, cts.Token);
        }
Exemple #11
0
 public ItemInfo(FileMetadata_Info thisdata)
 {
     info = thisdata;
 }
Exemple #12
0
        public async Task <Stream> downloadFile(FileMetadata_Info target, long?from = null, long?to = null, string enckey = null, bool autodecrypt = true, CancellationToken ct = default(CancellationToken))
        {
            string       id        = target.id;
            string       filename  = target.name;
            CryptMethods Encrypted = CryptMethods.Method0_Plain;

            if (enckey != null)
            {
                Encrypted = CryptMethods.Method1_CTR;
            }
            else
            {
                if (filename.StartsWith(Config.CarotDAV_CryptNameHeader))
                {
                    Encrypted = CryptMethods.Method2_CBC_CarotDAV;
                    enckey    = "";
                }
                else if (Regex.IsMatch(filename, ".*?\\.[a-z0-9]{8}\\.enc$"))
                {
                    Encrypted = CryptMethods.Method1_CTR;
                    enckey    = Path.GetFileNameWithoutExtension(filename);
                }
                else if (Regex.IsMatch(filename, "^[\u2800-\u28ff]+$"))
                {
                    enckey = DriveData.DecryptFilename(target);
                    if (enckey != null)
                    {
                        Encrypted = CryptMethods.Method1_CTR;
                    }
                }

                if (enckey == null)
                {
                    Encrypted = CryptMethods.Method0_Plain;
                }
            }
            if (!autodecrypt)
            {
                Encrypted = CryptMethods.Method0_Plain;
            }
            Config.Log.LogOut("\t[downloadFile] " + id);
            string error_str = "";
            var    client    = new HttpClient();

            client.Timeout = TimeSpan.FromDays(1);
            try
            {
                long?fix_from = from, fix_to = to;

                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Authkey.access_token);
                if (from != null || to != null)
                {
                    if (Encrypted == CryptMethods.Method2_CBC_CarotDAV)
                    {
                        if (fix_from != null)
                        {
                            // ひとつ前のブロックから要求する
                            fix_from -= CryptCarotDAV.BlockSizeByte;
                            if (fix_from < CryptCarotDAV.BlockSizeByte)
                            {
                                // 先頭ブロックを取得するときはファイルの先頭から
                                fix_from = 0;
                            }
                            else
                            {
                                // ブロックにアライメントを合わせる
                                fix_from -= ((fix_from - 1) % CryptCarotDAV.BlockSizeByte + 1);
                                // 途中のブロックを要求された場合は、ヘッダをスキップ
                                fix_from += CryptCarotDAV.CryptHeaderByte;
                            }
                        }
                        if (fix_to != null)
                        {
                            if (fix_to >= target.OrignalLength)
                            {
                                // 末尾まで読み込むときは、ハッシュチェックのために最後まで読み込む
                                fix_to = null;
                            }
                            else
                            {
                                // オリジナルの位置を、暗号化済みの位置に変更
                                fix_to += CryptCarotDAV.CryptHeaderByte;
                            }
                        }
                        if (fix_from != null || fix_to != null)
                        {
                            client.DefaultRequestHeaders.Range = new RangeHeaderValue(fix_from, fix_to);
                        }
                    }
                    else
                    {
                        client.DefaultRequestHeaders.Range = new RangeHeaderValue(from, to);
                    }
                }
                string url      = Config.contentUrl + "nodes/" + id + "/content?download=false";
                var    response = await client.GetAsync(
                    url,
                    HttpCompletionOption.ResponseHeadersRead,
                    ct).ConfigureAwait(false);

                response.EnsureSuccessStatusCode();
                if (Encrypted == CryptMethods.Method1_CTR)
                {
                    return(new CryptCTR.AES256CTR_CryptStream(new ThrottleDownloadStream(new HashStream(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), new MD5CryptoServiceProvider()), ct),
                                                              enckey,
                                                              from ?? 0));
                }
                else if (Encrypted == CryptMethods.Method2_CBC_CarotDAV)
                {
                    return(new CryptCarotDAV.CryptCarotDAV_DecryptStream(new ThrottleDownloadStream(new HashStream(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), new MD5CryptoServiceProvider()), ct),
                                                                         from ?? 0,
                                                                         fix_from ?? 0,
                                                                         target.contentProperties?.size ?? -1
                                                                         ));
                }
                else
                {
                    return(new ThrottleDownloadStream(new HashStream(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), new MD5CryptoServiceProvider()), ct));
                }
            }
            catch (HttpRequestException ex)
            {
                error_str = ex.Message;
                Config.Log.LogOut("\t[downloadFile] " + error_str);
                throw;
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                error_str = ex.ToString();
                Config.Log.LogOut("\t[downloadFile] " + error_str);
                throw;
            }
            throw new SystemException("fileDownload failed. " + error_str);
        }