3using System.Collections.Generic;
6using System.Reflection;
7using System.Security.Cryptography;
9using System.Threading.Tasks;
11using System.Xml.Schema;
155 private readonly Dictionary<CaseInsensitiveString, Dictionary<CaseInsensitiveString, CaseInsensitiveString>> petitionsByBareJid =
new Dictionary<CaseInsensitiveString, Dictionary<CaseInsensitiveString, CaseInsensitiveString>>();
158 private readonly
string attachmentsFolder;
178 this.pubsub = PubSub;
180 if (!Directory.Exists(
this.attachmentsFolder))
181 Directory.CreateDirectory(this.attachmentsFolder);
184 this.httpServer.Register(this.attachmentsResource);
186 #region Neuro-Foundation V1 handlers
188 this.
RegisterIqGetHandler(
"getPublicKey", NamespaceLegalIdentityNeuroFoundationV1, this.GetPublicKeyHandler,
true);
189 this.
RegisterIqGetHandler(
"applicationAttributes", NamespaceLegalIdentityNeuroFoundationV1, this.IdApplicationAttributesHandler,
false); ;
190 this.
RegisterIqSetHandler(
"apply", NamespaceLegalIdentityNeuroFoundationV1, this.ApplyHandler,
false);
191 this.
RegisterIqGetHandler(
"getLegalIdentities", NamespaceLegalIdentityNeuroFoundationV1, this.GetLegalIdentitiesHandler,
false);
192 this.
RegisterIqGetHandler(
"getLegalIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.GetLegalIdentityHandler,
false);
193 this.
RegisterIqGetHandler(
"validateSignature", NamespaceLegalIdentityNeuroFoundationV1, this.ValidateSignatureHandler,
false);
194 this.
RegisterIqSetHandler(
"obsoleteLegalIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.ObsoleteLegalIdentityHandler,
false);
195 this.
RegisterIqSetHandler(
"compromisedLegalIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.CompromiseLegalIdentityHandler,
false);
196 this.
RegisterIqSetHandler(
"petitionIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionIdentityHandler,
false);
197 this.
RegisterIqSetHandler(
"petitionIdentityResponse", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionIdentityResponseHandler,
false);
198 this.
RegisterIqSetHandler(
"addAttachment", NamespaceLegalIdentityNeuroFoundationV1, this.AddLegalIdAttachmentHandler,
false);
199 this.
RegisterIqSetHandler(
"removeAttachment", NamespaceLegalIdentityNeuroFoundationV1, this.RemoveLegalIdAttachmentHandler,
false);
200 this.
RegisterIqSetHandler(
"petitionSignature", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionSignatureHandler,
false);
201 this.
RegisterIqSetHandler(
"petitionSignatureResponse", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionSignatureResponseHandler,
false);
202 this.
RegisterIqSetHandler(
"authorizeAccess", NamespaceLegalIdentityNeuroFoundationV1, this.AuthorizeAccessToIdHandler,
false);
203 this.
RegisterIqGetHandler(
"getNetworkIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.GetNetworkLegalIdentityHandler,
false);
204 this.
RegisterIqGetHandler(
"canSignAs", NamespaceLegalIdentityNeuroFoundationV1, this.CanSignAsHandler,
false);
205 this.
RegisterIqSetHandler(
"readyForApproval", NamespaceLegalIdentityNeuroFoundationV1, this.ReadyForApprovalHandler,
false);
206 this.
RegisterIqGetHandler(
"reviewIdProviders", NamespaceLegalIdentityNeuroFoundationV1, this.GetReviewIdProvidersHandler,
false);
207 this.
RegisterIqSetHandler(
"selectReviewService", NamespaceLegalIdentityNeuroFoundationV1, this.SelectReviewServiceHandler,
false);
211 this.
RegisterIqSetHandler(
"createContract", NamespaceSmartContractsNeuroFoundationV1, this.CreateContractHandler,
true);
212 this.
RegisterIqGetHandler(
"getCreatedContracts", NamespaceSmartContractsNeuroFoundationV1, this.GetCreatedContractsHandler,
false);
213 this.
RegisterIqSetHandler(
"signContract", NamespaceSmartContractsNeuroFoundationV1, this.SignContractHandler,
false);
214 this.
RegisterIqGetHandler(
"getSignedContracts", NamespaceSmartContractsNeuroFoundationV1, this.GetSignedContractsHandler,
false);
215 this.
RegisterIqGetHandler(
"getContract", NamespaceSmartContractsNeuroFoundationV1, this.GetContractHandler,
false);
216 this.
RegisterIqGetHandler(
"getContracts", NamespaceSmartContractsNeuroFoundationV1, this.GetContractsHandler,
false);
217 this.
RegisterIqGetHandler(
"isPart", NamespaceSmartContractsNeuroFoundationV1, this.IsPartHandler,
false);
218 this.
RegisterIqSetHandler(
"obsoleteContract", NamespaceSmartContractsNeuroFoundationV1, this.ObsoleteContractHandler,
false);
219 this.
RegisterIqSetHandler(
"deleteContract", NamespaceSmartContractsNeuroFoundationV1, this.DeleteContractHandler,
false);
220 this.
RegisterIqSetHandler(
"updateContract", NamespaceSmartContractsNeuroFoundationV1, this.UpdateContractHandler,
false);
221 this.
RegisterIqGetHandler(
"getSchemas", NamespaceSmartContractsNeuroFoundationV1, this.GetSchemasHandler,
false);
222 this.
RegisterIqGetHandler(
"getSchema", NamespaceSmartContractsNeuroFoundationV1, this.GetSchemaHandler,
false);
223 this.
RegisterIqGetHandler(
"getLegalIdentities", NamespaceSmartContractsNeuroFoundationV1, this.GetLegalIdentitiesOfContractHandler,
false);
224 this.
RegisterIqGetHandler(
"getNetworkIdentities", NamespaceSmartContractsNeuroFoundationV1, this.GetNetworkIdentitiesHandler,
false);
225 this.
RegisterIqGetHandler(
"searchPublicContracts", NamespaceSmartContractsNeuroFoundationV1, this.SearchPublicContractsHandler,
false);
226 this.
RegisterIqSetHandler(
"petitionContract", NamespaceSmartContractsNeuroFoundationV1, this.PetitionContractHandler,
false);
227 this.
RegisterIqSetHandler(
"petitionContractResponse", NamespaceSmartContractsNeuroFoundationV1, this.PetitionContractResponseHandler,
false);
228 this.
RegisterIqSetHandler(
"addAttachment", NamespaceSmartContractsNeuroFoundationV1, this.AddContractAttachmentHandler,
false);
229 this.
RegisterIqSetHandler(
"removeAttachment", NamespaceSmartContractsNeuroFoundationV1, this.RemoveContractAttachmentHandler,
false);
230 this.
RegisterIqSetHandler(
"authorizeAccess", NamespaceSmartContractsNeuroFoundationV1, this.AuthorizeAccessToContractHandler,
false);
231 this.
RegisterMessageHandler(
"contractSigned", NamespaceSmartContractsNeuroFoundationV1, this.ContractSignedHandler,
false);
235 #region IEEE V1 handlers
237 this.
RegisterIqGetHandler(
"getPublicKey", NamespaceLegalIdentityIeeeV1, this.GetPublicKeyHandler,
true);
238 this.
RegisterIqGetHandler(
"applicationAttributes", NamespaceLegalIdentityIeeeV1, this.IdApplicationAttributesHandler,
false); ;
240 this.
RegisterIqGetHandler(
"getLegalIdentities", NamespaceLegalIdentityIeeeV1, this.GetLegalIdentitiesHandler,
false);
241 this.
RegisterIqGetHandler(
"getLegalIdentity", NamespaceLegalIdentityIeeeV1, this.GetLegalIdentityHandler,
false);
242 this.
RegisterIqGetHandler(
"validateSignature", NamespaceLegalIdentityIeeeV1, this.ValidateSignatureHandler,
false);
243 this.
RegisterIqSetHandler(
"obsoleteLegalIdentity", NamespaceLegalIdentityIeeeV1, this.ObsoleteLegalIdentityHandler,
false);
244 this.
RegisterIqSetHandler(
"compromisedLegalIdentity", NamespaceLegalIdentityIeeeV1, this.CompromiseLegalIdentityHandler,
false);
245 this.
RegisterIqSetHandler(
"petitionIdentity", NamespaceLegalIdentityIeeeV1, this.PetitionIdentityHandler,
false);
246 this.
RegisterIqSetHandler(
"petitionIdentityResponse", NamespaceLegalIdentityIeeeV1, this.PetitionIdentityResponseHandler,
false);
247 this.
RegisterIqSetHandler(
"addAttachment", NamespaceLegalIdentityIeeeV1, this.AddLegalIdAttachmentHandler,
false);
248 this.
RegisterIqSetHandler(
"removeAttachment", NamespaceLegalIdentityIeeeV1, this.RemoveLegalIdAttachmentHandler,
false);
249 this.
RegisterIqSetHandler(
"petitionSignature", NamespaceLegalIdentityIeeeV1, this.PetitionSignatureHandler,
false);
250 this.
RegisterIqSetHandler(
"petitionSignatureResponse", NamespaceLegalIdentityIeeeV1, this.PetitionSignatureResponseHandler,
false);
251 this.
RegisterIqSetHandler(
"authorizeAccess", NamespaceLegalIdentityIeeeV1, this.AuthorizeAccessToIdHandler,
false);
252 this.
RegisterIqGetHandler(
"getNetworkIdentity", NamespaceLegalIdentityIeeeV1, this.GetNetworkLegalIdentityHandler,
false);
253 this.
RegisterIqGetHandler(
"canSignAs", NamespaceLegalIdentityIeeeV1, this.CanSignAsHandler,
false);
254 this.
RegisterIqSetHandler(
"readyForApproval", NamespaceLegalIdentityIeeeV1, this.ReadyForApprovalHandler,
false);
255 this.
RegisterIqGetHandler(
"reviewIdProviders", NamespaceLegalIdentityIeeeV1, this.GetReviewIdProvidersHandler,
false);
256 this.
RegisterIqSetHandler(
"selectReviewService", NamespaceLegalIdentityIeeeV1, this.SelectReviewServiceHandler,
false);
260 this.
RegisterIqSetHandler(
"createContract", NamespaceSmartContractsIeeeV1, this.CreateContractHandler,
true);
261 this.
RegisterIqGetHandler(
"getCreatedContracts", NamespaceSmartContractsIeeeV1, this.GetCreatedContractsHandler,
false);
262 this.
RegisterIqSetHandler(
"signContract", NamespaceSmartContractsIeeeV1, this.SignContractHandler,
false);
263 this.
RegisterIqGetHandler(
"getSignedContracts", NamespaceSmartContractsIeeeV1, this.GetSignedContractsHandler,
false);
264 this.
RegisterIqGetHandler(
"getContract", NamespaceSmartContractsIeeeV1, this.GetContractHandler,
false);
265 this.
RegisterIqGetHandler(
"getContracts", NamespaceSmartContractsIeeeV1, this.GetContractsHandler,
false);
267 this.
RegisterIqSetHandler(
"obsoleteContract", NamespaceSmartContractsIeeeV1, this.ObsoleteContractHandler,
false);
268 this.
RegisterIqSetHandler(
"deleteContract", NamespaceSmartContractsIeeeV1, this.DeleteContractHandler,
false);
269 this.
RegisterIqSetHandler(
"updateContract", NamespaceSmartContractsIeeeV1, this.UpdateContractHandler,
false);
270 this.
RegisterIqGetHandler(
"getSchemas", NamespaceSmartContractsIeeeV1, this.GetSchemasHandler,
false);
271 this.
RegisterIqGetHandler(
"getSchema", NamespaceSmartContractsIeeeV1, this.GetSchemaHandler,
false);
272 this.
RegisterIqGetHandler(
"getLegalIdentities", NamespaceSmartContractsIeeeV1, this.GetLegalIdentitiesOfContractHandler,
false);
273 this.
RegisterIqGetHandler(
"getNetworkIdentities", NamespaceSmartContractsIeeeV1, this.GetNetworkIdentitiesHandler,
false);
274 this.
RegisterIqGetHandler(
"searchPublicContracts", NamespaceSmartContractsIeeeV1, this.SearchPublicContractsHandler,
false);
275 this.
RegisterIqSetHandler(
"petitionContract", NamespaceSmartContractsIeeeV1, this.PetitionContractHandler,
false);
276 this.
RegisterIqSetHandler(
"petitionContractResponse", NamespaceSmartContractsIeeeV1, this.PetitionContractResponseHandler,
false);
277 this.
RegisterIqSetHandler(
"addAttachment", NamespaceSmartContractsIeeeV1, this.AddContractAttachmentHandler,
false);
278 this.
RegisterIqSetHandler(
"removeAttachment", NamespaceSmartContractsIeeeV1, this.RemoveContractAttachmentHandler,
false);
279 this.
RegisterIqSetHandler(
"authorizeAccess", NamespaceSmartContractsIeeeV1, this.AuthorizeAccessToContractHandler,
false);
280 this.
RegisterMessageHandler(
"contractSigned", NamespaceSmartContractsIeeeV1, this.ContractSignedHandler,
false);
284 this.Server.OnPresenceLocalSender += this.Server_OnPresenceLocalSender;
285 this.petitions.Removed += this.Petitions_Removed;
296 this.Server.OnPresenceLocalSender -= this.Server_OnPresenceLocalSender;
298 if (!(this.petitions is
null))
300 this.petitions.Removed -= this.Petitions_Removed;
302 this.petitions =
null;
305 this.transientParameters?.
Dispose();
306 this.transientParameters =
null;
308 this.httpServer.Unregister(this.attachmentsResource);
310 #region Neuro-Foundation V1 handlers
312 this.
UnregisterIqGetHandler(
"getPublicKey", NamespaceLegalIdentityNeuroFoundationV1, this.GetPublicKeyHandler,
true);
313 this.
UnregisterIqGetHandler(
"applicationAttributes", NamespaceLegalIdentityNeuroFoundationV1, this.IdApplicationAttributesHandler,
false); ;
315 this.
UnregisterIqGetHandler(
"getLegalIdentities", NamespaceLegalIdentityNeuroFoundationV1, this.GetLegalIdentitiesHandler,
false);
316 this.
UnregisterIqGetHandler(
"getLegalIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.GetLegalIdentityHandler,
false);
317 this.
UnregisterIqGetHandler(
"validateSignature", NamespaceLegalIdentityNeuroFoundationV1, this.ValidateSignatureHandler,
false);
318 this.
UnregisterIqSetHandler(
"obsoleteLegalIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.ObsoleteLegalIdentityHandler,
false);
319 this.
UnregisterIqSetHandler(
"compromisedLegalIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.CompromiseLegalIdentityHandler,
false);
320 this.
UnregisterIqSetHandler(
"petitionIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionIdentityHandler,
false);
321 this.
UnregisterIqSetHandler(
"petitionIdentityResponse", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionIdentityResponseHandler,
false);
322 this.
UnregisterIqSetHandler(
"addAttachment", NamespaceLegalIdentityNeuroFoundationV1, this.AddLegalIdAttachmentHandler,
false);
323 this.
UnregisterIqSetHandler(
"removeAttachment", NamespaceLegalIdentityNeuroFoundationV1, this.RemoveLegalIdAttachmentHandler,
false);
324 this.
UnregisterIqSetHandler(
"petitionSignature", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionSignatureHandler,
false);
325 this.
UnregisterIqSetHandler(
"petitionSignatureResponse", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionSignatureResponseHandler,
false);
326 this.
UnregisterIqSetHandler(
"authorizeAccess", NamespaceLegalIdentityNeuroFoundationV1, this.AuthorizeAccessToIdHandler,
false);
327 this.
UnregisterIqGetHandler(
"getNetworkIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.GetNetworkLegalIdentityHandler,
false);
328 this.
UnregisterIqGetHandler(
"canSignAs", NamespaceLegalIdentityNeuroFoundationV1, this.CanSignAsHandler,
false);
329 this.
UnregisterIqSetHandler(
"readyForApproval", NamespaceLegalIdentityNeuroFoundationV1, this.ReadyForApprovalHandler,
false);
330 this.
UnregisterIqGetHandler(
"reviewIdProviders", NamespaceLegalIdentityNeuroFoundationV1, this.GetReviewIdProvidersHandler,
false);
331 this.
UnregisterIqSetHandler(
"selectReviewService", NamespaceLegalIdentityNeuroFoundationV1, this.SelectReviewServiceHandler,
false);
333 this.
Server.
UnregisterIqGetHandler(
"getNetworkIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.GetNetworkXmppIdentityHandler,
false);
335 this.
UnregisterIqSetHandler(
"createContract", NamespaceSmartContractsNeuroFoundationV1, this.CreateContractHandler,
true);
336 this.
UnregisterIqGetHandler(
"getCreatedContracts", NamespaceSmartContractsNeuroFoundationV1, this.GetCreatedContractsHandler,
false);
337 this.
UnregisterIqSetHandler(
"signContract", NamespaceSmartContractsNeuroFoundationV1, this.SignContractHandler,
false);
338 this.
UnregisterIqGetHandler(
"getSignedContracts", NamespaceSmartContractsNeuroFoundationV1, this.GetSignedContractsHandler,
false);
339 this.
UnregisterIqGetHandler(
"getContract", NamespaceSmartContractsNeuroFoundationV1, this.GetContractHandler,
false);
340 this.
UnregisterIqGetHandler(
"getContracts", NamespaceSmartContractsNeuroFoundationV1, this.GetContractsHandler,
false);
341 this.
UnregisterIqGetHandler(
"isPart", NamespaceSmartContractsNeuroFoundationV1, this.IsPartHandler,
false);
342 this.
UnregisterIqSetHandler(
"obsoleteContract", NamespaceSmartContractsNeuroFoundationV1, this.ObsoleteContractHandler,
false);
343 this.
UnregisterIqSetHandler(
"deleteContract", NamespaceSmartContractsNeuroFoundationV1, this.DeleteContractHandler,
false);
344 this.
UnregisterIqSetHandler(
"updateContract", NamespaceSmartContractsNeuroFoundationV1, this.UpdateContractHandler,
false);
345 this.
UnregisterIqGetHandler(
"getSchemas", NamespaceSmartContractsNeuroFoundationV1, this.GetSchemasHandler,
false);
346 this.
UnregisterIqGetHandler(
"getSchema", NamespaceSmartContractsNeuroFoundationV1, this.GetSchemaHandler,
false);
347 this.
UnregisterIqGetHandler(
"getLegalIdentities", NamespaceSmartContractsNeuroFoundationV1, this.GetLegalIdentitiesOfContractHandler,
false);
348 this.
UnregisterIqGetHandler(
"getNetworkIdentities", NamespaceSmartContractsNeuroFoundationV1, this.GetNetworkIdentitiesHandler,
false);
349 this.
UnregisterIqGetHandler(
"searchPublicContracts", NamespaceSmartContractsNeuroFoundationV1, this.SearchPublicContractsHandler,
false);
350 this.
UnregisterIqSetHandler(
"petitionContract", NamespaceSmartContractsNeuroFoundationV1, this.PetitionContractHandler,
false);
351 this.
UnregisterIqSetHandler(
"petitionContractResponse", NamespaceSmartContractsNeuroFoundationV1, this.PetitionContractResponseHandler,
false);
352 this.
UnregisterIqSetHandler(
"addAttachment", NamespaceSmartContractsNeuroFoundationV1, this.AddContractAttachmentHandler,
false);
353 this.
UnregisterIqSetHandler(
"removeAttachment", NamespaceSmartContractsNeuroFoundationV1, this.RemoveContractAttachmentHandler,
false);
354 this.
UnregisterIqSetHandler(
"authorizeAccess", NamespaceSmartContractsNeuroFoundationV1, this.AuthorizeAccessToContractHandler,
false);
355 this.
UnregisterMessageHandler(
"contractSigned", NamespaceSmartContractsNeuroFoundationV1, this.ContractSignedHandler,
false);
359 #region IEEE V1 handlers
361 this.
UnregisterIqGetHandler(
"getPublicKey", NamespaceLegalIdentityIeeeV1, this.GetPublicKeyHandler,
true);
362 this.
UnregisterIqGetHandler(
"applicationAttributes", NamespaceLegalIdentityIeeeV1, this.IdApplicationAttributesHandler,
false); ;
364 this.
UnregisterIqGetHandler(
"getLegalIdentities", NamespaceLegalIdentityIeeeV1, this.GetLegalIdentitiesHandler,
false);
365 this.
UnregisterIqGetHandler(
"getLegalIdentity", NamespaceLegalIdentityIeeeV1, this.GetLegalIdentityHandler,
false);
366 this.
UnregisterIqGetHandler(
"validateSignature", NamespaceLegalIdentityIeeeV1, this.ValidateSignatureHandler,
false);
367 this.
UnregisterIqSetHandler(
"obsoleteLegalIdentity", NamespaceLegalIdentityIeeeV1, this.ObsoleteLegalIdentityHandler,
false);
368 this.
UnregisterIqSetHandler(
"compromisedLegalIdentity", NamespaceLegalIdentityIeeeV1, this.CompromiseLegalIdentityHandler,
false);
369 this.
UnregisterIqSetHandler(
"petitionIdentity", NamespaceLegalIdentityIeeeV1, this.PetitionIdentityHandler,
false);
370 this.
UnregisterIqSetHandler(
"petitionIdentityResponse", NamespaceLegalIdentityIeeeV1, this.PetitionIdentityResponseHandler,
false);
371 this.
UnregisterIqSetHandler(
"addAttachment", NamespaceLegalIdentityIeeeV1, this.AddLegalIdAttachmentHandler,
false);
372 this.
UnregisterIqSetHandler(
"removeAttachment", NamespaceLegalIdentityIeeeV1, this.RemoveLegalIdAttachmentHandler,
false);
373 this.
UnregisterIqSetHandler(
"petitionSignature", NamespaceLegalIdentityIeeeV1, this.PetitionSignatureHandler,
false);
374 this.
UnregisterIqSetHandler(
"petitionSignatureResponse", NamespaceLegalIdentityIeeeV1, this.PetitionSignatureResponseHandler,
false);
375 this.
UnregisterIqSetHandler(
"authorizeAccess", NamespaceLegalIdentityIeeeV1, this.AuthorizeAccessToIdHandler,
false);
376 this.
UnregisterIqGetHandler(
"getNetworkIdentity", NamespaceLegalIdentityIeeeV1, this.GetNetworkLegalIdentityHandler,
false);
378 this.
UnregisterIqSetHandler(
"readyForApproval", NamespaceLegalIdentityIeeeV1, this.ReadyForApprovalHandler,
false);
379 this.
UnregisterIqGetHandler(
"reviewIdProviders", NamespaceLegalIdentityIeeeV1, this.GetReviewIdProvidersHandler,
false);
380 this.
UnregisterIqSetHandler(
"selectReviewService", NamespaceLegalIdentityIeeeV1, this.SelectReviewServiceHandler,
false);
384 this.
UnregisterIqSetHandler(
"createContract", NamespaceSmartContractsIeeeV1, this.CreateContractHandler,
true);
385 this.
UnregisterIqGetHandler(
"getCreatedContracts", NamespaceSmartContractsIeeeV1, this.GetCreatedContractsHandler,
false);
386 this.
UnregisterIqSetHandler(
"signContract", NamespaceSmartContractsIeeeV1, this.SignContractHandler,
false);
387 this.
UnregisterIqGetHandler(
"getSignedContracts", NamespaceSmartContractsIeeeV1, this.GetSignedContractsHandler,
false);
388 this.
UnregisterIqGetHandler(
"getContract", NamespaceSmartContractsIeeeV1, this.GetContractHandler,
false);
389 this.
UnregisterIqGetHandler(
"getContracts", NamespaceSmartContractsIeeeV1, this.GetContractsHandler,
false);
391 this.
UnregisterIqSetHandler(
"obsoleteContract", NamespaceSmartContractsIeeeV1, this.ObsoleteContractHandler,
false);
392 this.
UnregisterIqSetHandler(
"deleteContract", NamespaceSmartContractsIeeeV1, this.DeleteContractHandler,
false);
393 this.
UnregisterIqSetHandler(
"updateContract", NamespaceSmartContractsIeeeV1, this.UpdateContractHandler,
false);
396 this.
UnregisterIqGetHandler(
"getLegalIdentities", NamespaceSmartContractsIeeeV1, this.GetLegalIdentitiesOfContractHandler,
false);
397 this.
UnregisterIqGetHandler(
"getNetworkIdentities", NamespaceSmartContractsIeeeV1, this.GetNetworkIdentitiesHandler,
false);
398 this.
UnregisterIqGetHandler(
"searchPublicContracts", NamespaceSmartContractsIeeeV1, this.SearchPublicContractsHandler,
false);
399 this.
UnregisterIqSetHandler(
"petitionContract", NamespaceSmartContractsIeeeV1, this.PetitionContractHandler,
false);
400 this.
UnregisterIqSetHandler(
"petitionContractResponse", NamespaceSmartContractsIeeeV1, this.PetitionContractResponseHandler,
false);
401 this.
UnregisterIqSetHandler(
"addAttachment", NamespaceSmartContractsIeeeV1, this.AddContractAttachmentHandler,
false);
402 this.
UnregisterIqSetHandler(
"removeAttachment", NamespaceSmartContractsIeeeV1, this.RemoveContractAttachmentHandler,
false);
403 this.
UnregisterIqSetHandler(
"authorizeAccess", NamespaceSmartContractsIeeeV1, this.AuthorizeAccessToContractHandler,
false);
408 this.remoteComponents?.
Dispose();
409 this.remoteComponents =
null;
421 Gateway.ContractsClient.PetitionForPeerReviewIDReceived += this.ContractsClient_PetitionForPeerReviewIDReceived;
430 Gateway.ContractsClient.PetitionForPeerReviewIDReceived -= this.ContractsClient_PetitionForPeerReviewIDReceived;
452 if (this.eDaler is
null)
454 else if (this.eDaler != value)
455 throw new InvalidOperationException(
"Not allowed to change component reference.");
464 internal byte[] Sign(
byte[] Data)
469 internal byte[] Sign(Stream Data)
474 internal bool Verify(
byte[] Data,
byte[]
Signature)
488 #region Legal Identities
490 private Task GetPublicKeyHandler(
object Sender,
IqEventArgs e)
492 StringBuilder Xml =
new StringBuilder();
495 Xml.Append(
"<publicKey xmlns='");
497 Xml.Append(
"'><ed448 pub='");
499 Xml.Append(
"' xmlns='");
501 Xml.Append(
"'/></publicKey>");
505 return Task.CompletedTask;
508 private Task IdApplicationAttributesHandler(
object Sender,
IqEventArgs e)
510 StringBuilder Xml =
new StringBuilder();
513 Xml.Append(
"<idApplicationAttributes xmlns='");
518 Xml.Append(
"' peerReview='true' nrReviewers='");
520 Xml.Append(
"' nrPhotos='");
522 Xml.Append(
"' iso3166='");
527 Xml.Append(
"<required>FIRST</required>");
530 Xml.Append(
"<required>MIDDLE</required>");
533 Xml.Append(
"<required>LAST</required>");
536 Xml.Append(
"<required>PNR</required>");
539 Xml.Append(
"<required>ADDR</required>");
542 Xml.Append(
"<required>ZIP</required>");
545 Xml.Append(
"<required>AREA</required>");
548 Xml.Append(
"<required>CITY</required>");
551 Xml.Append(
"<required>REGION</required>");
554 Xml.Append(
"<required>COUNTRY</required>");
557 Xml.Append(
"<required>NATIONALITY</required>");
560 Xml.Append(
"<required>GENDER</required>");
564 Xml.Append(
"<required>BDAY</required>");
565 Xml.Append(
"<required>BMONTH</required>");
566 Xml.Append(
"<required>BYEAR</required>");
569 Xml.Append(
"</idApplicationAttributes>");
572 Xml.Append(
"' peerReview='false'/>");
576 return Task.CompletedTask;
579 private async Task ApplyHandler(
object Sender,
IqEventArgs e)
585 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can apply for registering legal identities.",
"en");
591 foreach (XmlNode N
in e.
Query.ChildNodes)
593 if (N is XmlElement E && E.LocalName ==
"identity" && E.NamespaceURI == e.
Query.NamespaceURI)
595 Identity =
LegalIdentity.Parse(E, out
bool HasStatus, out _);
598 await e.
IqErrorBadRequest(e.
To,
"Status element not permitted when applying for a legal identity.",
"en");
604 if (Identity is
null)
616 if (!Identity.HasClientPublicKey)
622 if (!Identity.HasClientSignature)
628 if (!(Identity.ServerSignature is
null))
634 if (!Identity.ValidateClientSignature(
this))
646 string JID = Identity[
"JID"];
647 if (!
string.IsNullOrEmpty(JID) && JID != e.
From.
BareJid)
657 string EMail = Identity[
"EMAIL"];
664 string PhoneNr = Identity[
"PHONE"];
675 Identity.Updated = DateTime.MinValue;
676 Identity.From = Identity.Created.Date;
685 "LegalIdDeleted", ToRemove.GetTags());
690 Identity.Id = Identity.ObjectId +
"@" + this.SubdomainSuffixed + e.
From.
Domain;
695 KeyValuePair<string, object>[] Tags = Identity.GetTags();
698 "LegalIdRegistered", Tags);
702 StringBuilder Xml =
new StringBuilder();
703 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
704 string IdentityXml = Xml.ToString();
708 StringBuilder Markdown =
new StringBuilder();
710 Markdown.Append(
"Legal identity application received: [`");
711 Markdown.Append(Identity.Id);
712 Markdown.Append(
"`](");
714 Markdown.Append(Identity.Id);
715 Markdown.AppendLine(
")");
716 Markdown.AppendLine();
717 Output(Markdown, Tags);
735 Markdown.AppendLine(
"Other identities registered for the same account:");
742 Markdown.Append(
"[`");
743 Markdown.Append(ID.Id);
744 Markdown.Append(
"`](");
746 Markdown.Append(ID.Id);
747 Markdown.AppendLine(
")");
748 Markdown.AppendLine();
750 Output(Markdown, ID.GetTags());
770 internal static PersonalInfo GetPersonalInfo(
LegalIdentity Identity)
772 return GetPersonalInfo(Identity.Properties);
780 internal static PersonalInfo GetPersonalInfo(IEnumerable<Property> Properties)
782 PersonalInfo Result =
new PersonalInfo();
789 Result.FirstName = P.
Value;
793 Result.MiddleNames = P.
Value;
797 Result.LastNames = P.
Value;
801 Result.Address = P.
Value;
805 Result.PostalCode = P.
Value;
809 Result.Area = P.
Value;
813 Result.City = P.
Value;
817 Result.Region = P.
Value;
821 Result.Country = P.
Value;
825 Result.Nationality = P.
Value;
832 Result.Gender = Gender.Male;
836 Result.Gender = Gender.Female;
840 Result.Gender = Gender.Other;
846 if (
int.TryParse(P.
Value, out
int i) && i >= 1 && i <= 31)
851 if (
int.TryParse(P.
Value, out i) && i >= 1 && i <= 12)
852 Result.BirthMonth = i;
856 if (
int.TryParse(P.
Value, out i) && i >= 1900 && i <= 2100)
857 Result.BirthYear = i;
861 Result.PersonalNumber = P.
Value;
865 Result.OrgName = P.
Value;
866 Result.HasOrg =
true;
870 Result.OrgDepartment = P.
Value;
871 Result.HasOrg =
true;
875 Result.OrgRole = P.
Value;
876 Result.HasOrg =
true;
880 Result.OrgAddress = P.
Value;
881 Result.HasOrg =
true;
885 Result.OrgPostalCode = P.
Value;
886 Result.HasOrg =
true;
890 Result.OrgArea = P.
Value;
891 Result.HasOrg =
true;
895 Result.OrgCity = P.
Value;
896 Result.HasOrg =
true;
900 Result.OrgRegion = P.
Value;
901 Result.HasOrg =
true;
905 Result.OrgCountry = P.
Value;
906 Result.HasOrg =
true;
910 Result.OrgNumber = P.
Value;
911 Result.HasOrg =
true;
916 Result.HasBirthDate =
917 Result.BirthDay.HasValue &&
918 Result.BirthMonth.HasValue &&
919 Result.BirthYear.HasValue &&
920 Result.BirthDay.Value <= DateTime.DaysInMonth(Result.BirthYear.Value, Result.BirthMonth.Value);
922 if (!Result.HasBirthDate)
924 Result.BirthDay =
null;
925 Result.BirthMonth =
null;
926 Result.BirthYear =
null;
932 internal class PersonalInfo
955 public Gender? Gender =
null;
956 public int? BirthYear =
null;
957 public int? BirthMonth =
null;
958 public int? BirthDay =
null;
959 public bool HasOrg =
false;
960 public bool HasBirthDate =
false;
962 public DateTime? BirthDate
966 if (this.HasBirthDate)
967 return new DateTime(this.BirthYear.Value,
this.BirthMonth.Value,
this.BirthDay.Value);
990 DateTime TP = DateTime.Now;
991 TP =
new DateTime(TP.Year, TP.Month, TP.Day, TP.Hour, TP.Minute, TP.Second);
996 internal static void Output(StringBuilder Markdown, KeyValuePair<string, object>[] Tags)
998 Output(Markdown, Tags,
true);
1001 internal static void Output(StringBuilder Markdown, KeyValuePair<string, object>[] Tags,
bool IncludeHeader)
1005 Markdown.AppendLine(
"| Key | Value |");
1006 Markdown.AppendLine(
"|:----|:------|");
1009 foreach (KeyValuePair<string, object> Tag
in Tags)
1011 Markdown.Append(
"| ");
1012 Markdown.Append(
MarkdownDocument.
Encode(Tag.Key).Replace(
"\r\n",
"\n").Replace(
"\n",
"<br/>").Replace(
"\r",
"<br/>"));
1013 Markdown.Append(
" | ");
1014 Markdown.Append(
MarkdownDocument.
Encode(Tag.Value.ToString()).Replace(
"\r\n",
"\n").Replace(
"\n",
"<br/>").Replace(
"\r",
"<br/>"));
1015 Markdown.AppendLine(
" |");
1019 private async Task GetLegalIdentitiesHandler(
object Sender,
IqEventArgs e)
1025 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can apply for registering legal identities.",
"en");
1035 catch (Exception ex)
1041 private string SerializeIdentities(IEnumerable<LegalIdentity> Identities, IEnumerable<Dictionary<string, string>> AttachmentUrls,
1044 StringBuilder Xml =
new StringBuilder();
1045 IEnumerator<Dictionary<string, string>> e = AttachmentUrls?.GetEnumerator();
1047 Xml.Append(
"<identities xmlns='");
1052 Identity.Serialize(Xml, Identity.Version != Version,
true,
true,
true,
true,
true,
true, (e?.MoveNext() ??
false) ? e.Current :
null,
this);
1054 Xml.Append(
"</identities>");
1056 return Xml.ToString();
1059 internal static Task<LegalIdentity> GetLocalLegalIdentity(
string LegalId)
1064 private async Task GetLegalIdentityHandler(
object Sender,
IqEventArgs e)
1073 if (Identity is
null)
1080 this.IsAccessToIdentityAuthorized(e.
From.
BareJid, Identity.Id))
1084 StringBuilder Xml =
new StringBuilder();
1085 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
1092 await e.
IqErrorForbidden(e.
To,
"A client can only access its own legal identities, and the legal identities of parts in smart contracts to which the client is part.",
"en");
1096 catch (Exception ex)
1102 private async Task PetitionIdentityHandler(
object Sender,
IqEventArgs e)
1111 byte[] Data = Encoding.UTF8.GetBytes(PetitionId +
":" + LegalId +
":" + Purpose +
":" + Nonce +
":" + e.
From.
BareJid.
LowerCase);
1112 XmlElement ContextXml =
null;
1114 foreach (XmlNode N
in e.
Query)
1116 if (!(N is XmlElement E))
1119 if (ContextXml is
null)
1128 LegalIdentity Identity = await GetLocalLegalIdentity(LegalId);
1129 if (Identity is
null)
1137 string JidDomain = i < 0 ? this.Server.Domain : LegalIdAddr.
Domain.
Substring(i + 1);
1139 (
LegalIdentity RequestorIdentity, Dictionary<string, string> RequestorAttachmentUrls) = await this.ValidateSenderSignature(
1142 if (RequestorIdentity is
null)
1145 StringBuilder Msg =
new StringBuilder();
1147 Msg.Append(
"<petitionIdentityMsg id=\"");
1149 Msg.Append(
"\" pid=\"");
1151 Msg.Append(
"\" from=\"");
1153 Msg.Append(
"\" purpose=\"");
1157 !
string.IsNullOrEmpty(Connection.RemoteEndpoint))
1159 Msg.Append(
"\" clientEp=\"");
1160 Msg.Append(
XML.
Encode(Connection.RemoteEndpoint));
1164 ClientInformation ClientInfo = await this.GetNetworkIdentity(RequestorIdentity.Id,
true,
false, Identity.Version);
1165 if (!(ClientInfo is
null))
1167 string ClientEndpoint = ClientInfo.MostRecentEndpoint;
1169 if (!
string.IsNullOrEmpty(ClientEndpoint))
1171 Msg.Append(
"\" clientEp=\"");
1177 Msg.Append(
"\" xmlns=\"");
1180 RequestorIdentity.Serialize(Msg, RequestorIdentity.Version != Identity.Version,
true,
true,
true,
true,
true,
true, RequestorAttachmentUrls,
this);
1182 if (!(ContextXml is
null))
1183 Msg.Append(ContextXml.OuterXml);
1185 Msg.Append(
"</petitionIdentityMsg>");
1192 catch (Exception ex)
1198 private async Task PetitionIdentityResponseHandler(
object Sender,
IqEventArgs e)
1207 XmlElement ContextXml =
null;
1209 foreach (XmlNode N
in e.
Query)
1211 if (!(N is XmlElement E))
1214 if (ContextXml is
null)
1223 Identity = await GetLocalLegalIdentity(LegalId);
1224 if (Identity is
null)
1230 StringBuilder Msg =
new StringBuilder();
1232 Msg.Append(
"<petitionIdentityResponseMsg pid=\"");
1234 Msg.Append(
"\" response=\"");
1238 !
string.IsNullOrEmpty(Connection.RemoteEndpoint))
1240 Msg.Append(
"\" clientEp=\"");
1241 Msg.Append(
XML.
Encode(Connection.RemoteEndpoint));
1244 Msg.Append(
"\" xmlns=\"");
1250 this.IdentityAuthorization(RequestorFullJid.
BareJid, e.
From.
BareJid, LegalId, Response);
1252 Identity.Serialize(Msg,
false,
true,
true,
true,
true,
true,
true,
null,
this);
1255 if (!(ContextXml is
null))
1256 Msg.Append(ContextXml.OuterXml);
1258 Msg.Append(
"</petitionIdentityResponseMsg>");
1264 catch (Exception ex)
1273 this.Authorization(
"I:", ToBareJid, FromBareJid, LegalId, Authorized ? 1 : 0);
1298 this.petitions.
Add(Key2, Value);
1300 lock (this.petitionsByBareJid)
1302 if (!this.petitionsByBareJid.
TryGetValue(ToBareJid, out Dictionary<CaseInsensitiveString, CaseInsensitiveString> ByLegalId))
1304 ByLegalId =
new Dictionary<CaseInsensitiveString, CaseInsensitiveString>();
1305 this.petitionsByBareJid[ToBareJid] = ByLegalId;
1308 ByLegalId[Key1] = FromBareJid;
1313 this.petitions.
Remove(Key2);
1315 lock (this.petitionsByBareJid)
1317 if (this.petitionsByBareJid.
TryGetValue(ToBareJid, out Dictionary<CaseInsensitiveString, CaseInsensitiveString> ByLegalId) &&
1318 ByLegalId.Remove(Key1) &&
1319 ByLegalId.Count == 0)
1321 this.petitionsByBareJid.
Remove(ToBareJid);
1332 int i1 = Key.IndexOf(
':');
1335 int i2 = Key.IndexOf(
':', i1 + 1);
1341 lock (this.petitionsByBareJid)
1343 if (this.petitionsByBareJid.
TryGetValue(ToBareJid, out Dictionary<CaseInsensitiveString, CaseInsensitiveString> ByLegalId) &&
1344 ByLegalId.Remove(Key1) &&
1345 ByLegalId.Count == 0)
1347 this.petitionsByBareJid.
Remove(ToBareJid);
1354 return Task.CompletedTask;
1360 return this.petitions.
TryGetValue(Key, out
int i) && (i > 0);
1363 private async Task Server_OnPresenceLocalSender(
object Sender,
PresenceEventArgs e)
1374 if (N is XmlElement E && E.LocalName ==
"identity" && E.NamespaceURI == Namespace)
1377 if (!(Identity is
null))
1381 LegalIdentity Identity2 = await GetLocalLegalIdentity(Identity.Id);
1382 if (Identity is
null)
1390 Log.
Warning(
"Client tried to forward someone else's identity in a presence subscription request.",
1393 new KeyValuePair<string, object>(
"ID", Identity.Id.
Value),
1394 new KeyValuePair<string, object>(
"ID Account", Identity.Account.
Value));
1401 StringBuilder Id1 =
new StringBuilder();
1402 Identity.Serialize(Id1,
true,
true,
true,
true,
true,
true,
false,
null,
this);
1403 string Id1Xml = Id1.ToString();
1405 StringBuilder Id2 =
new StringBuilder();
1406 Identity.Serialize(Id2,
true,
true,
true,
true,
true,
true,
false,
null,
this);
1407 string Id2Xml = Id2.ToString();
1409 if (Id1Xml == Id2Xml)
1413 Log.
Warning(
"Client tried to forward invalid ID in a presence subscription request.",
1416 new KeyValuePair<string, object>(
"ID", Identity.Id.
Value),
1417 new KeyValuePair<string, object>(
"Attempt", Id1Xml),
1418 new KeyValuePair<string, object>(
"Actual", Id2Xml));
1430 case "unsubscribed":
1431 LinkedList<KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>> ToRemove =
null;
1433 lock (this.petitionsByBareJid)
1435 if (this.petitionsByBareJid.
TryGetValue(e.
To.
BareJid, out Dictionary<CaseInsensitiveString, CaseInsensitiveString> ByLegalId))
1437 foreach (KeyValuePair<CaseInsensitiveString, CaseInsensitiveString> P
in ByLegalId)
1441 if (ToRemove is
null)
1442 ToRemove =
new LinkedList<KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>>();
1444 ToRemove.AddLast(P);
1450 if (!(ToRemove is
null))
1452 foreach (KeyValuePair<CaseInsensitiveString, CaseInsensitiveString> P
in ToRemove)
1453 this.Authorization(P.Key.Substring(0, 2), e.
To.
BareJid, P.
Value, P.Key.Substring(2), 0);
1460 private async Task PetitionSignatureHandler(
object Sender,
IqEventArgs e)
1469 string ContentStr =
null;
1470 XmlElement ContextXml =
null;
1472 foreach (XmlNode N
in e.
Query.ChildNodes)
1474 if (!(N is XmlElement E))
1477 if (E.LocalName ==
"content" && E.NamespaceURI == e.
Query.NamespaceURI)
1478 ContentStr = E.InnerText;
1479 else if (ContextXml is
null)
1488 if (ContentStr is
null)
1490 if (ContextXml is
null)
1491 ContentStr = e.
Query.InnerText;
1499 byte[] Content = Convert.FromBase64String(ContentStr);
1500 string DataStr = PetitionId +
":" + LegalId +
":" + Purpose +
":" + Nonce +
":" + e.From.BareJid.LowerCase +
":" + ContentStr;
1501 byte[] Data = Encoding.UTF8.GetBytes(DataStr);
1502 string s = Encoding.UTF8.GetString(Content);
1504 Dictionary<string, string> ReqAttachmentUrls =
null;
1505 bool PeerReview =
false;
1507 if (s.StartsWith(
"<identity") && s.EndsWith(
"</identity>"))
1511 XmlDocument Doc =
new XmlDocument()
1513 PreserveWhitespace =
true
1517 if (Doc.DocumentElement.LocalName ==
"identity")
1526 ReqIdentity = TempId;
1529 if (!TempId.ValidateSignature(Data,
Signature))
1531 await e.
IqErrorForbidden(e.
To,
"Signature of identity proving access to private keys not valid.",
"en");
1543 LegalIdentity Identity = await GetLocalLegalIdentity(LegalId);
1544 if (Identity is
null)
1552 string JidDomain = i < 0 ? this.Server.Domain : LegalIdAddr.
Domain.
Substring(i + 1);
1554 if (ReqIdentity is
null)
1556 (ReqIdentity, ReqAttachmentUrls) = await this.ValidateSenderSignature(e.
From,
new ExternalRequest(e), DateTime.Now, Data,
Signature, Identity.Account +
"@" + JidDomain);
1557 if (ReqIdentity is
null)
1561 StringBuilder Msg =
new StringBuilder();
1563 Msg.Append(
"<petitionSignatureMsg id=\"");
1565 Msg.Append(
"\" pid=\"");
1567 Msg.Append(
"\" from=\"");
1569 Msg.Append(
"\" purpose=\"");
1573 !
string.IsNullOrEmpty(Connection.RemoteEndpoint))
1575 Msg.Append(
"\" clientEp=\"");
1576 Msg.Append(
XML.
Encode(Connection.RemoteEndpoint));
1580 ClientInformation ClientInfo = await this.GetNetworkIdentity(ReqIdentity.Id,
true,
false, Identity.Version);
1581 if (!(ClientInfo is
null))
1583 string ClientEndpoint = ClientInfo.MostRecentEndpoint;
1585 if (!
string.IsNullOrEmpty(ClientEndpoint))
1587 Msg.Append(
"\" clientEp=\"");
1593 Msg.Append(
"\" xmlns=\"");
1595 Msg.Append(
"\"><content>");
1596 Msg.Append(ContentStr);
1597 Msg.Append(
"</content>");
1600 ReqIdentity.Serialize(Msg, ReqIdentity.Version != Identity.Version,
true,
true,
true,
true,
true,
true, ReqAttachmentUrls,
this);
1604 if (!(ContextXml is
null))
1606 Msg.Append(ContextXml.OuterXml);
1611 int Timeout =
XML.
Attribute(ContextXml,
"timeout", 3600);
1613 if (Timeout < 1 || Timeout > 3600)
1628 await e.
IqErrorBadRequest(e.
To,
"Requestor lacks DOMAIN property in its legal identity.",
"en");
1632 if (ReqDomain != Domain)
1634 await e.
IqErrorBadRequest(e.
To,
"Requestor domain does not match stated domain in agent API context.",
"en");
1638 this.AgentApiLoginCorrelation(e.
From.
BareJid, ClientBareJid.
Address, PetitionId, Timeout);
1642 Msg.Append(
"</petitionSignatureMsg>");
1648 catch (Exception ex)
1657 this.Authorization(
"A:", ToBareJid, FromBareJid, PetitionId, Timeout);
1665 if (!this.petitions.
TryGetValue(Key2, out Timeout))
1671 lock (this.petitionsByBareJid)
1673 if (!this.petitionsByBareJid.
TryGetValue(ToBareJid, out Dictionary<CaseInsensitiveString, CaseInsensitiveString> ByLegalId))
1679 if (!ByLegalId.TryGetValue(Key1, out
CaseInsensitiveString FromBareJid2) || FromBareJid != FromBareJid2)
1695 private async Task PetitionSignatureResponseHandler(
object Sender,
IqEventArgs e)
1703 string ContentStr =
null;
1704 string SignatureStr =
null;
1705 byte[] Content =
null;
1708 XmlElement ContextXml =
null;
1710 foreach (XmlNode N
in e.
Query.ChildNodes)
1712 if (!(N is XmlElement E))
1715 if (E.NamespaceURI == e.
Query.NamespaceURI)
1717 switch (E.LocalName)
1720 ContentStr = E.InnerText;
1721 Content = Convert.FromBase64String(ContentStr);
1725 SignatureStr = E.InnerText;
1726 Signature = Convert.FromBase64String(SignatureStr);
1730 else if (ContextXml is
null)
1739 Identity = await GetLocalLegalIdentity(LegalId);
1740 if (Identity is
null)
1746 StringBuilder Msg =
new StringBuilder();
1748 Msg.Append(
"<petitionSignatureResponseMsg pid=\"");
1750 Msg.Append(
"\" response=\"");
1754 !
string.IsNullOrEmpty(Connection.RemoteEndpoint))
1756 Msg.Append(
"\" clientEp=\"");
1757 Msg.Append(
XML.
Encode(Connection.RemoteEndpoint));
1760 Msg.Append(
"\" xmlns=\"");
1766 if (Content is
null)
1778 if (!Identity.ValidateSignature(Content,
Signature))
1784 Msg.Append(
"<signature>");
1785 Msg.Append(SignatureStr);
1786 Msg.Append(
"</signature>");
1787 Identity.Serialize(Msg,
false,
true,
true,
true,
true,
true,
true,
null,
this);
1789 this.IdentityAuthorization(RequestorFullJid.
BareJid, e.
From.
BareJid, LegalId, Response);
1791 if (ContextXml is
null &&
1792 this.IsAgentApiLoginCorrelated(RequestorFullJid.
BareJid, e.
From.
BareJid, PetitionId, out
int Timeout) &&
1808 int IssuedAt = (int)Math.Round(DateTime.UtcNow.Subtract(
JSON.
UnixEpoch).TotalSeconds);
1809 int Expires = IssuedAt + Timeout;
1818 Msg.Append(
"<agentApiToken xmlns='");
1822 Msg.Append(
"</agentApiToken>");
1826 if (!(ContextXml is
null))
1827 Msg.Append(ContextXml.OuterXml);
1829 Msg.Append(
"</petitionSignatureResponseMsg>");
1836 catch (Exception ex)
1842 private async Task ValidateSignatureHandler(
object Sender,
IqEventArgs e)
1850 string ForBareJid =
null;
1852 foreach (XmlAttribute Attr
in e.
Query.Attributes)
1861 BareJid = Attr.
Value;
1865 Data = Convert.FromBase64String(Attr.Value);
1869 Signature = Convert.FromBase64String(Attr.Value);
1873 ForBareJid = Attr.Value;
1886 await e.
IqErrorBadRequest(e.
To,
"Both the id and bareJid attributes cannot be specified at the same time.",
"en");
1896 Identity = await GetLocalLegalIdentity(Id);
1897 if (Identity is
null)
1903 if (!Identity.ValidateSignature(Data,
Signature))
1919 await e.
IqErrorForbidden(e.
To,
"Bare JID does not correspond to this Trust Provider.",
"en");
1931 DateTime Now = DateTime.Now;
1939 if (ID.ValidateSignature(Data,
Signature))
1946 if (Identity is
null)
1948 await e.
IqErrorForbidden(e.
To,
"No matching legal identity found that can validate the signature.",
"en");
1953 if (!
string.IsNullOrEmpty(ForBareJid))
1954 this.IdentityAuthorization(ForBareJid, BareJid, Identity.Id,
true);
1956 StringBuilder Xml =
new StringBuilder();
1957 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
1961 catch (Exception ex)
1967 private Task ObsoleteLegalIdentityHandler(
object Sender,
IqEventArgs e)
1969 return this.ChangeStateLegalIdentityHandler(e,
IdentityState.Obsoleted);
1972 private Task CompromiseLegalIdentityHandler(
object Sender,
IqEventArgs e)
1974 return this.ChangeStateLegalIdentityHandler(e,
IdentityState.Compromised);
1987 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can apply for registering legal identities.",
"en");
1992 if (Identity is
null)
2000 await e.
IqErrorForbidden(e.
To,
"Only allowed to obsolete your own legal identities.",
"en");
2017 if (Identity.State != State)
2019 switch (Identity.State)
2026 await e.
IqErrorForbidden(e.
To,
"Legal identity has been rejected, and cannot be changed.",
"en");
2030 await e.
IqErrorForbidden(e.
To,
"Legal identity has been flagged as compromised, and cannot be changed.",
"en");
2037 StringBuilder Xml =
new StringBuilder();
2038 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
2043 catch (Exception ex)
2053 Account.LatestIdentity = Identity.Id;
2065 foreach (
Property P
in Identity.Properties)
2077 Account.EMailVerified =
null;
2084 Account.PhoneNr = s;
2085 Account.PhoneNrVerified =
null;
2090 Account.FirstName = s;
2094 Account.MiddleNames = s;
2098 Account.LastNames = s;
2102 Account.PersonalNumber = s;
2106 Account.Country = s;
2110 Account.OrgName = s;
2114 Account.OrgNumber = s;
2118 Account.OrgDepartment = s;
2122 Account.OrgRole = s;
2126 Account.OrgCountry = s;
2136 if (Identity.State != State)
2140 Identity.State = State;
2142 Identity.Sign(
this);
2147 "LegalIdUpdated", Identity.GetTags());
2151 if (RefBefore && RefAfter)
2152 await UpdateLegalIdentityReference(Identity);
2154 await DeleteLegalIdentityReference(Identity.Id);
2156 await AddLegalIdentityReference(Identity);
2158 StringBuilder Xml =
new StringBuilder();
2159 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
2162 Identity.Account +
"@" + Identity.Provider.
Substring(
this.SubdomainSuffixed.Length),
string.
Empty, Xml.
ToString());
2165 await CopyPropertiesFromApprovedIdentity(Identity,
Account);
2176 return this.GetApprovedLegalIdentityAsync(
Account, DateTime.Now);
2193 if (ID.From <= Timestamp && ID.To >= Timestamp && (Result is
null || ID.Created > Result.Created))
2200 private async Task AddLegalIdAttachmentHandler(
object Sender,
IqEventArgs e)
2214 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can add attachments.",
"en");
2218 if (!Uri.TryCreate(GetUrl, UriKind.Absolute, out Uri GetUri))
2225 if (Identity is
null)
2233 await e.
IqErrorForbidden(e.
To,
"Only allowed to add attachments to your own legal identities.",
"en");
2239 await e.
IqErrorForbidden(e.
To,
"Attachments can only be added to newly created identities before they are approved.",
"en");
2256 if (!(Identity.Attachments is
null))
2258 string s = Convert.ToBase64String(
Signature);
2262 if (Convert.ToBase64String(Ref.
Signature) == s)
2276 if (!Identity.ValidateSignature(File,
Signature))
2283 bool IncNrPeerReviews =
false;
2284 StringBuilder sb =
new StringBuilder();
2285 List<LegalIdentity> Reviewers =
null;
2292 Doc =
new XmlDocument()
2294 PreserveWhitespace =
true
2298 if (Doc.DocumentElement.LocalName ==
"peerReview" && Doc.DocumentElement.NamespaceURI == Namespace)
2304 bool ReviewedHasStatus =
false;
2305 bool ReviewerHasStatus =
false;
2306 byte[] PeerSignature = Convert.FromBase64String(
XML.
Attribute(Doc.DocumentElement,
"s"));
2307 DateTime TP =
XML.
Attribute(Doc.DocumentElement,
"tp", DateTime.Now);
2308 byte[] SignedIdentity =
null;
2309 DateTime Now = DateTime.Now;
2311 foreach (XmlNode N
in Doc.DocumentElement.ChildNodes)
2313 if (!(N is XmlElement E) || N.NamespaceURI != Namespace)
2316 foreach (XmlNode N2
in E.ChildNodes)
2318 if (N2 is XmlElement E2 &&
2319 E2.LocalName ==
"identity" &&
2320 E2.NamespaceURI == Namespace)
2322 switch (E.LocalName)
2325 ReviewedIdentity =
LegalIdentity.Parse(E2, out ReviewedHasStatus,
2326 out Dictionary<string, string> ReviewedIdentityAttachmentsUrls);
2329 ReviewedIdentity.Serialize(sb,
true,
true,
true,
false,
false,
false,
false,
null,
this);
2330 string s1 = sb.ToString();
2333 Identity.Serialize(sb,
true,
true,
true,
false,
false,
false,
false,
null,
this);
2334 string s2 = sb.ToString();
2343 ReviewedIdentity.Serialize(sb,
true,
true,
true,
true,
true,
true,
true, ReviewedIdentityAttachmentsUrls,
this);
2344 SignedIdentity = Encoding.UTF8.GetBytes(sb.ToString());
2348 ReviewerIdentity =
LegalIdentity.Parse(E2, out ReviewerHasStatus,
2349 out Dictionary<string, string> ReviewerIdentityAttachmentsUrls);
2352 ReviewerIdentity.Serialize(sb,
false,
false,
false,
false,
false,
false,
false,
null,
this);
2353 byte[] Data = Encoding.UTF8.GetBytes(sb.ToString());
2354 ReviewerJid = ReviewerIdentity[
"JID"];
2358 (ReviewerIdentity, _) = await this.ValidateSignature(
new XmppAddress(ReviewerJid), TP, Data,
2359 ReviewerIdentity.ClientSignature);
2361 if (ReviewerIdentity is
null || ReviewerJid != ReviewerIdentity[
"JID"])
2374 if (Now.Date.AddDays(1) < ReviewerIdentity.From ||
2375 Now.Date.AddDays(-1) > ReviewerIdentity.To)
2387 if (
string.IsNullOrEmpty(ReviewerIdentity.ClientKeyName) ||
2388 ReviewerIdentity.ClientPubKey is
null ||
2389 ReviewerIdentity.ClientPubKey.Length == 0)
2395 if (ReviewerIdentity.ClientSignature is
null ||
2396 ReviewerIdentity.ClientSignature.Length == 0)
2404 await e.
IqErrorForbidden(e.
To,
"Reviewer identity not trusted for reviewing.",
"en");
2413 if (ReviewedIdentity is
null || !ReviewedHasStatus ||
2414 ReviewerIdentity is
null || !ReviewerHasStatus ||
2415 SignedIdentity is
null)
2417 await e.
IqErrorForbidden(e.
To,
"Attachment not a correctly formed peer-review document.",
"en");
2425 await e.
IqErrorForbidden(e.
To,
"Reviewer cannot be the same person as the reviewed person.",
"en");
2429 if (!ReviewerIdentity.ValidateSignature(SignedIdentity, PeerSignature))
2439 if (!(Identity.Attachments is
null))
2450 await e.
IqErrorForbidden(e.
To,
"Peer review not accepted: Identity lacks sufficient photos (" +
2455 PersonalInfo RI = GetPersonalInfo(ReviewerIdentity);
2459 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a First name. Peer review not accepted.",
"en");
2465 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Middle name. Peer review not accepted.",
"en");
2471 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Last name. Peer review not accepted.",
"en");
2477 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Personal number. Peer review not accepted.",
"en");
2483 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an address. Peer review not accepted.",
"en");
2489 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Postal Code (ZIP). Peer review not accepted.",
"en");
2495 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an Area. Peer review not accepted.",
"en");
2501 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a City. Peer review not accepted.",
"en");
2507 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Region. Peer review not accepted.",
"en");
2513 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Country. Peer review not accepted.",
"en");
2521 await e.
IqErrorBadRequest(e.
To,
"Reviewer Country is not an ISO 3166-1 Country Code. Peer review not accepted.",
"en");
2528 if (Valid.HasValue && !Valid.Value)
2530 await e.
IqErrorBadRequest(e.
To,
"The personal number format used by the reviewer does not comply with regulations.",
"en");
2538 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Nationality. Peer review not accepted.",
"en");
2544 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Gender. Peer review not accepted.",
"en");
2550 if (!RI.HasBirthDate)
2552 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Birth Date. Peer review not accepted.",
"en");
2556 DateTime BirthDate = RI.BirthDate.Value;
2560 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity too young. Peer review not accepted.",
"en");
2569 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization name. Peer review not accepted.",
"en");
2575 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a department. Peer review not accepted.",
"en");
2581 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a role. Peer review not accepted.",
"en");
2587 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization number. Peer review not accepted.",
"en");
2593 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization address. Peer review not accepted.",
"en");
2599 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization Postal Code (ZIP). Peer review not accepted.",
"en");
2605 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization Area. Peer review not accepted.",
"en");
2611 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization City. Peer review not accepted.",
"en");
2617 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization Region. Peer review not accepted.",
"en");
2623 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization Country. Peer review not accepted.",
"en");
2631 await e.
IqErrorBadRequest(e.
To,
"Reviewer organization Country is not an ISO 3166-1 Country Code. Peer review not accepted.",
"en");
2637 if (!await CheckPeerReviewFields(e, ReviewedIdentity))
2640 PersonalInfo PI = GetPersonalInfo(ReviewedIdentity);
2646 await e.
IqErrorBadRequest(e.
To,
"Peer reviewer lacks organization information. Peer review not accepted.",
"en");
2650 if (PI.OrgName != RI.OrgName ||
2651 PI.OrgNumber != RI.OrgNumber ||
2652 PI.OrgCountry != RI.OrgCountry)
2654 await e.
IqErrorBadRequest(e.
To,
"Peer reviewer must be from same company. Peer review not accepted.",
"en");
2659 if (!(Identity.Attachments is
null))
2661 LegalIdentity[] Reviewers2 = await GetPeerReviewers(Identity);
2665 if (ReviewerID[
"PNR"] == Pnr)
2667 await e.
IqErrorBadRequest(e.
To,
"A reviewer can only review the application once.",
"en");
2672 if (Reviewers is
null)
2673 Reviewers =
new List<LegalIdentity>();
2675 Reviewers.AddRange(Reviewers2);
2679 if (Reviewers is
null)
2680 Reviewers =
new List<LegalIdentity>();
2682 Reviewers.Add(ReviewerIdentity);
2683 IncNrPeerReviews =
true;
2689 KeyValuePair<Attachment, AttachmentReference> A = await this.CreateAttachment(GetUri,
2691 List<AttachmentReference> References =
new List<AttachmentReference>();
2692 bool Approved =
false;
2694 if (!(Identity.Attachments is
null))
2695 References.AddRange(Identity.Attachments);
2697 References.Add(A.Value);
2698 Identity.Attachments = References.ToArray();
2701 if (IncNrPeerReviews)
2703 Identity.NrPeerReviews++;
2712 StringBuilder Markdown =
new StringBuilder();
2714 Markdown.AppendLine(
"Peer reviewed Legal ID approved");
2715 Markdown.AppendLine(
"===================================");
2716 Markdown.AppendLine();
2718 this.AppendMarkdown(Markdown, Identity,
"Applicant");
2725 this.AppendMarkdown(Markdown, Reviewer,
"Reviewer " + Index.ToString());
2732 Identity.Sign(
this);
2736 await CopyPropertiesFromApprovedIdentity(Identity,
Account as
Account);
2740 "LegalIdUpdated", Identity.GetTags());
2743 Identity.Serialize(sb,
true,
true,
true,
true,
true,
true,
true,
null,
this);
2744 string Xml = sb.ToString();
2748 await AddLegalIdentityReference(Identity);
2752 string JidDomain = i < 0 ? this.Server.Domain : IdentityAddress.
Domain.
Substring(i + 1);
2755 new XmppAddress(Identity.Account +
"@" +
this.Server.Domain),
string.
Empty, Xml);
2762 catch (Exception ex)
2772 PersonalInfo PI = GetPersonalInfo(Identity);
2845 if (Valid.HasValue && !Valid.Value)
2847 await e.
IqErrorBadRequest(e.
To,
"The personal number format does not comply with regulations in your country.",
"en");
2875 await e.
IqErrorBadRequest(e.
To,
"Organization name is a required field for work identities.",
"en");
2881 await e.
IqErrorBadRequest(e.
To,
"Department is a required field for work identities.",
"en");
2893 await e.
IqErrorBadRequest(e.
To,
"Organization Number is a required field for work identites.",
"en");
2899 await e.
IqErrorBadRequest(e.
To,
"Organization Address is a required field for work identites.",
"en");
2905 await e.
IqErrorBadRequest(e.
To,
"Organization Postal Code (ZIP) is a required field for work identites.",
"en");
2911 await e.
IqErrorBadRequest(e.
To,
"Organization Area is a required field for work identites.",
"en");
2917 await e.
IqErrorBadRequest(e.
To,
"Organization City is a required field for work identites.",
"en");
2923 await e.
IqErrorBadRequest(e.
To,
"Organization Region is a required field for work identites.",
"en");
2929 await e.
IqErrorBadRequest(e.
To,
"Organization Country is a required field for work identites.",
"en");
2937 await e.
IqErrorBadRequest(e.
To,
"Organization Country must be a ISO 3166-1 Country Code.",
"en");
2947 internal static async Task<LegalIdentity[]> GetPeerReviewers(
LegalIdentity Identity)
2949 List<LegalIdentity> Result =
new List<LegalIdentity>();
2952 if (!(Identity?.Attachments is
null))
2965 Aes Aes = Aes.Create();
2967 Aes.BlockSize = 128;
2969 Aes.Mode = CipherMode.CBC;
2970 Aes.Padding = PaddingMode.Zeros;
2972 byte[] Key =
new byte[32];
2973 byte[] IV =
new byte[16];
2978 using (ICryptoTransform Decryptor = Aes.CreateDecryptor(Key, IV))
2980 using (CryptoStream DecryptedAttachmentFile =
new CryptoStream(AttachmentFile, Decryptor, CryptoStreamMode.Read))
2982 XmlDocument Doc =
new XmlDocument()
2984 PreserveWhitespace =
true
2986 Doc.Load(DecryptedAttachmentFile);
2988 if (Doc.DocumentElement.LocalName ==
"peerReview" &&
2989 Doc.DocumentElement.NamespaceURI == Namespace)
2991 foreach (XmlNode N
in Doc.DocumentElement.ChildNodes)
2993 if (N is XmlElement E &&
2994 E.LocalName ==
"reviewer" &&
2995 E.NamespaceURI == Namespace)
2997 foreach (XmlNode N2
in E.ChildNodes)
2999 if (N2 is XmlElement E2 &&
3000 E2.LocalName ==
"identity" &&
3001 E2.NamespaceURI == Namespace)
3004 Result.Add(ReviewerID);
3017 return Result.ToArray();
3020 internal void AppendMarkdown(StringBuilder Markdown,
LegalIdentity Identity,
string Title)
3022 Markdown.AppendLine(Title);
3023 Markdown.AppendLine(
new string(
'-', Title.Length + 3));
3024 Markdown.AppendLine();
3026 Markdown.Append(
"| `");
3027 Markdown.Append(Identity.Id);
3028 Markdown.AppendLine(
"` ||");
3029 Markdown.AppendLine(
"|:----|:----|");
3031 foreach (
Property P
in Identity.Properties)
3033 Markdown.Append(
"| `");
3034 Markdown.Append(P.
Name);
3035 Markdown.Append(
"` | ");
3037 Markdown.AppendLine(
" |");
3040 Markdown.AppendLine();
3043 private Task<KeyValuePair<Attachment, AttachmentReference>> CreateAttachment(Uri GetUri,
3047 return CreateAttachment(Path.GetFileName(GetUri.AbsolutePath), UploadingIdentity,
3048 Signature, File, ContentType,
Account, ContractId,
this.attachmentsFolder);
3051 internal static async Task<KeyValuePair<Attachment, AttachmentReference>> CreateAttachment(
string RemoteFileName,
3055 DateTime Timestamp = DateTime.Now;
3057 Timestamp.Month.ToString(
"D2"), Timestamp.Day.ToString(
"D2"));
3059 if (!Directory.Exists(Folder))
3060 Directory.CreateDirectory(Folder);
3063 byte[] Key =
new byte[32];
3064 byte[] IV =
new byte[16];
3065 string AttachmentId;
3068 Array.Copy(Salt, 0, Key, 0, 32);
3069 Array.Copy(Salt, 32, IV, 0, 16);
3075 ContractId = ContractId,
3076 RemoteFileName = RemoteFileName,
3078 Timestamp = Timestamp,
3079 UploaderLegalId = UploadingIdentity.Id,
3087 FileName = Path.Combine(Folder, AttachmentId +
".bin");
3089 Attachment.Id = AttachmentId +
"@" + UploadingIdentity.Provider;
3090 Attachment.LocalFileName = FileName;
3095 using (FileStream AttachmentFile = System.IO.File.Create(FileName))
3097 Aes Aes = Aes.Create();
3099 Aes.BlockSize = 128;
3101 Aes.Mode = CipherMode.CBC;
3102 Aes.Padding = PaddingMode.Zeros;
3104 using (ICryptoTransform Encryptor = Aes.CreateEncryptor(Key, IV))
3106 using (CryptoStream EncryptedAttachmentFile =
new CryptoStream(AttachmentFile, Encryptor, CryptoStreamMode.Write))
3109 EncryptedAttachmentFile.FlushFinalBlock();
3121 Timestamp = Timestamp
3124 return new KeyValuePair<Attachment, AttachmentReference>(
Attachment, Ref);
3127 private async Task RemoveLegalIdAttachmentHandler(
object Sender,
IqEventArgs e)
3135 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can remove attachments.",
"en");
3155 if (Identity is
null)
3163 await e.
IqErrorForbidden(e.
To,
"Only allowed to remove attachments from your own legal identities.",
"en");
3169 await e.
IqErrorForbidden(e.
To,
"Attachments can only be removed from newly created identities before they are approved.",
"en");
3176 if (!(Identity.Attachments is
null))
3178 List<AttachmentReference> Attachments =
new List<AttachmentReference>();
3182 if (Ref.
Id != AttachmentId)
3183 Attachments.Add(Ref);
3186 Identity.Attachments = Attachments.ToArray();
3187 Identity.Sign(
this);
3194 StringBuilder Xml =
new StringBuilder();
3195 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
3200 catch (Exception ex)
3221 throw new Exception(
"Expected server domain, not a component domain: " + Address.
Domain);
3224 ??
throw new Exception(
"Legal Identity not found: " + Id.
Value);
3230 if (Address.
Domain.
StartsWith(
this.SubdomainSuffixed, StringComparison.CurrentCultureIgnoreCase))
3239 return new ClientInformation()
3242 Connections = this.RemoveDisconnected(Connections)
3248 throw new Exception(
"Expected legal component domain, not server domain: " + Address.
Domain);
3267 return new ClientInformation()
3270 Connections = this.RemoveDisconnected(Connections)
3275 TaskCompletionSource<ClientInformation> Result =
new TaskCompletionSource<ClientInformation>();
3276 StringBuilder Xml =
new StringBuilder();
3279 Xml.Append(
"<getNetworkIdentity xmlns='");
3280 Xml.Append(Namespace);
3281 Xml.Append(
"' id='");
3289 XmlElement E = e2.FirstElement;
3291 if (!(E is null) && E.LocalName ==
"networkIdentity" && E.NamespaceURI == Namespace)
3293 string Jid = XML.Attribute(E,
"jid");
3294 List<ClientConnectionInformation> Connections = new List<ClientConnectionInformation>();
3296 foreach (XmlNode N in E.ChildNodes)
3298 if (N is XmlElement E2 &&
3299 E2.LocalName ==
"connection" &&
3300 E2.NamespaceURI == Namespace)
3302 Connections.Add(new ClientConnectionInformation()
3304 Endpoint = XML.Attribute(E2,
"clientEp"),
3305 LastPresenceTimestamp = XML.Attribute(E2,
"ts", DateTimeOffset.MinValue)
3310 Result.TrySetResult(new ClientInformation()
3313 Connections = Connections.ToArray()
3317 Result.TrySetException(new Exception(
"Unexpected response received."));
3320 Result.TrySetException(
new Exception(
string.IsNullOrEmpty(e2.ErrorText) ?
"Unable to get network identity." : e2.ErrorText));
3322 return Task.CompletedTask;
3325 return await Result.Task;
3329 private ClientConnectionInformation[] RemoveDisconnected(
IClientConnection[] Connections)
3331 if (Connections is
null)
3332 return new ClientConnectionInformation[0];
3334 List<ClientConnectionInformation> Result =
new List<ClientConnectionInformation>();
3347 Result.Add(
new ClientConnectionInformation()
3350 LastPresenceTimestamp = Connection.LastPresence.Timestamp
3354 return Result.ToArray();
3357 internal class ClientInformation
3360 public ClientConnectionInformation[] Connections {
get;
set; }
3362 public string MostRecentEndpoint
3366 DateTimeOffset Best = DateTimeOffset.MinValue;
3367 string Endpoint =
null;
3369 if (!(this.Connections is
null))
3371 foreach (ClientConnectionInformation Info
in this.Connections)
3373 if (Info.LastPresenceTimestamp > Best)
3375 Best = Info.LastPresenceTimestamp;
3376 Endpoint = Info.Endpoint;
3386 internal class ClientConnectionInformation
3388 public string Endpoint {
get;
set; }
3389 public DateTimeOffset LastPresenceTimestamp {
get;
set; }
3392 private Task GetNetworkLegalIdentityHandler(
object Sender,
IqEventArgs e)
3394 return this.GetNetworkIdentityHandler(e,
true);
3397 private Task GetNetworkXmppIdentityHandler(
object Sender,
IqEventArgs e)
3399 return this.GetNetworkIdentityHandler(e,
false);
3402 private async Task GetNetworkIdentityHandler(
IqEventArgs e,
bool ToLegalComponent)
3423 if (this.IsComponentDomain(IdAddress.
Domain,
true))
3425 if (!ToLegalComponent)
3440 if (Identity is
null)
3446 if (IdAddress.
Domain.
StartsWith(
this.SubdomainSuffixed, StringComparison.CurrentCultureIgnoreCase))
3447 NetworkIdentity = Identity.Account +
"@" + IdAddress.
Domain.
Substring(this.SubdomainSuffixed.Length);
3449 NetworkIdentity = Identity.Account +
"@" + this.Server.Domain;
3451 if (!this.Server.TryGetClientConnections(NetworkIdentity, out Connections))
3455 else if (this.Server.IsServerDomain(IdAddress.
Domain,
true))
3457 if (ToLegalComponent)
3465 NetworkIdentity = IdAddress.
Address;
3467 if (!this.Server.TryGetClientConnections(NetworkIdentity, out Connections))
3472 NetworkIdentity = IdAddress.
BareJid;
3492 StringBuilder Xml =
new StringBuilder();
3494 Xml.Append(
"<networkIdentity xmlns='");
3495 Xml.Append(NamespaceLegalIdentity(QueryVersion));
3496 Xml.Append(
"' jid='");
3497 Xml.Append(
XML.
Encode(NetworkIdentity));
3500 foreach (ClientConnectionInformation ClientInfo
in this.RemoveDisconnected(Connections))
3502 Xml.Append(
"<connection clientEp='");
3503 Xml.Append(
XML.
Encode(ClientInfo.Endpoint));
3504 Xml.Append(
"' ts='");
3505 Xml.Append(
XML.
Encode(ClientInfo.LastPresenceTimestamp));
3509 Xml.Append(
"</networkIdentity>");
3513 catch (Exception ex)
3519 private async Task CanSignAsHandler(
object Sender,
IqEventArgs e)
3540 if (ReferenceAddress.
Domain != SignatoryAddress.
Domain)
3548 if (!this.IsComponentDomain(ReferenceAddress.
Domain,
true))
3550 await e.
IqErrorBadRequest(e.
To, IncludeDetailedErrorMessage ?
"Reference identity not hosted by broker." :
string.
Empty,
"en");
3554 LegalIdentity ReferenceIdentity = await GetLocalLegalIdentity(ReferenceId);
3555 if (ReferenceIdentity is
null)
3561 switch (ReferenceIdentity.State)
3564 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Reference ID never approved." :
string.
Empty,
"en");
3568 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Reference ID still approved." :
string.
Empty,
"en");
3575 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Reference ID lacks encoded JID." :
string.
Empty,
"en");
3582 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Reference ID lacks encoded Personal Number." :
string.
Empty,
"en");
3589 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Reference ID lacks encoded Country." :
string.
Empty,
"en");
3593 LegalIdentity SignatoryIdentity = await GetLocalLegalIdentity(SignatoryId);
3594 if (SignatoryIdentity is
null)
3602 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Signatory ID not in an approved state." :
string.
Empty,
"en");
3606 if (SignatoryIdentity[
"JID"] != BareJid)
3612 if (SignatoryIdentity[
"PNR"] != PersonalNumber)
3614 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Personal Number mismatch." :
string.
Empty,
"en");
3618 if (SignatoryIdentity[
"COUNTRY"] != Country)
3626 catch (Exception ex)
3644 if (ReferenceAddress.
Domain != SignatoryAddress.
Domain)
3647 if (this.IsComponentDomain(ReferenceAddress.
Domain,
true))
3649 LegalIdentity ReferenceIdentity = await GetLocalLegalIdentity(ReferenceId);
3650 if (ReferenceIdentity is
null)
3653 switch (ReferenceIdentity.State)
3671 LegalIdentity SignatoryIdentity = await GetLocalLegalIdentity(SignatoryId);
3672 if (SignatoryIdentity is
null)
3678 if (SignatoryIdentity[
"JID"] != BareJid ||
3679 SignatoryIdentity[
"PNR"] != PersonalNumber ||
3680 SignatoryIdentity[
"COUNTRY"] != Country)
3689 TaskCompletionSource<bool> Result =
new TaskCompletionSource<bool>();
3690 StringBuilder Xml =
new StringBuilder();
3691 string Namespace = NamespaceLegalIdentity(
NamespaceSet.Current);
3693 Xml.Append(
"<canSignAs xmlns='");
3694 Xml.Append(Namespace);
3695 Xml.Append(
"' referenceId='");
3697 Xml.Append(
"' signatoryId='");
3701 await this.Server.SendIqRequest(
"get", this.MainDomain.Address, ReferenceAddress.
Domain,
string.
Empty, Xml.
ToString(), (sender2, e2) =>
3703 Result.TrySetResult(e2.Ok);
3704 return Task.CompletedTask;
3707 return await Result.Task;
3711 private async Task AuthorizeAccessToIdHandler(
object Sender,
IqEventArgs e)
3715 if (!this.Server.IsServerDomain(e.
From.
Domain,
true))
3737 if (!this.IsComponentDomain(IdAddress.
Domain,
true))
3762 if (Identity is
null)
3774 ClientInformation ClientInfo = await this.GetNetworkIdentity(RemoteId,
true,
true, Identity.Version);
3776 this.IdentityAuthorization(RemoteJid, e.
From.
BareJid, Id, Authorized);
3781 catch (Exception ex)
3787 private async Task ReadyForApprovalHandler(
object Sender,
IqEventArgs e)
3796 if (Identity is
null)
3804 await e.
IqErrorForbidden(e.
To,
"You can only mark your own identity applications for approval.",
"en");
3822 this.CheckAuthenticityOfIdentity(Identity, Identity.GetTags(), e.
To, e.
From,
Account as
Account);
3825 catch (Exception ex)
3831 internal async
void CheckAuthenticityOfIdentity(
LegalIdentity Identity, KeyValuePair<string, object>[] Tags,
3838 if (!(Identity.Attachments is
null))
3853 if (Authenticator is
null)
3856 List<IPhoto> Photos =
new List<IPhoto>();
3858 if (!(Identity.Attachments is
null))
3870 Aes Aes = Aes.Create();
3872 Aes.BlockSize = 128;
3874 Aes.Mode = CipherMode.CBC;
3875 Aes.Padding = PaddingMode.Zeros;
3877 byte[] Key =
new byte[32];
3878 byte[] IV =
new byte[16];
3883 using (ICryptoTransform Decryptor = Aes.CreateDecryptor(Key, IV))
3885 using (CryptoStream DecryptedAttachmentFile =
new CryptoStream(AttachmentFile, Decryptor, CryptoStreamMode.Read))
3888 byte[] Bin =
new byte[c];
3890 await DecryptedAttachmentFile.ReadAllAsync(Bin, 0, c);
3892 Photos.Add(
new Photo()
3908 if (Result.
ErrorType == global::Paiwise.ErrorType.Server || Result.
ErrorType == global::Paiwise.ErrorType.Service)
3913 StringBuilder Xml =
new StringBuilder();
3915 Xml.Append(
"<body>");
3917 Xml.Append(
"</body>");
3918 Xml.Append(
"<clientMessage xmlns='");
3919 Xml.Append(NamespaceLegalIdentity(Identity.Version));
3920 Xml.Append(
"' code='");
3922 Xml.Append(
"' type='");
3923 Xml.Append(Result.
ErrorType.ToString());
3926 await this.Server.SendMessage(
string.Empty,
string.Empty, ComponentAddress, ClientJid.
ToBareJID(), Result.
ErrorLanguage, Xml.ToString());
3929 if (!Result.
Result.HasValue)
3936 Log.
Notice(
"Legal identity application has been automatically approved.",
3937 Identity.Id.
Value, Authenticator.GetType().FullName, Tags);
3939 StringBuilder Markdown =
new StringBuilder();
3941 Markdown.Append(
"Legal identity application has been automatically approved: `");
3942 Markdown.Append(Identity.Id);
3943 Markdown.Append(
"` (by `");
3944 Markdown.Append(Authenticator.GetType().FullName);
3945 Markdown.AppendLine(
"`)");
3946 Markdown.AppendLine();
3947 Output(Markdown, Tags);
3955 Log.
Warning(
"Legal identity application has been automatically rejected.",
3956 Identity.Id.
Value, Authenticator.GetType().FullName, Tags);
3958 StringBuilder Markdown =
new StringBuilder();
3960 Markdown.Append(
"Legal identity application has been automatically rejected: `");
3961 Markdown.Append(Identity.Id);
3962 Markdown.AppendLine(
"`");
3963 Markdown.AppendLine();
3964 Output(Markdown, Tags);
3969 catch (Exception ex)
3983 return LoadEncryptedFile(FileName, Salt,
null);
3995 using (FileStream File = System.IO.File.OpenRead(FileName))
3997 Aes Aes = Aes.Create();
3999 Aes.BlockSize = 128;
4001 Aes.Mode = CipherMode.CBC;
4002 Aes.Padding = PaddingMode.Zeros;
4004 byte[] Key =
new byte[32];
4005 byte[] IV =
new byte[16];
4007 Array.Copy(Salt, 0, Key, 0, 32);
4008 Array.Copy(Salt, 32, IV, 0, 16);
4010 using (ICryptoTransform Decryptor = Aes.CreateDecryptor(Key, IV))
4012 using (CryptoStream DecryptedFile =
new CryptoStream(File, Decryptor, CryptoStreamMode.Read))
4016 long c = Size.Value;
4017 if (c >
int.MaxValue)
4018 throw new IOException(
"File too large.");
4021 byte[] Bin =
new byte[c0];
4023 await DecryptedFile.ReadAllAsync(Bin, 0, c0);
4029 using (MemoryStream ms =
new MemoryStream())
4031 await DecryptedFile.CopyToAsync(ms);
4032 return ms.ToArray();
4042 public KeyValuePair<string, object>[] Claims {
get;
set; }
4043 public int NrPhotos {
get;
set; }
4046 private class Photo :
IPhoto
4048 public string ContentType {
get;
set; }
4049 public byte[] Binary {
get;
set; }
4054 #region Legal Identity references
4056 internal static async Task CheckLegalIdentityReferences()
4060 if (Array.IndexOf(CollectionNames,
"LegalIdentityReferences") < 0)
4065 await UpdateLegalIdentityReference(Identity);
4070 internal static async Task AddLegalIdentityReference(
LegalIdentity Identity)
4074 Country = Identity[
"COUNTRY"],
4075 PNr = Identity[
"PNR"],
4076 LegalId = Identity.Id,
4077 Provider = Identity.Provider,
4078 ArchiveDays = CalcRefArchiveDays(Identity)
4110 private static async Task UpdateLegalIdentityReference(
LegalIdentity Identity)
4115 await AddLegalIdentityReference(Identity);
4118 string s = Identity[
"COUNTRY"];
4119 bool Updated =
false;
4127 s = Identity[
"PNR"];
4134 if (Ref.
Provider != Identity.Provider)
4136 Ref.Provider = Identity.Provider;
4145 private static Task DeleteLegalIdentityReference(
string LegalId)
4150 private static int CalcRefArchiveDays(
LegalIdentity Identity)
4152 DateTime Expires = Identity.To;
4153 if (Expires == DateTime.MaxValue)
4154 return int.MaxValue;
4156 TimeSpan Span = Expires - DateTime.Now;
4157 double Days = Math.Ceiling(Span.TotalDays);
4161 else if (Days >
int.MaxValue)
4162 return int.MaxValue;
4169 #region Smart Contracts
4173 TaskCompletionSource<IqResultEventArgs> T =
new TaskCompletionSource<IqResultEventArgs>();
4176 if (this.Server.IsServerDomain(ContractAddress.
Domain,
true) ||
this.IsComponentDomain(ContractAddress.
Domain,
true))
4180 if (!await this.Server.SendIqRequest(
"get",
this.MainDomain,
new XmppAddress(ContractAddress.
Domain),
string.
Empty,
4181 "<getContract xmlns='" + NamespaceSmartContracts(
NamespaceSet.Current) +
"' id='" +
XML.
Encode(ContractId) +
"'/>",
4185 return Task.CompletedTask;
4202 private async Task PetitionContractHandler(
object Sender,
IqEventArgs e)
4211 byte[] Data = Encoding.UTF8.GetBytes(PetitionId +
":" + ContractId +
":" + Purpose +
":" + Nonce +
":" + e.
From.
BareJid.
LowerCase);
4212 XmlElement ContextXml =
null;
4214 foreach (XmlNode N
in e.
Query)
4216 if (!(N is XmlElement E))
4219 if (ContextXml is
null)
4228 (
LegalIdentity ReqIdentity, Dictionary<string, string> ReqAttachmentUrls) = await this.ValidateSenderSignature(
4231 if (ReqIdentity is
null)
4241 StringBuilder Msg =
new StringBuilder();
4243 Msg.Append(
"<petitionContractMsg id=\"");
4245 Msg.Append(
"\" pid=\"");
4247 Msg.Append(
"\" from=\"");
4249 Msg.Append(
"\" purpose=\"");
4253 !
string.IsNullOrEmpty(Connection.RemoteEndpoint))
4255 Msg.Append(
"\" clientEp=\"");
4256 Msg.Append(
XML.
Encode(Connection.RemoteEndpoint));
4260 ClientInformation ClientInfo = await this.GetNetworkIdentity(ReqIdentity.Id,
true,
false,
Contract.Version);
4261 if (!(ClientInfo is
null))
4263 string ClientEndpoint = ClientInfo.MostRecentEndpoint;
4265 if (!
string.IsNullOrEmpty(ClientEndpoint))
4267 Msg.Append(
"\" clientEp=\"");
4273 Msg.Append(
"\" xmlns=\"");
4274 Msg.Append(NamespaceSmartContracts(
Contract.Version));
4276 ReqIdentity.Serialize(Msg,
true,
true,
true,
true,
true,
true,
true, ReqAttachmentUrls,
this);
4278 if (!(ContextXml is
null))
4279 Msg.Append(ContextXml.OuterXml);
4281 Msg.Append(
"</petitionContractMsg>");
4283 string Xml = Msg.ToString();
4285 if (!(
Contract.ClientSignatures is
null))
4296 catch (Exception ex)
4302 private async Task PetitionContractResponseHandler(
object Sender,
IqEventArgs e)
4311 XmlElement ContextXml =
null;
4313 foreach (XmlNode N
in e.
Query)
4315 if (!(N is XmlElement E))
4318 if (ContextXml is
null)
4334 this.ContractAuthorization(RequestorFullJid.
BareJid, e.
From.
BareJid, ContractId, Response);
4336 StringBuilder Msg =
new StringBuilder();
4338 Msg.Append(
"<petitionContractResponseMsg pid=\"");
4340 Msg.Append(
"\" response=\"");
4344 !
string.IsNullOrEmpty(Connection.RemoteEndpoint))
4346 Msg.Append(
"\" clientEp=\"");
4347 Msg.Append(
XML.
Encode(Connection.RemoteEndpoint));
4350 Msg.Append(
"\" xmlns=\"");
4351 Msg.Append(NamespaceSmartContracts(
Contract.Version));
4354 Contract?.
Serialize(Msg,
false,
true,
true,
true,
true,
true,
true,
null,
this);
4356 if (!(ContextXml is
null))
4357 Msg.Append(ContextXml.OuterXml);
4359 Msg.Append(
"</petitionContractResponseMsg>");
4361 await this.Server.SendMessage(
string.Empty,
string.Empty, e.
To, RequestorFullJid,
string.
Empty, Msg.
ToString());
4365 catch (Exception ex)
4374 this.Authorization(
"C:", ToBareJid, FromBareJid, ContractId, Authorized ? 1 : 0);
4380 return this.petitions.
TryGetValue(Key, out
int i) && (i > 0);
4383 private async Task CreateContractHandler(
object Sender,
IqEventArgs e)
4387 if (!this.Server.IsServerDomain(e.
From.
Domain,
true))
4389 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can create new contracts.",
"en");
4393 LinkedList<ClientSignature> SignaturesToTransfer =
null;
4394 XmlElement E =
null;
4397 Dictionary<CaseInsensitiveString, Parameter>
Parameters =
new Dictionary<CaseInsensitiveString, Parameter>();
4398 LinkedList<CaseInsensitiveString> ParameterOrder =
new LinkedList<CaseInsensitiveString>();
4399 Dictionary<CaseInsensitiveString, Parameter> TransientParameters =
null;
4400 bool ParametersChecked =
false;
4401 bool HasTransientParameters =
false;
4403 foreach (XmlNode N
in e.
Query.ChildNodes)
4405 E = N as XmlElement;
4409 switch (E.LocalName ??
string.Empty)
4426 await e.
IqErrorBadRequest(e.
To,
"Status element not permitted when creating new contract.",
"en");
4436 if (!(
Contract.ClientSignatures is
null) &&
Contract.ClientSignatures.Length > 0)
4442 if (!(
Contract.ServerSignature is
null))
4461 ParametersChecked =
true;
4474 Contract = await this.GetContract(TemplateId);
4503 if (!(
Contract.ClientSignatures is
null))
4509 if (SignaturesToTransfer is
null)
4510 SignaturesToTransfer =
new LinkedList<ClientSignature>();
4512 SignaturesToTransfer.AddLast(
Signature);
4519 Version = QueryVersion,
4520 ForMachines =
Contract.ForMachines,
4521 ForMachinesLocalName =
Contract.ForMachinesLocalName,
4522 ForMachinesNamespace =
Contract.ForMachinesNamespace,
4533 bool HasVisibility =
false;
4534 bool HasDuration =
false;
4535 bool HasArchiveReq =
false;
4536 bool HasArchiveOpt =
false;
4537 bool WellDefined =
true;
4539 foreach (XmlAttribute Attr
in E.Attributes)
4546 Contract.Visibility = Visibility;
4547 HasVisibility =
true;
4550 WellDefined =
false;
4556 Contract.Duration = D;
4560 WellDefined =
false;
4566 Contract.ArchiveRequired = D;
4567 HasArchiveReq =
true;
4570 WellDefined =
false;
4576 Contract.ArchiveOptional = D;
4577 HasArchiveOpt =
true;
4580 WellDefined =
false;
4587 WellDefined =
false;
4594 WellDefined =
false;
4597 case "canActAsTemplate":
4600 Contract.CanActAsTemplate = b;
4601 HasArchiveOpt =
true;
4604 WellDefined =
false;
4610 Contract.Nonce = Convert.FromBase64String(Attr.Value);
4624 if (Attr.Prefix !=
"xmlns")
4625 WellDefined =
false;
4630 if (!(WellDefined && HasVisibility && HasDuration && HasArchiveReq && HasArchiveOpt))
4642 foreach (XmlNode N2
in E.ChildNodes)
4644 if (N2 is XmlElement E2)
4646 switch (E2.LocalName)
4649 List<Part> Parts =
null;
4652 foreach (XmlNode N3
in E2.ChildNodes)
4654 if (N3 is XmlElement E3)
4656 switch (E3.LocalName)
4668 case "templateOnly":
4693 foreach (XmlAttribute Attr
in E3.Attributes)
4698 LegalId = Attr.
Value;
4702 RoleRef = Attr.
Value;
4709 if (Attr.Prefix !=
"xmlns")
4710 WellDefined =
false;
4721 bool RoleFound =
false;
4727 if (Role2.
Name == RoleRef)
4742 Parts =
new List<Part>();
4744 Parts.Add(
new Part()
4753 WellDefined =
false;
4759 if (!WellDefined || !Mode.HasValue)
4765 Contract.PartsMode = Mode.Value;
4766 Contract.Parts = Parts?.ToArray();
4781 ParameterOrder.AddLast(P3.
Name);
4785 foreach (XmlNode N3
in E2.ChildNodes)
4787 if (N3 is XmlElement E3)
4798 await e.
IqErrorBadRequest(e.
To,
"Parameter does not exist in original contract: " + Name,
"en");
4802 Parameter ParameterDefinition = await this.TryParseParameter(E3, e, Name, OrgParameter);
4803 if (ParameterDefinition is
null)
4812 ParametersChecked =
true;
4816 if (!(FailingParameter is
null))
4827 foreach (
string Name
in ParameterOrder)
4830 Contract.Parameters = NewParameters;
4848 if (ParameterOrder.First is
null)
4855 ParameterOrder.AddLast(P3.
Name);
4860 foreach (XmlNode N3
in E.ChildNodes)
4862 if (N3 is XmlElement E3)
4873 await e.
IqErrorBadRequest(e.
To,
"Parameter does not exist in original contract: " + Name,
"en");
4877 Parameter ParameterDefinition = await this.TryParseParameter(E3, e, Name, OrgParameter);
4878 if (ParameterDefinition is
null)
4881 if (TransientParameters is
null)
4882 TransientParameters =
new Dictionary<CaseInsensitiveString, Parameter>();
4884 TransientParameters[Name] = ParameterDefinition;
4888 if (!(TransientParameters is
null))
4890 foreach (
Parameter TransientParameter
in TransientParameters.Values)
4894 ContractParamteter.StringValue = TransientParameter.
StringValue;
4895 ContractParamteter.ProtectedValue = TransientParameter.
ProtectedValue;
4904 if (!(FailingParameter2 is
null))
4911 ParametersChecked =
true;
4912 HasTransientParameters =
true;
4933 if (!ParametersChecked)
4937 if (!(FailingParameter3 is
null))
4946 Contract.Created = NowSecond;
4947 Contract.Updated = DateTime.MinValue;
4950 string IntegrityParameter = P.Value;
4966 await e.
IqErrorBadRequest(e.
To,
"Role counts are incorrect for role " + IntegrityParameter,
"en");
4970 await e.
IqErrorBadRequest(e.
To,
"Duplicate role definition for role " + IntegrityParameter,
"en");
4974 await e.
IqErrorBadRequest(e.
To,
"Duplicate parameter definition for parameter " + IntegrityParameter,
"en");
4978 await e.
IqErrorBadRequest(e.
To,
"Invalid Legal ID reference: " + IntegrityParameter,
"en");
4994 await e.
IqErrorBadRequest(e.
To,
"Role index is invalid for role reference parameter " + IntegrityParameter,
"en");
4998 await e.
IqErrorBadRequest(e.
To,
"Missing property reference for role reference parameter " + IntegrityParameter,
"en");
5002 await e.
IqErrorBadRequest(e.
To,
"Machine-readable information is missing or is invalid.",
"en");
5006 await e.
IqErrorBadRequest(e.
To,
"Missing human-readable information for role " + IntegrityParameter,
"en");
5010 await e.
IqErrorBadRequest(e.
To,
"Missing human-readable information for parameter " + IntegrityParameter,
"en");
5014 await e.
IqErrorBadRequest(e.
To,
"Validation expression error for parameter " + IntegrityParameter,
"en");
5018 await e.
IqErrorBadRequest(e.
To,
"An undefined parameter is referenced: " + IntegrityParameter,
"en");
5026 await e.
IqErrorBadRequest(e.
To,
"Duplication language reference for human-readable text for contract: " + IntegrityParameter,
"en");
5030 await e.
IqErrorBadRequest(e.
To,
"Duplication language reference for human-readable text for role: " + IntegrityParameter,
"en");
5034 await e.
IqErrorBadRequest(e.
To,
"Duplication language reference for human-readable text for parameter: " + IntegrityParameter,
"en");
5043 if (Identity is
null)
5045 await e.
IqErrorForbidden(e.
To,
"No current approved legal identity found for account.",
"en");
5049 string Errors = await this.ValidateContent(
Contract);
5050 if (!
string.IsNullOrEmpty(Errors))
5056 StringBuilder Xml =
new StringBuilder();
5058 if (!(SignaturesToTransfer is
null))
5060 Dictionary<string, int> RoleCounters =
new Dictionary<string, int>();
5061 List<ClientSignature> Transfered =
null;
5063 Contract.
Serialize(Xml,
false,
false,
false,
false,
false,
false,
false,
null,
this);
5064 byte[] Data = Encoding.UTF8.GetBytes(Xml.ToString());
5071 if (!(Identity is
null))
5073 if (!RoleCounters.TryGetValue(
Signature.Role, out
int RoleIndex))
5079 if (Transfered is
null)
5080 Transfered =
new List<ClientSignature>();
5083 RoleCounters[
Signature.Role] = RoleIndex;
5088 Contract.ClientSignatures = Transfered?.ToArray();
5093 if (HasTransientParameters)
5098 Contract.ContractId = Contract.ObjectId +
"@" + e.
To.
Address;
5103 if (HasTransientParameters)
5106 KeyValuePair<string, object>[] Tags =
Contract.GetTags();
5129 string ContractXml = Xml.ToString();
5135 StringBuilder Markdown =
new StringBuilder();
5137 Markdown.Append(
"Contract proposal received: [");
5139 Markdown.Append(
"](");
5141 Markdown.AppendLine(
")");
5142 Markdown.AppendLine();
5143 Output(Markdown, Tags);
5148 await this.SendContractUpdatedEvent(
Contract,
true);
5150 catch (Exception ex)
5157 Dictionary<CaseInsensitiveString, Parameter> TransientParameters)
5159 this.transientParameters.
Add(ContractId, TransientParameters);
5164 byte[] ProtectedValue =
null;
5166 if (E3.HasAttribute(
"guide") &&
XML.
Attribute(E3,
"guide") != OrgParameter.
Guide)
5174 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
5178 if (E3.HasAttribute(
"protection"))
5182 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter protection rules.",
"en");
5187 if (E3.HasAttribute(
"protected"))
5191 ProtectedValue = Convert.FromBase64String(
XML.
Attribute(E3,
"protected"));
5202 switch (E3.LocalName)
5204 case "stringParameter":
5211 if ((E3.HasAttribute(
"regEx") &&
XML.
Attribute(E3,
"regEx") != OldStringParameter.RegEx) ||
5212 (E3.HasAttribute(
"min") &&
XML.
Attribute(E3,
"min") != OldStringParameter.Min) ||
5213 (E3.HasAttribute(
"max") &&
XML.
Attribute(E3,
"max") != OldStringParameter.Max) ||
5214 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldStringParameter.MinIncluded) ||
5215 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldStringParameter.MaxIncluded) ||
5216 (E3.HasAttribute(
"minLength") &&
XML.
Attribute(E3,
"minLength", 0) != OldStringParameter.MinLength) ||
5217 (E3.HasAttribute(
"maxLength") &&
XML.
Attribute(E3,
"maxLength", 0) != OldStringParameter.MaxLength) ||
5221 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
5229 Guide = OrgParameter.
Guide,
5231 RegEx = OldStringParameter.RegEx,
5232 Min = OldStringParameter.Min,
5233 Max = OldStringParameter.Max,
5234 MinIncluded = OldStringParameter.MinIncluded,
5235 MaxIncluded = OldStringParameter.MaxIncluded,
5236 MinLength = OldStringParameter.MinLength,
5237 MaxLength = OldStringParameter.MaxLength,
5240 ProtectedValue = ProtectedValue
5243 case "numericalParameter":
5250 if ((E3.HasAttribute(
"min") &&
XML.
Attribute(E3,
"min", 0.0m) != OldNumericalParameter.Min) ||
5251 (E3.HasAttribute(
"max") &&
XML.
Attribute(E3,
"max", 0.0m) != OldNumericalParameter.Max) ||
5252 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldNumericalParameter.MinIncluded) ||
5253 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldNumericalParameter.MaxIncluded) ||
5257 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
5264 Value = E3.HasAttribute(
"value") ?
XML.
Attribute(E3,
"value", 0.0m) : (decimal?)
null,
5265 Guide = OrgParameter.
Guide,
5267 Min = OldNumericalParameter.Min,
5268 Max = OldNumericalParameter.Max,
5269 MinIncluded = OldNumericalParameter.MinIncluded,
5270 MaxIncluded = OldNumericalParameter.MaxIncluded,
5273 ProtectedValue = ProtectedValue
5276 case "booleanParameter":
5283 if ((E3.HasAttribute(
"protection") &&
XML.
Attribute(E3,
"protection",
ProtectionLevel.Normal) != OldBooleanParameter.Protection) ||
5286 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
5293 Value = E3.HasAttribute(
"value") ?
XML.
Attribute(E3,
"value",
false) : (
bool?)
null,
5294 Guide = OrgParameter.
Guide,
5298 ProtectedValue = ProtectedValue
5301 case "dateParameter":
5308 if ((E3.HasAttribute(
"min") &&
XML.
Attribute(E3,
"min", DateTime.MinValue) != OldDateParameter.Min) ||
5309 (E3.HasAttribute(
"max") &&
XML.
Attribute(E3,
"max", DateTime.MinValue) != OldDateParameter.Max) ||
5310 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldDateParameter.MinIncluded) ||
5311 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldDateParameter.MaxIncluded) ||
5315 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
5322 Value = E3.HasAttribute(
"value") ?
XML.
Attribute(E3,
"value", DateTime.MinValue).Date : (DateTime?)
null,
5323 Guide = OrgParameter.
Guide,
5325 Min = OldDateParameter.Min,
5326 Max = OldDateParameter.Max,
5327 MinIncluded = OldDateParameter.MinIncluded,
5328 MaxIncluded = OldDateParameter.MaxIncluded,
5331 ProtectedValue = ProtectedValue
5334 case "dateTimeParameter":
5341 if ((E3.HasAttribute(
"min") &&
XML.
Attribute(E3,
"min", DateTime.MinValue) != OldDateTimeParameter.Min) ||
5342 (E3.HasAttribute(
"max") &&
XML.
Attribute(E3,
"max", DateTime.MinValue) != OldDateTimeParameter.Max) ||
5343 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldDateTimeParameter.MinIncluded) ||
5344 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldDateTimeParameter.MaxIncluded) ||
5348 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
5355 Value = E3.HasAttribute(
"value") ?
XML.
Attribute(E3,
"value", DateTime.MinValue) : (DateTime?)
null,
5356 Guide = OrgParameter.
Guide,
5358 Min = OldDateTimeParameter.Min,
5359 Max = OldDateTimeParameter.Max,
5360 MinIncluded = OldDateTimeParameter.MinIncluded,
5361 MaxIncluded = OldDateTimeParameter.MaxIncluded,
5364 ProtectedValue = ProtectedValue
5367 case "timeParameter":
5374 if ((E3.HasAttribute(
"min") &&
XML.
Attribute(E3,
"min", TimeSpan.Zero) != OldTimeParameter.Min) ||
5375 (E3.HasAttribute(
"max") &&
XML.
Attribute(E3,
"max", TimeSpan.Zero) != OldTimeParameter.Max) ||
5376 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldTimeParameter.MinIncluded) ||
5377 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldTimeParameter.MaxIncluded) ||
5381 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
5388 Value = E3.HasAttribute(
"value") ?
XML.
Attribute(E3,
"value", TimeSpan.Zero) : (TimeSpan?)
null,
5389 Guide = OrgParameter.
Guide,
5391 Min = OldTimeParameter.Min,
5392 Max = OldTimeParameter.Max,
5393 MinIncluded = OldTimeParameter.MinIncluded,
5394 MaxIncluded = OldTimeParameter.MaxIncluded,
5397 ProtectedValue = ProtectedValue
5400 case "durationParameter":
5409 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldDurationParameter.MinIncluded) ||
5410 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldDurationParameter.MaxIncluded) ||
5414 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
5422 Guide = OrgParameter.
Guide,
5424 Min = OldDurationParameter.Min,
5425 Max = OldDurationParameter.Max,
5426 MinIncluded = OldDurationParameter.MinIncluded,
5427 MaxIncluded = OldDurationParameter.MaxIncluded,
5430 ProtectedValue = ProtectedValue
5433 case "calcParameter":
5442 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
5449 Guide = OrgParameter.
Guide,
5453 ProtectedValue = ProtectedValue
5456 case "roleParameter":
5463 if ((E3.HasAttribute(
"role") &&
XML.
Attribute(E3,
"role") != OldRoleParameter.Role) ||
5464 (E3.HasAttribute(
"index") &&
XML.
Attribute(E3,
"index", 0) != OldRoleParameter.Index) ||
5465 (E3.HasAttribute(
"property") &&
XML.
Attribute(E3,
"property") != OldRoleParameter.Property) ||
5466 (E3.HasAttribute(
"required") &&
XML.
Attribute(E3,
"required",
false) != OldRoleParameter.Required) ||
5470 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
5477 Role = OldRoleParameter.Role,
5478 Index = OldRoleParameter.Index,
5480 Required = OldRoleParameter.Required,
5481 Guide = OrgParameter.
Guide,
5485 ProtectedValue = ProtectedValue
5488 case "contractReferenceParameter":
5495 if ((E3.HasAttribute(
"localName") &&
XML.
Attribute(E3,
"localName") != OldContractReferenceParameter.LocalName) ||
5496 (E3.HasAttribute(
"namespace") &&
XML.
Attribute(E3,
"namespace") != OldContractReferenceParameter.Namespace) ||
5497 (E3.HasAttribute(
"templateId") &&
XML.
Attribute(E3,
"templateId") != OldContractReferenceParameter.TemplateId) ||
5498 (E3.HasAttribute(
"provider") &&
XML.
Attribute(E3,
"provider") != OldContractReferenceParameter.Provider) ||
5499 (E3.HasAttribute(
"creatorRole") &&
XML.
Attribute(E3,
"creatorRole") != OldContractReferenceParameter.CreatorRole) ||
5500 (E3.HasAttribute(
"required") &&
XML.
Attribute(E3,
"required",
false) != OldContractReferenceParameter.Required) ||
5501 (E3.HasAttribute(
"protection") &&
XML.
Attribute(E3,
"protection",
ProtectionLevel.Normal) != OldContractReferenceParameter.Protection) ||
5504 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
5512 Guide = OrgParameter.
Guide,
5515 Labels = OldContractReferenceParameter.Labels,
5516 LocalName = OldContractReferenceParameter.LocalName,
5517 Namespace = OldContractReferenceParameter.Namespace,
5518 TemplateId = OldContractReferenceParameter.TemplateId,
5519 Provider = OldContractReferenceParameter.Provider,
5520 CreatorRole = OldContractReferenceParameter.CreatorRole,
5521 Required = OldContractReferenceParameter.Required,
5523 ProtectedValue = ProtectedValue
5535 string IntegrityParameter = P.Value;
5543 return "No roles have been defined.";
5546 return "Part definition expected.";
5549 return "Role counts are incorrect for role " + IntegrityParameter;
5552 return "Duplicate role definition for role " + IntegrityParameter;
5555 return "Duplicate parameter definition for parameter " + IntegrityParameter;
5558 return "Invalid Legal ID reference: " + IntegrityParameter;
5561 return "Invalid role reference: " + IntegrityParameter;
5564 return "Too few parts for role " + IntegrityParameter;
5567 return "Too many parts for role " + IntegrityParameter;
5570 return "Role index is invalid for role reference parameter " + IntegrityParameter;
5573 return "Missing property reference for role reference parameter " + IntegrityParameter;
5576 return "Machine-readable information is missing or is invalid.";
5579 return "Missing human-readable information for role " + IntegrityParameter;
5582 return "Missing human-readable information for parameter " + IntegrityParameter;
5585 return "Validation expression error for parameter " + IntegrityParameter;
5588 return "An undefined parameter is referenced: " + IntegrityParameter;
5591 return "Missing human-readable information.";
5594 return "Duplication language reference for human-readable text for contract: " + IntegrityParameter;
5597 return "Duplication language reference for human-readable text for role: " + IntegrityParameter;
5600 return "Duplication language reference for human-readable text for parameter: " + IntegrityParameter;
5603 return "Contract integrity check failed for unknown reasons.";
5609 Contract.ContentSchemaDigest =
null;
5610 Contract.ContentSchemaHashFunction =
HashFunction.SHA256;
5612 if (
string.IsNullOrEmpty(
Contract.ForMachines))
5613 return "No machine-readable content.";
5615 XmlDocument Doc =
new XmlDocument()
5617 PreserveWhitespace =
true
5624 if (Doc.DocumentElement is
null)
5625 return "Invalid machine-readable XML: No root element.";
5627 catch (XmlException ex)
5630 return "Invalid machine-readable XML: " + ex.Message;
5632 catch (Exception ex)
5634 return "Invalid machine-readable XML: " + ex.Message;
5637 (
string ErrorMessage, Dictionary<string, ValidationSchema> Schemas) = await this.ValidateContent(Doc);
5638 if (!
string.IsNullOrEmpty(ErrorMessage))
5639 return ErrorMessage;
5641 int NrSchemas = Schemas.Count;
5642 if (NrSchemas == 0 || !Schemas.ContainsKey(
Contract.ForMachinesNamespace))
5643 return "Machine-readable content not defined by schemas.";
5646 int c = Schemas.Count;
5654 Digest = Convert.FromBase64String(Schema2.
HashBase64),
5655 Algorithm = Schema2.Function
5659 Contract.SchemaReferences = References;
5663 Contract.ContentSchemaDigest = Ref.
Digest;
5664 Contract.ContentSchemaHashFunction = Ref.Algorithm;
5667 return "M2M content schema not found.";
5672 internal async Task<(string, Dictionary<string, ValidationSchema>)> ValidateContent(XmlDocument Doc)
5674 Dictionary<string, ValidationSchema> Schemas =
new Dictionary<string, ValidationSchema>();
5675 LinkedList<XmlNode> ToCheck =
new LinkedList<XmlNode>();
5677 ToCheck.AddLast(Doc.DocumentElement);
5679 while (!(ToCheck.First is
null))
5681 XmlNode N = ToCheck.First.Value;
5682 ToCheck.RemoveFirst();
5684 while (!(N is
null))
5686 if (N is XmlElement E)
5688 if (!
string.IsNullOrEmpty(E.NamespaceURI))
5689 Schemas[E.NamespaceURI] =
null;
5691 if (E.HasAttributes)
5693 foreach (XmlAttribute Attr
in E.Attributes)
5695 if (!
string.IsNullOrEmpty(Attr.NamespaceURI) &&
5696 Attr.NamespaceURI !=
"http://www.w3.org/XML/1998/namespace" &&
5697 Attr.NamespaceURI !=
"http://www.w3.org/2000/xmlns/")
5699 Schemas[Attr.NamespaceURI] =
null;
5704 foreach (XmlNode N2
in E.ChildNodes)
5705 ToCheck.AddLast(N2);
5712 int NrSchemas = Schemas.Count;
5715 string[] Namespaces =
new string[NrSchemas];
5716 Dictionary<string, bool> Loaded =
new Dictionary<string, bool>();
5717 Schemas.Keys.CopyTo(Namespaces, 0);
5719 foreach (
string Namespace
in Namespaces)
5725 (Schema, ErrorMsg) = await this.LoadSchema(Namespace,
null);
5726 if (!
string.IsNullOrEmpty(ErrorMsg))
5727 return (ErrorMsg,
null);
5729 Loaded[Namespace] =
true;
5732 Schemas[Namespace] = Schema;
5735 ErrorMsg = this.ValidateXml(Schemas.Values, Doc);
5736 if (!
string.IsNullOrEmpty(ErrorMsg))
5738 bool Changed =
false;
5740 foreach (
string Namespace
in Namespaces)
5742 if (Loaded.ContainsKey(Namespace))
5745 Schema = Schemas[Namespace];
5746 (
ValidationSchema Schema2,
string ErrorMsg2) = await this.LoadSchema(Namespace, Schema);
5747 if (!
string.IsNullOrEmpty(ErrorMsg2))
5748 return (ErrorMsg2,
null);
5750 if (Schema2 != Schema)
5752 Schemas[Namespace] = Schema2;
5758 return (ErrorMsg,
null);
5760 ErrorMsg = this.ValidateXml(Schemas.Values, Doc);
5761 if (!
string.IsNullOrEmpty(ErrorMsg))
5762 return (ErrorMsg,
null);
5765 return (
null, Schemas);
5775 case "http://www.w3.org/XML/1998/namespace":
5776 Type T = typeof(Networking.XMPP.Contracts.ContractsClient);
5777 Assembly A = T.Assembly;
5778 File = A.GetManifestResourceStream(T.Namespace +
".Schema.Xml.xsd");
5782 case "http://www.w3.org/2000/xmlns/":
5783 T = typeof(Networking.XMPP.Contracts.ContractsClient);
5785 File = A.GetManifestResourceStream(T.Namespace +
".Schema.Xmlns.xsd");
5790 Uri Uri =
new Uri(Namespace);
5793 return (
null,
"Schema not downloadable: " + Namespace);
5795 KeyValuePair<string, TemporaryStream> P;
5799 P = await Getter.GetTempStreamAsync(Uri,
null,
null, 10000,
5800 new KeyValuePair<string, string>(
"Accept",
"application/xml, text/xml"),
5801 new KeyValuePair<string, string>(
"Accept-Charset",
"utf-8"));
5806 catch (Exception ex)
5808 return (
null,
"Unable to get schema file " + Namespace +
". The following error was reported: " + ex.Message);
5815 if (File.Length >
int.MaxValue)
5816 throw new OutOfMemoryException(
"Schema file too large.");
5818 int Len = (int)File.Length;
5819 byte[] Bin =
new byte[Len];
5822 await File.ReadAllAsync(Bin, 0, Len);
5826 if (!(PrevSchema is
null) && Digest == PrevSchema.
HashBase64)
5827 return (PrevSchema,
null);
5831 Namespace = Namespace,
5833 HashBase64 = Digest,
5834 Created = NowSecond,
5841 return (Schema,
null);
5849 private string ValidateXml(IEnumerable<ValidationSchema> Schemas, XmlDocument Xml)
5851 StringBuilder Errors =
null;
5852 StringBuilder Warnings =
null;
5856 if (Xml.Schemas.Count > 0)
5858 LinkedList<XmlSchema> ToRemove =
new LinkedList<XmlSchema>();
5860 foreach (XmlSchema Schema
in Xml.Schemas.Schemas())
5861 ToRemove.AddLast(Schema);
5863 foreach (XmlSchema Schema
in ToRemove)
5864 Xml.Schemas.Remove(Schema);
5869 using (XmlReader r = XmlReader.Create(
new MemoryStream(Schema.
XmlSchema)))
5871 XmlSchema XmlSchema = XmlSchema.Read(r,
null);
5872 Xml.Schemas.Add(XmlSchema);
5876 Xml.Validate((sender2, e2) =>
5878 switch (e2.Severity)
5880 case XmlSeverityType.Error:
5882 Errors =
new StringBuilder();
5884 Errors.AppendLine(e2.Message);
5887 case XmlSeverityType.Warning:
5888 if (Warnings is
null)
5889 Warnings =
new StringBuilder();
5891 Warnings.AppendLine(e2.Message);
5896 catch (Exception ex)
5899 Errors =
new StringBuilder();
5901 Errors.AppendLine(ex.Message);
5904 if (!(Errors is
null) || !(Warnings is
null))
5906 StringBuilder Report =
new StringBuilder();
5908 if (!(Errors is
null))
5910 Report.AppendLine(
"Errors found during validation:");
5911 Report.AppendLine(
new string(
'-', 40));
5912 Report.Append(Errors.ToString());
5914 if (!(Warnings is
null))
5915 Report.AppendLine();
5918 if (!(Warnings is
null))
5920 Report.AppendLine(
"Warnings found during validation:");
5921 Report.AppendLine(
new string(
'-', 40));
5922 Report.Append(Warnings.ToString());
5925 return Report.ToString();
5936 public static async Task<Tuple<byte[], XmlSchema>>
LoadSchema(
string Url)
5940 HttpRequestMessage Request =
null;
5941 HttpResponseMessage Response =
null;
5942 HttpClient Client =
new HttpClient();
5946 Client.Timeout = TimeSpan.FromMilliseconds(30000);
5947 Client.DefaultRequestHeaders.ExpectContinue =
false;
5949 Uri Uri =
new Uri(Url);
5950 Request =
new HttpRequestMessage(HttpMethod.Head, Uri);
5951 Request.Headers.Add(
"Accept",
"application/xml, text/xml");
5952 Request.Headers.Add(
"Accept-Charset",
"utf-8");
5954 Response = await Client.SendAsync(Request);
5955 if (!Response.IsSuccessStatusCode)
5961 Request =
new HttpRequestMessage(HttpMethod.Get, Uri);
5962 Request.Headers.Add(
"Accept",
"application/xml, text/xml");
5963 Request.Headers.Add(
"Accept-Charset",
"utf-8");
5965 Response = await Client.SendAsync(Request);
5966 if (!Response.IsSuccessStatusCode)
5969 string ContentType =
null;
5971 if (Response.Headers.TryGetValues(
"Content-Type", out IEnumerable<string> Values))
5973 foreach (
string s
in Values)
5980 if (ContentType is
null)
5983 byte[] Data = await Response.Content.ReadAsByteArrayAsync();
5986 if (!(Decoded is XmlDocument Doc))
5989 using (XmlReader r = XmlReader.Create(
new MemoryStream(Data)))
5991 XmlSchema Schema = XmlSchema.Read(r,
null);
5992 return new Tuple<byte[], XmlSchema>(Data, Schema);
5998 Response?.Dispose();
6002 catch (Exception ex)
6010 private async Task GetCreatedContractsHandler(
object Sender,
IqEventArgs e)
6014 if (!this.Server.IsServerDomain(e.
From.
Domain,
true))
6028 string Xml = await this.SerializeContractReferences(Contracts, References, QueryVersion);
6032 catch (Exception ex)
6038 internal async Task<string> SerializeContractReferences(IEnumerable<IContractReference> Contracts,
bool References,
NamespaceSet Version)
6040 StringBuilder Xml =
new StringBuilder();
6043 Xml.Append(
"<contractReferences xmlns='");
6045 Xml.Append(
"<contracts xmlns='");
6047 Xml.Append(NamespaceSmartContracts(Version));
6054 Xml.Append(
"<ref id='");
6059 Contract2.Serialize(Xml, Contract2.Version != Version,
true,
true,
true,
true,
true,
true,
null,
this);
6063 if (Contract2 is
null)
6065 Xml.Append(
"<ref id='");
6070 Contract2.Serialize(Xml, Contract2.Version != Version,
true,
true,
true,
true,
true,
true,
null,
this);
6075 Xml.Append(
"</contractReferences>");
6077 Xml.Append(
"</contracts>");
6079 return Xml.ToString();
6082 public async Task<CaseInsensitiveString> GetComponent(
CaseInsensitiveString ServerDomain,
string Feature)
6084 KeyValuePair<CaseInsensitiveString, string> P = await this.GetComponent(ServerDomain,
new string[] { Feature });
6088 public async Task<KeyValuePair<CaseInsensitiveString, string>> GetComponent(
CaseInsensitiveString ServerDomain, params
string[] Features)
6092 KeyValuePair<string, string> P = await
Gateway.
XmppClient.FindComponentAsync(ServerDomain, Features);
6093 return new KeyValuePair<CaseInsensitiveString, string>(P.Key, P.Value);
6096 foreach (
string Feature
in Features)
6098 string Key = ServerDomain +
"#" + Feature;
6101 return new KeyValuePair<CaseInsensitiveString, string>(JID, Feature);
6104 TaskCompletionSource<KeyValuePair<CaseInsensitiveString, string>> Result =
6105 new TaskCompletionSource<KeyValuePair<CaseInsensitiveString, string>>();
6108 "<query xmlns='http://jabber.org/protocol/disco#items'/>", async (Sender, e) =>
6110 if (e.Ok && !(e.FirstElement is
null))
6112 List<CaseInsensitiveString> JIDs =
new List<CaseInsensitiveString>() { ServerDomain };
6113 object SynchObject =
new object();
6115 foreach (XmlNode N
in e.FirstElement)
6117 if (N is XmlElement E && E.LocalName ==
"item")
6125 int Count = JIDs.Count;
6129 await this.Server.SendIqRequest(
"get",
new XmppAddress(this.Server.Domain),
new XmppAddress(JID2),
string.Empty,
6130 "<query xmlns='http://jabber.org/protocol/disco#info'/>", (sender2, e2) =>
6134 foreach (XmlNode N2 in e2.FirstElement)
6136 if (!(N2 is XmlElement E2) || E2.LocalName !=
"feature")
6139 string Var = XML.Attribute(E2,
"var");
6141 foreach (string Feature in Features)
6153 CaseInsensitiveString s = (CaseInsensitiveString)e2.State;
6154 string Key = ServerDomain +
"#" + Feature;
6156 this.remoteComponents[Key] = s;
6157 Result.TrySetResult(new KeyValuePair<CaseInsensitiveString, string>(s, Feature));
6159 return Task.CompletedTask;
6169 return Task.CompletedTask;
6172 Result.TrySetResult(
new KeyValuePair<CaseInsensitiveString, string>(
null,
null));
6174 return Task.CompletedTask;
6179 Result.TrySetResult(
new KeyValuePair<CaseInsensitiveString, string>(
null,
null));
6182 return await Result.Task;
6185 private async Task SignContractHandler(
object Sender,
IqEventArgs e)
6192 bool Transferable =
false;
6194 foreach (XmlAttribute Attr
in e.
Query.Attributes)
6199 ContractId = Attr.
Value;
6207 Signature = Convert.FromBase64String(Attr.Value);
6210 case "transferable":
6222 if (ContractId is
null ||
Role is
null ||
Signature is
null)
6239 await e.
IqErrorForbidden(e.
To,
"Contract is a template only, and cannot be signed.",
"en");
6266 DateTime Now = DateTime.Now;
6284 if (!(FailingParameter is
null))
6291 int NrSignaturesForRole = 0;
6292 bool RoleFound =
false;
6294 if (!(
Contract.ClientSignatures is
null))
6299 NrSignaturesForRole++;
6309 if (NrSignaturesForRole >= Role2.
MaxCount)
6311 await e.
IqErrorForbidden(e.
To,
"No more signatures of specified role allowed.",
"en");
6327 StringBuilder Xml =
new StringBuilder();
6328 Contract.
Serialize(Xml,
false,
false,
false,
false,
false,
false,
false,
null,
this);
6329 byte[] Data = Encoding.UTF8.GetBytes(Xml.ToString());
6332 if (Identity is
null)
6335 if (!await CheckPeerReviewFields(e, Identity))
6340 bool InList =
false;
6366 bool HasSigned =
false;
6368 if (!(
Contract.ClientSignatures is
null))
6383 if (!await this.CanSignAs(
Part.
LegalId, Identity.Id))
6394 await e.
IqErrorForbidden(e.
To,
"Legal identity not in explicitly defined list of parts in contract.",
"en");
6399 if (!(
Contract.ClientSignatures is
null))
6416 DateTime SignatureTimestamp = DateTime.Now;
6418 if (!
string.IsNullOrEmpty(s))
6420 await e.
IqErrorForbidden(e.
To,
"Legal identity does not have required property " + s +
" defined.",
"en");
6424 int c = (
Contract.ClientSignatures?.Length ?? 0) + 1;
6427 Contract.ClientSignatures?.CopyTo(Signatures, 0);
6431 LegalId = Identity.Id,
6434 Timestamp = SignatureTimestamp,
6435 Transferable = Transferable
6438 Contract.ClientSignatures = Signatures;
6440 if (
Contract.From == DateTime.MinValue)
6448 Contract.To = Contract.From +
Contract.Duration.Value;
6463 LegalId = Identity.Id,
6464 BareJid = e.From.BareJid
6472 new KeyValuePair<string, object>(
"Role",
Role.Value),
6473 new KeyValuePair<string, object>(
"Transferable", Transferable));
6481 string ContractNamespace = NamespaceSmartContracts(
Contract.Version);
6482 Dictionary<CaseInsensitiveString, string> StatusRecipients =
new Dictionary<CaseInsensitiveString, string>()
6484 { Contract.Account +
"@" + this.Server.Domain, ContractNamespace }
6487 if (!(
Contract.ClientSignatures is
null))
6495 if (!this.Server.IsServerDomain(Addr.
Domain,
true))
6497 KeyValuePair<CaseInsensitiveString, string> P2 = await this.GetComponent(Addr.
Domain, NamespacesSmartContracts);
6505 foreach (KeyValuePair<CaseInsensitiveString, string> P3
in StatusRecipients)
6508 string Namespace = P3.
Value;
6512 Xml.Append(
"<contractSigned xmlns='");
6513 Xml.Append(Namespace);
6514 Xml.Append(
"' contractId='");
6516 Xml.Append(
"' legalId='");
6518 Xml.Append(
"' role='");
6526 await this.Server.SendMessage(
string.Empty,
string.Empty, e.
To,
new XmppAddress(StatusRecipient),
6527 string.Empty,
Event);
6529 catch (Exception ex)
6535 catch (Exception ex)
6542 await this.ContractSigned(
Contract,
true, this.eDaler, this.pubsub);
6544 catch (Exception ex)
6550 catch (Exception ex)
6560 throw new Exception(
"Contract is a template only, and cannot be signed.");
6565 throw new Exception(
"Contract is obsoleted.");
6568 throw new Exception(
"Contract is deleted.");
6571 throw new Exception(
"Contract is not yet approved to be signed.");
6574 throw new Exception(
"Contract proposal has been rejected.");
6577 throw new Exception(
"Contract proposal has failed.");
6580 DateTime Now = DateTime.Now;
6582 throw new Exception(
"Contract will be open for signatures after " +
Contract.SignAfter.ToString());
6585 throw new Exception(
"Contract closed for signatures as if " +
Contract.SignBefore.ToString());
6590 if (!(FailingParameter is
null))
6591 throw new Exception(
"Contract parameter " + FailingParameter.
Name +
" contains invalid value: " + P.
Value);
6593 int NrSignaturesForRole = 0;
6594 bool RoleFound =
false;
6596 if (!(
Contract.ClientSignatures is
null))
6601 NrSignaturesForRole++;
6611 if (NrSignaturesForRole >= Role2.
MaxCount)
6612 throw new Exception(
"No more signatures of specified role allowed.");
6621 throw new Exception(
"No such role defined in contract.");
6623 StringBuilder Xml =
new StringBuilder();
6624 Contract.
Serialize(Xml,
false,
false,
false,
false,
false,
false,
false,
null,
this);
6625 byte[] Data = Encoding.UTF8.GetBytes(Xml.ToString());
6628 (
LegalIdentity Identity, _) = await this.ValidateSenderSignature(SignerJid, Request, Now, Data,
Signature,
null);
6629 if (Identity is
null)
6632 if (
string.IsNullOrEmpty(Msg))
6633 Msg =
"Unable to validate sender signature.";
6635 throw new Exception(Msg);
6640 bool InList =
false;
6655 throw new Exception(
"Legal identity not in explicitly defined list of parts in contract.");
6658 if (!(
Contract.ClientSignatures is
null))
6667 DateTime SignatureTimestamp = DateTime.Now;
6669 if (!
string.IsNullOrEmpty(s))
6670 throw new Exception(
"Legal identity does not have required property " + s +
" defined.");
6672 int c = (
Contract.ClientSignatures?.Length ?? 0) + 1;
6675 Contract.ClientSignatures?.CopyTo(Signatures, 0);
6679 LegalId = Identity.Id,
6682 Timestamp = SignatureTimestamp,
6683 Transferable = Transferable
6686 Contract.ClientSignatures = Signatures;
6688 if (
Contract.From == DateTime.MinValue)
6696 Contract.To = Contract.From +
Contract.Duration.Value;
6711 LegalId = Identity.Id,
6712 BareJid = SignerJid.BareJid
6719 new KeyValuePair<string, object>(
"BareJid", SignerJid.
BareJid.
Value),
6720 new KeyValuePair<string, object>(
"Role",
Role.Value),
6721 new KeyValuePair<string, object>(
"Transferable", Transferable));
6725 string ContractNamespace = NamespaceSmartContracts(
Contract.Version);
6726 Dictionary<CaseInsensitiveString, string> StatusRecipients =
new Dictionary<CaseInsensitiveString, string>()
6728 { Contract.Account +
"@" + this.Server.Domain, ContractNamespace }
6731 if (!(
Contract.ClientSignatures is
null))
6739 if (!this.Server.IsServerDomain(Addr.
Domain,
true))
6741 KeyValuePair<CaseInsensitiveString, string> P2 = await this.GetComponent(Addr.
Domain, NamespacesSmartContracts);
6749 foreach (KeyValuePair<CaseInsensitiveString, string> P3
in StatusRecipients)
6752 string Namespace = P3.
Value;
6755 Xml.Append(
"<contractSigned xmlns='");
6756 Xml.Append(Namespace);
6757 Xml.Append(
"' contractId='");
6759 Xml.Append(
"' legalId='");
6761 Xml.Append(
"' role='");
6769 await this.Server.SendMessage(
string.Empty,
string.Empty, this.MainDomain,
new XmppAddress(StatusRecipient),
6770 string.Empty,
Event);
6772 catch (Exception ex)
6778 catch (Exception ex)
6785 await this.ContractSigned(
Contract, ContractIsLocked, this.eDaler, this.pubsub);
6787 catch (Exception ex)
6802 private async Task ContractSigned(
Contract Contract,
bool ContractIsLocked,
6806 out Dictionary<CaseInsensitiveString, Parameter> TransientParameters))
6808 TransientParameters =
null;
6811 switch (
Contract.ForMachinesNamespace)
6815 TransientParameters,
this,
EDaler, PubSub);
6820 TransientParameters,
this,
EDaler);
6825 TransientParameters,
this,
EDaler);
6842 if (this.Server.IsServerDomain(Sender.
Domain,
true))
6850 if (ID.ValidateSignature(Data,
Signature))
6854 e?.
IqErrorForbidden(e.
To,
"Signature proving access to private keys not correct.",
"en");
6857 e?.
IqErrorForbidden(e.
To,
"Sender must correspond to an account on the local machine.",
"en");
6866 Dictionary<string, string> AttachmentUrls =
null;
6868 if (this.Server.IsServerDomain(Sender.
Domain,
true))
6870 bool IdFound =
false;
6880 if (ID.ValidateSignature(Data,
Signature))
6882 if (!
string.IsNullOrEmpty(ForBareJid))
6883 this.IdentityAuthorization(ForBareJid, Sender.
BareJid, ID.Id,
true);
6886 AttachmentUrls = this.GetAttachmentUrls(ID);
6896 return (
null,
null);
6901 KeyValuePair<CaseInsensitiveString, string> P = await this.GetComponent(Sender.
Domain, NamespacesLegalIdentity);
6903 string RemoteNamespace = P.
Value;
6908 Request?.
Error(
EDalerUriErrorType.ServiceUnavailable,
this.MainDomain.Address +
" could not find legal component of " + Sender.
Domain +
", to validate signature.",
false);
6909 return (
null,
null);
6915 if (Identity2 is
null)
6917 Request?.
Error(
EDalerUriErrorType.Forbidden,
"Signature does not match any of the approved legal identities of " +
6921 StringBuilder sb =
new StringBuilder();
6922 Identity2.
Serialize(sb,
true,
true,
true,
true,
true,
true,
true);
6924 XmlDocument Doc =
new XmlDocument()
6926 PreserveWhitespace =
true
6928 Doc.LoadXml(sb.ToString());
6930 Identity =
LegalIdentity.Parse(Doc.DocumentElement, out _, out AttachmentUrls);
6937 Request?.
Error(
EDalerUriErrorType.ServiceUnavailable,
this.MainDomain.Address +
" was unable to validate remote signature.",
false);
6938 return (
null,
null);
6944 return (
null,
null);
6951 if (Identity is
null)
6953 Request?.
Error(
EDalerUriErrorType.Forbidden,
"Signature does not match any of the approved legal identities of " +
6957 return (Identity, AttachmentUrls);
6960 internal Dictionary<string, string> GetAttachmentUrls(
LegalIdentity Identity)
6962 if (Identity.Attachments is
null)
6965 Dictionary<string, string> Urls =
new Dictionary<string, string>();
6973 internal async Task<(
LegalIdentity, Dictionary<string, string>)> ValidateSignature(
XmppAddress Signatory, DateTime Timestamp,
byte[] Data,
6977 Dictionary<string, string> AttachmentUrls;
6979 if (this.Server.IsServerDomain(Signatory.
Domain,
true))
6987 if (ID.ValidateSignature(Data,
Signature))
6990 AttachmentUrls = this.GetAttachmentUrls(ID);
6995 AttachmentUrls =
null;
6999 KeyValuePair<CaseInsensitiveString, string> P = await this.GetComponent(Signatory.
Domain, NamespacesLegalIdentity);
7003 return (
null,
null);
7009 return (
null,
null);
7014 return (Identity, AttachmentUrls);
7017 private async Task<IqResultEventArgs> ValidateRemoteSignature(
string RemoteLegalComponent,
string BareJid,
byte[] Data,
byte[]
Signature,
7020 TaskCompletionSource<IqResultEventArgs> T =
new TaskCompletionSource<IqResultEventArgs>();
7021 StringBuilder Xml =
new StringBuilder();
7024 Xml.Append(
"<validateSignature data=\"");
7025 Xml.Append(Convert.ToBase64String(Data));
7026 Xml.Append(
"\" s=\"");
7027 Xml.Append(Convert.ToBase64String(
Signature));
7028 Xml.Append(
"\" bareJid=\"");
7031 if (!
string.IsNullOrEmpty(ForBareJid))
7033 Xml.Append(
"\" for=\"");
7037 Xml.Append(
"\" xmlns=\"");
7038 Xml.Append(NamespaceLegalIdentity(Version));
7041 if (!await this.Server.SendIqRequest(
"get",
this.MainDomain,
new XmppAddress(RemoteLegalComponent),
string.Empty,
7045 return Task.CompletedTask;
7051 return await T.Task;
7054 private async Task ContractSignedHandler(
object Sender,
MessageEventArgs e)
7065 Log.
Warning(
"Client signature message ignored. Source domain not equal to contract domain.");
7070 if (!this.IsComponentDomain(LegalAddress.
Domain,
true))
7072 Log.
Warning(
"Client signature message ignored. Destination domain not equal to domain of legal identity signing the contract.");
7079 Log.
Warning(
"Client signature message ignored. Unable to get contract.");
7083 if (
Contract.ClientSignatures is
null)
7085 Log.
Warning(
"Client signature message ignored. No recorded client signatures in contract.");
7100 if (BareJid is
null)
7102 Log.
Warning(
"Client signature message ignored. Legal Identity not in list of client signatures.");
7106 if (!await this.ValidateServerSignature(
Contract))
7108 Log.
Warning(
"Client signature message ignored. Server signature not valid.");
7125 return Task.FromResult(
false);
7127 StringBuilder Xml =
new StringBuilder();
7128 Contract.
Serialize(Xml,
false,
true,
true,
true,
true,
false,
false,
null,
this);
7129 byte[] Data = Encoding.UTF8.GetBytes(Xml.ToString());
7137 if (this.IsComponentDomain(ServerDomain,
true))
7146 public async Task<Networking.XMPP.IE2eEndpoint> GetPublicKey(
string ServerDomain)
7148 string Key = ServerDomain +
"|pub";
7150 if (this.remoteComponents.
TryGetValue(Key, out
object Obj) && Obj is Networking.XMPP.IE2eEndpoint PubKey)
7153 TaskCompletionSource<Networking.XMPP.IE2eEndpoint> Result =
new TaskCompletionSource<Networking.XMPP.IE2eEndpoint>();
7154 string Namespace = NamespaceLegalIdentity(
NamespaceSet.Current);
7156 await this.Server.SendIqRequest(
"get", this.MainDomain,
new XmppAddress(ServerDomain),
string.Empty,
7157 "<getPublicKey xmlns=\"" + Namespace +
"\"/>", (Sender, e) =>
7162 if (e.Ok && !((E = e.FirstElement) is
null) && E.LocalName ==
"publicKey" && E.NamespaceURI == Namespace)
7164 foreach (XmlNode N in E.ChildNodes)
7166 if (N is XmlElement E2)
7168 ServerKey = EndpointSecurity.ParseE2eKey(E2);
7169 if (!(ServerKey is null))
7171 Result.TrySetResult(ServerKey);
7172 return Task.CompletedTask;
7178 Result.TrySetResult(
null);
7179 return Task.CompletedTask;
7184 PubKey = Result.Task.Result;
7185 if (!(PubKey is
null))
7186 this.remoteComponents[Key] = PubKey;
7191 private async Task GetSignedContractsHandler(
object Sender,
IqEventArgs e)
7203 string Xml = await this.SerializeContractReferences(Signatures, References, QueryVersion);
7207 catch (Exception ex)
7213 private async Task GetContractHandler(
object Sender,
IqEventArgs e)
7249 StringBuilder Xml =
new StringBuilder();
7254 catch (Exception ex)
7260 private async Task GetContractsHandler(
object Sender,
IqEventArgs e)
7264 StringBuilder Xml =
new StringBuilder();
7266 Xml.Append(
"<contracts xmlns='");
7267 Xml.Append(e.
Query.NamespaceURI);
7270 foreach (XmlNode N
in e.
Query.ChildNodes)
7272 if (N is XmlElement E && E.LocalName ==
"ref" && E.NamespaceURI == e.
Query.NamespaceURI)
7288 Xml.Append(
"<ref id='");
7295 Xml.Append(
"</contracts>");
7299 catch (Exception ex)
7305 private async Task IsPartHandler(
object Sender,
IqEventArgs e)
7324 if (!this.Server.IsServerDomain(BareAddress.
Domain,
true))
7337 KeyValuePair<CaseInsensitiveString, string> P = await this.GetComponent(e.
From.
Address, NamespacesLegalIdentity);
7339 string Namespace = P.Value;
7347 foreach (XmlNode N
in e.
Query.ChildNodes)
7349 if (N is XmlElement E && E.LocalName ==
"idRef")
7356 if (!this.IsComponentDomain(LegalIdAddress.
Domain,
true))
7361 LegalIdentity Identity = await GetLocalLegalIdentity(LegalId);
7362 if (Identity is
null)
7365 if (Identity.Account == BareAddress.
Account)
7367 await e.
IqResult(
"<part xmlns='" + e.
Query.NamespaceURI +
"'>true</part>", e.
To);
7374 await e.
IqResult(
"<part xmlns='" + e.
Query.NamespaceURI +
"'>false</part>", e.
To);
7376 catch (Exception ex)
7382 private async Task ObsoleteContractHandler(
object Sender,
IqEventArgs e)
7404 await e.
IqErrorForbidden(e.
To,
"Contract is legally binding and cannot be obsoleted.",
"en");
7427 StringBuilder Xml =
new StringBuilder();
7431 await this.SendContractUpdatedEvent(
Contract,
false);
7434 catch (Exception ex)
7440 internal async Task SendContractUpdatedEvent(
Contract Contract,
bool Created)
7442 StringBuilder Xml =
new StringBuilder();
7444 Xml.Append(
"<contract");
7445 Xml.Append(Created ?
"Created" :
"Updated");
7446 Xml.Append(
" xmlns='");
7447 Xml.Append(NamespaceSmartContracts(
Contract.Version));
7448 Xml.Append(
"' contractId='");
7455 await this.Server.SendMessage(
string.Empty,
string.Empty,
Contract.Provider, StatusRecipient,
string.
Empty,
Event);
7458 private async Task DeleteContractHandler(
object Sender,
IqEventArgs e)
7481 await e.
IqErrorForbidden(e.
To,
"Contract is legally binding and cannot be deleted.",
"en");
7487 await e.
IqErrorForbidden(e.
To,
"Contract cannot be deleted before its required archivation period expires.",
"en");
7495 await this.DeleteAttachments(
Contract.Attachments);
7496 Contract.Attachments =
null;
7500 StringBuilder Xml =
new StringBuilder();
7501 Contract.
Serialize(Xml,
true,
true,
true,
false,
true,
true,
false,
null,
this);
7504 await this.SendContractDeletedEvent(
Contract);
7507 catch (Exception ex)
7515 if (!(AttachmentReferences is
null))
7530 catch (Exception ex)
7542 StringBuilder Xml =
new StringBuilder();
7544 Xml.Append(
"<contractDeleted xmlns='");
7545 Xml.Append(NamespaceSmartContracts(
Contract.Version));
7546 Xml.Append(
"' contractId='");
7553 await this.Server.SendMessage(
string.Empty,
string.Empty,
Contract.Provider, StatusRecipient,
string.
Empty,
Event);
7556 private async Task UpdateContractHandler(
object Sender,
IqEventArgs e)
7560 if (!this.Server.IsServerDomain(e.
From.
Domain,
true))
7562 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can manage contracts on the broker.",
"en");
7568 string Namespace = NamespaceSmartContracts(QueryVersion);
7570 foreach (XmlNode N
in e.
Query.ChildNodes)
7572 if (N is XmlElement E && E.LocalName ==
"contract" && E.NamespaceURI == Namespace)
7575 UpdatedContract = Parsed?.
Contract;
7577 if (UpdatedContract is
null)
7588 await e.
IqErrorBadRequest(e.
To,
"Status element not permitted when updating contract.",
"en");
7592 if (!ParametersValid)
7603 if (UpdatedContract is
null)
7616 if (!(UpdatedContract.ClientSignatures is
null) && UpdatedContract.ClientSignatures.Length > 0)
7622 if (!(UpdatedContract.ServerSignature is
null))
7631 if (PrevContract is
null)
7643 if (!(PrevContract.ClientSignatures is
null) && PrevContract.ClientSignatures.Length > 0)
7649 switch (PrevContract.State)
7662 await e.
IqErrorForbidden(e.
To,
"Current state of the contract does not allow updates.",
"en");
7667 if (Identity is
null)
7669 await e.
IqErrorForbidden(e.
To,
"No current approved legal identity found for account.",
"en");
7673 string Errors = await this.ValidateContent(UpdatedContract);
7674 if (!
string.IsNullOrEmpty(Errors))
7680 UpdatedContract.ObjectId = PrevContract.
ObjectId;
7681 UpdatedContract.TemplateId = PrevContract.TemplateId;
7682 UpdatedContract.Provider = PrevContract.Provider;
7683 UpdatedContract.Account = PrevContract.Account;
7684 UpdatedContract.Created = PrevContract.Created;
7685 UpdatedContract.Nonce = PrevContract.
Nonce;
7686 UpdatedContract.Updated = NowSecond;
7687 UpdatedContract.Version = QueryVersion;
7694 UpdatedContract.Sign(
this);
7700 StringBuilder Xml =
new StringBuilder();
7701 UpdatedContract.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
7704 await this.SendContractUpdatedEvent(UpdatedContract,
false);
7707 catch (Exception ex)
7713 private async Task GetSchemasHandler(
object Sender,
IqEventArgs e)
7717 StringBuilder Xml =
new StringBuilder();
7720 Xml.Append(
"<schemas xmlns='");
7721 Xml.Append(e.
Query.NamespaceURI);
7728 if (!(LastNamespace is
null))
7729 Xml.Append(
"</schemaRef>");
7733 Xml.Append(
"<schemaRef namespace='");
7738 Xml.Append(
"<digest function='");
7739 Xml.Append(Schema.
Function.ToString());
7742 Xml.Append(
"</digest>");
7745 if (!(LastNamespace is
null))
7746 Xml.Append(
"</schemaRef>");
7748 Xml.Append(
"</schemas>");
7752 catch (Exception ex)
7758 private async Task GetSchemaHandler(
object Sender,
IqEventArgs e)
7763 string DigestBase64 =
null;
7772 foreach (XmlNode N
in e.
Query.ChildNodes)
7774 if (N is XmlElement E && E.LocalName ==
"digest" && E.NamespaceURI == e.
Query.NamespaceURI)
7776 DigestBase64 = E.InnerText;
7777 if (!Enum.TryParse(
XML.
Attribute(E,
"function"), out Function))
7787 if (DigestBase64 is
null)
7804 (Schema, ErrorMsg) = await this.LoadSchema(Namespace,
null);
7805 if (!
string.IsNullOrEmpty(ErrorMsg))
7815 StringBuilder Xml =
new StringBuilder();
7817 Xml.Append(
"<schema xmlns='");
7818 Xml.Append(e.
Query.NamespaceURI);
7820 Xml.Append(Convert.ToBase64String(Schema.
XmlSchema));
7821 Xml.Append(
"</schema>");
7825 catch (Exception ex)
7831 private async Task GetLegalIdentitiesOfContractHandler(
object Sender,
IqEventArgs e)
7839 if (!(Current || Historic))
7841 await e.
IqErrorBadRequest(e.
To,
"Both current and historic attributes cannot both be false.",
"en");
7846 List<LegalIdentity> Identities =
new List<LegalIdentity>();
7847 List<Dictionary<string, string>> AttachmentUrlss =
new List<Dictionary<string, string>>();
7849 DateTime Now = DateTime.Now;
7851 if (this.IsComponentDomain(ContractAddress.
Domain,
true))
7871 if (!(
Contract.ClientSignatures is
null))
7873 Dictionary<string, bool> Domains =
null;
7878 if (this.IsComponentDomain(LegalId.
Domain,
true))
7880 Identity = await GetLocalLegalIdentity(
Signature.LegalId);
7884 Identities.Add(Identity);
7885 AttachmentUrlss.Add(
null);
7890 CurrentIdentity = await this.GetApprovedLegalIdentityAsync(Identity.Account, Now);
7891 if (CurrentIdentity.Id != Identity.Id)
7893 Identities.Add(CurrentIdentity);
7894 AttachmentUrlss.Add(
null);
7900 if (Domains is
null)
7901 Domains =
new Dictionary<string, bool>();
7903 Domains[LegalId.
Domain] =
true;
7907 if (!(Domains is
null))
7909 TaskCompletionSource<bool> Result =
new TaskCompletionSource<bool>();
7910 object SynchObj =
new object();
7911 int Count = Domains.Count;
7912 StringBuilder Xml =
new StringBuilder();
7913 string ContractsNamespace = NamespaceSmartContracts(
Contract.Version);
7915 Xml.Append(
"<getLegalIdentities xmlns='");
7916 Xml.Append(ContractsNamespace);
7917 Xml.Append(
"' contractId='");
7919 Xml.Append(
"' current='");
7921 Xml.Append(
"' historic='");
7925 string Request = Xml.ToString();
7926 bool Responded =
false;
7928 foreach (KeyValuePair<string, bool> ByDomain
in Domains)
7930 await this.Server.SendIqRequest(
"get", this.MainDomain,
7931 new XmppAddress(ByDomain.Key),
string.
Empty, Request, async (sender2, e2) =>
7937 Last = --Count == 0;
7944 if (!(E is
null) && E.LocalName ==
"identities")
7946 foreach (XmlNode N
in E.ChildNodes)
7948 if (N is XmlElement E2 && E2.LocalName ==
"identity")
7950 Identity =
LegalIdentity.Parse(E2, out
bool HasStatus, out Dictionary<string, string> AttachmentUrls);
7954 Identities.Add(Identity);
7955 AttachmentUrlss.Add(AttachmentUrls);
7961 Result.TrySetResult(
true);
7965 if (Result.TrySetResult(
false) && !Responded)
7974 if (!await Result.Task || Responded)
7992 Identity = await GetLocalLegalIdentity(
Signature.LegalId);
7996 Identities.Add(Identity);
7997 AttachmentUrlss.Add(
null);
8002 CurrentIdentity = await this.GetApprovedLegalIdentityAsync(Identity.Account, Now);
8003 if (CurrentIdentity.Id != Identity.Id)
8005 Identities.Add(CurrentIdentity);
8006 AttachmentUrlss.Add(
null);
8017 Response = this.SerializeIdentities(Identities, AttachmentUrlss, QueryVersion);
8022 catch (Exception ex)
8028 private async Task GetNetworkIdentitiesHandler(
object Sender,
IqEventArgs e)
8035 List<KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>> Identities =
new List<KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>>();
8037 if (this.IsComponentDomain(ContractAddress.
Domain,
true))
8058 if (!(ErrorResponse is
null))
8061 ErrorResponse.
To, ErrorResponse.
ErrorText,
string.Empty);
8077 Identities.Add(
new KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>(
Signature.LegalId,
Signature.BareJid));
8081 StringBuilder Response =
new StringBuilder();
8083 Response.Append(
"<networkIdentities xmlns='");
8084 Response.Append(NamespaceSmartContracts(QueryVersion));
8085 Response.Append(
"'>");
8089 foreach (KeyValuePair<CaseInsensitiveString, CaseInsensitiveString> P
in Identities)
8091 Response.Append(
"<networkIdentity bareJid='");
8092 Response.Append(
XML.
Encode(P.Value.Value));
8093 Response.Append(
"' legalId='");
8094 Response.Append(
XML.
Encode(P.Key.Value));
8095 Response.Append(
"'/>");
8099 Response.Append(
"</networkIdentities>");
8103 catch (Exception ex)
8109 internal async Task<IqResultEventArgs> GetNetworkIdentities(
Contract Contract,
8110 List<KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>> Identities)
8112 if (!(
Contract.ClientSignatures is
null))
8114 Dictionary<string, bool> Domains =
null;
8119 if (this.IsComponentDomain(LegalId.
Domain,
true))
8122 string JidDomain = i < 0 ? this.Server.Domain : LegalId.
Domain.
Substring(i + 1);
8124 Identities.Add(
new KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>(Identity.Id, Identity.Account +
"@" + JidDomain));
8128 if (Domains is
null)
8129 Domains =
new Dictionary<string, bool>();
8131 Domains[LegalId.
Domain] =
true;
8135 if (!(Domains is
null))
8137 TaskCompletionSource<bool> Result =
new TaskCompletionSource<bool>();
8138 object SynchObj =
new object();
8139 int Count = Domains.Count;
8140 StringBuilder Xml =
new StringBuilder();
8142 Xml.Append(
"<getNetworkIdentities xmlns='");
8144 Xml.Append(
"' contractId='");
8148 string Request = Xml.ToString();
8151 foreach (KeyValuePair<string, bool> ByDomain
in Domains)
8153 await this.Server.SendIqRequest(
"get", this.MainDomain,
8160 Last = --Count == 0;
8165 XmlElement E = e2.FirstElement;
8167 if (!(E is null) && E.LocalName ==
"networkIdentities")
8169 foreach (XmlNode N in E.ChildNodes)
8171 if (N is XmlElement E2 && E2.LocalName ==
"networkIdentity")
8175 Identities.Add(new KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>(
8176 XML.Attribute(E2,
"legalId"), XML.Attribute(E2,
"bareJid")));
8182 Result.TrySetResult(
true);
8186 if (ErrorResponse is
null)
8189 Result.TrySetResult(
false);
8193 return Task.CompletedTask;
8197 if (!await Result.Task)
8198 return ErrorResponse;
8205 private async Task SearchPublicContractsHandler(
object Sender,
IqEventArgs e)
8211 List<CustomFilter> CustomFilters =
new List<CustomFilter>();
8212 List<Filter> Filters =
new List<Filter>()
8217 foreach (XmlNode N
in e.
Query.ChildNodes)
8219 if (N is XmlElement E)
8221 switch (E.LocalName)
8224 if (!await this.AddStrFilter(E, e, Filters,
"ForMachinesLocalName"))
8229 if (!await this.AddStrFilter(E, e, Filters,
"ForMachinesNamespace"))
8234 if (!await this.AddStrFilter(E, e, Filters,
"TemplateId"))
8239 if (!await this.AddRoleFilter(E, e, CustomFilters))
8244 if (!await this.AddParameterFilter(E, e, CustomFilters,
XML.
Attribute(E,
"name")))
8249 if (!await this.AddDateTimeFilter(E, e, Filters,
"Created"))
8254 if (!await this.AddDateTimeFilter(E, e, Filters,
"Updated"))
8259 if (!await this.AddDateTimeFilter(E, e, Filters,
"From"))
8264 if (!await this.AddDateTimeFilter(E, e, Filters,
"To"))
8269 if (!await this.AddDurationFilter(E, e, CustomFilters))
8280 List<Contract> Result =
new List<Contract>();
8281 Filter SearchFilter = Filters.Count == 1 ? Filters[0] :
new FilterAnd(Filters.ToArray());
8282 bool HasCustomFilters = CustomFilters.Count > 0;
8283 IEnumerable<Contract> Contracts;
8286 if (HasCustomFilters)
8290 Contracts = await
Database.
Find<
Contract>(Offset, MaxCount == int.MaxValue ? MaxCount : MaxCount + 1, SearchFilter,
"ContractId");
8296 if (HasCustomFilters)
8298 bool Included =
true;
8300 foreach (CustomFilter
Filter in CustomFilters)
8331 StringBuilder Xml =
new StringBuilder();
8333 Xml.Append(
"<searchResult xmlns='");
8334 Xml.Append(NamespaceSmartContracts(QueryVersion));
8335 Xml.Append(
"' more='");
8341 Xml.Append(
"<ref id='");
8346 Xml.Append(
"</searchResult>");
8350 catch (Exception ex)
8356 private async Task<bool> AddStrFilter(XmlElement E,
IqEventArgs e, List<Filter> Filters,
string Field)
8358 foreach (XmlNode N2
in E.ChildNodes)
8360 if (N2 is XmlElement E2)
8362 switch (E2.LocalName)
8382 private async Task<bool> AddRoleFilter(XmlElement E,
IqEventArgs e, List<CustomFilter> Filters)
8384 foreach (XmlNode N2
in E.ChildNodes)
8386 if (N2 is XmlElement E2)
8388 switch (E2.LocalName)
8391 Filters.Add(
new RoleEqFilter()
8393 Value = E2.InnerText
8398 Filters.Add(
new RoleLikeFilter()
8400 Value = E2.InnerText
8414 private async Task<bool> AddParameterFilter(XmlElement E,
IqEventArgs e, List<CustomFilter> Filters,
string Name)
8416 foreach (XmlNode N2
in E.ChildNodes)
8418 if (N2 is XmlElement E2)
8420 switch (E2.LocalName)
8423 Filters.Add(
new StringParameterEqFilter()
8426 Value = E2.InnerText
8431 Filters.Add(
new StringParameterNEqFilter()
8434 Value = E2.InnerText
8439 Filters.Add(
new StringParameterGtFilter()
8442 Value = E2.InnerText
8447 Filters.Add(
new StringParameterGteFilter()
8450 Value = E2.InnerText
8455 Filters.Add(
new StringParameterLtFilter()
8458 Value = E2.InnerText
8463 Filters.Add(
new StringParameterLteFilter()
8466 Value = E2.InnerText
8471 Filters.Add(
new StringParameterLikeFilter()
8474 Value = E2.InnerText
8485 Filters.Add(
new NumericalParameterEqFilter()
8499 Filters.Add(
new NumericalParameterNEqFilter()
8513 Filters.Add(
new NumericalParameterGtFilter()
8527 Filters.Add(
new NumericalParameterGteFilter()
8541 Filters.Add(
new NumericalParameterLtFilter()
8555 Filters.Add(
new NumericalParameterLteFilter()
8569 Filters.Add(
new BooleanParameterEqFilter()
8583 Filters.Add(
new BooleanParameterNEqFilter()
8592 if (!
XML.
TryParse(E2.InnerText, out DateTime TP) || TP.TimeOfDay != TimeSpan.Zero)
8598 Filters.Add(
new DateParameterEqFilter()
8612 Filters.Add(
new DateParameterNEqFilter()
8626 Filters.Add(
new DateParameterGtFilter()
8640 Filters.Add(
new DateParameterGteFilter()
8654 Filters.Add(
new DateParameterLtFilter()
8668 Filters.Add(
new DateParameterLteFilter()
8682 Filters.Add(
new DateTimeParameterEqFilter()
8696 Filters.Add(
new DateTimeParameterNEqFilter()
8710 Filters.Add(
new DateTimeParameterGtFilter()
8724 Filters.Add(
new DateTimeParameterGteFilter()
8738 Filters.Add(
new DateTimeParameterLtFilter()
8752 Filters.Add(
new DateTimeParameterLteFilter()
8760 if (!TimeSpan.TryParse(E2.InnerText, out TimeSpan TS))
8766 Filters.Add(
new TimeParameterEqFilter()
8774 if (!TimeSpan.TryParse(E2.InnerText, out TS))
8780 Filters.Add(
new TimeParameterNEqFilter()
8788 if (!TimeSpan.TryParse(E2.InnerText, out TS))
8794 Filters.Add(
new TimeParameterGtFilter()
8802 if (!TimeSpan.TryParse(E2.InnerText, out TS))
8808 Filters.Add(
new TimeParameterGteFilter()
8816 if (!TimeSpan.TryParse(E2.InnerText, out TS))
8822 Filters.Add(
new TimeParameterLtFilter()
8830 if (!TimeSpan.TryParse(E2.InnerText, out TS))
8836 Filters.Add(
new TimeParameterLteFilter()
8850 Filters.Add(
new DurationParameterEqFilter()
8864 Filters.Add(
new DurationParameterNEqFilter()
8878 Filters.Add(
new DurationParameterGtFilter()
8892 Filters.Add(
new DurationParameterGteFilter()
8906 Filters.Add(
new DurationParameterLtFilter()
8920 Filters.Add(
new DurationParameterLteFilter()
8937 private async Task<bool> AddDateTimeFilter(XmlElement E,
IqEventArgs e, List<Filter> Filters,
string Field)
8939 foreach (XmlNode N2
in E.ChildNodes)
8941 if (N2 is XmlElement E2)
8949 switch (E2.LocalName)
8985 private async Task<bool> AddDurationFilter(XmlElement E,
IqEventArgs e, List<CustomFilter> Filters)
8987 foreach (XmlNode N2
in E.ChildNodes)
8989 if (N2 is XmlElement E2)
8997 switch (E2.LocalName)
9000 Filters.Add(
new DurationEqFilter()
9007 Filters.Add(
new DurationNEqFilter()
9014 Filters.Add(
new DurationGtFilter()
9021 Filters.Add(
new DurationGteFilter()
9028 Filters.Add(
new DurationLtFilter()
9035 Filters.Add(
new DurationLteFilter()
9051 private async Task AddContractAttachmentHandler(
object Sender,
IqEventArgs e)
9059 if (!this.Server.IsServerDomain(e.
From.
Domain,
true))
9061 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can add attachments.",
"en");
9065 if (!Uri.TryCreate(GetUrl, UriKind.Absolute, out Uri GetUri))
9082 await e.
IqErrorForbidden(e.
To,
"Only allowed to add attachments to your own contracts.",
"en");
9088 await e.
IqErrorForbidden(e.
To,
"Attachments can only be added to proposed or approved contracts, before they are signed.",
"en");
9092 if (!(
Contract.Attachments is
null))
9094 string s = Convert.ToBase64String(
Signature);
9098 if (Convert.ToBase64String(Ref.
Signature) == s)
9114 if (UploadingIdentity is
null)
9120 KeyValuePair<Attachment, AttachmentReference> A = await this.CreateAttachment(GetUri,
9122 List<AttachmentReference> References =
new List<AttachmentReference>();
9124 if (!(
Contract.Attachments is
null))
9125 References.AddRange(
Contract.Attachments);
9127 References.Add(A.Value);
9129 Contract.Attachments = References.ToArray();
9134 StringBuilder Xml =
new StringBuilder();
9141 catch (Exception ex)
9147 private async Task RemoveContractAttachmentHandler(
object Sender,
IqEventArgs e)
9153 if (!this.Server.IsServerDomain(e.
From.
Domain,
true))
9155 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can remove attachments.",
"en");
9183 await e.
IqErrorForbidden(e.
To,
"Only allowed to remove attachments to your own contracts.",
"en");
9189 await e.
IqErrorForbidden(e.
To,
"Attachments can only be removed to proposed or approved contracts, before they are signed.",
"en");
9196 if (!(
Contract.Attachments is
null))
9198 List<AttachmentReference> Attachments =
new List<AttachmentReference>();
9202 if (Ref.
Id != AttachmentId)
9203 Attachments.Add(Ref);
9206 Contract.Attachments = Attachments.ToArray();
9214 StringBuilder Xml =
new StringBuilder();
9220 catch (Exception ex)
9226 private async Task AuthorizeAccessToContractHandler(
object Sender,
IqEventArgs e)
9246 if (!this.IsComponentDomain(ContractIdAddress.
Domain,
true))
9283 ClientInformation ClientInfo = await this.GetNetworkIdentity(RemoteId,
true,
true,
Contract.Version);
9286 this.ContractAuthorization(RemoteJid, e.
From.
BareJid, ContractId, Authorized);
9291 catch (Exception ex)
9299 #region Third-party peer reviews
9301 private async Task GetReviewIdProvidersHandler(
object Sender,
IqEventArgs e)
9305 await e.
IqErrorForbidden(e.
To,
"Access to service providers only granted to accounts on broker.",
"en");
9313 await e.
IqErrorForbidden(e.
To,
"Access to service providers only granted to accounts on broker.",
"en");
9327 if (IdentityApplication is
null)
9333 KeyValuePair<string, object>[] Tags = IdentityApplication.GetTags();
9334 StringBuilder Xml =
new StringBuilder();
9336 Xml.Append(
"<providers xmlns='");
9337 Xml.Append(e.
Query.NamespaceURI);
9340 foreach (
IPeerReviewService Service
in await this.GetPeerReviewServices(Tags,
true,
true))
9342 Xml.Append(
"<provider id='");
9344 Xml.Append(
"' type='");
9346 Xml.Append(
"' name='");
9348 Xml.Append(
"' legalId='");
9350 Xml.Append(
"' external='");
9353 if (!
string.IsNullOrEmpty(Service.
IconUrl))
9355 Xml.Append(
"' iconUrl='");
9357 Xml.Append(
"' iconWidth='");
9358 Xml.Append(Service.
IconWidth.ToString());
9359 Xml.Append(
"' iconHeight='");
9366 Xml.Append(
"</providers>");
9371 private async Task SelectReviewServiceHandler(
object Sender,
IqEventArgs e)
9375 await e.
IqErrorForbidden(e.
To,
"Access to service providers only granted to accounts on broker.",
"en");
9383 await e.
IqErrorForbidden(e.
To,
"Access to service providers only granted to accounts on broker.",
"en");
9414 if (IdentityApplication is
null)
9420 KeyValuePair<string, object>[] Tags = IdentityApplication.GetTags();
9424 if (Service is
null)
9430 this.SelectServiceProvider(AccountName, Service);
9437 lock (this.selectedServicePerAccount)
9439 this.selectedServicePerAccount[AccountName] = Service;
9443 private readonly Dictionary<CaseInsensitiveString, IPeerReviewService> selectedServicePerAccount =
new Dictionary<CaseInsensitiveString, IPeerReviewService>();
9445 internal async Task<IPeerReviewService[]> GetPeerReviewServices(KeyValuePair<string, object>[] Tags,
bool IncludeInternal,
bool IncludeExternal)
9447 List<IPeerReviewService> Result =
new List<IPeerReviewService>();
9450 foreach (Type T
in ServiceTypes)
9463 if (IncludeExternal)
9464 Result.Add(Service);
9468 if (IncludeInternal)
9469 Result.Add(Service);
9474 return Result.ToArray();
9477 private async Task ContractsClient_PetitionForPeerReviewIDReceived(
object Sender,
9478 Networking.XMPP.Contracts.EventArguments.SignaturePetitionEventArgs e)
9485 KeyValuePair<string, object>[] Tags = e.RequestorIdentity.GetTags();
9490 Log.
Warning(
"Peer-review request denied. Access to service providers only granted to accounts on broker.",
9491 e.RequestorIdentity.
Id, e.
From, Tags);
9494 new byte[0], e.PetitionId, e.RequestorFullJid,
false);
9504 Log.
Warning(
"Peer-review request denied. Access to service providers only granted to accounts on broker.",
9505 e.RequestorIdentity.
Id, e.
From, Tags);
9508 new byte[0], e.PetitionId, e.RequestorFullJid,
false);
9515 Log.
Warning(
"Peer-review request denied. Account has been disabled.",
9516 e.RequestorIdentity.
Id, e.
From, Tags);
9519 new byte[0], e.PetitionId, e.RequestorFullJid,
false);
9525 if (!this.IsComponentDomain(RequestorIdentityId.
Domain,
true))
9527 Log.
Warning(
"Peer-review request denied. Requestor legal identity not on the server.",
9528 e.RequestorIdentity.
Id, e.
From, Tags);
9531 new byte[0], e.PetitionId, e.RequestorFullJid,
false);
9539 if (LocalRequestorIdentity is
null)
9541 Log.
Warning(
"Peer-review request denied. Proposed identity did not exist on server.",
9542 e.RequestorIdentity.
Id, e.
From, Tags);
9545 new byte[0], e.PetitionId, e.RequestorFullJid,
false);
9550 StringBuilder Xml1 =
new StringBuilder();
9551 StringBuilder Xml2 =
new StringBuilder();
9553 LocalRequestorIdentity.Serialize(Xml1,
true,
true,
true,
true,
true,
true,
false,
null,
this);
9554 e.RequestorIdentity.Serialize(Xml2,
true,
true,
true,
true,
true,
true,
false);
9556 if (Xml1.ToString() != Xml2.ToString())
9558 Log.
Warning(
"Peer-review request denied. Requestor legal identity representation not the same as local version.",
9559 e.RequestorIdentity.
Id, e.
From, Tags);
9562 new byte[0], e.PetitionId, e.RequestorFullJid,
false);
9567 IPeerReviewService[] PeerReviewServices = await this.GetPeerReviewServices(Tags,
true,
false);
9569 if (PeerReviewServices.Length == 0)
9571 Log.
Warning(
"Peer-review request denied. No local peer review services found.",
9572 e.RequestorIdentity.
Id, e.
From, Tags);
9575 new byte[0], e.PetitionId, e.RequestorFullJid,
false);
9582 lock (this.selectedServicePerAccount)
9584 if (!this.selectedServicePerAccount.TryGetValue(AccountName, out PeerReviewService))
9585 PeerReviewService =
null;
9588 if (PeerReviewService is
null)
9590 Log.
Warning(
"Peer-review request denied. No selected peer review service provider.",
9591 e.RequestorIdentity.
Id, e.
From, Tags);
9594 new byte[0], e.PetitionId, e.RequestorFullJid,
false);
9601 StringBuilder Message =
new StringBuilder();
9603 Message.Append(
"<petitionClientUrl xmlns='");
9604 Message.Append(NamespaceLegalIdentity(LocalRequestorIdentity.Version));
9605 Message.Append(
"' pid='");
9606 Message.Append(
XML.
Encode(e.PetitionId));
9607 Message.Append(
"' url='");
9609 Message.Append(
"'/>");
9611 await this.Server.SendMessage(
string.Empty,
string.Empty, e.
To, From.
BareJid,
string.
Empty, Message.
ToString());
9617 if (Result.
ErrorType == global::Paiwise.ErrorType.Server || Result.
ErrorType == global::Paiwise.ErrorType.Service)
9622 StringBuilder Xml =
new StringBuilder();
9624 Xml.Append(
"<body>");
9626 Xml.Append(
"</body>");
9627 Xml.Append(
"<clientMessage xmlns='");
9628 Xml.Append(NamespaceLegalIdentity(LocalRequestorIdentity.Version));
9629 Xml.Append(
"' code='");
9631 Xml.Append(
"' type='");
9632 Xml.Append(Result.
ErrorType.ToString());
9635 await this.Server.SendMessage(
string.Empty,
string.Empty, e.
To, e.RequestorFullJid,
9642 Networking.XMPP.Contracts.SignWith.LatestApprovedId);
9645 Signature, e.PetitionId, e.RequestorFullJid,
true);
9650 new byte[0], e.PetitionId, e.RequestorFullJid,
false);
9653 catch (Exception ex)
Contains information about a service provider.
Helps with parsing of commong data types.
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
Static class managing encoding and decoding of internet content.
static Task< object > DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri)
Decodes an object.
static bool CanGet(Uri Uri, out Grade Grade, out IContentGetter Getter)
If a resource can be gotten, given its URI.
static Task< KeyValuePair< string, TemporaryStream > > GetTempStreamAsync(Uri Uri, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
Helps with common JSON-related tasks.
static readonly DateTime UnixEpoch
Unix Date and Time epoch, starting at 1970-01-01T00:00:00Z
Contains a markdown document. This markdown document class supports original markdown,...
static string Encode(string s)
Encodes all special characters in a string so that it can be included in a markdown document without ...
const string DefaultContentType
Default content type for XML documents.
const string SchemaContentType
Default content type for XML schema documents.
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
static string Encode(string s)
Encodes a string for use in XML.
static bool TryParse(string s, out DateTime Value)
Tries to decode a string encoded DateTime.
static XmlException AnnotateException(XmlException ex)
Creates a new XML Exception object, with reference to the source XML file, for information.
Class representing an event.
override string ToString()
Static class managing the application event log. Applications and services log events on this static ...
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.
static void Warning(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a warning event.
static void Error(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an error event.
static void Informational(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an informational event.
static void Notice(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a notice event.
Static class managing the runtime environment of the IoT Gateway.
static CaseInsensitiveString Domain
Domain name.
static byte[] NextBytes(int NrBytes)
Generates an array of random bytes.
static Task SendNotification(Graph Graph)
Sends a graph as a notification message to configured notification recipients.
static string GetUrl(string LocalResource)
Gets a URL for a resource.
static ContractsClient ContractsClient
XMPP Contracts Client, if such a compoent is available on the XMPP broker.
static XmppClient XmppClient
XMPP Client connection of gateway.
Implements an HTTP server.
Static class managing editable parameters in objects. Editable parameters are defined by using the at...
void Serialize(StringBuilder Xml, bool IncludeNamespace, bool IncludeIdAttribute, bool IncludeClientSignature, bool IncludeAttachments, bool IncludeStatus, bool IncludeServerSignature, bool IncludeAttachmentReferences)
Serializes the identity to XML
Abstract base class for XMPP client connections
abstract string RemoteEndpoint
Remote endpoint
Base class for components.
bool UnregisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync< MessageEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters a message handler.
void RegisterIqSetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Set handler.
CaseInsensitiveString Subdomain
Subdomain name.
CaseInsensitiveString SubdomainSuffixed
Subdomain name, suffixed with a period (.).
void RegisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Get handler.
string Name
Component name.
XmppAddress MainDomain
Main/principal domain address
bool IsComponentDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
Checks if a domain is the component domain, or optionally, an alternative component domain.
XmppServer Server
XMPP Server.
bool UnregisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Get handler.
bool UnregisterIqSetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Set handler.
void RegisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync< MessageEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers a message handler.
Event arguments for IQ queries.
XmppAddress From
From address attribute
Task IqErrorNotAcceptable(XmppAddress From, string ErrorText, string Language)
Returns a not-acceptable error.
Task IqResult(string Xml, string From)
Returns a response to the current request.
Task IqErrorResourceConstraint(XmppAddress From, string ErrorText, string Language)
Returns a resource-constraint error.
Task IqErrorItemNotFound(XmppAddress From, string ErrorText, string Language)
Returns a item-not-found error.
XmlElement Query
Query element, if found, null otherwise.
XmppAddress To
To address attribute
async Task IqError(string ErrorType, string Xml, XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
Task IqErrorServiceUnavailable(XmppAddress From, string ErrorText, string Language)
Returns a service-unavailable error.
Task IqErrorBadRequest(XmppAddress From, string ErrorText, string Language)
Returns a bad-request error.
ISender Sender
Sender of stanza.
Task IqErrorForbidden(XmppAddress From, string ErrorText, string Language)
Returns a forbidden error.
string Id
ID of the request.
Event arguments for responses to IQ queries.
string ErrorTypeString
Error Type XML attribute string
XmlElement ErrorElement
Error element.
XmlElement FirstElement
First child element of the Response element.
XmppAddress To
To address attribute
bool Ok
If the response is an OK result response (true), or an error response (false).
string ErrorText
Any error specific text.
Event arguments for Messages.
XmppAddress From
From address attribute
XmlElement Content
Content element, if found, null otherwise.
Presence information event arguments.
string Type
Type attribute.
XmlElement Content
Content element, if found, null otherwise.
Task PresenceErrorItemNotFound(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
Task PresenceErrorForbidden(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
XmppAddress To
To attribute.
XmppAddress From
From attribute.
XmlElement StanzaElement
Stanza element.
Contains information about one XMPP address.
override string ToString()
object.ToString()
bool IsBareJID
If the address is a Bare JID.
bool HasAccount
If the address has an account part.
bool IsEmpty
If the address is empty.
CaseInsensitiveString Domain
Domain
CaseInsensitiveString Address
XMPP Address
bool IsDomain
If the Address is a domain.
XmppAddress ToBareJID()
Returns the Bare JID as an XmppAddress object.
CaseInsensitiveString BareJid
Bare JID
static readonly XmppAddress Empty
Empty address.
CaseInsensitiveString Account
Account
bool IsFullJID
If the Address is a Full JID.
Manages an XMPP server-to-server connection.
Task< bool > SendMessage(string Type, string Id, string From, string To, string Language, string ContentXml)
Sends a Message stanza to a recipient.
bool TryGetClientConnections(string BareJID, out IClientConnection[] Connections)
Tries to get available connections for a given client.
bool TryGetClientConnection(string FullJID, out IClientConnection Connection)
Tries to get an active client connection.
Task< bool > SendIqRequest(string Type, string From, string To, string Language, string ContentXml, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Sends an IQ stanza to a recipient.
bool IsServerDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
Checks if a domain is the server domain, or optionally, an alternative domain.
bool UnregisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Get handler.
void RegisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Get handler.
CaseInsensitiveString Domain
Domain name.
Represents a case-insensitive string.
string Value
String-representation of the case-insensitive string. (Representation is case sensitive....
static readonly CaseInsensitiveString Empty
Empty case-insensitive string
int Length
Gets the number of characters in the current CaseInsensitiveString object.
string LowerCase
Lower-case representation of the case-insensitive string.
int IndexOf(CaseInsensitiveString value, StringComparison comparisonType)
Reports the zero-based index of the first occurrence of the specified string in the current System....
static bool IsNullOrEmpty(CaseInsensitiveString value)
Indicates whether the specified string is null or an CaseInsensitiveString.Empty string.
bool StartsWith(CaseInsensitiveString value)
Determines whether the beginning of this string instance matches the specified string.
override string ToString()
CaseInsensitiveString Substring(int startIndex, int length)
Retrieves a substring from this instance. The substring starts at a specified character position and ...
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static Task< IEnumerable< object > > FindDelete(string Collection, params string[] SortOrder)
Finds objects in a given collection and deletes them in the same atomic operation.
static Task< string[]> GetCollections()
Gets an array of available collections.
static async Task Update(object Object)
Updates an object in the database.
static async Task Delete(object Object)
Deletes an object in the database.
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
This filter selects objects that conform to all child-filters provided.
This filter selects objects that have a named field equal to a given value.
This filter selects objects that have a named field greater or equal to a given value.
This filter selects objects that have a named field greater than a given value.
This filter selects objects that have a named field lesser or equal to a given value.
This filter selects objects that have a named field lesser than a given value.
This filter selects objects that have a named field matching a given regular expression.
This filter selects objects that have a named field not equal to a given value.
Base class for all filter classes.
Implements an in-memory cache.
void Dispose()
IDisposable.Dispose
bool Remove(KeyType Key)
Removes an item from the cache.
bool TryGetValue(KeyType Key, out ValueType Value)
Tries to get a value from the cache.
void Add(KeyType Key, ValueType Value)
Adds an item to the cache.
Event arguments for cache item removal events.
KeyType Key
Key of item that was removed.
RemovedReason Reason
Reason for removing the item.
Static class that dynamically manages types and interfaces available in the runtime environment.
static Type GetType(string FullName)
Gets a type, given its full name.
static object[] NoParameters
Contains an empty array of parameter values.
static object Instantiate(Type Type, params object[] Arguments)
Returns an instance of the type Type . If one needs to be created, it is. If the constructor requires...
static Type[] GetTypesImplementingInterface(string InterfaceFullName)
Gets all types implementing a given interface.
static ConstructorInfo GetDefaultConstructor(Type Type)
Gets the default constructor of a type, if one exists.
Static class managing persistent settings.
static async Task< string > GetAsync(string Key, string DefaultValue)
Gets a string-valued setting.
Manages a temporary stream. Contents is kept in-memory, if below a memory threshold,...
override async Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
Asynchronously reads the bytes from the current stream and writes them to another stream,...
override long Length
When overridden in a derived class, gets the length in bytes of the stream.
Represents a named semaphore, i.e. an object, identified by a name, that allows single concurrent wri...
Static class of application-wide semaphores that can be used to order access to editable objects.
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...
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...
Contains methods for simple hash calculations.
static byte[] ComputeHash(HashFunction Function, byte[] Data)
Computes a hash of a block of binary data.
Static class containing predefined JWT claim names.
const string Issuer
Issuer of the JWT
const string IssueTime
Time at which the JWT was issued; can be used to determine age of the JWT
const string JwtId
Unique identifier; can be used to prevent the JWT from being replayed (allows a token to be used only...
const string Subject
Subject of the JWT (the user)
const string ExpirationTime
Time after which the JWT expires
string Create(params KeyValuePair< string, object >[] Claims)
Creates a new JWT token.
Class that monitors login events, and help applications determine malicious intent....
static async void Success(string Message, string UserName, string RemoteEndpoint, string Protocol, params KeyValuePair< string, object >[] Tags)
Handles a successful login attempt.
Login state information relating to a remote endpoint
RemoteEndpoint()
Login state information relating to a remote endpoint
Contains information about a broker account.
CaseInsensitiveString EMail
E-mail address associated with account.
bool Enabled
If account is enabled
CaseInsensitiveString PhoneNr
Phone number associated with account.
Manages eDaler on accounts connected to the broker.
virtual void Error(EDalerUriErrorType ErrorType, string ErrorMessage, bool LogAsNotice)
Reports an error with the URI
string ErrorMessage
Error message, or null if no error.
Current state of URI from external source
Current state of URI from internal source
Represents an attachment to a document.
CaseInsensitiveString ContractId
Contract ID, if attachment is associated with a contract, or null otherwise.
CaseInsensitiveString UploaderLegalId
Legal ID of uploader
long Size
Size of attachment, in bytes.
CaseInsensitiveString Id
Attachment ID
string ObjectId
Object ID of attachment.
string LocalFileName
Local Filename of attachment.
byte[] Salt
Salt used for deriving keys for decrypting attachment file.
string RemoteFileName
Remote Filename of attachment.
Represents an attachment to a document.
string ContentType
Internet Content Type of binary attachment.
byte[] Signature
Binary signature of the attachment, generated by an approved legal identity of the account-holder....
CaseInsensitiveString Id
Attachment ID
Boolean contractual parameter
Calculation contractual parameter
Represents a digital signature on a contract.
CaseInsensitiveString BareJid
Bare JID of the client used to generate the signature.
CaseInsensitiveString LegalId
ID of legal identity signing the contract.
CaseInsensitiveString Role
Role of the legal identity in the contract.
Contains the definition of a contract
async Task< int > CanRevoke(XmppAddress Jid, XmppServer Server, LegalComponent LegalComponent)
Checks if an entity can revoke a contract.
IEnumerable< string > GetStakeholders(XmppServer Server)
Gets the JIDs of the stakeholders of the contract (i.e. the creator and signed parties).
async Task< KeyValuePair< ContentIntegrity, string > > CheckContentIntegrity(LegalComponent Legal)
Checks content integrity.
static async Task< ParsedContract > Parse(XmlElement Xml, LegalComponent Legal)
Parses a contract from is XML representation.
async Task< bool > IsLegallyBinding(bool CheckCurrentTime, bool ExcludeSigningStage, LegalComponent Legal)
Checks if a contract is legally binding.
bool HasEncryptedParameters
If contract has parameters that require encryption and decryption.
string TrySetRoleParameters(string Role, int RoleIndex, LegalIdentity Identity, DateTime SignatureTimestamp, byte[] Signature)
Tries to set role parameters.
bool UpdateRequiresReview(Contract UpdatedContract)
Checks if an updated contract requires review.
void Serialize(StringBuilder Xml, bool IncludeNamespace, bool IncludeIdAttribute, bool IncludeClientSignatures, bool IncludeAttachments, bool IncludeStatus, bool IncludeServerSignature, bool IncludeAttachmentReferences, Dictionary< string, string > AttachmentsUrls, LegalComponent LegalComponent)
Serializes the Contract, in normalized form.
Task< KeyValuePair< Parameter, string > > CheckParameters(LegalComponent Legal, bool CheckTransient)
Checks if the parameters in the contract are valid.
bool TryGetParameter(CaseInsensitiveString ParameterName, out Parameter Result)
Tries to get a parameter, given its name.
byte[] Nonce
An optional nonce value that is used when encrypting protected parameter values.
CaseInsensitiveString ContractId
Contract Identity
bool HasTransientParameters
If contract has parameters that are transient.
bool IsCreator(XmppAddress Jid, XmppServer Server)
Checks if an address belongs to the creator of the contract.
void ProtectTransientParameters()
Protects transient values, by generating GUIDs for those that lack GUIDs.
Task< bool > CanRead(XmppAddress Jid, XmppServer Server, LegalComponent LegalComponent)
Checks if a client with a given Jid is allowed to read the contract.
Contract-reference parameter
Contains information about a contract signature.
Date contractual parameter
DateTime contractual parameter
Duration contractual parameter
Numerical contractual parameter
Abstract base class for contractual parameters
byte[] ProtectedValue
Protected value, in case Protection is not equal to ProtectionLevel.Normal.
Parameter Clone()
Clones a parameter.
CaseInsensitiveString Name
Parameter name
string Expression
Parameter validation script expression.
HumanReadableText[] Descriptions
Discriptions of the role, in different languages.
string Guide
Parameter guide text
ProtectionLevel Protection
Level of confidentiality of the information provided by the parameter.
abstract string StringValue
String representation of value.
Contains information about a parsed contract.
bool HasStatus
If a status element was found.
Contract Contract
Contract object
CaseInsensitiveString FirstParameterErrorName
Name of first parameter with error.
string FirstParameterError
Error message for first parameter with error.
bool ParametersValid
If parameter values in the contract are valid.
Class defining a part in a contract
CaseInsensitiveString Role
Role of the part in the contract
CaseInsensitiveString LegalId
Legal identity of part
int MaxCount
Largest amount of signatures of this role required for a legally binding contract.
CaseInsensitiveString Name
Name of the role.
Role-reference contractual parameter
Contains an XML schema reference, used to validate a contract.
byte[] Digest
Digest of version used during XML validation.
Abstract base class of signatures
byte[] DigitalSignature
Digital Signature
DateTime Timestamp
Timestamp of signature.
String-valued contractual parameter
Time contractual parameter
byte[] XmlSchema
XML Schema
HashFunction Function
Hash Function used
CaseInsensitiveString Namespace
Namespace of schema
string HashBase64
Hash of schema
Class representing human-readable text.
Data in accordance with ISO 3166
static bool TryGetCountry(string Code, out string Country)
Tries to get the Country Name from a ISO 3166-1 Country Code. String comparisons are case-insensitive...
Personal Number Schemes available in different countries.
static async Task< bool?> IsValid(string CountryCode, string PersonalNumber)
Checks if a personal number is valid, in accordance with registered personal number schemes.
CaseInsensitiveString Name
Property name
CaseInsensitiveString Value
Property value
Provisioning and registry service component.
EDalerComponent EDaler
e-Daler component
static async Task< Tuple< byte[], XmlSchema > > LoadSchema(string Url)
Tries to get a schema from the web.
static string NamespaceLegalIdentity(NamespaceSet Version)
Returns the namespace for legal identities.
LegalComponent(XmppServer Server, CaseInsensitiveString Subdomain, string Name, HttpServer HttpServer, string AttachmentsFolder, EDalerComponent EDaler, PubSubComponent PubSub)
Provisioning and registry service component.
static string NamespaceE2E(NamespaceSet Version)
Returns the namespace for End-to-End Encryption.
void RegisterPeerReviewHandlers()
Registers peer-review handlers.
const string NamespaceSmartContractsNeuroFoundationV1
urn:nf:iot:leg:sc:1.0
static readonly string[] NamespacesLegalIdentity
Supported legal identity namespaces, ordered by preference
static string NamespaceSmartContracts(NamespaceSet Version)
Returns the namespace for smart contracts.
static readonly string[] NamespacesSmartContracts
Supported smart contract namespaces, ordered by preference
static async Task< byte[]> LoadEncryptedFile(string FileName, byte[] Salt, long? Size)
Loads an encrypted file.
const string NamespaceLegalIdentityIeeeV1
urn:ieee:iot:leg:id:1.0
static async Task< LegalIdentityReference > FindLegalIdentityReference(string LegalId)
Finds the legal identity reference of a legal identity in the federated network, if found in the loca...
static Task< byte[]> LoadEncryptedFile(string FileName, byte[] Salt)
Loads an encrypted file.
const string NamespaceLegalIdentityNeuroFoundationV1
urn:nf:iot:leg:id:1.0
void UnregisterPeerReviewHandlers()
Unregisters peer-review handlers.
static Task< string > GetOnboardingNeuronDomainName()
Gets the domain name of the Nnboarding Neuron.
string AttachmentsFolder
Attachments folder.
const string NamespaceE2ENeuroFoundationV1
urn:nf:iot:e2e:1.0
const string NamespaceSmartContractsIeeeV1
urn:ieee:iot:leg:sc:1.0
static DateTime NowSecond
Current Date & Time, to a precision of one second.
const string NamespaceE2EIeeeV1
urn:ieee:iot:e2e:1.0
static async Task< IEnumerable< LegalIdentityReference > > FindLegalIdentityReferences(string Country, string PNr)
Finds the legal identity reference objects corresponding to a (COUNTRY,PNR) pair related to a person,...
override void Dispose()
IDisposable.Dispose
override bool SupportsAccounts
If the component supports accounts (true), or if the subdomain name is the only valid address.
Contains a reference to a legal identity, and its related PNR and COUNTRY fields. Allows for distribu...
CaseInsensitiveString Provider
Provider of identity
CaseInsensitiveString PNr
PNR field
CaseInsensitiveString Country
COUNTRY field
Web resource that allows calling applications to enable Quick-Login using legal identities.
const string NamespaceTagSignature
https://tagroot.io/schema/Signature
Marketplace processor, brokering sales of items via tenders and offers defined in smart contracts.
const string MarketplaceNamespace
https://paiwise.tagroot.io/Schema/Marketplace.xsd
Marketplace processor, brokering sales of items via tenders and offers defined in smart contracts.
const string NeuroFeaturesNamespace
https://paiwise.tagroot.io/Schema/NeuroFeatures.xsd
Paiwise processor, processing payment instructions defined in smart contracts.
const string PaymentInstructionsNamespace
https://paiwise.tagroot.io/Schema/PaymentInstructions.xsd
Contains information about a payment instruction.
DateTime? Processed
When object was successfully processed.
PubSub component, as defined in XEP-0060. https://xmpp.org/extensions/xep-0060.html
Provides the user configuration options regarding peer-review of new legal identities.
static PeerReviewConfiguration Instance
Current instance of configuration.
Abstract base class for agent resources
Service Module hosting the XMPP broker and its components.
static NamespaceSet GetVersion(string Namespace)
Gets the namespace set version corresponding to a given a namespace.
static bool Verify(byte[] Data, byte[] Signature)
Verifies a digital signature, supposedly made by the ledger.
static byte[] Sign(byte[] Data)
Signs data with the private key of the ledger.
static LedgerConfiguration Instance
Current instance of configuration.
byte[] PublicKey
Public key used to validate signatures.
Interface for authentication results
KeyValuePair< string, object >[] Tags
Tags annotating the error message.
ErrorType ErrorType
Type of error.
string ErrorLanguage
Optional language of error message
string ErrorMessage
Optional Error message
string ErrorCode
Optional Machine-readable error code.
bool? Result
true = authentication successful false = authentication rejected null = unable to perform authenticat...
Interface for identity applications.
Interface for currency converter services
Task< IAuthenticationResult > IsValid(KeyValuePair< string, object >[] Identity, IEnumerable< IPhoto > Photos)
Checks the veracity of identity claims.
Interface for currency converter service providers
IPeerReviewServiceProvider PeerReviewServiceProvider
Reference to service provider.
Task< IAuthenticationResult > IsValid(Waher.Networking.XMPP.Contracts.EventArguments.SignaturePetitionEventArgs PeerReivewRequest, ClientUrlEventHandler ClientUrlCallback, object State)
Checks the veracity of identity claims.
bool External
If the PeerReviewerLegalId is an external legal identity (true), or represents the neuron itself (fal...
string PeerReviewerLegalId
Legal ID of peer reviewer
Interface for peer-review service providers.
Task< IPeerReviewService > GetServiceForPeerReview(string ServiceId, KeyValuePair< string, object >[] Identity)
Gets a peer-review service.
string Id
ID of service provider.
int IconWidth
Width of icon, if available.
string IconUrl
Optional URL to icon of service provider.
int IconHeight
Height of icon, if available.
string Name
Displayable name of service provider.
Basic interface for Internet Content getters. A class implementing this interface and having a defaul...
string RemoteEndpoint
Remote endpoint.
Abstract base class for End-to-End encryption schemes.
bool Verify(byte[] Data, byte[] Signature)
Verifies a signature.
Interface for XMPP user accounts.
Interface for client connections.
PresenceEventArgs LastPresence
Last presence received.
bool CheckLive()
Checks if the connection is live.
Interface for identifiable legal objects
class Photo(byte[] Binary, int Rotation)
Class containing information about a photo.
RemovedReason
Reason for removing the item.
Prefix
SI prefixes. http://physics.nist.gov/cuu/Units/prefixes.html
ContentType
DTLS Record content type.
HashFunction
Hash method enumeration.
EDalerUriErrorType
Type of URI Error
ContentIntegrity
Result of a contract content integrity check.
ProtectionLevel
Parameter protection levels
ContractState
Recognized contract states
ContractVisibility
Visibility types for contracts.
ContractParts
How the parts of the contract are defined.
IdentityState
Lists recognized legal identity states.
NamespaceSet
Namespace versions
Represents a duration value, as defined by the xsd:duration data type: http://www....
int Years
Number of years.
static bool TryParse(string s, out Duration Result)
Tries to parse a duration value.
static readonly Duration Zero
Zero value
static Duration GetDurationBetween(System.DateTime From, System.DateTime To)
Calculates the duration between two dates.