Esempio n. 1
0
        public void SaveSessionsToFile()
        {
            bool   bSuccess  = false;
            string sFilename = GetSazFilePath();

            try
            {
                try
                {
                    Monitor.Enter(oAllSessions);
                    TranscoderTuple oExporter = FiddlerApplication.oTranscoders.GetExporter("SAZ");

                    if (null != oExporter)
                    {
                        var dictOptions = new Dictionary <string, object>();
                        dictOptions.Add("Filename", sFilename);
                        bSuccess = FiddlerApplication.DoExport("SAZ", oAllSessions.ToArray(), dictOptions, null);
                    }
                    else
                    {
                        WriteCommandResponse("Save failed because the SAZ Format Exporter was not available.");
                    }
                }
                finally
                {
                    Monitor.Exit(oAllSessions);
                }

                WriteCommandResponse(bSuccess ? ("Wrote: " + sFilename) : ("Failed to save: " + sFilename));
            }
            catch (Exception eX)
            {
                WriteCommandResponse("Save failed: " + eX.Message);
            }
        }
Esempio n. 2
0
        public static void ReadSessions(List <Fiddler.Session> oAllSessions)
        {
            TranscoderTuple oImporter = FiddlerApplication.oTranscoders.GetImporter("SAZ");

            //
            if (null != oImporter)
            {
                openFileDialog1                  = new System.Windows.Forms.OpenFileDialog();
                openFileDialog1.FileName         = "";
                openFileDialog1.Filter           = "saz文件|*.saz";
                openFileDialog1.RestoreDirectory = true;
                openFileDialog1.FilterIndex      = 1;
                openFileDialog1.InitialDirectory = Environment.CurrentDirectory.ToString() + @"\log";
                string fName = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\ToLoad.saz";
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    fName = openFileDialog1.FileName;
                    //MessageBox.Show(fName);
                }
                 
                Dictionary <string, object> dictOptions = new Dictionary <string, object>();
                dictOptions.Add("Filename", fName);

                Session[] oLoaded = FiddlerApplication.DoImport("SAZ", false, dictOptions, null);

                if ((oLoaded != null) && (oLoaded.Length > 0))
                {
                    oAllSessions.AddRange(oLoaded);
                    WriteCommandResponse("Loaded: " + oLoaded.Length + " sessions.");
                }
            }
        }
Esempio n. 3
0
        private static void SaveSessionsToDesktop(List <Fiddler.Session> oAllSessions)
        {
            bool   bSuccess  = false;
            string sFilename = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
                               + @"\" + DateTime.Now.ToString("hh-mm-ss") + ".saz";

            try
            {
                try
                {
                    Monitor.Enter(oAllSessions);
                    TranscoderTuple oExporter = FiddlerApplication.oTranscoders.GetExporter("SAZ");

                    if (null != oExporter)
                    {
                        Dictionary <string, object> dictOptions = new Dictionary <string, object>();
                        dictOptions.Add("Filename", sFilename);
                        // dictOptions.Add("Password", "pencil");

                        bSuccess = FiddlerApplication.DoExport("SAZ", oAllSessions.ToArray(), dictOptions, null);
                    }
                }
                finally
                {
                    Monitor.Exit(oAllSessions);
                }

                WriteCommandResponse(bSuccess ? ("Wrote: " + sFilename) : ("Failed to save: " + sFilename));
            }
            catch (Exception eX)
            {
                Console.WriteLine("Save failed: " + eX.Message);
            }
        }
Esempio n. 4
0
        private void SaveSessionsToDumpFolder(List <Fiddler.Session> Sessions, bool FullSession = false)
        {
            bool bSuccess = false;


            if (!Directory.Exists("proxydumps"))
            {
                try
                {
                    Directory.CreateDirectory("proxydumps");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("[ERROR] ExportSessions: " + ex.ToString());
                }
            }

            string sFilename = @"proxydumps\" + DateTime.Now.ToString("hh-mm-ss-fff") + "_dump_SPLIT.saz";

            if (FullSession)
            {
                sFilename = @"proxydumps\" + DateTime.Now.ToString("hh-mm-ss-fff") + "_dump_FULL.saz";
            }
            try
            {
                try
                {
                    Monitor.Enter(Sessions);
                    TranscoderTuple oExporter = FiddlerApplication.oTranscoders.GetExporter("SAZ");

                    if (null != oExporter)
                    {
                        Dictionary <string, object> dictOptions = new Dictionary <string, object>();
                        dictOptions.Add("Filename", sFilename);
                        // dictOptions.Add("Password", "pencil");

                        bSuccess = FiddlerApplication.DoExport("SAZ", Sessions.ToArray(), dictOptions, null);
                    }
                    else
                    {
                        Console.WriteLine("Save failed because the SAZ Format Exporter was not available.");
                    }
                }
                finally
                {
                    Monitor.Exit(Sessions);
                }

                WriteCommandResponse(bSuccess ? ("Wrote: " + sFilename) : ("Failed to save: " + sFilename));
            }
            catch (Exception eX)
            {
                Console.WriteLine("Save failed: " + eX.Message);
            }
        }
Esempio n. 5
0
        private static void ReadSessions(List <Fiddler.Session> oAllSessions)
        {
            TranscoderTuple oImporter = FiddlerApplication.oTranscoders.GetImporter("SAZ");

            if (null != oImporter)
            {
                Dictionary <string, object> dictOptions = new Dictionary <string, object>();
                dictOptions.Add("Filename", Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\ToLoad.saz");

                Session[] oLoaded = FiddlerApplication.DoImport("SAZ", false, dictOptions, null);

                if ((oLoaded != null) && (oLoaded.Length > 0))
                {
                    oAllSessions.AddRange(oLoaded);
                    WriteCommandResponse("Loaded: " + oLoaded.Length + " sessions.");
                }
            }
        }
Esempio n. 6
0
        private void ImportSessions(List <Session> oAllSessions)
        {
            TranscoderTuple oImporter = oTranscoders.GetImporter("SAZ");

            if (null != oImporter)
            {
                Dictionary <string, object> dictOptions = new Dictionary <string, object>();
                dictOptions.Add("Filename", Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\ToLoad.saz");

                Session[] oLoaded = DoImport("SAZ", false, dictOptions, null);

                if ((oLoaded != null) && (oLoaded.Length > 0))
                {
                    oAllSessions.AddRange(oLoaded);
                    Console.WriteLine("Loaded: " + oLoaded.Length + " sessions.");
                }
            }
        }
        /// <summary>
        /// reads SAZ file which is Fiddler format for exporting captured traffic
        /// </summary>
        /// <param name="oAllSessions"></param>
        public void ReadSessions(List <Fiddler.Session> oAllSessions)
        {
            TranscoderTuple oImporter = FiddlerApplication.oTranscoders.GetImporter("SAZ");

            if (null != oImporter)
            {
                foreach (var fileToRead in this.FilesToRead)
                {
                    Dictionary <string, object> dictOptions = new Dictionary <string, object>();
                    dictOptions.Add("Filename", fileToRead);

                    Session[] oLoaded = FiddlerApplication.DoImport("SAZ", false, dictOptions, null);

                    if ((oLoaded != null) && (oLoaded.Length > 0))
                    {
                        oAllSessions.AddRange(oLoaded);
                    }
                }
            }
        }
Esempio n. 8
0
        public void SaveSessionsToDesktop()
        {
            bool   bSuccess  = false;
            string sFilename = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
                               + Path.DirectorySeparatorChar + DateTime.Now.ToString("hh-mm-ss") + ".saz";

            try
            {
                try
                {
                    Monitor.Enter(oAllSessions);
                    TranscoderTuple oExporter = FiddlerApplication.oTranscoders.GetExporter("SAZ");

                    if (null != oExporter)
                    {
                        var dictOptions = new Dictionary <string, object>();
                        dictOptions.Add("Filename", sFilename);
                        // dictOptions.Add("Password", "pencil");

                        bSuccess = FiddlerApplication.DoExport("SAZ", oAllSessions.ToArray(), dictOptions, null);
                    }
                    else
                    {
                        WriteCommandResponse("Save failed because the SAZ Format Exporter was not available.");
                    }
                }
                finally
                {
                    Monitor.Exit(oAllSessions);
                }

                WriteCommandResponse(bSuccess ? ("Wrote: " + sFilename) : ("Failed to save: " + sFilename));
            }
            catch (Exception eX)
            {
                WriteCommandResponse("Save failed: " + eX.Message);
            }
        }
Esempio n. 9
0
        public ProxyDump()
        {
            // List holding all sessions
            oAllSessions = new List <Fiddler.Session>();
            // List for single dumped session
            oSingleSession = new List <Fiddler.Session>();

            int _counter = 0;

            try
            {
                if (!Directory.Exists(ResponsePath))
                {
                    Directory.CreateDirectory(ResponsePath);
                }
            }
            catch (Exception ex)
            {
                WriteCommandResponse("Error while creating directory: " + ResponsePath + Environment.NewLine + ex);
            }

            WriteCommandResponse("ProxyDump [Alpha] 2018 by phono");


            //Load URIFilter
            LoadURIFilter();

            LoadResponseFile();

            #region AttachEventListeners
            //
            // It is important to understand that FiddlerCore calls event handlers on session-handling
            // background threads.  If you need to properly synchronize to the UI-thread (say, because
            // you're adding the sessions to a list view) you must call .Invoke on a delegate on the
            // window handle.
            //
            // If you are writing to a non-threadsafe data structure (e.g. List<t>) you must
            // use a Monitor or other mechanism to ensure safety.
            //

            // Simply echo notifications to the console.  Because Fiddler.CONFIG.QuietMode=true
            // by default, we must handle notifying the user ourselves.
            if (fiddlermessages && !HandlerRegistered)
            {
                Fiddler.FiddlerApplication.OnNotification  += delegate(object sender, NotificationEventArgs oNEA) { Console.WriteLine("** NotifyUser: "******"**NotifyUser: "******"** LogString: " + oLEA.LogString); WriteCommandResponse("**LogString: " + oLEA.LogString); };
            }

            if (!HandlerRegistered)
            {
                Fiddler.FiddlerApplication.BeforeRequest += delegate(Fiddler.Session oS)
                {
                    HandlerRegistered = true;

                    // Console.WriteLine("Before request for:\t" + oS.fullUrl);
                    // In order to enable response tampering, buffering mode MUST
                    // be enabled; this allows FiddlerCore to permit modification of
                    // the response in the BeforeResponse handler rather than streaming
                    // the response to the client as the response comes in.
                    oS.bBufferResponse = false;
                    Monitor.Enter(oAllSessions);
                    oAllSessions.Add(oS);
                    Monitor.Exit(oAllSessions);

                    #region OwnCode
                    if (connectionmessages)
                    {
                        Console.Write(String.Format("{0} {1} {2}\n{3} {4}\n\n", oS.id, oS.oRequest.headers.HTTPMethod, Ellipsize(oS.fullUrl, 60), oS.responseCode, oS.oResponse.MIMEType));
                    }
                    WriteCommandResponse(String.Format("{0} {1} {2}\n{3} {4}\n\n", oS.id, oS.oRequest.headers.HTTPMethod, Ellipsize(oS.fullUrl, 60), oS.responseCode, oS.oResponse.MIMEType));

                    //string URIFilterFilePath = "responses/urifilter.txt";
                    // Declare new List.
                    List <string> lines = new List <string>();

                    if (URIFilterList != null && URIFilterList.Count > 0)
                    {
                        lines.AddRange(URIFilterList);
                    }

                    foreach (string s in lines)
                    {
                        if (DebugMessages)
                        {
                            WriteCommandResponse("Filter is active: " + filteractive);
                        }
                        if (DebugMessages)
                        {
                            WriteCommandResponse("oS.uriContains(s): " + oS.uriContains(s) + " " + oS.url);
                        }
                        if (oS.uriContains(s) && filteractive)
                        {
                            WriteCommandResponse("INTERCEPTED CALL TO: " + Environment.NewLine);
                            WriteCommandResponse(String.Format("{0} {1} {2}\n{3} {4}\n\n", oS.id, oS.oRequest.headers.HTTPMethod, Ellipsize(oS.fullUrl, 60), oS.responseCode, oS.oResponse.MIMEType));


                            // if DumpMode add Session and directly save it and clear it to only write a single session for each file
                            if (DumpMode)
                            {
                                Monitor.Enter(oSingleSession);
                                oSingleSession.Add(oS);
                                Monitor.Exit(oSingleSession);
                            }

                            if (DebugMessages)
                            {
                                WriteCommandResponse("DumpMode is active: " + DumpMode);
                            }
                            if (!DumpMode)
                            {
                                //Send SINGLE RESPONSE

                                oS.utilCreateResponseAndBypassServer();

                                // Inside your main object, create a list to hold the sessions
                                // This generic list type requires your source file includes #using System.Collections.Generic.
                                List <Fiddler.Session> ReplaySessions = new List <Fiddler.Session>();
                                Session[] ReplaySession;

                                TranscoderTuple oImporter = FiddlerApplication.oTranscoders.GetImporter("SAZ");
                                if (null != oImporter && CurrentResponseFile != null)
                                {
                                    Dictionary <string, object> dictOptions = new Dictionary <string, object>();
                                    dictOptions.Add("Filename", CurrentResponseFile);

                                    ReplaySession = FiddlerApplication.DoImport("SAZ", false, dictOptions, null);

                                    if ((ReplaySession != null) && (ReplaySession.Length > 0))
                                    {
                                        ReplaySessions.AddRange(ReplaySession);

                                        oS.responseBodyBytes = ReplaySession[0].responseBodyBytes;
                                        oS.oResponse.headers = (HTTPResponseHeaders)ReplaySession[0].oResponse.headers.Clone();

                                        string shortResponseBody = System.Text.Encoding.UTF8.GetString(ReplaySession[0].responseBodyBytes).Substring(0, 100);
                                        WriteCommandResponse(ReplaySession[0].oResponse.headers.ToString());
                                        WriteCommandResponse(shortResponseBody + " ...");
                                        WriteCommandResponse("Loaded: " + ReplaySession.Length + " sessions.");
                                    }
                                }
                                else if (CurrentResponseFile == null)
                                {
                                    WriteCommandResponse("Error: no recorded sessions found");
                                }
                            }//END if (!DumpMode)
                        }
                    }
                    #endregion OwnCode



                    /* If the request is going to our secure endpoint, we'll echo back the response.
                     *
                     * Note: This BeforeRequest is getting called for both our main proxy tunnel AND our secure endpoint,
                     * so we have to look at which Fiddler port the client connected to (pipeClient.LocalPort) to determine whether this request
                     * was sent to secure endpoint, or was merely sent to the main proxy tunnel (e.g. a CONNECT) in order to *reach* the secure endpoint.
                     *
                     * As a result of this, if you run the demo and visit https://localhost:7777 in your browser, you'll see
                     *
                     * Session list contains...
                     *
                     *  1 CONNECT http://localhost:7777
                     *  200                                         <-- CONNECT tunnel sent to the main proxy tunnel, port 8877
                     *
                     *  2 GET https://localhost:7777/
                     *  200 text/html                               <-- GET request decrypted on the main proxy tunnel, port 8877
                     *
                     *  3 GET https://localhost:7777/
                     *  200 text/html                               <-- GET request received by the secure endpoint, port 7777
                     */

                    if ((oS.oRequest.pipeClient.LocalPort == iSecureEndpointPort) && (oS.hostname == sSecureEndpointHostname))
                    {
                        oS.utilCreateResponseAndBypassServer();
                        oS.oResponse.headers.HTTPResponseStatus = "200 Ok";
                        oS.oResponse["Content-Type"]            = "text/html; charset=UTF-8";
                        oS.oResponse["Cache-Control"]           = "private, max-age=0";
                        oS.utilSetResponseBody("<html><body>Request for httpS://" + sSecureEndpointHostname + ":" + iSecureEndpointPort.ToString() + " received. Your request was:<br /><plaintext>" + oS.oRequest.headers.ToString());
                    }
                }; // END before Request
            }

            /*
             *  // The following event allows you to examine every response buffer read by Fiddler. Note that this isn't useful for the vast majority of
             *  // applications because the raw buffer is nearly useless; it's not decompressed, it includes both headers and body bytes, etc.
             *  //
             *  // This event is only useful for a handful of applications which need access to a raw, unprocessed byte-stream
             *  Fiddler.FiddlerApplication.OnReadResponseBuffer += new EventHandler<RawReadEventArgs>(FiddlerApplication_OnReadResponseBuffer);
             */

            /*
             * Fiddler.FiddlerApplication.BeforeResponse += delegate(Fiddler.Session oS) {
             *  // Console.WriteLine("{0}:HTTP {1} for {2}", oS.id, oS.responseCode, oS.fullUrl);
             *
             *  // Uncomment the following two statements to decompress/unchunk the
             *  // HTTP response and subsequently modify any HTTP responses to replace
             *  // instances of the word "Microsoft" with "Bayden". You MUST also
             *  // set bBufferResponse = true inside the beforeREQUEST method above.
             *  //
             *  //oS.utilDecodeResponse(); oS.utilReplaceInResponse("Microsoft", "Bayden");
             * };*/

            Fiddler.FiddlerApplication.AfterSessionComplete += delegate(Fiddler.Session oS)
            {
                //Console.WriteLine("Finished session:\t" + oS.fullUrl);
                if (bUpdateTitle)
                {
                    try
                    {
                        Console.Title = ("Session list contains: " + oAllSessions.Count.ToString() + " sessions");
                    }
                    catch (Exception ex)
                    {
                        //not running in console
                    }
                }

                // if DumpMode add Session and directly save it and clear it to only write a single session for each file
                if (DumpMode)
                {
                    if (SplitSessionsFiles)
                    {
                        WriteSessionList(oSingleSession);

                        if (oSingleSession.Count > 0)
                        {
                            //SaveSessionsToDesktop(oSingleSession);
                            SaveSessionsToDumpFolder(oSingleSession);
                        }
                        else
                        {
                            WriteCommandResponse("No sessions have been captured");
                        }

                        Monitor.Enter(oSingleSession);
                        oSingleSession.Clear();
                        Monitor.Exit(oSingleSession);
                    }

                    //test dump all sessions
                    SaveSessionsToDumpFolder(oAllSessions, true);
                }
            };

            // Tell the system console to handle CTRL+C by calling our method that
            // gracefully shuts down the FiddlerCore.
            //
            // Note, this doesn't handle the case where the user closes the window with the close button.
            // See http://geekswithblogs.net/mrnat/archive/2004/09/23/11594.aspx for info on that...
            //
            Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
            #endregion AttachEventListeners

            string sSAZInfo = "NoSAZ";
#if SAZ_SUPPORT
            // If this demo was compiled with a SAZ-Transcoder, then the following lines will load the
            // Transcoders into the available transcoders. You can load other types of Transcoders from
            // a different assembly if you'd like, using the ImportTranscoders(string AssemblyPath) overload.
            // See https://www.fiddler2.com/dl/FiddlerCore-BasicFormats.zip for an example.
            //
            if (!FiddlerApplication.oTranscoders.ImportTranscoders(Assembly.GetExecutingAssembly()))
            {
                Console.WriteLine("This assembly was not compiled with a SAZ-exporter");
            }
            else
            {
                sSAZInfo = SAZFormat.GetZipLibraryInfo();
            }
#endif

            if (fiddlermessages)
            {
                Console.WriteLine(String.Format("Starting {0} ({1})...", Fiddler.FiddlerApplication.GetVersionString(), sSAZInfo));
            }

            // For the purposes of this demo, we'll forbid connections to HTTPS
            // sites that use invalid certificates. Change this from the default only
            // if you know EXACTLY what that implies.
            Fiddler.CONFIG.IgnoreServerCertErrors = true;

            // ... but you can allow a specific (even invalid) certificate by implementing and assigning a callback...
            // FiddlerApplication.OverrideServerCertificateValidation += new OverrideCertificatePolicyHandler(FiddlerApplication_OverrideServerCertificateValidation);

            FiddlerApplication.Prefs.SetBoolPref("fiddler.network.streaming.abortifclientaborts", true);

            // For forward-compatibility with updated FiddlerCore libraries, it is strongly recommended that you
            // start with the DEFAULT options and manually disable specific unwanted options.
            //FiddlerCoreStartupFlags oFCSF = FiddlerCoreStartupFlags.Default;
            // E.g. uncomment the next line if you don't want FiddlerCore to act as the system proxy
            FCSF = (FCSF & ~FiddlerCoreStartupFlags.RegisterAsSystemProxy);
            // or uncomment the next line if you don't want to decrypt SSL traffic.
            //FCSF = (FCSF & ~FiddlerCoreStartupFlags.DecryptSSL);

            //Start(oFCSF);

            /*
             * // Console App
             *
             * bool bDone = false;
             * do
             * {
             *  Console.WriteLine("\nEnter a command [C=Clear; L=List; d=Toggle Connection Messages;\n\tF=Toggle Filters; G=Collect Garbage; H=Toggle ResponseSessionFile;\n\tI=Toggle Infomessages; J=Toggle DumpMode; W=write SAZ; R=read SAZ;\n\tS=Toggle Forgetful Streaming; T=Toggle Title Counter; Q=Quit]:");
             *  Console.Write(">");
             *  ConsoleKeyInfo cki = Console.ReadKey();
             *  Console.WriteLine();
             *  switch (cki.KeyChar)
             *  {
             *      case 'c':
             *          Monitor.Enter(oAllSessions);
             *          oAllSessions.Clear();
             *          Monitor.Exit(oAllSessions);
             *          WriteCommandResponse("Clear...");
             *          FiddlerApplication.Log.LogString("Cleared session list.");
             *          break;
             *
             *      case 'l':
             *          WriteSessionList(oAllSessions);
             *          break;
             *
             *      case 'd':
             *          connectionmessages = !connectionmessages;
             *          WriteCommandResponse("Show Connection Messages: " + connectionmessages);
             *          break;
             *
             *      case 'f':
             *          filteractive = !filteractive;
             *          WriteCommandResponse("Filters active: " + filteractive);
             *          break;
             *
             *      case 'h':
             *          actualSAZfile = _SAZfiles[_counter++ % _SAZfiles.Length];
             *          WriteCommandResponse("Using for AutoResponse: " + actualSAZfile);
             *          break;
             *
             *      case 'i':
             *          fiddlermessages = !fiddlermessages;
             *          WriteCommandResponse("Show Infomessages: " + fiddlermessages);
             *          break;
             *
             *      case 'j':
             *          DumpMode = !DumpMode;
             *          WriteCommandResponse("DumpMode active: " + DumpMode);
             *          break;
             *
             *      case 'g':
             *          Console.WriteLine("Working Set:\t" + Environment.WorkingSet.ToString("n0"));
             *          Console.WriteLine("Begin GC...");
             *          GC.Collect();
             *          Console.WriteLine("GC Done.\nWorking Set:\t" + Environment.WorkingSet.ToString("n0"));
             *          break;
             *
             *      case 'q':
             *          bDone = true;
             *          DoQuit();
             *          break;
             *
             *      case 'r':
             #if SAZ_SUPPORT
             *          ReadSessions(oAllSessions);
             #else
             *          WriteCommandResponse("This demo was compiled without SAZ_SUPPORT defined");
             #endif
             *          break;
             *
             *      case 'w':
             #if SAZ_SUPPORT
             *          if (oAllSessions.Count > 0)
             *          {
             *              SaveSessionsToDesktop(oAllSessions);
             *          }
             *          else
             *          {
             *              WriteCommandResponse("No sessions have been captured");
             *          }
             #else
             *          WriteCommandResponse("This demo was compiled without SAZ_SUPPORT defined");
             #endif
             *          break;
             *
             *      case 't':
             *          bUpdateTitle = !bUpdateTitle;
             *          Console.Title = (bUpdateTitle) ? "Title bar will update with request count..." :
             *              "Title bar update suppressed...";
             *          break;
             *
             *      // Forgetful streaming
             *      case 's':
             *          bool bForgetful = !FiddlerApplication.Prefs.GetBoolPref("fiddler.network.streaming.ForgetStreamedData", false);
             *          FiddlerApplication.Prefs.SetBoolPref("fiddler.network.streaming.ForgetStreamedData", bForgetful);
             *          Console.WriteLine(bForgetful ? "FiddlerCore will immediately dump streaming response data." : "FiddlerCore will keep a copy of streamed response data.");
             *          break;
             *
             *  }
             * } while (!bDone);
             */
        }