protected override void ImportData(XmlNode fieldNode) { XmlAttribute attachmentAttr = fieldNode.Attributes["attachment"]; BinaryData binaryData = this.GetData() as BinaryData; if (binaryData == null) { binaryData = new BinaryData(); } if (attachmentAttr == null) { binaryData.SetStream(RepositoryTools.GetStreamFromString(fieldNode.InnerXml)); binaryData.FileName = String.Concat(this.Content.ContentHandler.Name, ".", this.Name, ".txt"); } else { binaryData.FileName = attachmentAttr.Value.Replace("$amp;", "&"); var stream = Stream.Null; if (stream == null) { return; } binaryData.SetStream(stream); } this.SetData(binaryData); }
public void Apply() { foreach (var resourceBuilder in ResourceContentBuilders) { var resourcePath = RepositoryPath.Combine(RepositoryStructure.ResourceFolderPath, resourceBuilder.ContentName); var resource = Node.Load <Resource>(resourcePath) ?? Node.Load <Resource>(resourcePath + ".xml"); // create resource content if necessary if (resource == null) { resource = new Resource(Node.LoadNode(RepositoryStructure.ResourceFolderPath)) { Name = resourceBuilder.ContentName }; var binData = new BinaryData { FileName = new BinaryFileName(resourceBuilder.ContentName) }; binData.SetStream(RepositoryTools.GetStreamFromString(EmptyResource)); resource.Binary = binData; resource.Save(); //TODO: log! //context.Console.WriteLine("NEW resource content: {0}", resource.Path); } EditResource(resource, resourceBuilder); } }
protected async Task <User> CreateUser(string nameCandidate, string loginName, string email, string fullName, Action <Content> setProperties, CancellationToken cancellationToken) { var parentPath = string.IsNullOrEmpty(_options.ParentPath) ? "/Root/IMS/Public" : _options.ParentPath; var userType = string.IsNullOrEmpty(_options.UserType) ? "User" : _options.UserType; var parent = RepositoryTools.CreateStructure(parentPath, "Domain") ?? await Content.LoadAsync(parentPath, cancellationToken).ConfigureAwait(false); // If a user with the same name exists, make sure we create // a new one and let the application deal with merging them later. var name = ContentNamingProvider.GetNameFromDisplayName(nameCandidate); if (Node.Exists(RepositoryPath.Combine(parent.Path, name))) { name = ContentNamingProvider.IncrementNameSuffixToLastName(name, parent.Id); } var user = Content.CreateNew(userType, parent.ContentHandler, name); user["LoginName"] = loginName; user["Email"] = email; user["FullName"] = string.IsNullOrEmpty(fullName) ? name : fullName; user.DisplayName = string.IsNullOrEmpty(fullName) ? name : fullName; user["Enabled"] = true; setProperties?.Invoke(user); user.Save(); await AddUserToDefaultGroupsAsync(user.ContentHandler as User, cancellationToken).ConfigureAwait(false); return(user.ContentHandler as User); }
private void CreateProfileTemplate() { RepositoryTools.CreateStructure("/Root/ContentTemplates/UserProfile", "SystemFolder"); RepositoryTools.CreateStructure("/Root/ContentTemplates/UserProfile/UserProfile", "UserProfile"); RepositoryTools.CreateStructure("/Root/ContentTemplates/UserProfile/UserProfile/DocLib", "DocumentLibrary"); RepositoryTools.CreateStructure("/Root/ContentTemplates/UserProfile/UserProfile/DocLib/f1/f2", "Folder"); }
public override void Initialize(Content context, string backUri, Application application, object parameters) { base.Initialize(context, backUri, application, parameters); if (context == null) { this.Visible = false; return; } // if the Views folder does not exist, we have to create it // (but only in case of a content list) var cl = ContentList.GetContentListByParentWalk(context.ContentHandler); if (cl != null) { var viewsFolderPath = RepositoryPath.Combine(cl.Path, ViewManager.VIEWSFOLDERNAME); if (!Node.Exists(viewsFolderPath)) { using (new SystemAccount()) { RepositoryTools.CreateStructure(viewsFolderPath, "SystemFolder"); } } } }
public void MultiStep_Existing_Incremental_CSrv() { Test(() => { var root = CreateTestRoot(); var file = new File(root) { Name = "test.txt" }; file.Binary.SetStream(RepositoryTools.GetStreamFromString("test file")); file.Save(); // ACTION: create a new file with the same name var expected = "new file content"; var file2 = new File(root) { Name = file.Name }; file2.Binary.SetStream(RepositoryTools.GetStreamFromString(expected)); // this should prevent the exception and simply generate a new name file2.AllowIncrementalNaming = true; // this is normal in case of chunk upload, it should not throw an exception file2.Save(SavingMode.StartMultistepSave); file2.FinalizeContent(); // ASSERT: Do not throw any exception and file is saved var loaded = Node.Load <File>(file2.Id); var actual = RepositoryTools.GetStreamString(loaded.Binary.GetStream()); Assert.AreEqual(expected, actual); }); }
public override string EvaluateTemplate(string templateName, string templateExpression, object templatingContext) { switch (templateName) { case "currentdate": return(DateTime.Today.ToShortDateString()); case "currenttime": return(EvaluateExpression(DateTime.UtcNow, templateExpression, templatingContext)); case "currentuser": return(EvaluateExpression(User.Current as GenericContent, templateExpression, templatingContext)); case "fullname": return(TemplateManager.GetProperty(User.Current as GenericContent, "FullName")); case "email": return(TemplateManager.GetProperty(User.Current as GenericContent, "Email")); case "ipaddress": return(RepositoryTools.GetClientIpAddress()); default: return(base.EvaluateTemplate(templateName, templateExpression, templatingContext)); } }
private static void CheckExecutableType(NodeHead nodeHead, string actioName) { if (nodeHead == null) { return; } // check if the extension interests us if (!RepositoryTools.IsExecutableExtension(Path.GetExtension(nodeHead.Name))) { return; } // If this is not an action request: if the extension indicates an executable file, // but the type is wrong OR the user does not have Run application // permission: rewrite the action to simply return the text of the file. if (string.IsNullOrEmpty(actioName) && (!RepositoryTools.IsExecutableType(nodeHead.GetNodeType()) || !SecurityHandler.HasPermission(nodeHead, PermissionType.RunApplication))) { PortalContext.Current.ActionName = "BinarySpecial"; // Workaround: at this point we cannot change the action in any other way: we need // to rewrite the context to point to the binary highlighter page instead of the // executable content itself. This is how we prevent executing the file and allow // only showing the text content of the file (if Open permission is present). var action = HttpActionManager.CreateAction(PortalContext.Current); action.Execute(); } }
private void HackDatabaseForMorePermissiveLoadTest(string contentTypeName, string oldCtd, string newCtd) { // Get related data row (FileDoc of the InMemoryDatabase) var dataProvider = (InMemoryDataProvider)Providers.Instance.DataProvider; var db = dataProvider.DB; var fileRow = db.Files.First(x => x.FileNameWithoutExtension == contentTypeName); // Get blob id var bp = (InMemoryBlobProvider)Providers.Instance.BlobStorage.GetProvider(0); var data = (InMemoryBlobProviderData)bp.ParseData(fileRow.BlobProviderData); // Get and check the old CTD from the related blob var bpAcc = new ObjectAccessor(bp); var blobs = (Dictionary <Guid, byte[]>)bpAcc.GetField("_blobStorage"); var oldBuffer = blobs[data.BlobId]; Assert.AreEqual(oldCtd, RepositoryTools.GetStreamString(new MemoryStream(oldBuffer))); // Change the related blob to the invalid CTD var stream = (MemoryStream)RepositoryTools.GetStreamFromString(newCtd); var newBuffer = new byte[stream.Length]; var newStream = new MemoryStream(newBuffer); stream.CopyTo(newStream); fileRow.Buffer = newBuffer; fileRow.Size = newBuffer.Length; }
public void Search_ReferenceField() { IntegrationTest(() => { ContentTypeInstaller.InstallContentType(CtdSearchTestReference); var parent = RepositoryTools.CreateStructure("/Root/" + Guid.NewGuid(), "SystemFolder"); var folder1 = Content.CreateNew("Folder", parent.ContentHandler, "f1"); folder1.SaveSameVersion(); var folder2 = Content.CreateNew("Folder", parent.ContentHandler, "f2"); folder2.SaveSameVersion(); var folder3 = Content.CreateNew("Folder", parent.ContentHandler, "f3"); folder3.SaveSameVersion(); var content1 = Content.CreateNew("GenericContentWithReferenceTest", parent.ContentHandler, "content1"); content1["SearchTestReference"] = new[] { folder1.ContentHandler, folder2.ContentHandler, folder3.ContentHandler }; content1.SaveSameVersion(); // find content by the reference field var result1 = CreateSafeContentQuery($"+SearchTestReference:{folder1.Id}").Execute().Nodes.FirstOrDefault(); var result2 = CreateSafeContentQuery($"+SearchTestReference:{folder2.Id}").Execute().Nodes.FirstOrDefault(); var result3 = CreateSafeContentQuery($"+SearchTestReference:{folder3.Id}").Execute().Nodes.FirstOrDefault(); Assert.IsNotNull(result1); Assert.IsNotNull(result2); Assert.IsNotNull(result3); Assert.AreEqual(content1.Id, result1.Id); Assert.AreEqual(content1.Id, result2.Id); Assert.AreEqual(content1.Id, result3.Id); }); }
private void ExecuteOnContent(ExecutionContext context) { context.AssertRepositoryStarted(); var path = (string)context.ResolveVariable(Path); var content = Content.Load(path); var data = content[Field ?? "Binary"]; BinaryData binaryData = null; var text = data as string; if (text == null) { binaryData = data as BinaryData; if (binaryData != null) { using (var r = new StreamReader(binaryData.GetStream())) text = r.ReadToEnd(); } } text = Edit(text, context); if (binaryData != null) { binaryData.SetStream(RepositoryTools.GetStreamFromString(text)); } else { content[Field] = text; } content.SaveSameVersion(); }
private void CreateFileTest(string fileName, string expectedMimeType, string fileContent = null, bool searchable = false) { Test(() => { var root = CreateTestRoot(); var file = new File(root) { Name = fileName }; file.Save(); if (fileContent != null) { file.Binary.SetStream(RepositoryTools.GetStreamFromString(fileContent)); file.Save(); } // check mime type file = Node.Load <File>(file.Id); Assert.AreEqual(expectedMimeType, file.Binary.ContentType); // check searchability if (fileContent != null && searchable) { var queryResult = CreateSafeContentQuery(fileContent.Split(' ')[1]).Execute(); Assert.AreEqual(1, queryResult.Count); } }); }
private void EditResource(Resource resource, ResourceContentBuilder builder) { // load resource xml from repository var xDoc = new XmlDocument(); using var resStream = resource.Binary.GetStream(); xDoc.Load(resStream); foreach (var classBuilder in builder.Classes) { // load or create the class element var resClassElement = LoadOrAddElement(xDoc.DocumentElement, $"ResourceClass[@name='{classBuilder.ClassName}']", "ResourceClass", new Dictionary <string, string> { { "name", classBuilder.ClassName } }, @"<Languages></Languages>"); foreach (var cultureBuilder in classBuilder.Cultures) { foreach (var resourceItem in cultureBuilder.Resources) { // main operation: add or modify xml elements for one resource AddOrEditResource(resClassElement, cultureBuilder.CultureName, resourceItem.Key, resourceItem.Value); } } } // save the resource content using var modifiedStream = RepositoryTools.GetStreamFromString(xDoc.OuterXml); resource.Binary.SetStream(modifiedStream); resource.Save(SavingMode.KeepVersion); }
protected void LoginControll_LoggedIn(object sender, EventArgs e) { var targetUrl = GetPostLoginUrl(); var userName = ((Login)sender).UserName; if (this._ssoEnabled) { this.GetCookie().Value = CryptoApi.Crypt(userName, "sensenet60beta1", "SenseNetContentRepository"); } if (OnUserLoggedIn != null) { OnUserLoggedIn(sender, e); } SnLog.WriteAudit(AuditEvent.LoginSuccessful, new Dictionary <string, object> { { "UserName", userName }, { "ClientAddress", RepositoryTools.GetClientIpAddress() } }); LoginExtender.OnLoggedIn(new LoginInfo { UserName = userName }); HttpContext.Current.Response.Redirect(targetUrl); }
private void SetBinaryDataProperties(BinaryData data, FileUpload fileUpload, ITextControl editor) { if (editor == null) { return; } var textMode = ((TextBox)editor).Visible; if (textMode) { data.SetStream(RepositoryTools.GetStreamFromString(editor.Text)); } else { if (fileUpload != null && fileUpload.HasFile) { var fileStream = fileUpload.PostedFile.InputStream; var contentType = fileUpload.PostedFile.ContentType; var fileName = fileUpload.PostedFile.FileName; data.ContentType = contentType; data.FileName = fileName; data.SetStream(fileStream); } } }
private void DeleteBinaryPropertyTest(string fileContent, int sizeLimit) { using (new SystemAccount()) using (new SizeLimitSwindler(this, sizeLimit)) { var testRoot = CreateTestRoot(); var file = new File(testRoot) { Name = "File1.file" }; file.Binary.SetStream(RepositoryTools.GetStreamFromString(fileContent)); file.Save(); var fileId = file.Id; file = Node.Load <File>(fileId); // action file.Binary = null; file.Save(); // assert var dbFiles = BlobStoragePlatform.LoadDbFiles(file.VersionId); Assert.AreEqual(0, dbFiles.Length); } }
// ================================================================================================ Public methods /// <summary> /// Gets Binary of a Content Repository File in a string. /// </summary> /// <param name="filePath"></param> /// <returns></returns> public static string GetMarkupString(string filePath) { var skinResolvedPath = SkinManager.Resolve(filePath); // Elevation: post and comment markup files should not be // visible to users. Please Control post and comment // visibility by assigning permissions to // post and comment content. using (new SystemAccount()) { var file = Node.Load <SNCR.File>(skinResolvedPath); if (file == null) { return(null); } string markupStr = null; using (var stream = file.Binary.GetStream()) { markupStr = RepositoryTools.GetStreamString(stream); } return(markupStr); } }
protected override object GetModel() { string subscriptionCtd; using (new SystemAccount()) { var ctdFile = Node.LoadNode("/Root/System/Schema/ContentTypes/GenericContent/Subscription") as ContentType; if (ctdFile != null) { using (var ctdStream = ctdFile.Binary.GetStream()) { subscriptionCtd = RepositoryTools.GetStreamString(ctdStream); } } else { throw new InvalidOperationException("Subscription CTD not found."); } } var currentSite = PortalContext.Current.Site; var siteUrl = PortalContext.Current.SiteUrl; if (this.User == null) { return(null); } // edit subscription or create new if not exists var subscription = Subscription.GetSubscriptionByUser(this.User.Path, this.ContentPath); if (subscription != null) { IsSubscriptionNew = false; } else { subscription = new Subscription() { ContentPath = this.ContentPath, Frequency = NotificationFrequency.Immediately, IsActive = true, UserEmail = this.User.Email, UserPath = this.User.Path, UserId = this.User.Id, UserName = this.User.Name, Language = "en", SitePath = currentSite?.Path, SiteUrl = siteUrl }; IsSubscriptionNew = true; } var sct = Content.Create(subscription, subscriptionCtd); var rch = sct.ContentHandler as Content.RuntimeContentHandler; rch?.SetIsNew(IsSubscriptionNew); return(sct); }
public static void Main(string[] args) { var builder = CreateWebHostBuilder(args); var host = builder.Build(); SnTrace.EnableAll(); using (InMemoryExtensions.StartInMemoryRepository(repositoryBuilder => { repositoryBuilder .UseAccessProvider(new UserAccessProvider()) .UseLogger(new SnFileSystemEventLogger()) .UseTracer(new SnFileSystemTracer()); })) { using (new SystemAccount()) { // FOR TESTING PURPOSES: create a default user with a well-known password // login: [email protected] // password: Edvin123% var parentPath = "/Root/IMS/BuiltIn/Temp"; var parent = RepositoryTools.CreateStructure(parentPath, "OrganizationalUnit"); var user = new User(parent.ContentHandler) { Name = "edvin-example.com", LoginName = "*****@*****.**", PasswordHash = "AQAAAAEAACcQAAAAEKEsynr6baKE5rYqS4Rn6pjqckl+NG4W9UQqqGh4g23zlJQpQvnaZnzx44+z78FVsg==", Email = "*****@*****.**" }; user.Save(); // set the new user as administrator Group.Administrators.AddMember(user); // create a container for test content parent = RepositoryTools.CreateStructure("/Root/MyContent", "SystemFolder"); // create a doclib that contains a file var docLib = RepositoryTools.CreateStructure("/Root/MyContent/MyFiles", "DocumentLibrary"); ((GenericContent)docLib.ContentHandler).AllowChildType("Image", save: true); var file = new File(docLib.ContentHandler) { Name = "testfile.txt" }; file.Binary.SetStream(RepositoryTools.GetStreamFromString($"temp text data {DateTime.UtcNow}")); file.Save(); //var installer = new Installer(); //installer.Import("C:\\temp\\import\\Root"); } SnTrace.EnableAll(); host.Run(); } }
protected override bool ParseValue(string value) { var binaryData = new BinaryData(); binaryData.SetStream(RepositoryTools.GetStreamFromString(value)); this.SetData(binaryData); return(true); }
public OperationContext WopiSave(string lockValue, string newContent) { //WopiHandler.ProcessPutFileRequest(LoadTestFile(), lockValue, RepositoryTools.GetStreamFromString(newContent)); WopiMiddleware.ProcessPutFileRequestAsync(LoadTestFile(), lockValue, RepositoryTools.GetStreamFromString(newContent), CancellationToken.None) .ConfigureAwait(false).GetAwaiter().GetResult(); return(this); }
public OperationContext UpdateFileContent(string newContent) { var file = LoadTestFile(); file.Binary.SetStream(RepositoryTools.GetStreamFromString(newContent)); file.Save(); return(this); }
public void SharedLock_Save_CheckedOutForMe_Unlocked_Upload() { var newContent = "Dolor sit amet..."; var context = OperationContext.Create().Checkout().UpdateFileContent(newContent); Assert.AreEqual(newContent, RepositoryTools.GetStreamString(context.LoadTestFile().Binary.GetStream())); }
/// <summary> /// Logs out the current user. /// </summary> /// <param name="ultimateLogout">Whether this should be an ultimate logout. If set to True, the user will be logged out from all clients.</param> public static void Logout(bool ultimateLogout = false) { var user = User.Current; var info = new CancellableLoginInfo { UserName = user.Username }; LoginExtender.OnLoggingOut(info); if (info.Cancel) { return; } FormsAuthentication.SignOut(); AccessTokenVault.DeleteTokensByUser(user.Id); SnLog.WriteAudit(AuditEvent.Logout, new Dictionary <string, object> { { "UserName", user.Username }, { "ClientAddress", RepositoryTools.GetClientIpAddress() } }); LoginExtender.OnLoggedOut(new LoginInfo { UserName = user.Username }); if (HttpContext.Current != null) { if (HttpContext.Current.Session != null) { HttpContext.Current.Session.Abandon(); } // remove session cookie var sessionCookie = new HttpCookie(GetSessionIdCookieName(), string.Empty) { Expires = DateTime.UtcNow.AddDays(-1) }; HttpContext.Current.Response.Cookies.Add(sessionCookie); // in case of ultimate logout saves the time on user if (ultimateLogout || Configuration.Security.DefaultUltimateLogout) { using (new SystemAccount()) { if (user is User userNode) { userNode.LastLoggedOut = DateTime.UtcNow; userNode.Save(SavingMode.KeepVersion); } } } } }
public void SharedLock_Save_CheckedOutForMe_LockedSame_PutFile() { var newContent = "Dolor sit amet..."; var lockValue = "LCK_" + Guid.NewGuid(); var context = OperationContext.Create().Lock(lockValue).Checkout().WopiSave(lockValue, newContent); Assert.AreEqual(newContent, RepositoryTools.GetStreamString(context.LoadTestFile().Binary.GetStream())); }
private DbFile UpdateByChunksTest(string initialContent, string updatedText, int sizeLimit, int chunkSize) { using (new SystemAccount()) using (new SizeLimitSwindler(this, sizeLimit)) { var testRoot = CreateTestRoot(); var file = new File(testRoot) { Name = "File1.file" }; file.Binary.SetStream(RepositoryTools.GetStreamFromString(initialContent)); file.Save(); var fileId = file.Id; var chunks = SplitFile(updatedText, chunkSize, out var fullSize); file = Node.Load <File>(fileId); file.Save(SavingMode.StartMultistepSave); var token = BinaryData.StartChunk(fileId, fullSize); var offset = 0; foreach (var chunk in chunks) { BinaryData.WriteChunk(fileId, token, fullSize, chunk, offset); offset += chunkSize; } BinaryData.CommitChunk(fileId, token, fullSize); file = Node.Load <File>(fileId); file.FinalizeContent(); // assert var dbFiles = BlobStoragePlatform.LoadDbFiles(file.VersionId); Assert.AreEqual(1, dbFiles.Length); var dbFile = dbFiles[0]; if (NeedExternal(BlobStoragePlatform.ExpectedBlobProviderDataType, updatedText, sizeLimit)) { Assert.AreEqual(BlobStoragePlatform.ExpectedExternalBlobProviderType.FullName, dbFile.BlobProvider); Assert.IsNotNull(dbFile.BlobProviderData); } else { Assert.IsNull(dbFile.BlobProvider); Assert.IsNull(dbFile.BlobProviderData); } Assert.AreEqual(false, dbFile.IsDeleted); Assert.AreEqual(false, dbFile.Staging); Assert.AreEqual(0, dbFile.StagingVersionId); Assert.AreEqual(0, dbFile.StagingPropertyTypeId); Assert.AreEqual(fullSize, dbFile.Size); return(dbFile); } }
public void ContentType_MorePermissiveLoad_MissingBinding_Create() { Test(() => { var ctd0 = @"<ContentType name=""MyType1"" parentType=""GenericContent"" handler=""SenseNet.ContentRepository.GenericContent"" xmlns=""http://schemas.sensenet.com/SenseNet/ContentRepository/ContentTypeDefinition""> <Fields> <Field name=""Image2"" type=""Image""></Field> </Fields> </ContentType>"; var ctd1 = @"<ContentType name=""MyType1"" parentType=""GenericContent"" handler=""SenseNet.ContentRepository.GenericContent"" xmlns=""http://schemas.sensenet.com/SenseNet/ContentRepository/ContentTypeDefinition""> <Fields> <Field name=""ImageRef"" type=""Reference""></Field> <Field name=""ImageData"" type=""Binary""></Field> <Field name=""Image2"" type=""Image""> <Bind property=""ImageRef"" /> <Bind property=""ImageData"" /> </Field> </Fields> </ContentType>"; // ACTION-1: Try install an invalid CTD. try { //ContentTypeInstaller.InstallContentType(ctd0); var binaryData = new BinaryData(); binaryData.FileName = "MyType1"; binaryData.SetStream(RepositoryTools.GetStreamFromString(ctd0)); var contentType = new ContentType(ContentType.GetByName("GenericContent")) { Name = "MyType1", Binary = binaryData }; contentType.Save(); Assert.Fail("The expected exception was not thrown."); } catch (ContentRegistrationException e) { // do nothing } // ACTION-2: reinstall without any problem. ContentTypeInstaller.InstallContentType(ctd1); // ACTION-3: Reload schema from the database. Cache.Reset(); ContentTypeManager.Reload(); // ASSERT: the ContentType is loaded and valid. var myType1 = ContentType.GetByName("MyType1"); Assert.AreEqual(ctd1, myType1.ToXml()); Assert.IsFalse(myType1.IsInvalid); Assert.IsNotNull(myType1.FieldSettings.FirstOrDefault(x => x.Name == "Image2")); }); }
public void SharedLock_Save_CheckedOutForMe_Unlocked_PutFile() { var newContent = "Dolor sit amet..."; var lockValue = "LCK_" + Guid.NewGuid(); var context = OperationContext.Create().Checkout().WopiSave(lockValue, newContent); // expected result: file was not changed Assert.AreEqual(OperationContext.OriginalFileContent, RepositoryTools.GetStreamString(context.LoadTestFile().Binary.GetStream())); }
//[TestMethod] public void InitialData_CtdLoad() { InitialDataTest(() => { var fileContentType = ContentType.GetByName("File"); var ctd = RepositoryTools.GetStreamString(fileContentType.Binary.GetStream()); Assert.IsNotNull(ctd); Assert.IsTrue(ctd.Length > 10); }); }
private void WriteTextFileSettings(string settingsJson) { var settings = new SenseNet.ContentRepository.Settings(Node.LoadNode(Repository.SettingsFolderPath)) { Name = "TextFiles.settings" }; settings.Binary.SetStream(RepositoryTools.GetStreamFromString(settingsJson)); settings.Save(); }