digigrupp.com       Home  Downloads  Support  About  Contact  Search 

Simple SNMP Query Tool - Open Source - C# (C-sharp)

Downloadmain.cssnmp.cssnmpsocket.csmib.csrfc2mib.cscompile.cmd  

RFC downloader and MIB extractor module

// Author: Toomas Kaljus
// http://www.digigrupp.com

namespace DG
{
    public class Rfc2Mib
    {
        public void DownloadAndExtract(string RFCPath, string MIBPath, string RFCUrl, int RFCFirstNumber, int RFCLastNumber, bool ExtractOnly)
        {
            System.Net.WebClient WebClient = new System.Net.WebClient();
            for (int rfc=RFCFirstNumber; rfc<=RFCLastNumber; rfc++) {
                // download rfc texts
                string Filename = RFCPath + "\\rfc" + rfc + ".txt";
                if ((ExtractOnly) || (!System.IO.File.Exists(Filename))) {
                    if (!ExtractOnly) try {
                        System.Console.Write(("Downloading RFC" + rfc).PadRight(79) + "\r");                
                        WebClient.DownloadFile(RFCUrl.Replace("{n}", rfc.ToString()), Filename + ".~");
                        System.IO.File.Move(Filename + ".~", Filename);
                    } catch {
                        System.Console.Error.WriteLine(("Error downloading RFC" + rfc).PadRight(79));
                    }
                    if (System.IO.File.Exists(Filename)) {
                        System.Console.Write(("Reading RFC" + rfc).PadRight(79) + "\r");
                        string Buffer;
                        using (System.IO.StreamReader StreamReader = new System.IO.StreamReader(Filename)) Buffer = StreamReader.ReadToEnd();
                        // remove form-feeds (page breaks)
                        string[] Pages = Buffer.Split((char)0x0c);
                        for (int p=0; p<Pages.Length; p++) {
                            string[] Lines = Pages[p].Split((char)0x0a);
                            if (p > 0) for (int l=0; l<10; l++) {
                                if (l >= Lines.Length) break;
                                if (Lines[l].Trim().StartsWith("RFC " + rfc)) {
                                    Lines[l] = "";
                                    break;
                                }
                                if (Lines[l].Trim() != "") break;
                            }
                            if (p < Pages.Length - 1) for (int l=Lines.Length-1; l>Lines.Length-10; l--) {
                                if (l == -1) break;
                                if (Lines[l].Trim().EndsWith("]")) // "[Page " + (p + 1) + "]" is not working for some RFC-s as some pages have roman numbers
                                if (Lines[l].Trim().IndexOf("[Page ") > 0) {
                                    Lines[l] = "";
                                    break;
                                }
                                if (Lines[l].Trim() != "") break;
                            }
                            Pages[p] = string.Join("\n", Lines);
                        }
                        Buffer = string.Join("\n", Pages);

                        string FileBuffer = "";
                        string Data = "";
                        string MIBName = "";

                        // search for DEFINITIONS
                        int i = Buffer.IndexOf("DEFINITIONS");
                        while (i > 0) {
                            // search for BEGIN
                            int ib = SearchForBEGIN(Buffer, i + 11, 128);
                            if (ib < 0) break;
                            // search for END
                            int ie = SearchForEND(Buffer, ib + 5);
                            if (ie < 0) break;

                            // resolve MIB name
                            string Name = "";
                            int n = i - 1;
                            int Ident = 0;
                            do {
                                while ((n > 0) && (Buffer[n] > ' ')) n--;
                                while ((n > 0) && (Buffer[n - 1] <= ' ')) n--;
                                if ((n > 0) && (Buffer[n - 1] == '}')) while ((n > 0) && Buffer[n] != '{') n--;
                                while ((n > 0) && (Buffer[n - 1] <= ' ')) n--;
                                int n2 = n;
                                while ((n > 0) && (Buffer[n - 1] >= ' ')) n--;
                                Name = Buffer.Substring(n, n2 - n);
                                while (Name[Ident] == ' ') Ident++;
                                Name = Name.Trim();
                            } while (Name.StartsWith("--"));

                            Data = Buffer.Substring(n + Ident, ie - n + 3 - Ident).Replace("\n" + ("".PadRight(Ident, ' ')), "\n");

                            int z = Data.LastIndexOf("\n\n\n");
                            while (z >= 0) {
                                Data = Data.Remove(z, 1);
                                z = Data.LastIndexOf("\n\n\n", z + 3);
                            }

                            // older rfcs sometimes publish more than one mib with same name
                            if (Name != MIBName) {
                                FileBuffer =
                                    "-- Source: " + ((ExtractOnly) ? "rfc" + rfc + ".txt" : RFCUrl.Replace("{n}", rfc.ToString())) + "\n" +
                                    "-- Date extracted: " + System.DateTime.Now.ToString("yyyy-MM-dd") + "\n" +
                                    "-- " + Application.TitleForMibs + "\n" +
                                    "-- " + Application.Url + "\n\n";
                                MIBName = Name;
                            } else {
                                FileBuffer += "\n\n";
                            }
                            FileBuffer += Data;

                            System.Console.Write(("Saving RFC" + (rfc.ToString().PadLeft(4, '0')) + "_" + Name).PadRight(79) + "\r");
                            string MIBFilename = MIBPath + "\\RFC" + (rfc.ToString().PadLeft(4, '0')) + "_" + Name + ".mib";

                            using (System.IO.StreamWriter StreamWriter = new System.IO.StreamWriter(MIBFilename)) StreamWriter.Write(FileBuffer);

                            i = Buffer.IndexOf("DEFINITIONS", ie);
                        }
                    }
                }
            }
        }

        private int SearchForBEGIN(string Buffer, int Start, int Len)
        {
            int Result = -1;
            int Temp = -1;
            int Test = -1;
            // search for BEGIN
            Temp = Buffer.IndexOf("BEGIN", Start, Len);
            while (Temp >= 0) {
                // check if it is valid by checking if ::= is in front of BEGIN
                int TestLen = Temp - Start;
                if (TestLen > 50) TestLen = 50;
                Test = Buffer.LastIndexOf("::=", Temp, TestLen);
                if (Test >= 0) {
                    // valid BEGIN found
                    Result = Temp;
                    break;
                }
                Len -= Temp - Start;
                Start = Temp + 5;
                Temp = Buffer.IndexOf("BEGIN", Start, Len);
            }
            return Result;
        }

        private int SearchForEND(string Buffer, int Start)
        {
            int Result = -1;
            int Temp = -1;
            int Test = Start;
            int Count = 0;
            // search for END
            Temp = Buffer.IndexOf("END", Start);
            // test if END is preceded with whitespace character
            while ((Temp > 0) && (Buffer.Substring(Temp - 1, 1).Trim() != ""))
                Temp = Buffer.IndexOf("END", Temp + 3);
            while (Temp >= 0) {
                // count BEGINs in front of END
                Test = SearchForBEGIN(Buffer, Test, Temp - Test);
                while (Test >= 0) {
                    Test += 5;
                    Count++;
                    Test = SearchForBEGIN(Buffer, Test, Temp - Test);
                }
                if (Count == 0) {
                    // END is valid
                    Result = Temp;
                    break;
                }
                Test = Temp + 3;
                // search for next END and decrease count
                Temp = Buffer.IndexOf("END", Temp + 3);
                // test if END is preceded with whitespace character
                while ((Temp > 0) && (Buffer.Substring(Temp - 1, 1).Trim() != ""))
                    Temp = Buffer.IndexOf("END", Temp + 3);
                if (Temp >= 0) Count--;
            };
            return Result;
        }
    }
}