C# Encode connection string from win1251 to utf8 and back - c#

I'm trying to work around the problem with connection string encoding in Firebird .net provider ver >= 5.6.0.0 (current is 5.8.0.0). The full description of the problem (if you are interested in) is here, but I think I could explain it briefly. So let's start! I have a system default encoding win1251 and a connection string that contains a param calls "DbPath" with value
"F:\\Рабочая\\БД\\2.14.1\\January_2017\\MYDB.IB"
When I pass this connection string to firebird .net provider it takes "DbPath" param from connection string and get bytes from its value using Encoding.UTF-8. That's how it looks in their code:
protected virtual void SendAttachToBuffer(DatabaseParameterBuffer dpb, string database)
{
XdrStream.Write(IscCodes.op_attach);
XdrStream.Write(0);
if (!string.IsNullOrEmpty(Password))
{
dpb.Append(IscCodes.isc_dpb_password, Password);
}
//database is DbPath
XdrStream.WriteBuffer(Encoding.UTF8.GetBytes(database));
XdrStream.WriteBuffer(dpb.ToArray());
}
As you see they don't convert encoding from win1251 to utf-8, they just get bytes using Encoding.UTF8.GetBytes();
And later in their code I see that they just get a string using current Encoding (Encoding.Default):
public string GetString(byte[] buffer, int index, int count)
{
//_encoding is Encoding.Default == win1251
return _encoding.GetString(buffer, index, count);
}
And the result of this lines of code is that I get an I/O Exception cause my DbPath becomes to
"F:\\Рабочая\\БД\\2.14.1\\January_2017\\MYDB.IB"
So the first thing that I've tried is to convert my connection string to utf-8
using this lines of code:
private static string Win1251ToUTF8(string source)
{
Encoding utf8 = Encoding.GetEncoding("utf-8");
Encoding win1251 = Encoding.GetEncoding("windows-1251");
byte[] win1251Bytes = win1251.GetBytes(source);
byte[] utf8bytes = Encoding.Convert(win1251, utf8, win1251Bytes);
source = utf8.GetString(utf8bytes);
return source;
//Actually I'm not sure that I'm converting Encoding correctly
}
But it didn't affect. I've tried many variants with Encoding.Convert but I've not a solution yet. Can someone tell me please what I'm doing wrong and how I can solve the problem. Regards.

I recommend you to try the following code, maybe it helps you. Create a new C# WindowsFormApplication, put a BIG multiline texBox "textBox1" and a button "button1" on it. In the button click handler put this code:
// ----- The work -------------------------------------------------
string source = "F:\\\\Рабочая\\\\БД\\\\2.14.1\\\\January_2017\\\\MYDB.IB";
Encoding utf8 = Encoding.UTF8;
Encoding unicode = Encoding.Unicode;
Encoding win1251 = Encoding.GetEncoding("windows-1251");
byte[] utf8Bytes = utf8.GetBytes(source);
byte[] win1251Bytes = win1251.GetBytes(source);
byte[] utf8ofwinBytes = Encoding.Convert(win1251, utf8, win1251Bytes);
string unicodefromutf8 = utf8.GetString(utf8Bytes);
string unicodefromwin1251 = win1251.GetString(win1251Bytes);
// ----- The show -------------------------------------------------
textBox1.Text = "";
textBox1.Text += "Literal Unicode soource" + Environment.NewLine;
textBox1.Text += source + Environment.NewLine + Environment.NewLine;
string s1 = "";
textBox1.Text += "UTF8" + Environment.NewLine;
for (int i = 0; i < utf8Bytes.Length; i++)
{
s1 += utf8Bytes[i].ToString() + ", ";
}
textBox1.Text += s1 + Environment.NewLine + Environment.NewLine;
s1 = "";
textBox1.Text += "WIN 1251" + Environment.NewLine;
for (int i = 0; i < win1251Bytes.Length; i++)
{
s1 += win1251Bytes[i].ToString() + ", ";
}
textBox1.Text += s1 + Environment.NewLine + Environment.NewLine;
s1 = "";
textBox1.Text += "UTF8 of WIN 1251" + Environment.NewLine;
for (int i = 0; i < utf8ofwinBytes.Length; i++)
{
s1 += utf8ofwinBytes[i].ToString() + ", ";
}
textBox1.Text += s1 + Environment.NewLine + Environment.NewLine;
textBox1.Text += "Unicode string of UTF8 bytes" + Environment.NewLine;
textBox1.Text += unicodefromutf8 + Environment.NewLine + Environment.NewLine;
textBox1.Text += "Unicode string of WIN 1251 bytes" + Environment.NewLine;
textBox1.Text += unicodefromwin1251 + Environment.NewLine + Environment.NewLine;
Run it, click the button and you will see, all converting, encoding is done as it should.
You asked for a way to convert Unicode to UTF8 to WIN1251 to UTF8 to UNICODE - here it is.
Your misunderstanding may be:
source = utf8.GetString(utf8bytes);
return source;
This will convert the created UTF8 byte sequence array to an Unicode string. So you return an Unicode string, not a UTF8-byte-sequence of your win-1251 string. Exactly, you return the same string you get.
You have to push the (proper zero terminated) UTF8-byte-sequence to the .Net provider.

Use Encoding.Convert to convert charsets:
Encoding utf8 = Encoding.UTF8;
Encoding win = Encoding.GetEncoding("windows-1251");
byte[] winBytes = win.GetBytes(source);
byte[] utfBytes = Encoding.Convert(win, utf8, winBytes);
string result = utf8.GetString(utfBytes);

Related

create certificateRequest from base64 string in .net Framework 4.7.2

In the past I used for our certTool the com CERTENROLLLib to create the csr. Since Version 4.7.2 you can use the .net Framework.
It is possible to create the csr by passing all the necessary Attributes in the CreateSigningRequest Method and convert it into a pem base64 string.
Unfortunately I couldn't find the other way around, copy a csr in pem Format in a field and read all the csr Attributes from it (cn, san, organization, etc.)
I don't want to use the com lib CERTENROLLLib, openssl or other 3rd parties.
Here is what I have done (to get the csr pem string) found good examples in here and at MS Framework class description, thanks for your help
protected void createButton_Click(object sender, EventArgs e)
{
string csr_cn = txtb_csr_cn.Text;
string csr_c = txtb_csr_c.Text;
string csr_l = txtb_csr_l.Text;
string csr_o = txtb_csr_o.Text;
string csr_ou = txtb_csr_ou.Text;
string csr_s = txtb_csr_s.Text;
csr_san = sanMemo.Text.Replace(" ", "");
if (csr_san.IndexOf(csr_cn) == -1)
{
if (csr_san == "")
{
csr_san = csr_cn;
}
else
{
csr_san = csr_cn + "," + csr_san;
}
}
csr_key_size = Convert.ToInt32(combobox_csr_key.Text);
csr_info = "CN=" + csr_cn + "," + "OU=" + csr_ou + "," + "O=" + csr_o + "," + "L=" + csr_l + "," + "S=" + csr_s + "," + "C=" + csr_c;
notesMemo.Text = CreateCSR(); //CreateRequest();
}
public static string CreateCSR()
{
string[] arrSeperator = new string[] { "," };
RSA keySize = RSA.Create(csr_key_size);
CertificateRequest parentReq = new CertificateRequest(csr_info,
//"CN=Experimental Issuing Authority",
keySize,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
parentReq.CertificateExtensions.Add(
new X509BasicConstraintsExtension(true, false, 0, true));
parentReq.CertificateExtensions.Add(
new X509SubjectKeyIdentifierExtension(parentReq.PublicKey, false));
var sanBuilder = new SubjectAlternativeNameBuilder();
Array arrsan = csr_san.Split(arrSeperator, StringSplitOptions.RemoveEmptyEntries);
foreach (string sanvalue in arrsan)
{
sanBuilder.AddDnsName(sanvalue);
}
parentReq.CertificateExtensions.Add(sanBuilder.Build());
string csrdecrypt = PemEncodeSigningRequest(parentReq);
return csrdecrypt;
}
public static string PemEncodeSigningRequest(CertificateRequest request)
{
byte[] pkcs10 = request.CreateSigningRequest();
StringBuilder builder = new StringBuilder();
builder.AppendLine("-----BEGIN CERTIFICATE REQUEST-----");
string base64 = Convert.ToBase64String(pkcs10);
int offset = 0;
const int LineLength = 64;
while (offset < base64.Length)
{
int lineEnd = Math.Min(offset + LineLength, base64.Length);
builder.AppendLine(base64.Substring(offset, lineEnd - offset));
offset = lineEnd;
}
builder.AppendLine("-----END CERTIFICATE REQUEST-----");
string tester2 = builder.ToString();
return builder.ToString();
}
There is no pure-managed way to read a Certification Signing Request without third party libraries.
You could try using a P/Invoke to CryptDecodeObjectEx, possibly using the structure identifier of X509_CERT (per https://learn.microsoft.com/en-us/windows/desktop/SecCrypto/constants-for-cryptencodeobject-and-cryptdecodeobject).
But the CertificateRequest class is a PKCS#10 writer without a reader in .NET Framework.
Update (2023-01-30): LoadSigningRequestPem and friends were added in .NET 7.

Unity string to binary converter output error

I've been trying to make a simple string to the binary converter in unity using C#. The code is converting it well but the problem I am getting is that when outputting, the output is only the last letter typed.
For example, when "Hello" is typed I want it to display
01001000 01100101 01101100 01101100 01101111
But I am only getting the o conversion which is 01101111
Here is my code in unity c#:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TextInput : MonoBehaviour
{
InputField textInput;
InputField.SubmitEvent se;
public Text output;
// Use this for initialization
void Start()
{
textInput = gameObject.GetComponent<InputField>();
se = new InputField.SubmitEvent();
se.AddListener(SubmitInput);
textInput.onEndEdit = se;
}
private void SubmitInput(string arg0)
{
string currentText = output.text;
string newtext = currentText + "\n" + arg0;
foreach (char c in newtext)
output.text = newtext + " in binary is " + "\n" + (Convert.ToString(c, 2).PadLeft(8, '0'));
textInput.text = "";
textInput.ActivateInputField();
}
}
You're overwriting the output.text every time you loop through a character in newtext.
Currently you are doing :
output.text = newtext + " in binary is " + binary thing 1
output.text = newtext + " in binary is " + binary thing 2
You should be using the += operator, however this will create a string that prints
:
Hello in binary is "value for h" Hello in binary is "value for e"
etc.
You should create a string variable that you add to for the binary value, and then add that to output.text after the foreach loop.
private void SubmitInput(string arg0)
{
string currentText = output.text;
string newtext = currentText + "\n" + arg0;
string binaryText; //This string will contain the Binary Data
foreach (char c in newtext)
{
binaryText += (Convert.ToString(c, 2).PadLeft(8, '0')); //Add that character's binary data to the binary string
}
output.text = newtext + " in binary is " + "\n" + binaryText;//Print the binary string after the speicifed text
textInput.text = "";
textInput.ActivateInputField();
}
Hello your code works correctly for me, you are overwriting your data use: output.text +=
Also verify that your text field is multiline or try removing the
\n
The BestFit option in the Text component can also help improve visualization
To get the desired output change your codes as follows:
string binaryText = "";
foreach (char c in newtext)
binaryText += (Convert.ToString(c, 2).PadLeft(8, '0')) + " ";
output.text = newtext + " in binary is " + "\n" + binaryText;
If you use LINQ you can simplify it:
var binaryText = string.Join(" ", newtext.ToList().Select(x => Convert.ToString(x, 2).PadLeft(8, '0')));

When use String.Insert(int index, string text) insert at the end of the new string: "00000"

I need to insert in a specific position of the string line, another string, so I compute the specific position for start to insert:
string info1 = "info1";
string info2 = "info2";
string info3 = "info3";
string info4 = "info4";
string keyWord = "BELEGIT";
start = line.IndexOf(keyWord, 0) + keyWord.Length + 13;
var aStringBuilder = new StringBuilder(line);
aStringBuilder.Remove(start, 19);
line = aStringBuilder.ToString();
string newLine = line.Insert(start, "\r\n" + info1 + "\r\n" + "\r\n" + info2 + "\r\n" + info3 + "\r\n" + info4 + "\r\n");
(newLine will be the content of a file in my application).
newline contains the correct content except the string "00000" that inserts after "info4". So in my new file with the content that is newline there is newline and immediately after "00000". I do not really understand why.
Thanks in advance.
INPUT:
line contains:
#~11\r\nT-02040121R\r\n\r\n\r\n\r\n\r\n\r\n\n2.000000000\r\n
OUTPUT
newLine contains:
#~11\r\nT-02040121R\r\ninfo1\r\n\r\ninfo2\r\ninfo3\r\ninfo4\r\n00000\r\n
Assuming that you want just the first 19 chars of lineyou could use Substringto get them and string.Formatto build the new string.
Something like this
var start = line.Substring(0, 19);
string newLine = $"{start}\r\n{info1}\r\n\r\n{info2}\r\n{info3}\r\n{info4}\r\n";
The second line is the short form for
string newLine = string.Format("{0}\r\n{1}\r\n\r\n{2}\r\n{3}\r\n{4}\r\n", start, info1, info2, info3, info4);
if you need more information about string.Formathave a look at the MSDN.

NavigationContext returning incomplete data

I have a code in which i'm passing email data to another page. The email body may contain HTML.
On the second page, I have observed that when '&' or '#' etc comes into body content (while getting data from NavigationContext.QueryString.TryGetValue()), the string breaks & further data is not obtained.
Code on first page to send data:
string strParameters = string.Empty;
strParameters += "subject=" + objEmail.Subject;
strParameters += "&from=" + objEmail.FromAddress;
strParameters += "&to=";
for (int i = 0; i < objEmail.NumTo; i++)
{
strParameters += objEmail.GetToAddr(i) + "; ";
}
strParameters += "&cc=";
for (int i = 0; i < objEmail.NumCC; i++)
{
strParameters += objEmail.GetCcAddr(i) + "; ";
}
strParameters += "&body=" + objEmail.Body;
NavigationService.Navigate(new Uri("/PageReadMail.xaml?" + strParameters, UriKind.Relative));
Code on second page to receive data:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
string strOriginalString = e.Uri.OriginalString;
//get data received from navigation service
string strBody = "";
string strSubject = "";
string strTo = "";
string strCc = "";
string strFrom = "";
NavigationContext.QueryString.TryGetValue("body", out strBody);
NavigationContext.QueryString.TryGetValue("subject", out strSubject);
NavigationContext.QueryString.TryGetValue("from", out strFrom);
NavigationContext.QueryString.TryGetValue("to", out strTo);
NavigationContext.QueryString.TryGetValue("cc", out strCc);
}
Here, strBody is having incomplete data.
The parameters should be Url-encoded
You should use HttpUtility.UrlEncode() or Uri.EscapeDataString() on each parameter of the Uri. Alternatively, you can use Uri.EscapeUriString() on the whole Uri.
There's a limit on the lenght of a Uri
Perhaps your string is longer and is getting trimmed? Although, I think if it was longer, it will just throw an exception, rather than trimming it, but you should check it out.
Better pass the whole email object to PageReadMail
I think it will be easier and safer to just pass the whole email object to the page, rather than converting it to a string and passing it in the Uri.
Just add a static property of type YourEmailObjectType to the PageReadMail class and set that property before you navigate to the page. Once you've navigated, get the data that for the email from that property, rather than from the navigation Uri.
You can just replace characters ('&' and '#') :
strParameters += "&body=" + objEmail.Body.Replace("&", "%26").Replace("#", "%23");

How to replace an actual "\n" string, not the line break escape

I've been trying for the last two hours, but i can't replace the string \n, this is what i did:
Encoding enc = Encoding.ASCII;
for (int i = 0; i < numpntr; i++)
{
bw.BaseStream.Position = strt + i*var;
bw.Write(
enc.GetBytes(listView1.Items[i].SubItems[1].Text.Replace("\n","\x0A") + (new string('\0',
bytecnt - enc.GetByteCount(listView1.Items[i].SubItems[1].Text.Replace("\n" + "\x0A"))))));
}
bw.Flush();
bw.Close();
bw = null;
is there anyway to replace it as a string ?
You could use " \\n " or you can put ' # ' begining of your string like this:
enc.GetBytes(listView1.Items[i].SubItems[1].Text.Replace(#"\n" + "\x0A")
They are called verbatim strings, you can take a look at this documentation.

Categories

Resources