source: trunk/CrypPlugins/Vigenere/VigenereSettings.cs @ 1259

Last change on this file since 1259 was 1259, checked in by Matthäus Wander, 12 years ago

shortened license text to boilerplate notice in all source files

File size: 14.7 KB
Line 
1/*
2   Copyright 2008 Sebastian Przybylski, University of Siegen
3
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7
8       http://www.apache.org/licenses/LICENSE-2.0
9
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15*/
16
17using System;
18using System.Collections.Generic;
19using System.Linq;
20using System.Text;
21using System.IO;
22using Cryptool.PluginBase;
23using System.ComponentModel;
24
25namespace Cryptool.Vigenere
26{
27    public class VigenereSettings : ISettings
28    {
29        #region Public Vigenere specific interface
30
31        /// <summary>
32        /// We use this delegate to send log messages from the settings class to the Vigenere plugin
33        /// </summary>
34        /// <param name="sender"></param>
35        /// <param name="msg"></param>
36        /// <param name="logLevel"></param>
37        public delegate void VigenereLogMessage(string msg, NotificationLevel logLevel);
38
39        /// <summary>
40        /// An enumaration for the different modes of dealing with unknown characters
41        /// </summary>
42        public enum UnknownSymbolHandlingMode { Ignore = 0, Remove = 1, Replace = 2 };
43
44        /// <summary>
45        /// Fire if a new text has to be shown in the status bar
46        /// </summary>
47        public event VigenereLogMessage LogMessage;
48
49        /// <summary>
50        /// Retrieves the current shift values of Vigenere (i.e. the key), or sets it
51        /// </summary>
52        [PropertySaveOrder(0)]
53        public int[] ShiftKey
54        {
55            get { return shiftValue; }
56            set { setKeyByValue(value); }
57        }
58
59        /// <summary>
60        /// Retrieves the current setting whether the alphabet should be treated as case sensitive or not
61        /// </summary>
62        [PropertySaveOrder(1)]
63        public bool CaseSensitiveAlphabet
64        {
65            get
66            {
67                if (caseSensitiveAlphabet == 0) return false;
68                else return true;
69            }
70            set { } //readonly
71        }
72
73        /// <summary>
74        /// Returns true if some settings have been changed. This value should be set externally to false. e.g
75        /// when a project was saved.
76        /// </summary>
77        [PropertySaveOrder(2)]
78        public bool HasChanges
79        {
80            get { return hasChanges; }
81            set { hasChanges = value; }
82        }
83
84        #endregion
85
86        #region Private variables
87        private bool hasChanges;
88        private int selectedAction = 0;
89        private string upperAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
90        private string lowerAlphabet = "abcdefghijklmnopqrstuvwxyz";
91        private string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
92        private char[] shiftChar = { 'B', 'C', 'D' };
93        private int[] shiftValue = { 1, 2, 3 };
94        private UnknownSymbolHandlingMode unknowSymbolHandling = UnknownSymbolHandlingMode.Ignore;
95        private int caseSensitiveAlphabet = 0; //0=case insensitive, 1 = case sensitive
96        #endregion
97
98        #region Private methods
99        private string removeEqualChars(string value)
100        {
101            int length = value.Length;
102
103            for (int i = 0; i < length; i++)
104            {
105                for (int j = i + 1; j < length; j++)
106                {
107                    if((value[i]) == value[j] || (!CaseSensitiveAlphabet & (char.ToUpper(value[i]) == char.ToUpper(value[j]))))
108                    {
109                        LogMessage("Removing duplicate letter: \'" + value[j] + "\' from alphabet!", NotificationLevel.Warning);
110                        value = value.Remove(j,1);
111                        j--;
112                        length--;
113                    }
114                }
115            }
116            return value;
117        }
118
119        /// <summary>
120        /// Parse the offset string and set the shiftValue/ShiftChar accordingly
121        /// </summary>
122        /// <param name="offsetString"></param>
123        private void setKeyByValue(string offsetString)
124        {
125            try
126            {
127                string[] offsetStr = offsetString.Split(',');
128                int[] offset = new int[offsetStr.Length];
129                for (int i = 0; i < offsetStr.Length; i++)
130                {
131                    offset[i] = int.Parse(offsetStr[i]);
132                }
133                setKeyByValue(offset);
134            }
135            catch (Exception e)
136            {
137                LogMessage("Bad input \"" + offsetString + "\"! (" + e.Message + ") Reverting to " + shiftValue.ToString() + "!", NotificationLevel.Error);
138                OnPropertyChanged("ShiftValue");
139            }
140        }
141
142        /// <summary>
143        /// Set the new shiftValue and the new shiftCharacter to offset % alphabet.Length
144        /// </summary>
145        /// <param name="offset"></param>
146        public void setKeyByValue(int[] offset)
147        {
148            hasChanges = true;
149
150            //making sure the shift value lies within the alphabet range
151            for (int i = 0; i < offset.Length; i++)
152                offset[i] = offset[i] % alphabet.Length;
153
154            //set the new shiftChar
155            shiftChar = new char[offset.Length];
156            for (int i = 0; i < offset.Length; i++)
157                shiftChar[i] = alphabet[offset[i]];
158
159            //set the new shiftValue
160            shiftValue = new int[offset.Length];
161            for (int i = 0; i < offset.Length; i++)
162                shiftValue[i] = offset[i];
163
164            //Anounnce this to the settings pane
165            OnPropertyChanged("ShiftValue");
166            OnPropertyChanged("ShiftChar");
167
168            //print some info in the log.
169            LogMessage("Accepted new shift value " + offset.ToString() + "! (Adjusted shift character to '" + shiftChar.ToString() + "\'", NotificationLevel.Info);
170        }
171
172        private void setKeyByCharacter(string value)
173        {
174            try
175            {
176                int[] offset = new int[value.Length];
177                if (this.CaseSensitiveAlphabet)
178                {
179                    for (int i = 0; i < value.Length; i++)
180                        offset[i] = alphabet.IndexOf(value[i]);
181                }
182                else
183                {
184                    for (int i = 0; i < value.Length; i++)
185                        offset[i] = alphabet.ToUpper().IndexOf(char.ToUpper(value[i]));
186                }
187                for (int i = 0; i < offset.Length; i++)
188                {
189                    if (offset[i] >= 0)
190                    {
191                        hasChanges = true;
192                        shiftValue = new int[offset.Length];
193                        for (int j = 0; j < offset.Length; j++)
194                            shiftValue[j] = offset[j];
195                        shiftChar = new char[shiftValue.Length];
196                        for (int j = 0; j < shiftValue.Length; j++)
197                            shiftChar[j] = alphabet[shiftValue[j]];
198                        LogMessage("Accepted new shift character \'" + shiftChar.ToString() + "\'! (Adjusted shift value to " + shiftValue.ToString() + ")", NotificationLevel.Info);
199                        OnPropertyChanged("ShiftValue");
200                        OnPropertyChanged("ShiftChar");
201                        break;
202                    }
203                    else
204                    {
205                        LogMessage("Bad input \"" + value + "\"! (Character not in alphabet!) Reverting to " + shiftChar.ToString() + "!", NotificationLevel.Error);
206                    }
207                }
208            }
209            catch (Exception e)
210            {
211                LogMessage("Bad input \"" + value + "\"! (" + e.Message + ") Reverting to " + shiftChar.ToString() + "!", NotificationLevel.Error);
212            }
213        }
214        #endregion
215
216        #region Algorithm settings properties (visible in the Settings pane)
217
218        [PropertySaveOrder(3)]
219        [ContextMenu("Action","Select the Algorithm action",1,DisplayLevel.Beginner,ContextMenuControlType.ComboBox,new int[]{1,2},"Encrypt","Decrypt")]
220        [TaskPane("Action", "Select the Algorithm action", null, 1, false, DisplayLevel.Beginner, ControlType.ComboBox, new string[] { "Encrypt", "Decrypt"})]
221        public int Action
222        {
223            get { return this.selectedAction; }
224            set
225            {
226                if (value != selectedAction) HasChanges = true;
227                this.selectedAction = value;
228                OnPropertyChanged("Action");
229            }
230        }
231
232        [PropertySaveOrder(4)]
233        [TaskPane("Shift value (integer)", "Enter the numbers of letters to shift seperated by comma.", null, 2, false, DisplayLevel.Beginner, ControlType.TextBox, null)]
234        public string ShiftValue
235        {
236            get
237            {
238                StringBuilder str = new StringBuilder(string.Empty);
239                for (int i = 0; i < this.shiftValue.Length; i++)
240                {
241                    str.Append(this.shiftValue[i].ToString());
242                    if (i != this.shiftValue.Length - 1)
243                        str.Append(",");
244                }
245                return str.ToString();
246            }
247            set { setKeyByValue(value); }
248        }
249
250        [PropertySaveOrder(5)]
251        [TaskPane("Shift key (multiple letters)", "Enter multiple letters as the key", null, 3, false, DisplayLevel.Experienced, ControlType.TextBox, null)]
252        public string ShiftChar
253        {
254            get { return new String(this.shiftChar); }
255            set { setKeyByCharacter(value); }
256        }
257
258        [PropertySaveOrder(6)]
259        [ContextMenu("Unknown symbol handling","What should be done with ecountered characters at the input which are not in the alphabet?",4,DisplayLevel.Beginner,ContextMenuControlType.ComboBox,null,"Ignore (leave unmodified)","Remove","Replace with \'?\'")]
260        [TaskPane("Unknown symbol handling", "What should be done with encountered characters at the input which are not in the alphabet?", null, 4, false, DisplayLevel.Expert, ControlType.ComboBox, new string[] { "Ignore (leave unmodified)", "Remove", "Replace with \'?\'" })]
261        public int UnknownSymbolHandling
262        {
263            get { return (int)this.unknowSymbolHandling; }
264            set
265            {
266                if ((UnknownSymbolHandlingMode)value != unknowSymbolHandling) hasChanges = true;
267                this.unknowSymbolHandling = (UnknownSymbolHandlingMode)value;
268                OnPropertyChanged("UnknownSymbolHandling");
269            }
270        }
271
272        [PropertySaveOrder(7)]
273        [ContextMenu("Alphabet case sensitive","Should upper and lower case be treated differently? (Should a == A)",7,DisplayLevel.Beginner,ContextMenuControlType.ComboBox,null, "Case insensitive","Case sensitive")]
274        [TaskPane("Alphabet case sensitive", "Should upper and lower case be treated differently? (Should a == A)", null, 7, false, DisplayLevel.Expert, ControlType.ComboBox, new string[] { "Case insensitive", "Case sensitive" })]
275        public int AlphabetCase
276        {
277            get { return this.caseSensitiveAlphabet; }
278            set
279            {
280                if (value != caseSensitiveAlphabet) hasChanges = true;
281                this.caseSensitiveAlphabet = value;
282                if (value == 0)
283                {
284                    if (alphabet == (upperAlphabet + lowerAlphabet))
285                    {
286                        alphabet = upperAlphabet;
287                        LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + "Symbols)",NotificationLevel.Info);
288                        OnPropertyChanged("AlphabetSymbols");
289                        //re-set also the key (shifvalue/shiftchar to be in the range of the new alphabet
290                        setKeyByValue(shiftValue);
291                    }
292                }
293                else
294                {
295                    if(alphabet == upperAlphabet)
296                    {
297                        alphabet = upperAlphabet + lowerAlphabet;
298                        LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
299                        OnPropertyChanged("AlphabetSymbols");
300                    }
301                }
302
303                //remove equal characters from the current alphabet
304                string a = alphabet;
305                alphabet = removeEqualChars(alphabet);
306
307                if(a != alphabet)
308                {
309                    OnPropertyChanged("AlphabetSymbols");
310                    LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)",NotificationLevel.Info);
311                }
312                OnPropertyChanged("CaseSensitiveAlphabet");
313            }
314        }
315
316        [PropertySaveOrder(8)]
317        [TaskPane("Alphabet", "This is the used alphabet.", null, 6, false, DisplayLevel.Expert, ControlType.TextBox, null)]
318        public string AlphabetSymbols
319        {
320            get { return this.alphabet; }
321            set
322            {
323                string a = removeEqualChars(value);
324                if (a.Length == 0) //cannot accept empty alphabets
325                {
326                    LogMessage("Ignoring empty alphabet from user! Using previous alphabet: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
327                }
328                else if (!alphabet.Equals(a))
329                {
330                    hasChanges = true;
331                    this.alphabet = a;
332                    setKeyByValue(shiftValue); //re-evaluate if the shiftvalue is stillt within the range
333                    LogMessage("Accepted new alphabet from user: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
334                    OnPropertyChanged("AlphabetSymbols");
335                }
336            }
337        }
338        #endregion
339
340        #region INotifyPropertyChanged Members
341
342        public event PropertyChangedEventHandler PropertyChanged;
343
344        protected void OnPropertyChanged(string name)
345        {
346            if (PropertyChanged != null)
347            {
348                PropertyChanged(this, new PropertyChangedEventArgs(name));
349            }
350        }
351
352        #endregion
353    }
354}
Note: See TracBrowser for help on using the repository browser.