Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
AttachmentCache.cs
1using System;
3using System.IO;
5using System.Threading.Tasks;
6using Waher.Events;
12
14{
18 public static class AttachmentCache
19 {
20 private static readonly Cache<CaseInsensitiveString, AttachmentCacheItem> cache =
21 new Cache<CaseInsensitiveString, AttachmentCacheItem>(int.MaxValue, TimeSpan.FromHours(1), TimeSpan.FromMinutes(1));
22
28 public static async Task<AttachmentCacheItem> TryGetAttachment(CaseInsensitiveString AttachmentId)
29 {
30 using Semaphore Semaphore = await Semaphores.BeginRead("attachment:" + AttachmentId.LowerCase);
31
32 if (cache.TryGetValue(AttachmentId, out AttachmentCacheItem Item))
33 return Item;
34
35 Item = await Database.FindFirstIgnoreRest<AttachmentCacheItem>(
36 new FilterFieldEqualTo("AttachmentId", AttachmentId));
37
38 if (!(Item is null))
39 cache.Add(AttachmentId, Item);
40
41 return Item;
42 }
43
49 public static async Task<bool> ContainsAttachment(CaseInsensitiveString AttachmentId)
50 {
51 return !((await TryGetAttachment(AttachmentId)) is null);
52 }
53
61 public static async Task<bool> AddLocalAttachment(Attachment Attachment, DateTime Expires)
62 {
63 using Semaphore Semaphore = await Semaphores.BeginWrite("attachment:" + Attachment.Id.LowerCase);
64
65 if (cache.TryGetValue(Attachment.Id, out AttachmentCacheItem Item))
66 return false;
67
68 Item = await Database.FindFirstIgnoreRest<AttachmentCacheItem>(
69 new FilterFieldEqualTo("AttachmentId", Attachment.Id));
70
71 if (!(Item is null))
72 {
73 cache.Add(Attachment.Id, Item);
74 return false;
75 }
76
77 Item = new AttachmentCacheItem()
78 {
79 AttachmentId = Attachment.Id,
80 Created = DateTime.UtcNow,
81 Expires = Expires,
82 ContentType = Attachment.ContentType,
83 LocalAttachmentId = Attachment.ObjectId,
84 FileName = Attachment.LocalFileName,
85 Size = Attachment.Size,
86 Salt = Attachment.Salt
87 };
88
89 await Database.Insert(Item);
90
91 return true;
92 }
93
104 public static async Task<bool> AddRemoteAttachment(CaseInsensitiveString AttachmentId,
105 DateTime Expires, byte[] Data, string ContentType, LegalComponent Legal)
106 {
107 using Semaphore Semaphore = await Semaphores.BeginWrite("attachment:" + AttachmentId.LowerCase);
108
109 if (cache.TryGetValue(AttachmentId, out AttachmentCacheItem Item))
110 return false;
111
112 Item = await Database.FindFirstIgnoreRest<AttachmentCacheItem>(
113 new FilterFieldEqualTo("AttachmentId", AttachmentId));
114
115 if (!(Item is null))
116 {
117 cache.Add(AttachmentId, Item);
118 return false;
119 }
120
121 string Folder = LegalComponent.GetFolderName(Legal.AttachmentsFolder, out DateTime Timestamp);
122 byte[] Salt = Gateway.NextBytes(48);
123 byte[] Key = new byte[32];
124 byte[] IV = new byte[16];
125
126 Item = new AttachmentCacheItem()
127 {
128 AttachmentId = AttachmentId,
129 Created = DateTime.UtcNow,
130 Expires = Expires.ToUniversalTime(),
131 ContentType = ContentType,
132 LocalAttachmentId = null,
133 FileName = Path.Combine(Folder, AttachmentId + ".bin"),
134 Size = Data.Length,
135 Salt = Salt
136 };
137
138 await Database.Insert(Item);
139
140 using FileStream AttachmentFile = File.Create(Item.FileName);
141 Aes Aes = Aes.Create();
142
143 Aes.BlockSize = 128;
144 Aes.KeySize = 256;
145 Aes.Mode = CipherMode.CBC;
146 Aes.Padding = PaddingMode.Zeros;
147
148 using ICryptoTransform Encryptor = Aes.CreateEncryptor(Key, IV);
149 using CryptoStream EncryptedAttachmentFile = new CryptoStream(AttachmentFile, Encryptor, CryptoStreamMode.Write);
150
151 await EncryptedAttachmentFile.WriteAsync(Data, 0, Data.Length);
152 EncryptedAttachmentFile.FlushFinalBlock();
153
154 return true;
155 }
156
161 public static async Task<int> DeleteOldAttachments()
162 {
163 DateTime Limit = DateTime.UtcNow;
164 const int MaxCount = 10;
165 int Result = 0;
166 int c;
167 IEnumerable<AttachmentCacheItem> Items;
168
169 Items = await Database.FindDelete<AttachmentCacheItem>(0, MaxCount,
170 new FilterFieldLesserOrEqualTo("Expires", Limit));
171
172 do
173 {
174 c = 0;
175 foreach (AttachmentCacheItem Item in Items)
176 {
177 cache.Remove(Item.AttachmentId);
178 Result++;
179 c++;
180
181 if (string.IsNullOrEmpty(Item.LocalAttachmentId) && File.Exists(Item.FileName))
182 {
183 try
184 {
185 File.Delete(Item.FileName);
186 }
187 catch (Exception ex)
188 {
189 Log.Exception(ex);
190 }
191 }
192 }
193 }
194 while (c == MaxCount);
195
196 return Result;
197 }
198 }
199}
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1657
Static class managing the runtime environment of the IoT Gateway.
Definition: Gateway.cs:147
static byte[] NextBytes(int NrBytes)
Generates an array of random bytes.
Definition: Gateway.cs:4335
Represents a case-insensitive string.
string LowerCase
Lower-case representation of the case-insensitive string.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:21
static Task< IEnumerable< object > > FindDelete(string Collection, params string[] SortOrder)
Finds objects in a given collection and deletes them in the same atomic operation.
Definition: Database.cs:1442
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
Definition: Database.cs:97
This filter selects objects that have a named field equal to a given value.
This filter selects objects that have a named field lesser or equal to a given value.
Implements an in-memory cache.
Definition: Cache.cs:17
Represents a named semaphore, i.e. an object, identified by a name, that allows single concurrent wri...
Definition: Semaphore.cs:19
Static class of application-wide semaphores that can be used to order access to editable objects.
Definition: Semaphores.cs:17
static async Task< Semaphore > BeginRead(string Key)
Waits until the semaphore identified by Key is ready for reading. Each call to BeginRead must be fol...
Definition: Semaphores.cs:54
static async Task< Semaphore > BeginWrite(string Key)
Waits until the semaphore identified by Key is ready for writing. Each call to BeginWrite must be fo...
Definition: Semaphores.cs:91