How to find prevent ResourceManager to default back to default Resource file? - c#

Ive got some code which works somehow good, with except of one tiny little problem.
I have 3 resource files:
- Resource.da.resx (cultureID = 6)
-Resource.en.resx (cultureID = 9)
-Resource.resx - default
If browser loads and it would like to have "en" or "en-US" culture, this method works fine. However if i ask for german ("de") culture getResourceSet returns default Resource set, which i would like to prevent, to just find out that this resource set is not available. Can it be done?
public bool doesCultureExist(string cultureName)
{
try
{
global::System.Resources.ResourceManager rm =
new global::System.Resources.ResourceManager("Resources.Resource", global::System.Reflection.Assembly.Load("App_GlobalResources"));
var cult = CultureInfo.GetCultureInfo(cultureName);
ResourceSet rs = rm.GetResourceSet(cult, true, true);
if (rs != null)
{
return true;
}
else { return false; }
}
catch
{
return false;
}
}

Have you tried passing a false as the third .GetResourceSet() parameter (tryParents), like:
ResourceSet rs = rm.GetResourceSet(cult, true, false);
?

Related

C# How to get the AD user cannot change the password property from LDAP attribute userAccountControl?

I am trying to get the user account control properties using library Novell.Directory.Ldap in ASP .NET Core 5. When I search the users attributes I found the attribute name userAccountControl which is set to some number. After searching solution I am able to find:
bool isUserActive = false;
bool userMustChangePassword = false;
bool passwordNeverExpires = false;
bool passwordCannotBeChanged = false;
var flags = Convert.ToInt32(attributeSet.GetAttribute("userAccountControl").StringValue);
isUserActive = !Convert.ToBoolean(flags & 0x0002); //1. checks if user is enabled
if ((flags == 66048)) //65536+512
{
passwordNeverExpires = true; //2. Password never expires property
}
long value = Convert.ToInt64(attributeSet.GetAttribute("pwdLastSet").StringValue);
if (value == 0)
{
userMustChangePassword = true; //3. User must change password at next login
}
But I am not able to figure out how to get the User cannot change password and if the account is locked properties? Or how can I compare the binary value like 0x0040? Please help
Edit:
I tried the steps given by #Gabriel Luci in https://www.gabescode.com/active-directory/2019/07/25/nt-security-descriptors.html and tried following code:
var act = attributeSet.GetAttribute("nTSecurityDescriptor").ByteValue;
ADsSecurityUtility secUtility = new ADsSecurityUtility();
IADsSecurityDescriptor convertAttrToSD = (IADsSecurityDescriptor)secUtility.ConvertSecurityDescriptor(act, (int)ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_RAW, (int)ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_IID);
var byteArray = (byte[])secUtility.ConvertSecurityDescriptor(
convertAttrToSD,
(int)ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_IID,
(int)ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_RAW
);
var security = new CommonSecurityDescriptor(true, true, byteArray, 0);
If I check the security it shows
I am not getting where to look user cannot change the password settings?
Edit 2:
According to #Gabriel Luci updated answer, it worked for me like this:
var constraints = new LdapSearchConstraints();
constraints.SetControls(new LdapControl("1.2.840.113556.1.4.801", true, new byte[] { 48, 3, 2, 1, 7 }));
var getNtSecurityByteValue=attributeSet.GetAttribute("nTSecurityDescriptor").ByteValue;
var security = new CommonSecurityDescriptor(true, true, getNtSecurityByteValue, 0);
var self = new SecurityIdentifier(WellKnownSidType.SelfSid, null);
var userChangePassword = new Guid("AB721A53-1E2F-11D0-9819-00AA0040529B");
foreach (var ace in security.DiscretionaryAcl)
{
if(ace.GetType().Name == "ObjectAce")
{
ObjectAce objAce = (ObjectAce)ace;
if (objAce.AceType == AceType.AccessDeniedObject && objAce.SecurityIdentifier == self && objAce.ObjectAceType == userChangePassword)
{
cannotChangePassword = true;
break;
}
}
}
The userAccountControl value is a bit flag, meaning that every bit in the binary representation of the number is an "on" or "off" depending on if it's a 1 or 0. So the decimal value is meaningless.
You are already checking the value properly when you're checking if it's enabled:
isUserActive = !Convert.ToBoolean(flags & 0x0002); //1. checks if user is enabled
Likewise, you should do the same when checking any of the other flags. The value of each is listed in the documentation.
When you're checking if the password is set to never expire, you're comparing the decimal value, which won't always give you a correct answer. Instead, check the bit value:
passwordNeverExpires = Convert.ToBoolean(flags & 0x10000);
Similar for account is locked:
var accountLocked = Convert.ToBoolean(flags & 0x0010);
For the user cannot change password setting, unfortunately that's more difficult and requires reading the permissions on the user account, which I have never done using the Novell.Directory.Ldap library. But I can try to point you in the right direction.
The account permissions are in the nTSecurityDescriptor attribute. Read this issue about how to get the byte array from that attribute: How to read/set NT-Security-Descriptor attributes?
I wrote an article about how to get the byte array into a usable format: Active Directory: Handling NT Security Descriptor attributes.
Then you'll be looking for two permissions that get added when the 'User cannot change password' checkbox is checked:
Deny Change Password to 'Everyone'
Deny Change Password to 'SELF'
You can probably get away with only looking for #2.
Update: I finally tried this out for myself. I had never used the Novell.Directory.Ldap library before, so this was new to me.
With the help of this answer, I figured out that you need to set an LDAP control for it to return the nTSecurityDescriptor attribute at all:
var constraints = new LdapSearchConstraints();
constraints.SetControls(new LdapControl("1.2.840.113556.1.4.801", true
, new byte[] {48, 3, 2, 1, 7}));
Once you retrieve the object, you can check the permissions like this:
var byteValue = attributeSet.GetAttribute("nTSecurityDescriptor").ByteValue;
var security = new CommonSecurityDescriptor(true, true, byteValue, 0);
var self = new SecurityIdentifier(WellKnownSidType.SelfSid, null);
var userChangePassword = new Guid("AB721A53-1E2F-11D0-9819-00AA0040529B");
var cannotChangePassword = false;
foreach (var ace in (security.DiscretionaryAcl)) {
if (ace is ObjectAce objAce && objAce.AceType == AceType.AccessDeniedObject
&& objAce.SecurityIdentifier == self && objAce.ObjectAceType == userChangePassword) {
cannotChangePassword = true;
break;
}
}
The GUID of the User-Change-Password permission is taken from the Control Access Rights documentation.
Notice that you don't need to use IADsSecurityDescriptor, and thus you don't need a reference to Interop.ActiveDs. This is because we're given the value as a byte array already.

CefSharp ignores Preferences set with RequestContext (Spellcheck)

I try to enable spell check for the CefSharp Chromium embedded browser (v3.3396.1786 installed with NuGet) and the CefSharp.WPF component (v67). I can get spell check to work with a single language but I'm not able to change the dictionary for spellchecking at runtime. I tried the examples shown and linked on CefSharps github page but without success.
My CefSharp browser always uses the the Locale to determine the language to use for spell checking no matter what I set with RequestContext.SetPreference()
This is my code which initializes Cef:
public static void Initialize()
{
var settings = new CefSettings
{
BrowserSubprocessPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
Environment.Is64BitProcess ? "x64" : "x86",
"CefSharp.BrowserSubprocess.exe"),
Locale = "de-DE",
RemoteDebuggingPort = 8088,
};
// Set BrowserSubProcessPath based on app bitness at runtime
// Make sure you set performDependencyCheck false
Cef.Initialize
(
settings,
performDependencyCheck: false,
browserProcessHandler: null
);
CefSharpSettings.LegacyJavascriptBindingEnabled = true;
}
The actual browser is set up and created in another method:
private void create_web_browser()
{
current_web_browser = new ChromiumWebBrowser
{
Visibility = Visibility.Hidden,
BrowserSettings = new BrowserSettings
{
FileAccessFromFileUrls = CefState.Enabled,
UniversalAccessFromFileUrls = CefState.Enabled,
Javascript = CefState.Enabled,
ImageLoading = CefState.Enabled,
JavascriptAccessClipboard = CefState.Enabled,
JavascriptCloseWindows = CefState.Enabled,
JavascriptDomPaste = CefState.Enabled
}
};
current_helper = new ChromiumObjectForScriptingHelper(web_browser_ready_async, current_web_browser);
if (ToolbarConfig != null)
{
current_helper.SetToolbarConfig(ToolbarConfig);
}
current_web_browser.RegisterJsObject("callbackObj", current_helper);
var cur_dir = Directory.GetCurrentDirectory();
var url = $"file://{cur_dir}/ckeditor/editor.html";
current_web_browser.Address = url;
current_web_browser.RequestContext = new RequestContext();
current_web_browser.RequestContext.SetPreference("browser.enable_spellchecking", true, out _);
current_web_browser.RequestContext.SetPreference("spellcheck.dictionaries", new List<string> { "en-US" }, out _);
grid.Children.Add(current_web_browser);
}
An additional method is used to enable the user to change language later:
public void SetSpellcheck(Spellcheck language)
{
if (language == Spellcheck.None) return;
current_web_browser.RequestContext.SetPreference("spellcheck.dictionaries", new List<string> { get_locale_for_language(language) }, out _);
}
As you can see I try to set the spell checking settings but no matter what I set there, it has no effect. I could set enable_spellcheckto false and it still checks the spelling and the dictionaries I set are also ignored. Instead of what I put in dictionaries, the language previously set in Locale will be used. (I checked the out variable but there were no errors)
I also tried using the global RequestContext but with no success.
Apparently other people got it to work somehow so I'm feeling like I miss something important here, or doing something completely stupid.
Another thing is that, if I use GetAllPreferences(true), to get a list of all the settings with defaults, I just get null.
Thanks to #amaitlands's comments I now know that the issue was that I was setting the preferences in the wrong thread. I had the misconception that CefSharp was running in my applications UI-Thread, when it actually was running in its own.
The solution is to use Cef.UIThreadTaskFactory.StartNew() to run the code inside of the CefSharp UI-Thread
Cef.UIThreadTaskFactory.StartNew(delegate
{
current_web_browser.RequestContext.SetPreference("browser.enable_spellchecking", true, out _);
current_web_browser.RequestContext.SetPreference("spellcheck.dictionaries", new List<object> { "en-US" }, out _);
});
I also had to change the type of the List<> to object since I'm using an older version of CefSharp.WPF otherwise I'd get a Trying to set a preference of type LIST to value of type NULL error.

Is there a general way of getting which hour format (12/24) the device is using?

I have seen this question where OP asks if there's a way to check which hour format the device is using for iOS. The selected answer also has the solution for Android. However, in my xamarin.forms application, I cannot build or run the app in iOS because I get Java.Interop missing error. I'm writing a simple method to return bool if its using 12 hour format.
public bool GetHourFormat()
{
bool TwelveHourFormat = true;
if (Device.RuntimePlatform == "iOS")
{
var dateFormatter = new NSDateFormatter();
dateFormatter.DateStyle = NSDateFormatterStyle.None;
dateFormatter.TimeStyle = NSDateFormatterStyle.Short;
var dateString = dateFormatter.ToString(NSDate.Now);
TwelveHourFormat =
dateString.Contains(dateFormatter.AMSymbol) ||
dateString.Contains(dateFormatter.PMSymbol);
}
else if (Device.RuntimePlatform == "Android")
{
TwelveHourFormat = Android.Text.Format.DateFormat.Is24HourFormat(Android.App.Application.Context);
}
return TwelveHourFormat;
}
Is there any general way to get this information without relying on platform? If not, how can I get this information in both platforms?
I will use Preprocessor, so only platform specific are compiled depending on the platform (Android / iOS) you are using.
private bool CheckIsTwelveTimeFormat()
{
#if __ANDROID__
// code in this #if block is only compiled on Android
return !Android.Text.Format.DateFormat.Is24HourFormat(Android.App.Application.Context);
#elif __IOS__
// code in this #elif block is only compiled on iOS
var dateFormatter = new Foundation.NSDateFormatter {
DateStyle = Foundation.NSDateFormatterStyle.None,
TimeStyle = Foundation.NSDateFormatterStyle.Short
};
var dateString = dateFormatter.ToString(Foundation.NSDate.Now);
var isTwelveHourFormat =
dateString.Contains(dateFormatter.AMSymbol) ||
dateString.Contains(dateFormatter.PMSymbol);
return isTwelveHourFormat;
#endif
}

How do I set my Oracle session's globalization to be the same as Windows in .NET?

For example, it would be great if I could do the following:
private void SetSessionGlobalization(Oracle.DataAccess.Client.OracleConnection aConnection)
{
System.Globalization.CultureInfo lCultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture;
aConnection.SetSessionInfo(lCultureInfo);
}
But that does not work because SetSessionInfo takes a OracleGlobalization class as a parameter, not a CultureInfo!
And this does not work either:
private void SetSessionGlobalization(Oracle.DataAccess.Client.OracleConnection aConnection)
{
Oracle.DataAccess.Client.OracleGlobalization lClientGlobalization = Oracle.DataAccess.Client.OracleGlobalization.GetClientInfo());
aConnection.SetSessionInfo(lClientGlobalization);
}
Because GetClientInfo gets Oracle's version of the client globalization settings, not Windows.
What am I missing here? How do I set my database connection session to be the same as that used by my thread (which will be the same as Windows by default)?
I think you have to assign each property manually.
It would be like this.
private void SetSessionGlobalization(Oracle.DataAccess.Client.OracleConnection aConnection)
{
OracleGlobalization info = aConnection.GetSessionInfo();
System.Globalization.CultureInfo lCultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture;
var ri = new System.Globalization.RegionInfo(lCultureInfo.LCID);
info.Calendar = lCultureInfo.Calendar.GetType().Name.Replace("Calendar", String.Empty);
info.Currency = ri.CurrencySymbol;
info.DualCurrency = ri.CurrencySymbol;
info.ISOCurrency = ri.ISOCurrencySymbol;
info.DateFormat = lCultureInfo.DateTimeFormat.ShortDatePattern + " " + lCultureInfo.DateTimeFormat.ShortTimePattern.Replace("HH", "HH24").Replace("mm", "mi");
info.DateLanguage = System.Text.RegularExpressions.Regex.Replace(lCultureInfo.EnglishName , #" \(.+\)",String.Empty);
info.NumericCharacters = lCultureInfo.NumberFormat.NumberDecimalSeparator + lCultureInfo.NumberFormat.NumberGroupSeparator;
info.TimeZone = String.Format("{0}:{1}", TimeZoneInfo.Local.BaseUtcOffset.Hours, TimeZoneInfo.Local.BaseUtcOffset.Minutes);
info.Language = ...
info.Territory = ...
info.TimeStampFormat = ...
info.TimeStampTZFormat = ...
try {
aConnection.SetSessionInfo(info);
} catch ( OracleException err ) {
MessageBox.Show(err.Message);
}
}
You have to to several kind of translations, e.g. for Date format or Region/Language. I hope you got an idea how to do it.
Note some (important) settings (e.g. ClientCharacterSet) are Read/only, these values are derived from Registry or Environment variables and are set while opening the connection.
So, the preferred way is to use Registry or Environment variables, then you don't have to set OracleGlobalization.

Write In Config File Problem

hi
this code works fine and my config file changes correctly.
//Local Variable Declaration
System.Configuration.Configuration oConfig =
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(
Request.ApplicationPath);
if (oConfig .AppSettings.Settings["CompanyName"] == null)
{
oConfig AppSettings.Settings.Add("CompanyName", "MyCompanyName");
oConfig .Save();
}
but when I want to use a property for this purpose Nothing happend in Config File.
// Property Declaration
private System.Configuration.Configuration _oRootConfig;
public System.Configuration.Configuration oRootConfig
{
get
{
return
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(
Request.ApplicationPath);
}
set { _oRootConfig = value; }
}
if (oRootConfig.AppSettings.Settings["CompanyName"] == null)
{
oRootConfig.AppSettings.Settings.Add("CompanyName", "MyCompanyName");
oRootConfig.Save(System.Configuration.ConfigurationSaveMode.Modified, true);
}
now i have two question:
1-why this code doesnot work ,and there
is no error.
2-if i want to programn in object oriented
manner ,what can i do to fix this property
if the problem is related to the property.
thanks
You're reopening the config on every get, do this instead:
get
{
if(this._oRootConfig == null)
this._oRootConfig = (System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath));
return this._oRootConfig;
}
this line of code:
get
{
return (System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath));
}
set { _oRootConfig = value; }
you are not setting _oRootConfig in your get. You need this code:
get
{
_oRootConfig = (System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath));
return _oRootConfig;
}
set
{
_oRootConfig = value;
}

Categories