source: trunk/Documentation/Developer/PluginHowTo/part2.tex @ 1181

Last change on this file since 1181 was 1181, checked in by Patrick Vacek, 12 years ago

HowTo: small changes and revisions over the first 18 pages

File size: 62.4 KB
Line 
1\chapter{Plugin Implementation}
2\label{sec:PluginImplementation}
3In this chapter we provide step-by-step instructions for implementing your own CrypTool 2.0 plugin. The given instructions refer mostly to the usage of the Visual C\# Express and Visual Studio Professional 2008 editions, so before starting you should have a copy of \textbf{Microsoft Visual Studio 2008} (or \textbf{Microsoft Visual C\# 2008 Express Edition}) installed on your computer. We will use the \textbf{Caesar cipher} (also known as the \textbf{shift cipher}) for our example implemenation.
4
5\section{Creating a new project}
6\label{sec:CreatingANewProject}
7
8To begin, open Visual Studio, go to the menu bar and select ``File"~$\rightarrow$ ``New" $\rightarrow$ ``Project\ldots ". The following window will appear:
9
10\begin{figure}[h!]
11        \centering
12                \includegraphics[width=1.00\textwidth]{figures/vs_create_new_project.jpg}
13        \caption{Creating a new Visual Studio project.}
14        \label{fig:vs_create_new_project}
15\end{figure}
16
17\noindent If you are using Visual Studio 2008, select \textbf{``.NET-Framework 3.5"} as the target framework; the Express Edition will automatically choose the target framework. Then choose \textbf{``Class Library"} as the default template, as this will build the project for your plugin as a DLL file. Give the project a unique and meaningful name (such as ``Caesar" in our case), and choose a location to save it to. (The Express Edition will ask for a save location later when you close your project or environment). Select the subdirectory ``CrypPlugins" from your SVN trunk as the location. Finally, confirm by pressing the ``OK" button. Note that creating a new project in this manner also creates a new solution into which the project is placed.
18
19\begin{figure}[h!]
20        \centering
21                \includegraphics[width=0.80\textwidth]{figures/save_solution_csharp_express.JPG}
22        \caption{The Microsoft C\# Express Edition ``Save Project" dialog window.}
23        \label{fig:save_solution_csharp_express}
24\end{figure}
25
26\noindent At this point, your Visual Studio\slash C\# Express solution should look like this:
27
28\begin{figure}[h!]
29        \centering
30                \includegraphics[width=1.00\textwidth]{figures/solution_start_up.jpg}
31        \caption{A newly created solution and project.}
32        \label{fig:solution_start_up}
33\end{figure}
34\clearpage
35
36\section{Interface selection}
37\label{sec:InterfaceSelection}
38
39To include our new plugin in the CrypTool program, we must first add a reference to the CrypTool library, \textbf{\textit{CrypPluginBase.dll}}, where all the necessary CrypTool plugin interfaces are declared.
40
41\begin{figure}[h!]
42        \includegraphics{figures/add_reference.jpg}
43        \caption{Adding a new reference.}
44        \label{fig:add_reference}
45\end{figure}
46
47\noindent Right-click in the Solution Explorer on the ``Reference" item and choose ``Add Reference". A window like the following should appear:
48
49\begin{figure}[h!]
50        \centering
51                \includegraphics{figures/add_pluginbase_source.jpg}
52        \caption{Adding a reference to the PluginBase source code.}
53        \label{fig:add_pluginbase_source}
54\end{figure}
55\clearpage
56
57\noindent Select the project ``CrypPluginBase". If you do not have the ``CrypPluginBase" source code, it is also possible to add a reference the binary DLL. In this case browse to the path where the library file \textit{CrypPluginBase.dll} is located, e.g.\ \textit{C:\textbackslash Documents and Settings\textbackslash $<$Username$>$\textbackslash My Documents\textbackslash Visual Studio 2008\textbackslash Projects\textbackslash CrypPluginBase\textbackslash bin\textbackslash Debug} and select the library by double clicking the file or pressing the ``OK" button. (You can also select the binary DLL located in the folder where \textit{CrypWin.exe} was placed when you downloaded CrypTool2.)
58
59\begin{figure}[h!]
60        \centering
61                \includegraphics{figures/browse_reference.jpg}
62        \caption{Browsing for a reference.}
63        \label{fig:browse_reference}
64\end{figure}
65
66\noindent Besides CrypPluginBase you will need to add three assembly references to provide the necessary ``Windows" namespaces for the \textbf{user control} functions ``Presentation" and ``QuickWatchPresentation". This can be done in the same manner as before with the ``CrypPluginBase" but by selecting the ``.NET" tab. Select the following .NET components:
67
68\begin{itemize}
69    \item PresentationCore
70    \item PresentationFramework
71    \item WindowsBase
72\end{itemize}
73\clearpage
74
75\noindent Afterwards your reference tree view should look like this:
76
77\begin{figure}[h!]
78                \includegraphics{figures/reference_tree.jpg}
79        \caption{A reference tree with the essential components.}
80        \label{fig:reference_tree}
81\end{figure}
82
83\noindent If your plugin will be based on other additional libraries, you can add them in the same way.
84
85\section{Modifing the project properties}
86\label{sec:ModifyTheProjectProperties}
87
88It is important to make two small changes to your plugin's assembly data to make sure that it will be imported correctly into CrypTool 2. Go to the Solution Explorer and open ``AssemblyInfo.cs", which can be found in the ``Properties" folder. Make the following two changes:
89
90\begin{itemize}
91        \item Change the attribute ``AssemblyVersion" to have the value ``2.0.*", and
92        \item Comment out the attribute ``AssemblyFileVersion".
93\end{itemize}
94
95\noindent This section of your assembly file should now look something like this:
96
97\begin{lstlisting}
98[assembly: AssemblyVersion("2.0.*")]
99//[assembly: AssemblyFileVersion("1.0.0.0")]
100\end{lstlisting}
101
102\section{Creating classes for the algorithm and its settings}
103\label{sec:CreatingClassesForTheAlgorithmAndItsSettings}
104
105In the next step we will create two classes. The first class will be the main driver; we will call ours ``Caesar" since that is the name of the cipher that it will implement. In our case, this class has to inherit from IEncryption because it will be an ecryption plugin. If it was instead a hash plugin, this class should inherit from IHash. The second class will be used to store setting information for the plugin, and thus we will name ours ``CaesarSettings". It has to inherit from ISettings.
106\clearpage
107
108\subsection{Creating a class for the algorithm}
109\label{sec:CreatingAClassForTheAlgorithm}
110
111When starting a new project, Visual Studio automatically creates a class which has the name ``Class1.cs".  Since this is a rather non-descriptive name, we will change it. In our example, it should be ``Caesar.cs". There are two ways to change the name:
112
113\begin{itemize}
114        \item Rename the existing class, or
115        \item Delete the existing class and create a new one.
116\end{itemize}
117%\clearpage
118
119\noindent Both options will achieve the same results. We will guide you through the second method. First, delete ``Class1.cs".
120
121\begin{figure}[h!]
122        \centering
123                \includegraphics{figures/new_class.jpg}
124        \caption{Deleting a class.}
125        \label{fig:new_class}
126\end{figure}
127\clearpage
128
129\noindent Then right-click on the project item (in our case, ``Caesar") and select ``Add $\rightarrow$ Class\ldots ":
130
131\begin{figure}[h]
132        \centering
133                \includegraphics{figures/add_new_class.jpg}
134        \caption{Adding a new class.}
135        \label{fig:add_new_class}
136\end{figure}
137\clearpage
138
139\noindent Finally, give your class a unique name. We will call our class ``Caesar.cs" and define it as public so that it will be available to other classes.
140
141\begin{figure}[h!]
142        \centering
143                \includegraphics[width=1.00\textwidth]{figures/name_new_class.jpg}
144        \caption{Naming the new class.}
145        \label{fig:name_new_class}
146\end{figure}
147
148\noindent Visual Studio will automatically generate a basic code outline for the new class. In our example, we will not use the all the namespaces that are automatically imported, so you can delete the lines \texttt{using System;} and \texttt{using System.Linq;}.
149
150\subsection{Creating a settings class}
151\label{sec:CreatingASettingsClass}
152
153Add a second public class in the same way. We will call the class ``CaesarSettings". The settings class stores the necessary information about controls, captions, descriptions and default parameters (e.g.\ for key settings, alphabets, key length and type of action) to build the \textbf{TaskPane} in the CrypTool application.
154\clearpage
155
156\noindent Below is an example of what a completed TaskPane for the existing Caesar plugin in CrypTool 2 looks like:
157
158\begin{figure}[h!]
159        \centering
160                \includegraphics{figures/task_pane.jpg}
161        \caption{The completed TaskPane for the existing Caesar plugin.}
162        \label{fig:task_pane}
163\end{figure}
164\clearpage
165
166\subsection{Adding the namespaces and inheritance sources for the Caesar class}
167\label{sec:AddingTheNamespacesAndInheritanceSourcesForTheCaesarClass}
168
169Open the ``Caesar.cs" file by double clicking on it in the Solution Explorer. To include the necessary namespaces in the class header, use the ``using" statement followed by the name of the desired namespace. The CrypTool 2.0 API provides the following namespaces:
170
171\begin{itemize}
172        \item Cryptool.PluginBase --- contains interfaces such as IPlugin, IHash, and ISettings, as well as attributes, enumerations, delegates and extensions.
173        \item Cryptool.PluginBase.Analysis --- contains interfaces for cryptanalysis plugins (such as ``Stream Comparator").
174        \item Cryptool.PluginBase.Control --- contains global interfaces for the IControl feature for defining custom controls.
175        \item Cryptool.PluginBase.Cryptography --- contains interfaces for encryption and hash algorithms such as AES, DES and MD5.
176        \item Cryptool.PluginBase.Editor --- contains interfaces for editors that can be implemented in CrypTool 2.0, such as the default editor.
177        \item Cryptool.PluginBase.Generator --- contains interfaces for generators, including the random input generator.
178        \item Cryptool.PluginBase.IO --- contains interfaces for input, output and the CryptoolStream.
179        \item Cryptool.PluginBase.Miscellaneous --- contains assorted helper classes, including \textit{GuiLogMessage} and \textit{PropertyChanged}.
180        \item Cryptool.PluginBase.Resources --- used only by CrypWin and the editor; not necessary for plugin development.
181        \item Cryptool.PluginBase.Tool --- contains an interface for all external tools implemented by CrypTool 2.0 that do not entirely support the CrypTool 2.0 API .
182        \item Cryptool.PluginBase.Validation --- contains interfaces for validation methods, including regular expressions.
183\end{itemize}
184
185\noindent In our example, the Caesar algorithm necessitates the inclusion of the following namespaces:
186
187\begin{itemize}
188        \item Cryptool.PluginBase --- to implement ISettings in the CaesarSettings class.
189        \item Cryptool.PluginBase.Cryptography --- to implement IEncryption in the Caesar class.
190        \item Cryptool.PluginBase.IO --- to use CryptoolStream for data input and output.
191        \item Cryptool.PluginBase.Miscellaneous --- to use the CrypTool event handler.
192\end{itemize}
193
194\noindent It is important to define a new default namespace for our public class (``Caesar"). In CrypTool 2.0  the standard namespace convention is \textit{Cryptool.[name of class]}. Therefore our namespace will be defined as \textit{Cryptool.Caesar}.\clearpage
195
196\noindent At this point, the source code should look like the following:
197
198\begin{lstlisting}
199using System.Collections.Generic;
200using System.Text;
201
202//required CrypTool namespaces
203using Cryptool.PluginBase;
204using Cryptool.PluginBase.Cryptography;
205using Cryptool.PluginBase.IO;
206using Cryptool.PluginBase.Miscellaneous;
207
208namespace Cryptool.Caesar
209{
210        public class Caesar
211        {
212        }
213}
214\end{lstlisting}
215
216\ \\ % ugly but functional
217\noindent Next we should let the ``Caesar" class inherit from IEncryption by making the following alteration:
218
219\begin{lstlisting}
220namespace Cryptool.Caesar
221{
222        public class Caesar : IEncryption
223        {
224        }
225}
226\end{lstlisting}
227
228\subsection{Adding interface functions for the Caesar class}
229\label{sec:AddingInterfaceFunctionsForTheCaesarClass}
230
231There is an underscore at the ''I'' in IEncryption statement. Move your mouse over it or place the cursor at it and press ''Shift+Alt+F10'' and you will see the following submenu:
232\begin{figure}[h!]
233        \centering
234                \includegraphics{figures/inherit_submenu.jpg}
235        \caption{Inherit submenu}
236        \label{fig:inherit_submenu}
237\end{figure}\\
238Choose the item ''Implement interface 'IEncryption'''. Visual Studio/C\# Express will now place all available and needed interface members to interact with the CrypTool core (this saves you also a lot of typing code).\\
239Your code will now look like this:
240\begin{lstlisting}
241using System.Collections.Generic;
242using System.Text;
243
244using Cryptool.PluginBase;
245using Cryptool.PluginBase.Cryptography;
246using Cryptool.PluginBase.IO;
247using Cryptool.PluginBase.Miscellaneous;
248
249namespace Cryptool.Caesar
250{
251    public class Caesar : IEncryption
252    {
253        #region IPlugin Members
254
255        public void Dispose()
256        {
257            throw new NotImplementedException();
258        }
259
260        public void Execute()
261        {
262            throw new NotImplementedException();
263        }
264
265        public void Initialize()
266        {
267            throw new NotImplementedException();
268        }
269
270        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
271
272        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
273
274        public event StatusChangedEventHandler OnPluginStatusChanged;
275
276        public void Pause()
277        {
278            throw new NotImplementedException();
279        }
280
281        public void PostExecution()
282        {
283            throw new NotImplementedException();
284        }
285
286        public void PreExecution()
287        {
288            throw new NotImplementedException();
289        }
290
291        public System.Windows.Controls.UserControl Presentation
292        {
293            get { throw new NotImplementedException(); }
294        }
295
296        public System.Windows.Controls.UserControl QuickWatchPresentation
297        {
298            get { throw new NotImplementedException(); }
299        }
300
301        public ISettings Settings
302        {
303            get { throw new NotImplementedException(); }
304        }
305
306        public void Stop()
307        {
308            throw new NotImplementedException();
309        }
310
311        #endregion
312
313        #region INotifyPropertyChanged Members
314
315        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
316
317        #endregion
318    }
319}
320\end{lstlisting}
321\subsection{Add namespace and interfaces for the class CaesarSettings}\label{sec:AddNamespaceAndInterfacesForTheClassCaesarSettings}
322Let's now take a look at the second class "CaesarSettings" by double clicking at the "CaesarSettings.cs" file at the Solution Explorer. First we also have to include the namespace of "Cryptool.PluginBase" to the class header and let the settings class inherit from "ISettings" analogous as seen before at the Caesar class. Visual Studio/C\# Express will here also automatically place code from the CrypTool interface if available.
323\begin{lstlisting}
324using System.Collections.Generic;
325using System.Text;
326
327using Cryptool.PluginBase;
328
329namespace Cryptool.Caesar
330{
331    public class CaesarSettings : ISettings
332    {
333        #region ISettings Members
334
335        public bool HasChanges
336        {
337            get
338            {
339                throw new NotImplementedException();
340            }
341            set
342            {
343                throw new NotImplementedException();
344            }
345        }
346
347        #endregion
348
349        #region INotifyPropertyChanged Members
350
351        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
352
353        #endregion
354    }
355}
356\end{lstlisting}
357\subsection{Add controls for the class CaesarSettings (if needed)}\label{sec:AddControlsForTheClassCaesarSettingsIfNeeded}
358Now we have to implement some kind of controls (like button, text box) if we need them in the CrypTool \textbf{TaskPane} to modify settings of the algorithm. If you decided to provide an algorithm (e.g. Hash) which do not have any kind of settings you can leave this class now empty. The only part you have to modify is the ''HasChanges'' property to avoid any ''NotImplementedException''. How to modify this property you can see in the following code which demonstrate the modifications fot the TaskPane for our Caesar algorithm. You can also take a look at the other algorithm source codes which are stored in our subversion how you can provide a TaskPane. The following source code demonstrates how we provide our TaskPane as seen above.
359\begin{lstlisting}
360using System;
361using System.ComponentModel;
362using System.Windows;
363using Cryptool.PluginBase;
364using System.Windows.Controls;
365
366namespace Cryptool.Caesar
367{
368    public class CaesarSettings : ISettings
369    {
370        #region Public Caesar specific interface
371
372        /// <summary>
373        /// We use this delegate to send log messages from the settings class to the Caesar plugin
374        /// </summary>
375        public delegate void CaesarLogMessage(string msg, NotificationLevel loglevel);
376
377        /// <summary>
378        /// An enumaration for the different modes of dealing with unknown characters
379        /// </summary>
380        public enum UnknownSymbolHandlingMode { Ignore = 0, Remove = 1, Replace = 2 };
381
382        /// <summary>
383        /// Fire if a new status message was send
384        /// </summary>
385        public event CaesarLogMessage LogMessage;
386
387        public delegate void CaesarReExecute();
388
389        public event CaesarReExecute ReExecute;
390
391        /// <summary>
392        /// Retrieves the current sihft value of Caesar (i.e. the key), or sets it
393        /// </summary>
394        [PropertySaveOrder(0)]
395        public int ShiftKey
396        {
397            get { return shiftValue; }
398            set
399            {
400                setKeyByValue(value);
401            }
402        }
403
404        /// <summary>
405        /// Retrieves the current setting whether the alphabet should be treated as case sensitive or not
406        /// </summary>
407        [PropertySaveOrder(1)]
408        public bool CaseSensitiveAlphabet
409        {
410            get
411            {
412                if (caseSensitiveAlphabet == 0)
413                {   return false;   }
414                else
415                {   return true;    }
416            }
417            set {} // readonly, because there are some problems if we omit the set part.
418        }
419
420
421        /// <summary>
422        /// Returns true if some settings have been changed. This value should be set externally to false e.g.
423        /// when a project was saved.
424        /// </summary>
425        [PropertySaveOrder(3)]
426        public bool HasChanges
427        {
428            get { return hasChanges; }
429            set { hasChanges = value; }
430        }
431
432        #endregion
433
434        #region Private variables
435        private bool hasChanges;
436        private int selectedAction = 0;
437        private string upperAlphabet = ''ABCDEFGHIJKLMNOPQRSTUVWXYZ'';
438        private string lowerAlphabet = ''abcdefghijklmnopqrstuvwxyz'';
439        private string alphabet = ''ABCDEFGHIJKLMNOPQRSTUVWXYZ'';
440        private char shiftChar = 'C';
441        private int shiftValue = 2;
442        // private int shiftValue = 2;
443        private UnknownSymbolHandlingMode unknownSymbolHandling = UnknownSymbolHandlingMode.Ignore;
444        private int caseSensitiveAlphabet = 0; // 0 = case insensitve, 1 = case sensitive
445        private bool sensitivityEnabled = true;
446        #endregion
447
448        #region Private methods
449
450        private string removeEqualChars(string value)
451        {
452            int length = value.Length;
453
454            for (int i = 0; i < length; i++)
455            {
456                for (int j = i + 1; j < length; j++)
457                {
458                    if ((value[i] == value[j]) || (!CaseSensitiveAlphabet & (char.ToUpper(value[i]) == char.ToUpper(value[j]))))
459                    {
460                        LogMessage(''Removing duplicate letter: \''' + value[j] + ''\' from alphabet!'', NotificationLevel.Warning);
461                        value = value.Remove(j,1);
462                        j--;
463                        length--;
464                    }
465                }
466            }
467
468            return value;
469        }
470
471        /// <summary>
472        /// Set the new shiftValue and the new shiftCharacter to offset % alphabet.Length
473        /// </summary>
474        private void setKeyByValue(int offset)
475        {
476            HasChanges = true;
477
478            // making sure the shift value lies within the alphabet range
479            offset = offset % alphabet.Length;
480
481            // set the new shiftChar
482            shiftChar = alphabet[offset];
483
484            // set the new shiftValue
485            shiftValue = offset;
486
487            // Anounnce this to the settings pane
488            OnPropertyChanged(''ShiftValue'');
489            OnPropertyChanged(''ShiftChar'');
490
491            // print some info in the log.
492            LogMessage(''Accepted new shift value '' + offset + ''! (Adjusted shift character to \''' + shiftChar + ''\')'', NotificationLevel.Info);
493        }
494
495        private void setKeyByCharacter(string value)
496        {
497            try
498            {
499                int offset;
500                if (this.CaseSensitiveAlphabet)
501                {
502                    offset = alphabet.IndexOf(value[0]);
503                }
504                else
505                {
506                    offset = alphabet.ToUpper().IndexOf(char.ToUpper(value[0]));
507                }
508
509                if (offset >= 0)
510                {
511                    HasChanges = true;
512                    shiftValue = offset;
513                    shiftChar = alphabet[shiftValue];
514                    LogMessage(''Accepted new shift character \''' + shiftChar + ''\'! (Adjusted shift value to '' + shiftValue + '')'', NotificationLevel.Info);
515                    OnPropertyChanged(''ShiftValue'');
516                    OnPropertyChanged(''ShiftChar'');
517                }
518                else
519                {
520                    LogMessage(''Bad input \'''' + value + ''\''! (Character not in alphabet!) Reverting to '' + shiftChar.ToString() + ''!'', NotificationLevel.Error);
521                }
522            }
523            catch (Exception e)
524            {
525                LogMessage(''Bad input \'''' + value + ''\''! ('' + e.Message + '') Reverting to '' + shiftChar.ToString() + ''!'', NotificationLevel.Error);
526            }
527        }
528
529        #endregion
530
531        #region Algorithm settings properties (visible in the Settings pane)
532
533        [PropertySaveOrder(4)]
534        [ContextMenu(''Action'', ''Select the Algorithm action'', 1, DisplayLevel.Beginner, ContextMenuControlType.ComboBox, new int[] { 1, 2 }, ''Encrypt'', ''Decrypt'')]
535        [TaskPane(''Action'', ''setAlgorithmActionDescription'', null, 1, true, DisplayLevel.Beginner, ControlType.ComboBox, new string[] { ''Encrypt'', ''Decrypt'' })]
536        public int Action
537        {
538            get
539            {
540                return this.selectedAction;
541            }
542            set
543            {
544                if (value != selectedAction) HasChanges = true;
545                this.selectedAction = value;
546                OnPropertyChanged(''Action'');
547
548                if (ReExecute != null) ReExecute();
549            }
550        }
551
552        [PropertySaveOrder(5)]
553        [TaskPane(''Key as integer'', ''Enter the number of letters to shift. For instance a value of 1 means that the plaintext character a gets mapped to the ciphertext character B, b to C and so on.'', null, 2, true, DisplayLevel.Beginner, ControlType.NumericUpDown, ValidationType.RangeInteger, 0, 100)]
554        public int ShiftValue
555        {
556            get { return shiftValue; }
557            set
558            {
559                setKeyByValue(value);
560                if (ReExecute != null) ReExecute();
561            }
562        }
563
564
565        [PropertySaveOrder(6)]
566        [TaskPaneAttribute(''Key as single letter'', ''Enter a single letter as the key. This letter is mapped to an integer stating the position in the alphabet. The values for 'Key as integer' and 'Key as single letter' are always synchronized.'', null, 3, true, DisplayLevel.Beginner, ControlType.TextBox, ValidationType.RegEx, ''^([A-Z]|[a-z]){1,1}'')]
567        public string ShiftChar
568        {
569            get { return this.shiftChar.ToString(); }
570            set
571            {
572                setKeyByCharacter(value);
573                if (ReExecute != null) ReExecute();
574            }
575        }
576
577        [PropertySaveOrder(7)]
578        [ContextMenu(''Unknown symbol handling'', ''What should be done with encountered characters at the input which are not in the alphabet?'', 4, DisplayLevel.Expert, ContextMenuControlType.ComboBox, null, new string[] { ''Ignore (leave unmodified)'', ''Remove'', ''Replace with \'?\''' })]
579        [TaskPane(''Unknown symbol handling'', ''What should be done with encountered characters at the input which are not in the alphabet?'', null, 4, true, DisplayLevel.Expert, ControlType.ComboBox, new string[] { ''Ignore (leave unmodified)'', ''Remove'', ''Replace with \'?\''' })]
580        public int UnknownSymbolHandling
581        {
582            get { return (int)this.unknownSymbolHandling; }
583            set
584            {
585                if ((UnknownSymbolHandlingMode)value != unknownSymbolHandling) HasChanges = true;
586                this.unknownSymbolHandling = (UnknownSymbolHandlingMode)value;
587                OnPropertyChanged(''UnknownSymbolHandling'');
588
589                if (ReExecute != null) ReExecute();
590            }
591        }
592
593        [SettingsFormat(0, ''Normal'', ''Normal'', ''Black'', ''White'', Orientation.Vertical)]
594        [PropertySaveOrder(9)]
595        [TaskPane(''Alphabet'', ''This is the used alphabet.'', null, 6, true, DisplayLevel.Expert, ControlType.TextBox, '''')]
596        public string AlphabetSymbols
597        {
598          get { return this.alphabet; }
599          set
600          {
601            string a = removeEqualChars(value);
602            if (a.Length == 0) // cannot accept empty alphabets
603            {
604              LogMessage(''Ignoring empty alphabet from user! Using previous alphabet: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info);
605            }
606            else if (!alphabet.Equals(a))
607            {
608              HasChanges = true;
609              this.alphabet = a;
610              setKeyByValue(shiftValue); //re-evaluate if the shiftvalue is still within the range
611              LogMessage(''Accepted new alphabet from user: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info);
612              OnPropertyChanged(''AlphabetSymbols'');
613
614              if (ReExecute != null) ReExecute();
615            }
616          }
617        }
618
619        /// <summary>
620        /// Visible setting how to deal with alphabet case. 0 = case insentive, 1 = case sensitive
621        /// </summary>
622        //[SettingsFormat(1, ''Normal'')]
623        [PropertySaveOrder(8)]
624        [ContextMenu(''Alphabet case sensitivity'', ''Should upper and lower case be treated differently? (Should a == A)'', 7, DisplayLevel.Expert, ContextMenuControlType.ComboBox, null, new string[] { ''Case insensitive'', ''Case sensitive'' })]
625        [TaskPane(''Alphabet case sensitivity'', ''Should upper and lower case be treated differently? (Should a == A)'', null, 7, true, DisplayLevel.Expert, ControlType.ComboBox, new string[] { ''Case insensitive'', ''Case sensitive'' })]
626        public int AlphabetCase
627        {
628            get { return this.caseSensitiveAlphabet; }
629            set
630            {
631                if (value != caseSensitiveAlphabet) HasChanges = true;
632                this.caseSensitiveAlphabet = value;
633                if (value == 0)
634                {
635                    if (alphabet == (upperAlphabet + lowerAlphabet))
636                    {
637                        alphabet = upperAlphabet;
638                        LogMessage(''Changing alphabet to: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info);
639                        OnPropertyChanged(''AlphabetSymbols'');
640                        // re-set also the key (shiftvalue/shiftChar to be in the range of the new alphabet
641                        setKeyByValue(shiftValue);
642                    }
643                }
644                else
645                {
646                    if (alphabet == upperAlphabet)
647                    {
648                        alphabet = upperAlphabet + lowerAlphabet;
649                        LogMessage(''Changing alphabet to: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info);
650                        OnPropertyChanged(''AlphabetSymbols'');
651                    }
652                }
653
654                // remove equal characters from the current alphabet
655                string a = alphabet;
656                alphabet = removeEqualChars(alphabet);
657
658                if (a != alphabet)
659                {
660                    OnPropertyChanged(''AlphabetSymbols'');
661                    LogMessage(''Changing alphabet to: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info);
662                }
663
664                OnPropertyChanged(''AlphabetCase'');
665                if (ReExecute != null) ReExecute();
666            }
667        }
668
669        #endregion
670
671        #region INotifyPropertyChanged Members
672
673        public event PropertyChangedEventHandler PropertyChanged;
674
675        protected void OnPropertyChanged(string name)
676        {
677          if (PropertyChanged != null)
678          {
679            PropertyChanged(this, new PropertyChangedEventArgs(name));
680          }
681        }
682
683        #endregion
684
685        #region TaskPaneAttributeChanged-Sample
686        /// <summary>
687        /// This event is just used here for sample reasons
688        /// </summary>
689        public event TaskPaneAttributeChangedHandler TaskPaneAttributeChanged;
690
691        [TaskPane(''Enable/Disable sensitivity'', ''This setting is just a sample and shows how to enable / disable a setting.'', ''AttributeChangedSample'', 8, false, DisplayLevel.Beginner, ControlType.Button)]
692        public void EnableDisableSesitivity()
693        {
694          if (TaskPaneAttributeChanged!= null)
695          {
696            sensitivityEnabled = !sensitivityEnabled;
697            if (sensitivityEnabled)
698            {
699              TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer(''AlphabetCase'', Visibility.Visible)));
700            }
701            else
702            {
703              TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer(''AlphabetCase'', Visibility.Collapsed)));
704            }
705          }
706        }
707        #endregion TaskPaneAttributeChanged-Sample
708    }
709}
710\end{lstlisting}
711\section{Select and add an image as icon for the class Caesar}\label{sec:SelectAndAddAnImageAsIconForTheClassCaesar}
712Before we go back to the code of the Caesar class, we have to add an icon image to our project, which will be shown in the CrypTool \textbf{ribbon bar} or/and \textbf{navigation pane}. As there is no default, using an icon image is mandatory.\\\\
713\textit{\small Note: This will be changed in future. A default icon will be used if no icon image has been provided.}\\\\
714For testing purposes you may create a simple black and white PNG image with MS Paint or Paint.NET. As image size you can use 40x40 pixels for example, but as the image will be scaled when required, any size should do it. Place the image file in your project directory or in a subdirectory.\clearpage
715Then make a right click on the project item "Caesar" or any subdirectory within the Solution Explorer, and select ''Add-$>$Existing Item...'':
716
717\begin{figure}[h!]
718        \centering
719                \includegraphics{figures/add_existing_item.jpg}
720        \caption{Add existing item}
721        \label{fig:add_existing_item}
722\end{figure}
723
724As you can see, in our solution we create an new folder named ''Images'' (make a right click on the project item ''Caesar'' and select ''Add-$>$New Folder'') and placed there the new icon by clicking right on the folder as mentioned aboved.\clearpage
725Then select ''Image Files'' as file type, and choose the icon for your plugin:
726\begin{figure}[h!]
727        \centering
728                \includegraphics{figures/choose_icon.jpg}
729        \caption{Choose the right icon}
730        \label{fig:choose_icon}
731\end{figure}
732Finally we have to set the icon as a ''Resource'' to avoid providing the icon as a separate file. Make a right click on the icon and select the item ''Properties'':\clearpage
733\begin{figure}[h!]
734        \centering
735                \includegraphics{figures/icon_properties.jpg}
736        \caption{Icon properties}
737        \label{fig:icon_properties}
738\end{figure}
739In the ''Properties'' panel you have to set the ''Build Action'' to ''Resource'' (not embedded resource):
740\begin{figure}[h!]
741        \centering
742                \includegraphics{figures/icon_build_action.jpg}
743        \caption{Icon  build action}
744        \label{fig:icon_build_action}
745\end{figure}
746\section{Set the attributes for the class Caesar}\label{sec:SetTheAttributesForTheClassCaesar}
747Now let's go back to the code of the Caesar class (''Caesar.cs'' file). First we have to set the necessary attributes for our class. This attributes are used to provide additional information for the CrypTool 2.0 environment. If not set, your plugin won't show up in the GUI, even if everything else is implemented correctly.
748
749Attributes are used for \textbf{declarative} programming and provide meta data, that can be attached to the existing .NET meta data , like classes and properties. CrypTool provides a set of custom attributes, that are used to mark the different parts of your plugin.
750
751
752\textit{[Author]}\\
753The first attribute called ''Author'' is optional, which means we are not forced to define this attribute. It provides the additional information about the plugin developer. This informations you can see for example in the TaskPane as shown on a screenshot above. We set this attribute to demonstrate how it has to look in case you want to provide this attribute.
754\begin{figure}[h!]
755        \centering
756                \includegraphics[width=1.00\textwidth]{figures/attribute_author.jpg}
757        \caption{Attribute author}
758        \label{fig:attribute_author}
759\end{figure}
760
761As we can see above the author attribute takes four elements of type string. These elements are:
762\begin{itemize}
763        \item Author = name of the plugin developer
764        \item Email = email of the plugin developer if he wants to be contact
765        \item Institute = current employment of the developer like University or Company
766        \item Url = the website or homepage of the developer
767\end{itemize}
768All this elements are also optional. The developer decides what he wants to publish. Unused elements shall be set to null or a zero-length string ('''').
769
770Our author attribute should look now as you can see below:
771\begin{figure}[h!]
772        \centering
773                \includegraphics[width=1.00\textwidth]{figures/attribute_author_filled.jpg}
774        \caption{Filled author auttribute}
775        \label{fig:attribute_author_filled}
776\end{figure}
777
778
779\textit{[PluginInfo]}\\
780The second attribute called ''PluginInfo'' provides the necessary information about the plugin like caption and tool tip. This attribute is mandatory. The attribute has the definition as you can see below:
781\begin{figure}[h]
782        \centering
783                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo.jpg}
784        \caption{Attribute PluginInfo}
785        \label{fig:attribute_plugininfo}
786\end{figure}
787
788This attribute expects the following elements:
789\begin{itemize}
790        \item resourceFile = Defines if resource files will be provided and where to find them. E.g. to provide the plugin multilingual you can store the labels in such a resource file. This element is optional.
791        \item startable = Set this flag to true only if your plugin is some kind of input or generator plugin (probably if your plugin just has outputs and no inputs). In all other cases use false here. This flag is important. Setting this flag to true for a non input/generator plugin will result in unpredictable chain runs. This element is mandatory.
792        \item caption = from type string, the name of the plugin or the resource field name if you provide the caption in a resource file (e.g. to provide the button content). This element is mandatory.
793        \item toolTip = from type string, description of the plugin or the resource field name if you provide the toolTip in a resource file (e.g. to provide the button tool tip). This element is optional.
794        \item descriptionUrl = from type string, define where to find the whole description files (e.g. XAML files). This element is optional.
795        \item icons = from type string array, which provides all necessary icon paths you want to use in the plugin (e.g. the plugin icon as seen above). This element is mandatory.
796\end{itemize}
797Unused optional elements shall be set to null or a zero-length string ('''').
798
799
800\textit{\small Note 1: It is possible to use the plugin without setting a caption though it is not recommended. This will be changed in future and the plugin will fail to load without a caption.\\\\
801\small Note 2: Currently a zero-length toolTip string appears as empty box. This will be changed in future.\\\\
802\small Note 3: Tooltip and description currently do not support internationalization and localization. This will be changed in future.\\\\}
803In our example the first parameter called ''resourceFile'' has to be set to ''Cryptool.Caesar.Resource.res'' because we want to provide the plugin multilingual and want to store the labels and caption in a resource file. Otherwise ignore this element.
804\begin{figure}[h]
805        \centering
806                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo_resourceFile.JPG}
807        \caption{Attribute PluginInfo element resourceFile}
808        \label{fig:attribute_plugininfo_resourceFile}
809\end{figure}
810
811The second parameter called ''startable'' has to be set to ''false'', because our encryption algorithm is neither an input nor generator plugin.
812\begin{figure}[h!]
813        \centering
814                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo_startable.jpg}
815        \caption{Attribute PluginInfo startable}
816        \label{fig:attribute_plugininfo_startable}
817\end{figure}
818
819The next two parameters are needed to define the plugin's name and its description. Now that we decided to provide a resource file we have to place here the both resource field names which contains the description and captions. Otherwise just write here a simple string text:
820\begin{figure}[h!]
821        \centering
822                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo_description.jpg}
823        \caption{Attribute PluginInfo name and description}
824        \label{fig:attribute_plugininfo_description}
825\end{figure}
826
827The next element defines the location path of the description file. The parameter is made up by $<$Assembly name$>$/$<$filename$>$ or $<$Assembly name$>$/$<$Path$>$/$<$file name$>$ if you want to store your description files in a separate folder (as seen on the icon). The description file has to be of type XAML. In our case we create a folder called ''DetailedDescription'' and store our XAML file there with the necessary images if needed. How you manage the files and folders is up to you. This folder could now look as you can see below:
828\begin{figure}[h!]
829        \centering
830                \includegraphics{figures/attribute_plugininfo_detailed_descr_path.jpg}
831        \caption{Attribute PluginInfo icon and description file path}
832        \label{fig:attribute_plugininfo_icon_path}
833\end{figure}
834
835Accordingly the attribute parameter has to be set to:
836\begin{figure}[h!]
837        \centering
838                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo_detailed_descr.jpg}
839        \caption{Attribute PluginInfo description file}
840        \label{fig:attribute_plugininfo_icon}
841\end{figure}
842
843The detailed description could now look like this in CrypTool (right click plugin icon on workspace and select ''Show description''):\clearpage
844\begin{figure}[h!]
845        \centering
846                \includegraphics[width=1.00\textwidth]{figures/xaml_description.jpg}
847        \caption{XAML detailed description}
848        \label{fig:xaml_description}
849\end{figure}
850
851The last parameter tells CrypTool the names of the provided icons. This parameter is made up by $<$Assembly name$>$/$<$file name$>$ or $<$Assembly name$>$/$<$Path$>$/$<$file name$>$.\\\\
852The most important icon is the plugin icon, which will be shown in CrypTool in the ribbon bar or navigation pane (This is the first icon in list, so you have to provide at least one icon for a plugin). As named above how to add an icon to the solution accordingly we have to tell CrypTool where to find the icon by setting this parameter as you can see below:
853\begin{figure}[h!]
854        \centering
855                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo_icons.jpg}
856        \caption{Attribute PluginInfo icons}
857        \label{fig:attribute_plugininfo_icons}
858\end{figure}
859
860You can define further icon paths if needed, by adding the path string separated by a comma. We just add here two further icons (don't forget to add the icons to your solution) to provide them for the context menu in the CrypTool workspace.\\\\
861\textit{[EncryptionType]}\\
862The third and last attribute called ''EncryptionType'' is needed to tell CrypTool which type of plugin we want to provide. CrypTool is now able to place the plugin in the right group at the navigation pane or/and ribbon bar. Therefore Caesar is a classical algorithm so we have to set the following attribute:
863\begin{figure}[h]
864        \centering
865                \includegraphics[width=1.00\textwidth]{figures/attribute_encryption_type.JPG}
866        \caption{Attribute encryption type}
867        \label{fig:attribute_encryption_type}
868\end{figure}
869
870The ''EncryptionType'' attribute can also be set as the following types:
871\begin{itemize}
872        \item Asymmetric = for asymmetric encryption algorithms like RSA
873        \item Classic = for classic encryption or hash algorithms like Caesar or MD5
874        \item Hybrid = for a combination of several algorithm where the data is encrypted symmetric and the encryption key asymmetric
875        \item SymmetricBlock = for all block cipher algorithms like DES, AES or Twofish
876        \item SymmetricStream = for all stream cipher algorithms like RC4, Rabbit or SEAL
877\end{itemize}
878
879
880\section{Set the private variables for the settings in the class Caesar}\label{sec:SetThePrivateVariablesForTheSettingsInTheClassCaesar}
881The next step is to define some private variables needed for the settings, input and output data which could look like this:
882\begin{lstlisting}
883public class Caesar : IEncryption
884{
885        #region Private variables
886        private CaesarSettings settings;
887        private string inputString;
888        private string outputString;
889        private enum CaesarMode { encrypt, decrypt };
890        private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
891        #endregion
892\end{lstlisting}
893Please notice if there is a sinuous line at the code you type for example at the ''CryptoolStream'' type of the variable listCryptoolStreamsOut. ''CryptoolStream'' is a data type for input and output between plugins and is able to handle large data amounts. To use the CrypTool own stream type, include the namespace ''Cryptool.PluginBase.IO'' with a ''using'' statement as explained in chapter \ref{sec:CaesarNamespacesAndInheritance}. Check the other code entries while typing and update the missing namespaces.\\
894The following private variables are being used in this example:
895\begin{itemize}
896        \item CaesarSettings settings: required to implement the IPlugin interface properly
897        \item string inputString: sting to read the input data from
898        \item string outputString: string to save the output data
899        \item enum CaesarMode: our own definition how to select between an encryption or decryption. It's up to you how to solve your algorithm
900        \item List$<$CryptoolStream$>$ listCryptoolStreamsOut: list of all streams being created by Caesar plugin, required to perform a clean dispose
901\end{itemize}
902\section{Define the code of the class Caesar to fit the interface}\label{sec:DefineTheCodeOfTheClassCaesarToFitTheInterface}
903Next we have to complete our code to correctly serve the interface.\\
904First we add a constructor to our class where we can create an instance of our settings class and a function to handle events:
905\begin{lstlisting}
906public class Caesar : IEncryption
907{
908        #region Private variables
909        private CaesarSettings settings;
910        private string inputString;
911        private string outputString;
912        private enum CaesarMode { encrypt, decrypt };
913        private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
914        #endregion
915       
916        public Caesar()
917        {
918                this.settings = new CaesarSettings();
919                this.settings.LogMessage += Caesar_LogMessage;
920        }
921\end{lstlisting}
922Secondly, we have to implement the property ''Settings'' defined in the interface:
923\begin{lstlisting}
924public ISettings Settings
925{
926        get { return (ISettings)this.settings; }
927        set { this.settings = (CaesarSettings)value; }
928}
929\end{lstlisting}
930Thirdly we have to define five properties with their according attributes. This step is necessary to tell CrypTool that these properties are input/output properties used for data exchange with other plugins or to provide our plugin with external data.\\
931The attribute is named ''PropertyInfo'' and consists of the following elements:
932\begin{itemize}
933        \item direction = defines whether this property is an input or output property, i.e. whether it reads input data or writes output data
934        \begin{itemize}
935                \item Direction.Input
936                \item Direction.Output
937        \end{itemize}
938        \item caption = caption of the property (e.g. shown at the input on the dropped icon in the editor), see below:
939\begin{figure}[h]
940        \centering
941                \includegraphics{figures/property_caption.jpg}
942        \caption{Possible property caption}
943        \label{fig:property_caption}
944\end{figure}
945        \item toolTip = tooltip of the property (e.g. shown at the input arrow on the dropped icon in the editor), see above
946        \item descriptionUrl = not used right now
947        \item mandatory = this flag defines whether an input is required to be connected by the user. If set to true, there has to be an input connection that provides data. If no input data is provided for mandatory input, your plugin will not be executed in the workflow chain. If set to false, connecting the input is optional. This only applies to input properties. If using Direction.Output, this flag is ignored.
948        \item hasDefaultValue = if this flag is set to true, CrypTool treats this plugin as though the input has already input data.
949        \item DisplayLevel = define in which display levels your property will be shown in CrypTool. CrypTool provides the following display levels:
950        \begin{itemize}
951                \item DisplayLevel.Beginner
952                \item DisplayLevel.Experienced
953                \item DisplayLevel.Expert
954                \item DisplayLevel.Professional
955        \end{itemize}
956        \item QuickWatchFormat = defines how the content of the property will be shown in the quick watch. CrypTool accepts the following quick watch formats:
957        \begin{itemize}
958                \item QuickWatchFormat.Base64
959                \item QuickWatchFormat.Hex
960                \item QuickWatchFormat.None
961                \item QuickWatchFormat.Text\\
962                A quick watch in Hex could look like this:
963\begin{figure}[h]
964        \centering
965                \includegraphics{figures/quick_watch.jpg}
966        \caption{Possible quick watch}
967        \label{fig:quick_watch}
968\end{figure}
969        \end{itemize}
970        \item quickWatchConversionMethod = this string points to a conversion method; most plugins can use a ''null'' value here, because no conversion is necessary. The QuickWatch function uses system ''default'' encoding to display data. So only if your data is in some other format, like Unicode or UTF8, you have to provide the name of a conversion method as string. The method header has to look like this:
971\begin{lstlisting}
972object YourMethodName(string PropertyNameToConvert)
973\end{lstlisting}
974\end{itemize}
975First we define the ''InputString'' property getter and setter which is needed to provide our plugin with data which has to be encrypted or decrypted:
976\begin{lstlisting}
977[PropertyInfo(Direction.InputData, ''Text input'', ''Input a string to be processed by the Caesar cipher'', '''', true, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
978public string InputString
979{
980        get { return this.inputString; }
981        set
982  {
983                if (value != inputString)
984                {
985                        this.inputString = value;
986                        OnPropertyChanged(''InputString'');
987                }
988        }
989}
990\end{lstlisting}
991In the getter we return the value of the input data.\\\\
992\textit{\small Note 1: It is currently not possible to read directly from the input data stream without creating an intermediate CryptoolStream.\\\\
993\small Note 2: The naming may be confusing. The new CryptoolStream is not an output stream, but it is added to the list of output streams to enable a clean dispose afterwards. See chapter 9 below.\\\\}
994The setter checkes if the input value has changed and sets the new input data and announces the data to the CrypTool 2.0 environment by using the expression ''OnPropertyChanged($<$Property name$>$)''. For input properties this step is necessary to update the quick watch view.\\
995The output data property (which provides the encrypted or decrypted input data) could look like this:
996\begin{lstlisting}
997[PropertyInfo(Direction.OutputData, ''Text output'', ''The string after processing with the Caesar cipher'', '''', false, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
998public string OutputString
999{
1000        get { return this.outputString; }
1001        set
1002        {
1003                outputString = value;
1004                OnPropertyChanged(''OutputString'');
1005        }
1006}
1007\end{lstlisting}
1008CrypTool does not require implementing output setters, as they will never be called from outside of the plugin. Nevertheless in this example our plugin accesses the property itself, therefore we chose to implement the setter.\\
1009You can also provide additional output data types if you like. For example we provide also an output data of type CryptoolStream, an input data for external alphabets and an input data for the shift value of our Caesar algorithm:
1010\begin{lstlisting}
1011[PropertyInfo(Direction.OutputData, ''propStreamOutputToolTip'', ''propStreamOutputDescription'', '''', false, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
1012public CryptoolStream OutputData
1013{
1014        get
1015        {
1016                if (outputString != null)
1017                {
1018                        CryptoolStream cs = new CryptoolStream();
1019                        listCryptoolStreamsOut.Add(cs);
1020                        cs.OpenRead(Encoding.Default.GetBytes(outputString.ToCharArray()));
1021                        return cs;
1022                }
1023                else
1024                {
1025                        return null;
1026                }
1027        }
1028        set { }
1029}
1030
1031[PropertyInfo(Direction.InputData, ''External alphabet input'', ''Input a string containing the alphabet which should be used by Caesar.\nIf no alphabet is provided on this input, the internal alphabet will be used.'', '''', false, false, DisplayLevel.Expert, QuickWatchFormat.Text, null)]
1032public string InputAlphabet
1033{
1034        get { return ((CaesarSettings)this.settings).AlphabetSymbols; }
1035        set
1036        {
1037                if (value != null && value != settings.AlphabetSymbols)
1038                {
1039                        ((CaesarSettings)this.settings).AlphabetSymbols = value;
1040                        OnPropertyChanged(''InputAlphabet'');
1041                }
1042        }
1043}
1044
1045[PropertyInfo(Direction.InputData, ''Shift value (integer)'', ''Same setting as Shift value in Settings-Pane but as dynamic input.'', '''', false, false, DisplayLevel.Expert, QuickWatchFormat.Text, null)]
1046public int ShiftKey
1047{
1048        get { return settings.ShiftKey; }
1049        set
1050        {
1051                if (value != settings.ShiftKey)
1052                {
1053                        settings.ShiftKey = value;
1054                }
1055        }
1056}
1057\end{lstlisting}
1058This property's setter is not called and therefore not implemented.\\
1059The CrypTool-API provides two methods to send messages to the CrypTool. The method ''GuiLogMessage'' is used to send messages to the CrypTool status bar. This is a nice feature to inform the user what your plugin is currently doing.
1060\begin{figure}[h]
1061        \centering
1062                \includegraphics[width=1.00\textwidth]{figures/status_bar.jpg}
1063        \caption{Status Bar}
1064        \label{fig:status_bar}
1065\end{figure}\\
1066The method takes two parameters which are:
1067\begin{itemize}
1068        \item Message = will be shown in the status bar and is of type string
1069        \item NotificationLevel = to group the messages to their alert level
1070        \begin{itemize}
1071                \item NotificationLevel.Error
1072                \item NotificationLevel.Warning
1073                \item NotificationLevel.Info
1074                \item NotificationLevel.Debug
1075        \end{itemize}
1076\end{itemize}
1077As we can recognize we have two methods named ''OnPropertyChanged'' and ''GuiLogMessage'' which are not defined. So we have to define these two methods as you can see below:
1078\begin{lstlisting}
1079public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
1080private void GuiLogMessage(string message, NotificationLevel logLevel)
1081{
1082        EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(message, this, logLevel));
1083}
1084
1085public event PropertyChangedEventHandler PropertyChanged;
1086
1087public void OnPropertyChanged(String name)
1088{
1089        EventsHelper.PropertyChanged(PropertyChanged, this, new PropertyChangedEventArgs(name));
1090}
1091\end{lstlisting}
1092To use the ''PropertyChangedEventHandler'' you have to include the namespace ''System.ComponentModel''.\\
1093Our whole included namespaces looks now like this:
1094\begin{lstlisting}
1095using System.Collections.Generic;
1096using System.Text;
1097using System.ComponentModel;
1098using System.Windows.Control;
1099
1100using Cryptool.PluginBase;
1101using Cryptool.PluginBase.Cryptography;
1102using Cryptool.PluginBase.IO;
1103using Cryptool.PluginBase.Miscellaneous;
1104\end{lstlisting}
1105\section{Complete the actual code for the class Caesar}\label{sec:CompleteTheActualCodeForTheClassCaesar}
1106Up to now, the plugin is ready for the CrypTool base application to be accepted and been shown correctly in the CrypTool menu. What we need now, is the implementation of the actual algorithm in the function ''Execute()'' which is up to you as the plugin developer. CrypTool will always call first the Execute() function.If you place the whole algorithm in this function or split in other as needed is also up to you.
1107
1108We decided to split our algorithm encryption and decryption in two separate functions, which finally call the function ProcessCaesar.
1109
1110Let us demonstrate the Execute() function, too:
1111\begin{lstlisting}
1112private void ProcessCaesar(CaesarMode mode)
1113{
1114        CaesarSettings cfg = (CaesarSettings)this.settings;
1115        StringBuilder output = new StringBuilder('''');
1116        string alphabet = cfg.AlphabetSymbols;
1117
1118  // in case we want don't consider case in the alphabet, we use only capital letters, hence transform
1119        // the whole alphabet to uppercase
1120        if (!cfg.CaseSensitiveAlphabet)
1121        {
1122                alphabet = cfg.AlphabetSymbols.ToUpper(); ;
1123        }
1124
1125        if (inputString != null)
1126        {
1127                for (int i = 0; i < inputString.Length; i++)
1128                {
1129                        // get plaintext char which is currently processed
1130                        char currentchar = inputString[i];
1131
1132                        // remember if it is upper case (otherwise lowercase is assumed)
1133                        bool uppercase = char.IsUpper(currentchar);
1134
1135                        // get the position of the plaintext character in the alphabet
1136                        int ppos = 0;
1137                        if (cfg.CaseSensitiveAlphabet)
1138                        {
1139                                ppos = alphabet.IndexOf(currentchar);
1140                        }
1141                        else
1142                        {
1143                                ppos = alphabet.IndexOf(char.ToUpper(currentchar));
1144                        }
1145
1146                        if (ppos >= 0)
1147                        {
1148                                // we found the plaintext character in the alphabet, hence we do the shifting
1149                                int cpos = 0; ;
1150                                switch (mode)
1151                                {
1152                                        case CaesarMode.encrypt:
1153                                                cpos = (ppos + cfg.ShiftKey) % alphabet.Length;
1154                                                break;
1155                                        case CaesarMode.decrypt:
1156                                                cpos = (ppos - cfg.ShiftKey + alphabet.Length) % alphabet.Length;
1157                                                break;
1158                                }
1159
1160                                // we have the position of the ciphertext character, hence just output it in the correct case
1161                                if (cfg.CaseSensitiveAlphabet)
1162                                {
1163                                        output.Append(alphabet[cpos]);
1164                                }
1165                                else
1166                                {
1167                                        if (uppercase)
1168                                        {
1169                                                output.Append(char.ToUpper(alphabet[cpos]));
1170                                        }
1171                                        else
1172                                        {
1173                                                output.Append(char.ToLower(alphabet[cpos]));
1174                                        }
1175                                }
1176                        }
1177                        else
1178                        {
1179                                // the plaintext character was not found in the alphabet, hence proceed with handling unknown characters
1180                                switch ((CaesarSettings.UnknownSymbolHandlingMode)cfg.UnknownSymbolHandling)
1181                                {
1182                                        case CaesarSettings.UnknownSymbolHandlingMode.Ignore:
1183                                                output.Append(inputString[i]);
1184                                                break;
1185                                        case CaesarSettings.UnknownSymbolHandlingMode.Replace:
1186                                                output.Append('?');
1187                                                break;
1188                                }
1189                        }
1190
1191                        //show the progress
1192                        if (OnPluginProgressChanged != null)
1193                        {
1194                                OnPluginProgressChanged(this, new PluginProgressEventArgs(i, inputString.Length - 1));
1195                        }
1196                }
1197                outputString = output.ToString();
1198                OnPropertyChanged(''OutputString'');
1199                OnPropertyChanged(''OutputData'');
1200        }
1201}
1202
1203public void Encrypt()
1204{
1205        ProcessCaesar(CaesarMode.encrypt);
1206}
1207
1208public void Decrypt()
1209{
1210        ProcessCaesar(CaesarMode.decrypt);
1211}
1212
1213public void Execute()
1214{
1215        switch (settings.Action)
1216        {
1217                case 0:
1218                        Caesar_LogMessage(''encrypting'', NotificationLevel.Debug);
1219                        Encrypt();
1220                        break;
1221                case 1:
1222                        Decrypt();
1223                        break;
1224                default:
1225        break;
1226        }
1227}
1228\end{lstlisting}
1229It is important to make sure that all changes of output properties will be announced to the CrypTool environment. In this example this happens by calling the setter of OutputData which in turn calls ''OnPropertyChanged'' for both output properties ''OutputData'' and ''OutputDataStream''. Instead of calling the property's setter you can as well call ''OnPropertyChanged'' directly within the ''Execute()'' method.\clearpage
1230Certainly you have seen the unknown method ''ProgressChanged'' which you can use to show the current algorithm process as a progress on the plugin icon.
1231To use this method you also have to declare this method to afford a successful compilation:
1232\begin{lstlisting}
1233public event PluginProgressChangedEventHandler OnPluginProgressChanged;
1234private void ProgressChanged(double value, double max)
1235{
1236        EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, max));
1237}
1238\end{lstlisting}
1239\section{Perform a clean dispose}\label{sec:PerformACleanDispose}
1240Be sure you have closed and cleaned all your streams after execution and when CrypTool decides to dispose the plugin instance. Though not required, we run the dispose code before execution as well:
1241\begin{lstlisting}
1242public void Dispose()
1243{
1244        foreach(CryptoolStream stream in listCryptoolStreamOut)
1245        {
1246                stream.Close();
1247        }
1248        listCryptoolStreamOut.Clear();
1249}
1250
1251public void PostExecution()
1252{
1253        Dispose();
1254}
1255
1256public void PreExecution()
1257{
1258        Dispose();
1259}
1260\end{lstlisting}\clearpage
1261\section{Finish implementation}\label{sec:FinishImplementation}
1262When adding plugin instances to the CrypTool workspace, CrypTool checks whether the plugin runs without any exception. If any IPlugin method throws an exception, CrypTool will show an error and prohibit using the plugin. Therefore we have to remove the ''NotImplementedException'' from the methods ''Initialize()'', ''Pause()'' and ''Stop()''. In our example it's sufficient to provide empty implementations.
1263\begin{lstlisting}
1264public void Initialize()
1265{
1266}
1267
1268public void Pause()
1269{
1270}
1271
1272public void Stop()
1273{
1274}
1275\end{lstlisting}
1276The methods ''Presentation()'' and ''QuickWatchPresentation()'' can be used if a plugin developer wants to provide an own visualization of the plugin algorithm which will be shown in CrypTool. Take a look at the PRESENT plugin to see how a custom visualization can be realized. For our Caesar example we don't want to implement a custom visualization, therefore we return ''null'':
1277\begin{lstlisting}
1278public UserControl Presentation
1279{
1280        get { return null; }
1281}
1282
1283public UserControl QuickWatchPresentation
1284{
1285        get { return null; }
1286}
1287\end{lstlisting}
1288Your plugin should compile without errors at this point.\clearpage
1289
1290\section{Import the plugin to CrypTool and test it}\label{sec:ImportThePluginToCryptoolAndTestIt}
1291After you have built the plugin, you need to move the newly created plugin DLL to a location, where CrypTool can find it. To do this, there are the following ways:
1292\begin{itemize}
1293        \item Copy your plugin DLL file in the folder ''CrypPlugins'' which has to be in the same folder as the CrypTool executable, called ''CrypWin.exe''. If necessary, create the folder ''CrypPlugins''.
1294\begin{figure}[h]
1295        \centering
1296                \includegraphics{figures/copy_dll_global_storage.jpg}
1297        \caption{Copy plugin to global storage}
1298        \label{fig:copy_dll_global_storage}
1299\end{figure}
1300
1301This folder is called ''Global storage'' in the CrypTool architecture. Changes in this folder will take effect for all users on a multi user Windows. Finally restart CrypTool.\clearpage
1302\begin{figure}[h]
1303        \centering
1304                \includegraphics{figures/global_storage.jpg}
1305        \caption{Plugins global storage}
1306        \label{fig:global_storage}
1307\end{figure}
1308
1309        \item Copy your plugin DLL file in the folder ''CrypPlugins'' which is located in your home path in the folder ''ApplicationData'' and restart CrypTool.  This home folder path is called ''Custom storage'' in the CrypTool architecture. Changes in this folder will only take effect for current user.  On a German Windows XP the home folder path could look like:
1310''C:\textbackslash Dokumente und Einstellungen\textbackslash $<$User$>$\textbackslash Anwendungsdaten\textbackslash CrypPlugins'' and in Vista/Windows7 the path will look like ''C:\textbackslash Users\textbackslash $<$user$>$\textbackslash Application Data\textbackslash CrypPlugins''.\clearpage
1311\begin{figure}[h]
1312        \centering
1313                \includegraphics[width=1.00\textwidth]{figures/custom_storage.jpg}
1314        \caption{Plugins custom storage}
1315        \label{fig:custom_storage}
1316\end{figure}
1317        \item You can also import new plugins directly from the CrypTool interface. Just execute CrypWin.exe and select the ''Download Plugins'' button. An ''Open File Dialog'' will open and ask where the new plugin is located. After selecting the new plugin, CrypTool will automatically import the new plugin in the custom storage folder. With this option you will not have to restart CrypTool. All according menu entries will be updated automatically.
1318Notice, that this plugin importing function only accepts \textbf{signed} plugins.
1319
1320\textit{\small Note: This option is a temporary solution for importing new plugins. In the future this will be done online by a web service.}\clearpage
1321
1322        \item Use post-build in your project properties to copy the DLL automatically after building it in Visual Studio with other plugins. Right-click on your plugin project and select ''Properties'':
1323\begin{figure}[h]
1324        \centering
1325                \includegraphics{figures/solution_properties.JPG}
1326        \caption{Solution Properties}
1327        \label{fig:solution_properties}
1328\end{figure}\clearpage
1329Select ''Build Events'':
1330\begin{figure}[h]
1331        \centering
1332                \includegraphics{figures/post_build.JPG}
1333        \caption{Build Events}
1334        \label{fig:post_build}
1335\end{figure}
1336
1337Enter the following text snippet into ''Post-build event command line'':\\\\
1338cd ''\$(ProjectDir)''\\
1339cd ..\textbackslash ..\textbackslash CrypWin\$(OutDir)\\
1340if not exist ''./CrypPlugins'' mkdir ''./CrypPlugins''\\
1341del /F /S /Q /s /q ''\fcolorbox{yellow}{yellow}{Caesar}*.*''\\
1342copy ''\$(TargetDir)\fcolorbox{yellow}{yellow}{Caesar}*.*'' ''./CrypPlugins''\\\\
1343You need to adapt the yellow marked field to your actual project name.
1344\end{itemize}
1345
1346
1347\section{Source code and source template}\label{sec:SourceCodeAndSourceTemplate}
1348Here you can download the whole source code which was presented in this ''Howto'' as a Visual Studio \textbf{solution}:\\\\
1349\textit{username: anonymous\\
1350password: not required\\}
1351\htmladdnormallink{https://www.cryptool.org/svn/CrypTool2/trunk/CrypPlugins/Caesar/}{https://www.cryptool.org/svn/CrypTool2/trunk/CrypPlugins/Caesar/}\\\\
1352%\textit{\small Note: You should commit your sources to our subversion so often you can. This will ensure your interoperability for further development.}\\\\
1353Here you can download the Visual Studio plugin \textbf{template} to begin with the development of a new CrypTool plugin:\\\\
1354\htmladdnormallink{http://cryptool2.vs.uni-due.de/downloads/template/encryptionplugin.zip}{http://cryptool2.vs.uni-due.de/downloads/template/encryptionplugin.zip}\clearpage
1355\section{Provide a workflow file of your plugin}\label{ProvideAWorkflowFileOfYourPlugin}
1356Every plugin developer should provide a workflow file which shows his algorithm working in CrypTool2. You will automatically create a workflow file by saving your project which was created on CrypTool2 work space. Here is an example how a workflow could look like:
1357\begin{figure}[h]
1358        \centering
1359                \includegraphics{figures/sample.jpg}
1360        \caption{Plugin sample}
1361        \label{fig:sample}
1362\end{figure}
Note: See TracBrowser for help on using the repository browser.