Beispiel #1
0
        private void butImport_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFD = new OpenFileDialog();

            openFD.Multiselect = true;
            if (openFD.ShowDialog() != DialogResult.OK)
            {
                return;
            }
            Invalidate();
            foreach (string fileName in openFD.FileNames)
            {
                //check file types?
                string destinationPath = WikiPages.GetWikiPath() + "\\" + Path.GetFileName(fileName);
                if (File.Exists(destinationPath))
                {
                    switch (MessageBox.Show(Lan.g(this, "Overwrite Existing File") + ": " + destinationPath, "", MessageBoxButtons.YesNoCancel))
                    {
                    case DialogResult.No:                            //rename, do not overwrite
                        InputBox ip = new InputBox(Lan.g(this, "New file name."));
                        ip.textResult.Text = Path.GetFileName(fileName);
                        ip.ShowDialog();
                        if (ip.DialogResult != DialogResult.OK)
                        {
                            continue;                                    //cancel, next file.
                        }
                        bool cancel = false;
                        while (File.Exists(WikiPages.GetWikiPath() + "\\" + ip.textResult.Text) && !cancel)
                        {
                            MsgBox.Show(this, "File name already exists.");
                            if (ip.ShowDialog() != DialogResult.OK)
                            {
                                cancel = true;
                            }
                        }
                        if (cancel)
                        {
                            continue;                                    //cancel rename, and go to next file.
                        }
                        destinationPath = WikiPages.GetWikiPath() + "\\" + ip.textResult.Text;
                        break;                                //proceed to save file.

                    case DialogResult.Yes:                    //overwrite
                        try {
                            File.Delete(destinationPath);
                        }
                        catch (Exception ex) {
                            MessageBox.Show(Lan.g(this, "Cannot copy file") + ":" + fileName + "\r\n" + ex.Message);
                            continue;
                        }
                        break;                          //file deleted, proceed to save.

                    default:                            //cancel
                        continue;                       //skip this file.
                    }
                }
                File.Copy(fileName, destinationPath);
            }
            FillGrid();
        }
Beispiel #2
0
        /// <summary></summary>
        private void FillGrid()
        {
            gridMain.BeginUpdate();
            gridMain.Columns.Clear();
            ODGridColumn col = new ODGridColumn(Lan.g(this, "Image Name"), 70);

            gridMain.Columns.Add(col);
            gridMain.Rows.Clear();
            string[] fileNames = System.IO.Directory.GetFiles(WikiPages.GetWikiPath());          //All files from the wiki file path, including images and other files.
            ImageNamesList = new List <string>();
            for (int i = 0; i < fileNames.Length; i++)
            {
                //If the user has entered a search keyword, then only show file names which contain the keyword.
                if (textSearch.Text != "" && !Path.GetFileName(fileNames[i]).ToLower().Contains(textSearch.Text.ToLower()))
                {
                    continue;
                }
                //Only add image files to the ImageNamesList, not other files such at text files.
                if (ImageHelper.HasImageExtension(fileNames[i]))
                {
                    ImageNamesList.Add(fileNames[i]);
                }
            }
            for (int i = 0; i < ImageNamesList.Count; i++)
            {
                ODGridRow row = new ODGridRow();
                row.Cells.Add(Path.GetFileName(ImageNamesList[i]));
                gridMain.Rows.Add(row);
            }
            gridMain.EndUpdate();
            labelImageSize.Text  = Lan.g(this, "Image Size") + ":";
            picturePreview.Image = null;
            picturePreview.Invalidate();
        }
Beispiel #3
0
 private void Folder_Link_Click()
 {
     if (CloudStorage.IsCloudStorage)
     {
         FormFilePicker FormFP = new FormFilePicker(CloudStorage.PathTidy(WikiPages.GetWikiPath()));
         FormFP.DoHideLocalButton = true;
         FormFP.ShowDialog();
         if (FormFP.DialogResult != DialogResult.OK)
         {
             return;
         }
         textContent.SelectedText = "[[foldercloud:" + FormFP.SelectedFiles[0] + "]]";
     }
     else
     {
         FormWikiFileFolder formWFF = new FormWikiFileFolder();
         formWFF.IsFolderMode = true;
         formWFF.ShowDialog();
         if (formWFF.DialogResult != DialogResult.OK)
         {
             return;
         }
         textContent.SelectedText = "[[folder:" + formWFF.SelectedLink + "]]";
     }
     textContent.SelectionLength = 0;
     //RefreshHtml();
 }
Beispiel #4
0
        private void File_Link_Click()
        {
            string fileLink;

            if (CloudStorage.IsCloudStorage)
            {
                FormFilePicker FormFP = new FormFilePicker(WikiPages.GetWikiPath());
                FormFP.DoHideLocalButton = true;
                FormFP.ShowDialog();
                if (FormFP.DialogResult != DialogResult.OK)
                {
                    return;
                }
                fileLink = FormFP.SelectedFiles[0];
                textContent.SelectedText = "[[filecloud:" + fileLink + "]]";
            }
            else              //Not cloud
            {
                FormWikiFileFolder FormWFF = new FormWikiFileFolder();
                FormWFF.ShowDialog();
                if (FormWFF.DialogResult != DialogResult.OK)
                {
                    return;
                }
                fileLink = FormWFF.SelectedLink;
                textContent.SelectedText = "[[file:" + fileLink + "]]";
            }
            textContent.SelectionLength = 0;
            //RefreshHtml();
        }
Beispiel #5
0
        /// <summary></summary>
        private void FillGrid()
        {
            gridMain.BeginUpdate();
            gridMain.Columns.Clear();
            ODGridColumn col = new ODGridColumn(Lan.g(this, "Image Name"), 70);

            gridMain.Columns.Add(col);
            gridMain.Rows.Clear();
            string wikiPath = "";

            try {
                wikiPath = WikiPages.GetWikiPath();
            }
            catch (Exception ex) {
                MessageBox.Show(this, ex.Message);
                DialogResult = DialogResult.Cancel;
                return;
            }
            List <string> listFileNames = FileAtoZ.GetFilesInDirectory(wikiPath);         //All files from the wiki file path, including images and other files.

            ImageNamesList = new List <string>();
            for (int i = 0; i < listFileNames.Count; i++)
            {
                //If the user has entered a search keyword, then only show file names which contain the keyword.
                if (textSearch.Text != "" && !Path.GetFileName(listFileNames[i]).ToLower().Contains(textSearch.Text.ToLower()))
                {
                    continue;
                }
                //Only add image files to the ImageNamesList, not other files such at text files.
                if (ImageHelper.HasImageExtension(listFileNames[i]))
                {
                    ImageNamesList.Add(listFileNames[i]);
                }
            }
            for (int i = 0; i < ImageNamesList.Count; i++)
            {
                ODGridRow row = new ODGridRow();
                row.Cells.Add(Path.GetFileName(ImageNamesList[i]));
                gridMain.Rows.Add(row);
            }
            gridMain.EndUpdate();
            labelImageSize.Text  = Lan.g(this, "Image Size") + ":";
            picturePreview.Image = null;
            picturePreview.Invalidate();
        }
Beispiel #6
0
        private void Image_Click()
        {
            //if storing images in database, GetWikiPath will throw an exception, cannot be storing in database to use images in the wiki
            string wikiPath = "";

            try {
                wikiPath = WikiPages.GetWikiPath();
            }
            catch (Exception ex) {
                MessageBox.Show(this, ex.Message);
                return;
            }
            FormImagePicker FormWI = new FormImagePicker(wikiPath);

            FormWI.ShowDialog();
            if (FormWI.DialogResult != DialogResult.OK)
            {
                return;
            }
            textContent.SelectionLength = 0;
            textContent.SelectedText    = "[[img:" + FormWI.SelectedImageName + "]]";
            //webBrowserWiki.AllowNavigation=true;
            //RefreshHtml();
        }
Beispiel #7
0
        ///<summary>Validates content, and keywords.  isForSaving can be false if just validating for refresh.</summary>
        public static bool ValidateMarkup(ODcodeBox textContent, bool isForSaving, bool showMsgBox = true, bool isEmail = false)
        {
            MatchCollection matches;
            //xml validation----------------------------------------------------------------------------------------------------
            string s = textContent.Text;

            //"<",">", and "&"-----------------------------------------------------------------------------------------------------------
            s = s.Replace("&", "&amp;");
            s = s.Replace("&amp;<", "&lt;");         //because "&" was changed to "&amp;" in the line above.
            s = s.Replace("&amp;>", "&gt;");         //because "&" was changed to "&amp;" in the line above.
            s = "<body>" + s + "</body>";
            XmlDocument  doc    = new XmlDocument();
            StringReader reader = new StringReader(s);

            try {
                doc.Load(reader);
            }
            catch (Exception ex) {
                if (showMsgBox)
                {
                    MessageBox.Show(ex.Message);
                }
                return(false);
            }
            try{
                //we do it this way to skip checking the main node itself since it's a dummy node.
                if (!isEmail)                 //We are allowing any XHTML markup in emails.
                {
                    MarkupEdit.ValidateNodes(doc.DocumentElement.ChildNodes);
                }
            }
            catch (Exception ex) {
                if (showMsgBox)
                {
                    MessageBox.Show(ex.Message);
                }
                return(false);
            }
            //Cannot have CR within tag definition---------------------------------------------------------------------------------
            //(?<!&) means only match strings that do not start with an '&'. This is so we can continue to use '&' as an escape character for '<'.
            //<.*?> means anything as short as possible that is contained inside a tag
            MatchCollection tagMatches = Regex.Matches(textContent.Text, "(?<!&)<.*?>", RegexOptions.Singleline);

            for (int i = 0; i < tagMatches.Count; i++)
            {
                if (tagMatches[i].ToString().Contains("\n"))
                {
                    if (showMsgBox)
                    {
                        MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(tagMatches[i].Index) + " - "
                                        + Lans.g(_lanThis, "Tag definitions cannot contain a return line:") + " " + tagMatches[i].Value.Replace("\n", ""));
                    }
                    return(false);
                }
            }
            //wiki image validation-----------------------------------------------------------------------------------------------------
            if (!isEmail)
            {
                string wikiImagePath = "";
                try {
                    wikiImagePath = WikiPages.GetWikiPath();                  //this also creates folder if it's missing.
                }
                catch (Exception ex) {
                    ex.DoNothing();
                    //do nothing, the wikiImagePath is only important if the user adds an image to the wiki page and is checked below
                }
                matches = Regex.Matches(textContent.Text, @"\[\[(img:).*?\]\]");             // [[img:myimage.jpg]]
                if (matches.Count > 0 && PrefC.AtoZfolderUsed == DataStorageType.InDatabase)
                {
                    if (showMsgBox)
                    {
                        MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(matches[0].Index) + " - "
                                        + Lans.g(_lanThis, "Cannot use images in wiki if storing images in database."));
                    }
                    return(false);
                }
                if (isForSaving)
                {
                    for (int i = 0; i < matches.Count; i++)
                    {
                        string imgPath = FileAtoZ.CombinePaths(wikiImagePath, matches[i].Value.Substring(6).Trim(']'));
                        if (!FileAtoZ.Exists(imgPath))
                        {
                            if (showMsgBox)
                            {
                                MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(matches[i].Index) + " - "
                                                + Lans.g(_lanThis, "Not allowed to save because image does not exist:") + " " + imgPath);
                            }
                            return(false);
                        }
                    }
                }
            }
            //Email image validation----------------------------------------------------------------------------------------------
            if (isEmail)
            {
                string emailImagePath = "";
                try {
                    emailImagePath = ImageStore.GetEmailImagePath();
                }
                catch (Exception ex) {
                    ex.DoNothing();
                }
                matches = Regex.Matches(textContent.Text, @"\[\[(img:).*?\]\]");
                if (isForSaving)
                {
                    for (int i = 0; i < matches.Count; i++)
                    {
                        string imgPath = FileAtoZ.CombinePaths(emailImagePath, matches[i].Value.Substring(6).Trim(']'));
                        if (!FileAtoZ.Exists(imgPath))
                        {
                            if (showMsgBox)
                            {
                                MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(matches[i].Index) + " - "
                                                + Lans.g(_lanThis, "Not allowed to save because image does not exist: ") + " " + imgPath);
                            }
                        }
                    }
                }
            }
            //List validation-----------------------------------------------------------------------------------------------------
            matches = Regex.Matches(textContent.Text, @"\[\[(list:).*?\]\]");         // [[list:CustomList]]
            foreach (Match match in matches)
            {
                if (!WikiLists.CheckExists(match.Value.Substring(7).Trim(']')))
                {
                    if (showMsgBox)
                    {
                        MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(match.Index) + " - "
                                        + Lans.g(_lanThis, "Wiki list does not exist in database:") + " " + match.Value.Substring(7).Trim(']'));
                    }
                    return(false);
                }
            }
            //spacing around bullets-----------------------------------------------------------------------------------------------
            string[] lines = textContent.Text.Split(new string[] { "\n" }, StringSplitOptions.None);
            for (int i = 0; i < lines.Length; i++)
            {
                if (lines[i].Trim().StartsWith("*"))
                {
                    if (!lines[i].StartsWith("*"))
                    {
                        if (showMsgBox)
                        {
                            MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + (i + 1) + " - "
                                            + Lans.g(_lanThis, "Stars used for lists may not have a space before them."));
                        }
                        return(false);
                    }
                    if (lines[i].Trim().StartsWith("* "))
                    {
                        if (showMsgBox)
                        {
                            MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + (i + 1) + " - "
                                            + Lans.g(_lanThis, "Stars used for lists may not have a space after them."));
                        }
                        return(false);
                    }
                }
                if (lines[i].Trim().StartsWith("#"))
                {
                    if (!lines[i].StartsWith("#"))
                    {
                        if (showMsgBox)
                        {
                            MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + (i + 1) + " - "
                                            + Lans.g(_lanThis, "Hashes used for lists may not have a space before them."));
                        }
                        return(false);
                    }
                    if (lines[i].Trim().StartsWith("# "))
                    {
                        if (showMsgBox)
                        {
                            MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + (i + 1) + " - "
                                            + Lans.g(_lanThis, "Hashes used for lists may not have a space after them."));
                        }
                        return(false);
                    }
                }
            }
            //Invalid characters inside of various tags--------------------------------------------
            matches = Regex.Matches(textContent.Text, @"\[\[.*?\]\]");
            foreach (Match match in matches)
            {
                if (match.Value.Contains("\"") && !match.Value.StartsWith("[[color:") && !match.Value.StartsWith("[[font:"))                 //allow colored text to have quotes.
                {
                    if (showMsgBox)
                    {
                        MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(match.Index) + " - "
                                        + Lans.g(_lanThis, "Link cannot contain double quotes:") + " " + match.Value);
                    }
                    return(false);
                }
                //This is not needed because our regex doesn't even catch them if the span a line break.  It's just interpreted as plain text.
                //if(match.Value.Contains("\r") || match.Value.Contains("\n")) {
                //	MessageBox.Show(Lan.g(this,"Link cannot contain carriage returns: ")+match.Value);
                //	return false;
                //}
                if (match.Value.StartsWith("[[img:") ||
                    match.Value.StartsWith("[[keywords:") ||
                    match.Value.StartsWith("[[file:") ||
                    match.Value.StartsWith("[[folder:") ||
                    match.Value.StartsWith("[[list:") ||
                    match.Value.StartsWith("[[color:") ||
                    match.Value.StartsWith("[[font:"))
                {
                    //other tags
                }
                else
                {
                    if (match.Value.Contains("|"))
                    {
                        if (showMsgBox)
                        {
                            MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(match.Index) + " - "
                                            + Lans.g(_lanThis, "Internal link cannot contain a pipe character:") + " " + match.Value);
                        }
                        return(false);
                    }
                }
            }
            //Table markup rigorously formatted----------------------------------------------------------------------
            //{|
            //!Width="100"|Column Heading 1!!Width="150"|Column Heading 2!!Width="75"|Column Heading 3
            //|-
            //|Cell 1||Cell 2||Cell 3
            //|-
            //|Cell A||Cell B||Cell C
            //|}
            //Although rarely needed, it might still come in handy in certain cases, like paste, or when user doesn't add the |} until later, and other hacks.
            matches = Regex.Matches(s, @"\{\|\n.+?\n\|\}", RegexOptions.Singleline);
            //matches = Regex.Matches(textContent.Text,
            //	@"(?<=(?:\n|<body>))" //Checks for preceding newline or beggining of file
            //	+@"\{\|.+?\n\|\}" //Matches the table markup.
            //	+@"(?=(?:\n|</body>))" //Checks for following newline or end of file
            //	,RegexOptions.Singleline);
            foreach (Match match in matches)
            {
                lines = match.Value.Split(new string[] { "{|\n", "\n|-\n", "\n|}" }, StringSplitOptions.RemoveEmptyEntries);
                if (!lines[0].StartsWith("!"))
                {
                    if (showMsgBox)
                    {
                        MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(match.Index) + " - "
                                        + Lans.g(_lanThis, "The second line of a table markup section must start with ! to indicate column headers."));
                    }
                    return(false);
                }
                if (lines[0].StartsWith("! "))
                {
                    if (showMsgBox)
                    {
                        MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(match.Index) + " - "
                                        + Lans.g(_lanThis, "In the table, at line 2, there cannot be a space after the first !"));
                    }
                    return(false);
                }
                string[] cells = lines[0].Substring(1).Split(new string[] { "!!" }, StringSplitOptions.None);             //this also strips off the leading !
                for (int c = 0; c < cells.Length; c++)
                {
                    if (!Regex.IsMatch(cells[c], @"^(Width="")\d+""\|"))                    //e.g. Width="90"|
                    {
                        if (showMsgBox)
                        {
                            MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(match.Index) + " - "
                                            + Lans.g(_lanThis, "In the table markup, each header must be formatted like this: Width=\"#\"|..."));
                        }
                        return(false);
                    }
                }
                for (int i = 1; i < lines.Length; i++)           //loop through the lines after the header
                {
                    if (!lines[i].StartsWith("|"))
                    {
                        if (showMsgBox)
                        {
                            MessageBox.Show(Lans.g(_lanThis, "Table rows must start with |.  At line ") + (i + 1).ToString() + Lans.g(_lanThis, ", this was found instead:")
                                            + lines[i]);
                        }
                        return(false);
                    }
                }
            }
            return(true);
        }
Beispiel #8
0
        private void butImport_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFD = new OpenFileDialog();

            openFD.Multiselect = true;
            if (openFD.ShowDialog() != DialogResult.OK)
            {
                return;
            }
            Invalidate();
            string wikiPath = "";

            try {
                wikiPath = WikiPages.GetWikiPath();
            }
            catch (Exception ex) {
                MessageBox.Show(this, ex.Message);
                return;
            }
            foreach (string fileName in openFD.FileNames)
            {
                //check file types?
                string destinationPath = FileAtoZ.CombinePaths(wikiPath, Path.GetFileName(fileName));
                if (FileAtoZ.Exists(destinationPath))
                {
                    switch (MessageBox.Show(Lan.g(this, "Overwrite Existing File") + ": " + destinationPath, "", MessageBoxButtons.YesNoCancel))
                    {
                    case DialogResult.No:                            //rename, do not overwrite
                        InputBox ip = new InputBox(Lan.g(this, "New file name."));
                        ip.textResult.Text = Path.GetFileName(fileName);
                        ip.ShowDialog();
                        if (ip.DialogResult != DialogResult.OK)
                        {
                            continue;                                    //cancel, next file.
                        }
                        bool cancel = false;
                        while (!cancel && FileAtoZ.Exists(FileAtoZ.CombinePaths(wikiPath, ip.textResult.Text)))
                        {
                            MsgBox.Show(this, "File name already exists.");
                            if (ip.ShowDialog() != DialogResult.OK)
                            {
                                cancel = true;
                            }
                        }
                        if (cancel)
                        {
                            continue;                                    //cancel rename, and go to next file.
                        }
                        destinationPath = FileAtoZ.CombinePaths(wikiPath, ip.textResult.Text);
                        break;                                //proceed to save file.

                    case DialogResult.Yes:                    //overwrite
                        try {
                            FileAtoZ.Delete(destinationPath);
                        }
                        catch (Exception ex) {
                            MessageBox.Show(Lan.g(this, "Cannot copy file") + ":" + fileName + "\r\n" + ex.Message);
                            continue;
                        }
                        break;                          //file deleted, proceed to save.

                    default:                            //cancel
                        continue;                       //skip this file.
                    }
                }
                FileAtoZ.Copy(fileName, destinationPath, FileAtoZSourceDestination.LocalToAtoZ);
            }
            FillGrid();
            if (openFD.FileNames.Length == 1)           //if importing exactly one image, select it upon returning.
            {
                textSearch.Text = Path.GetFileName(openFD.FileNames[0]);
            }
        }
Beispiel #9
0
        ///<summary>Validates content, and keywords.  isForSaving can be false if just validating for refresh.</summary>
        private bool ValidateWikiPage(bool isForSaving)
        {
            //xml validation----------------------------------------------------------------------------------------------------
            string s = textContent.Text;

            //"<",">", and "&"-----------------------------------------------------------------------------------------------------------
            s = s.Replace("&", "&amp;");
            s = s.Replace("&amp;<", "&lt;");         //because "&" was changed to "&amp;" in the line above.
            s = s.Replace("&amp;>", "&gt;");         //because "&" was changed to "&amp;" in the line above.
            s = "<body>" + s + "</body>";
            XmlDocument  doc    = new XmlDocument();
            StringReader reader = new StringReader(s);

            try {
                doc.Load(reader);
            }
            catch (Exception ex) {
                MessageBox.Show(ex.Message);
                return(false);
            }
            try{
                //we do it this way to skip checking the main node itself since it's a dummy node.
                ValidateNodes(doc.DocumentElement.ChildNodes);
            }
            catch (Exception ex) {
                MessageBox.Show(ex.Message);
                return(false);
            }
            //Cannot have CR within tag definition---------------------------------------------------------------------------------
            //(?<!&) means only match strings that do not start with an '&'. This is so we can continue to use '&' as an escape character for '<'.
            //<.*?> means anything as short as possible that is contained inside a tag
            MatchCollection tagMatches = Regex.Matches(textContent.Text, "(?<!&)<.*?>", RegexOptions.Singleline);

            for (int i = 0; i < tagMatches.Count; i++)
            {
                if (tagMatches[i].ToString().Contains("\r\n"))
                {
                    MessageBox.Show(Lan.g(this, "Tag definitions cannot contain a return line: ") + tagMatches[i].Value.Replace("\r\n", ""));
                    return(false);
                }
            }
            //image validation-----------------------------------------------------------------------------------------------------
            string          wikiImagePath = WikiPages.GetWikiPath();                               //this also creates folder if it's missing.
            MatchCollection matches       = Regex.Matches(textContent.Text, @"\[\[(img:).*?\]\]"); // [[img:myimage.jpg]]

            if (matches.Count > 0 && !PrefC.AtoZfolderUsed)
            {
                MsgBox.Show(this, "Cannot use images in wiki if storing images in database.");
                return(false);
            }
            if (isForSaving)
            {
                for (int i = 0; i < matches.Count; i++)
                {
                    string imgPath = ODFileUtils.CombinePaths(wikiImagePath, matches[i].Value.Substring(6).Trim(']'));
                    if (!System.IO.File.Exists(imgPath))
                    {
                        MessageBox.Show(Lan.g(this, "Not allowed to save because image does not exist: ") + imgPath);
                        return(false);
                    }
                }
            }
            //List validation-----------------------------------------------------------------------------------------------------
            matches = Regex.Matches(textContent.Text, @"\[\[(list:).*?\]\]");         // [[list:CustomList]]
            foreach (Match match in matches)
            {
                if (!WikiLists.CheckExists(match.Value.Substring(7).Trim(']')))
                {
                    MessageBox.Show(Lan.g(this, "Wiki list does not exist in database") + " : " + match.Value.Substring(7).Trim(']'));
                    return(false);
                }
            }
            //spacing around bullets-----------------------------------------------------------------------------------------------
            string[] lines = textContent.Text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
            for (int i = 0; i < lines.Length; i++)
            {
                if (lines[i].Trim().StartsWith("*"))
                {
                    if (!lines[i].StartsWith("*"))
                    {
                        MsgBox.Show(this, "Stars used for lists may not have a space before them.");
                        return(false);
                    }
                    if (lines[i].Trim().StartsWith("* "))
                    {
                        MsgBox.Show(this, "Stars used for lists may not have a space after them.");
                        return(false);
                    }
                }
                if (lines[i].Trim().StartsWith("#"))
                {
                    if (!lines[i].StartsWith("#"))
                    {
                        MsgBox.Show(this, "Hashes used for lists may not have a space before them.");
                        return(false);
                    }
                    if (lines[i].Trim().StartsWith("# "))
                    {
                        MsgBox.Show(this, "Hashes used for lists may not have a space after them.");
                        return(false);
                    }
                }
            }
            //Invalid characters inside of various tags--------------------------------------------
            matches = Regex.Matches(textContent.Text, @"\[\[.*?\]\]");
            foreach (Match match in matches)
            {
                if (match.Value.Contains("\"") && !match.Value.StartsWith("[[color:"))                 //allow colored text to have quotes.
                {
                    MessageBox.Show(Lan.g(this, "Link cannot contain double quotes: ") + match.Value);
                    return(false);
                }
                //This is not needed because our regex doesn't even catch them if the span a line break.  It's just interpreted as plain text.
                //if(match.Value.Contains("\r") || match.Value.Contains("\n")) {
                //	MessageBox.Show(Lan.g(this,"Link cannot contain carriage returns: ")+match.Value);
                //	return false;
                //}
                if (match.Value.StartsWith("[[img:") ||
                    match.Value.StartsWith("[[keywords:") ||
                    match.Value.StartsWith("[[file:") ||
                    match.Value.StartsWith("[[folder:") ||
                    match.Value.StartsWith("[[list:") ||
                    match.Value.StartsWith("[[color:"))
                {
                    //other tags
                }
                else
                {
                    if (match.Value.Contains("|"))
                    {
                        MessageBox.Show(Lan.g(this, "Internal link cannot contain a pipe character:") + match.Value);
                        return(false);
                    }
                }
            }
            //Table markup rigorously formatted----------------------------------------------------------------------
            //{|
            //!Width="100"|Column Heading 1!!Width="150"|Column Heading 2!!Width="75"|Column Heading 3
            //|-
            //|Cell 1||Cell 2||Cell 3
            //|-
            //|Cell A||Cell B||Cell C
            //|}
            //Although this is rarely needed, it might still come in handy in certain cases, like paste, or when user doesn't add the |} until later, and other hacks.
            matches = Regex.Matches(s, @"\{\|(.+?)\|\}", RegexOptions.Singleline);
            foreach (Match match in matches)
            {
                lines = match.Value.Split(new string[] { "{|\r\n", "\r\n|-\r\n", "\r\n|}" }, StringSplitOptions.RemoveEmptyEntries);
                if (!match.Value.StartsWith("{|"))
                {
                    MsgBox.Show(this, "The first line of a table markup section must be exactly {|, with no additional characters.");
                    return(false);
                }
                if (!lines[0].StartsWith("!"))
                {
                    MsgBox.Show(this, "The second line of a table markup section must start with ! to indicate column headers.");
                    return(false);
                }
                if (lines[0].StartsWith("! "))
                {
                    MsgBox.Show(this, "In the table, at line 2, there cannot be a space after the first !");
                    return(false);
                }
                string[] cells = lines[0].Substring(1).Split(new string[] { "!!" }, StringSplitOptions.None);             //this also strips off the leading !
                for (int c = 0; c < cells.Length; c++)
                {
                    if (!Regex.IsMatch(cells[c], @"^(Width="")\d+""\|"))                    //e.g. Width="90"|
                    {
                        MsgBox.Show(this, "In the table markup, each header must be formatted like this: Width=\"#\"|...");
                        return(false);
                    }
                }
                for (int i = 1; i < lines.Length; i++)           //loop through the lines after the header
                {
                    if (!lines[i].StartsWith("|"))
                    {
                        MessageBox.Show(Lan.g(this, "Table rows must start with |.  At line ") + (i + 1).ToString() + Lan.g(this, ", this was found instead:") + lines[i]);
                        return(false);
                    }
                    //if(lines[i].StartsWith("| ")) {
                    //	MessageBox.Show(Lan.g(this,"In the table, at line ")+(i+1).ToString()+Lan.g(this,", there cannot be a space after the first |."));
                    //	return false;
                    //}
                    //lines[i].in
                    //I guess we don't really care what they put in a row.  We can just interpret garbage as a single cell.
                }
                if (!match.Value.EndsWith("\r\n|}"))
                {
                    MsgBox.Show(this, "The last line of a table markup section must be exactly |}, with no additional characters.");                   //this doesn't work since the match stops after |}.
                    return(false);
                }
            }
            return(true);
        }