source: branches/eraser6/6.0/Eraser.DefaultPlugins/CustomMethodPassEditor.cs @ 1476

Revision 1476, 6.6 KB checked in by lowjoel, 4 years ago (diff)

When switching from Hex to Text view is impossible do not display the error message twice.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Drawing;
5using System.Data;
6using System.Linq;
7using System.Text;
8using System.Windows.Forms;
9using System.Globalization;
10using Eraser.Util;
11
12namespace Eraser.DefaultPlugins
13{
14    public partial class CustomMethodPassEditor : UserControl
15    {
16        public CustomMethodPassEditor()
17        {
18            InitializeComponent();
19            UXThemeApi.UpdateControlTheme(this);
20        }
21
22        /// <summary>
23        /// Gets or sets the type of this pass.
24        /// </summary>
25        [Description("The type of pass being edited")]
26        [Category("Behavior")]
27        public CustomMethodPassEditorPassType PassType
28        {
29            get
30            {
31                if (passTypeText.Checked)
32                    return CustomMethodPassEditorPassType.Text;
33                else if (passTypeHex.Checked)
34                    return CustomMethodPassEditorPassType.Hex;
35                return CustomMethodPassEditorPassType.Random;
36            }
37            set
38            {
39                switch (value)
40                {
41                    case CustomMethodPassEditorPassType.Text:
42                    case CustomMethodPassEditorPassType.Hex:
43                        UpdateEditorSuitably();
44                        break;
45                    default:
46                        passTypeRandom.Checked = true;
47                        break;
48                }
49            }
50        }
51
52        [Description("The pass constant being edited.")]
53        [Category("Behavior")]
54        public byte[] PassData
55        {
56            get
57            {
58                //Return the cached string if the pass is a constant-writing pass.
59                switch (PassType)
60                {
61                    case CustomMethodPassEditorPassType.Random:
62                        return null;
63                    default:
64                        return passData;
65                }
66            }
67            set
68            {
69                //Store the data into our class variable, so it can be edited.
70                passData = value;
71
72                //Update the UI
73                UpdateEditorSuitably();
74            }
75        }
76
77
78        /// <summary>
79        /// Parses a string either for UTF-8 characters or hexadecimal digits, returning
80        /// its value in a byte array.
81        /// </summary>
82        /// <param name="text">The string to parse.</param>
83        /// <param name="parseHex">Parses <paramref name="text"/> as a string of
84        /// hexadecimal numbers if true; a UTF-8 string otherwise.</param>
85        /// <returns>An array containing the byte-wise representation of the input
86        /// string.</returns>
87        /// <exception cref="FormatException">Throws a <see cref="System.FormatException"/>
88        /// if the array cannot be displayed in the given representation.</exception>
89        private static byte[] GetConstantArray(string text, bool parseHex)
90        {
91            if (parseHex)
92            {
93                string str = text.Replace(" ", "").ToUpper(CultureInfo.CurrentCulture);
94                List<byte> passConstantList = new List<byte>();
95
96                if (str.Length >= 2)
97                {
98                    for (int i = 0, j = str.Length - 2; i < j; i += 2)
99                        passConstantList.Add(Convert.ToByte(str.Substring(i, 2), 16));
100                    passConstantList.Add(Convert.ToByte(str.Substring(str.Length - 2), 16));
101                }
102
103                byte[] result = new byte[passConstantList.Count];
104                passConstantList.CopyTo(result);
105                return result;
106            }
107
108            return Encoding.UTF8.GetBytes(text);
109        }
110
111        /// <summary>
112        /// Displays the pass constant stored by the <see cref="GetConstantArray"/>
113        /// function.
114        /// </summary>
115        /// <param name="array">The array containing the constant to display.</param>
116        /// <param name="asHex">Sets whether the array should be displayed as a
117        /// hexadecimal string.</param>
118        /// <exception cref="System.FormatException">Thrown when the hexadecimal string
119        /// cannot be parsed as a a UTF-8 string, including the presence of NULL
120        /// bytes</exception>
121        /// <returns>A string containing the user-visible representation of the
122        /// input array.</returns>
123        private static string GetConstantStr(byte[] array, bool asHex)
124        {
125            if (array == null || array.Length == 0)
126                return string.Empty;
127
128            //Check for the presence of null bytes in the source string. If so,
129            //the display is always hexadecimal.
130            foreach (byte b in array)
131                if (b == 0)
132                    throw new DecoderFallbackException("The custom pass constant contains " +
133                        "embedded NULL bytes which cannot be represented as text.");
134
135            if (asHex)
136            {
137                StringBuilder displayText = new StringBuilder();
138                foreach (byte b in array)
139                    displayText.Append(string.Format(CultureInfo.CurrentCulture,
140                        "{0:X2} ", b, 16));
141                return displayText.ToString();
142            }
143
144            UTF8Encoding encoding = new UTF8Encoding(false, true);
145            return encoding.GetString(array);
146        }
147
148        /// <summary>
149        /// Updates the editor with the pass constant, choosing a suitable display
150        /// format based on the data.
151        /// </summary>
152        private void UpdateEditorSuitably()
153        {
154            //Try to display the pass data as a string, if possible, since it is
155            //easier for users to understand.
156            if (passData != null && passData.Length > 0)
157                try
158                {
159                    passTxt.Text = GetConstantStr(passData, false);
160                    passTypeText.Checked = true;
161                }
162                catch (DecoderFallbackException)
163                {
164                    passTxt.Text = GetConstantStr(passData, true);
165                    passTypeHex.Checked = true;
166                }
167        }
168
169        /// <summary>
170        /// Updates the editor with the pass constant in the format requested by the user.
171        /// </summary>
172        private void UpdateEditor()
173        {
174            try
175            {
176                //Display the constant on the Text Field, if the pass type requires it.
177                if (!passTypeRandom.Checked)
178                    passTxt.Text = GetConstantStr(passData, passTypeHex.Checked);
179                else
180                    passTxt.Text = string.Empty;
181                passTxt.Enabled = PassType != CustomMethodPassEditorPassType.Random;
182            }
183            catch (DecoderFallbackException)
184            {
185                MessageBox.Show(this, S._("The pass constant cannot be displayed as " +
186                    "text because it contains invalid characters."), S._("Eraser"),
187                     MessageBoxButtons.OK, MessageBoxIcon.Information,
188                     MessageBoxDefaultButton.Button1,
189                     S.IsRightToLeft(this) ? MessageBoxOptions.RtlReading : 0);
190
191                passTypeHex.CheckedChanged -= passType_CheckedChanged;
192                passTypeHex.Checked = true;
193                passTypeHex.CheckedChanged += passType_CheckedChanged;
194            }
195        }
196
197        private void passText_Validating(object sender, CancelEventArgs e)
198        {
199            //Try to parse the pass constant, showing the error if it fails.
200            try
201            {
202                passData = GetConstantArray(passTxt.Text, passTypeHex.Checked);
203            }
204            catch (FormatException)
205            {
206                e.Cancel = true;
207                errorProvider.SetError(passTxt, S._("The input text is invalid " +
208                    "for the current data type. Valid hexadecimal characters are the " +
209                    "digits 0-9 and letters A-F"));
210            }
211        }
212
213        private void passType_CheckedChanged(object sender, EventArgs e)
214        {
215            //We are only concerned with the check event (since the uncheck event is
216            //processed by the validate function.)
217            if (!((RadioButton)sender).Checked)
218                return;
219
220            //Ok, update the UI.
221            UpdateEditor();
222        }
223
224        /// <summary>
225        /// The last-saved pass data.
226        /// </summary>
227        private byte[] passData;
228    }
229
230    /// <summary>
231    /// The different pass types which this editor can edit.
232    /// </summary>
233    public enum CustomMethodPassEditorPassType
234    {
235        Text,
236        Hex,
237        Random
238    }
239}
Note: See TracBrowser for help on using the repository browser.