Represents a Local Page.
Inheritance: System.PageInfo
        /// <summary>
        /// Verifies the need for a data upgrade, and performs it when needed.
        /// </summary>
        private void VerifyAndPerformUpgradeForPages()
        {
            // Load file lines
            // Parse first line (if any) with old (v2) algorithm
            // If parsing is successful, then the file must be converted
            // Conversion consists in removing the 'Status' field and properly modifying permissions of pages

            host.LogEntry("Upgrading pages format from 2.0 to 3.0", LogEntryType.General, null, this);

            //string[] lines = File.ReadAllLines(GetFullPath(PagesFile));
            string[] lines = File.ReadAllText(GetFullPath(PagesFile)).Replace("\r", "").Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

            if(lines.Length > 0) {
                LocalPageInfo[] pages = new LocalPageInfo[lines.Length];
                char[] oldStylePermissions = new char[lines.Length];

                char[] splitter = new char[] { '|' };

                for(int i = 0; i < lines.Length; i++) {
                    string[] fields = lines[i].Split(splitter, StringSplitOptions.RemoveEmptyEntries);

                    // Structure in version 1.0
                    // PageName|PageFile

                    // Structure in version 2.0
                    // PageName|PageFile|Status|DateTime

                    // Use default values (status and date/time were not available in earlier versions)
                    DateTime creationDateTime = new DateTime(2000, 1, 1);

                    // Default to Normal
                    oldStylePermissions[i] = 'N';

                    if(fields.Length == 2) {
                        // Version 1.0
                        // Use the Date/Time of the file
                        FileInfo fi = new FileInfo(GetFullPathForPageContent(fields[1]));
                        creationDateTime = fi.CreationTime;
                    }
                    if(fields.Length >= 3) {
                        // Might be version 2.0
                        switch(fields[2].ToLowerInvariant()) {
                            case "locked":
                                oldStylePermissions[i] = 'L';
                                break;
                            case "public":
                                oldStylePermissions[i] = 'P';
                                break;
                            case "normal":
                                oldStylePermissions[i] = 'N';
                                break;
                            default:
                                try {
                                    // If this succeeded, then it's Version 3.0, not 2.0 (at least for this line)
                                    creationDateTime = DateTime.Parse(fields[2]);
                                }
                                catch {
                                    // Use the Date/Time of the file
                                    FileInfo fi = new FileInfo(GetFullPathForPageContent(fields[1]));
                                    creationDateTime = fi.CreationTime;
                                }
                                break;
                        }
                        if(fields.Length == 4) {
                            // Version 2.0
                            creationDateTime = DateTime.Parse(fields[3]);
                        }
                    }

                    pages[i] = new LocalPageInfo(fields[0], this, creationDateTime, fields[1]);
                    pages[i].FullName = pages[i].FullName.Replace(".", "_");
                    // TODO: host.UpdateContentForPageRename(oldName, newName);
                }

                // Setup permissions for single pages
                for(int i = 0; i < oldStylePermissions.Length; i++) {
                    if(oldStylePermissions[i] != 'N') {
                        // Need to set permissions emulating old-style behavior
                        host.UpgradePageStatusToAcl(pages[i], oldStylePermissions[i]);
                    }
                }

                string backupFile = GetFullPath(Path.GetFileNameWithoutExtension(PagesFile) + "_v2" + Path.GetExtension(PagesFile));
                File.Copy(GetFullPath(PagesFile), backupFile);

                // Re-dump pages so that old format data is discarded
                DumpPages(pages);
            }
        }
        /// <summary>
        /// Find a free Message ID for a Page.
        /// </summary>
        /// <param name="page">The Page.</param>
        /// <returns>The Message ID.</returns>
        private int GetFreeMessageID(LocalPageInfo page)
        {
            lock(this) {
                if(!File.Exists(GetFullPathForMessages(page.File))) return 0;

                int result = 0;

                string data = File.ReadAllText(GetFullPathForMessages(page.File)).Replace("\r", "");

                string[] lines = data.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
                int idx, tmp;
                for(int i = 0; i < lines.Length; i++) {
                    idx = lines[i].IndexOf('|');
                    tmp = int.Parse(lines[i].Substring(0, idx));
                    if(tmp > result) result = tmp;
                }

                result++;

                return result;
            }
        }
        /// <summary>
        /// Adds a Page.
        /// </summary>
        /// <param name="nspace">The target namespace (<c>null</c> for the root).</param>
        /// <param name="name">The Page Name.</param>
        /// <param name="creationDateTime">The creation Date/Time.</param>
        /// <returns>The correct PageInfo object or null.</returns>
        /// <remarks>This method should <b>not</b> create the content of the Page.</remarks>
        /// <exception cref="ArgumentNullException">If <paramref name="name"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">If <paramref name="name"/> is empty.</exception>
        public PageInfo AddPage(string nspace, string name, DateTime creationDateTime)
        {
            if(name == null) throw new ArgumentNullException("name");
            if(name.Length == 0) throw new ArgumentException("Name cannot be empty", "name");

            lock(this) {
                if(!NamespaceExists(nspace)) return null;
                if(PageExists(new PageInfo(NameTools.GetFullName(nspace, name), this, DateTime.Now))) return null;

                LocalPageInfo result = new LocalPageInfo(NameTools.GetFullName(nspace, name), this, creationDateTime,
                    GetNamespacePartialPathForPageContent(nspace) + name + ".cs");

                BackupPagesFile();

                // Structure
                // Namespace.Page|File|CreationDateTime
                File.AppendAllText(GetFullPath(PagesFile), result.FullName + "|" + result.File + "|" + creationDateTime.ToString("yyyy'/'MM'/'dd' 'HH':'mm':'ss") + "\r\n");
                //File.Create(GetFullPathForPageContent(result.File)).Close(); // Empty content file might cause problems with backups
                File.WriteAllText(GetFullPathForPageContent(result.File), "--\r\n--|1900/01/01 0:00:00|\r\n##PAGE##\r\n--");
                pagesCache = null;

                return result;
            }
        }
 private string GetDraftFullPath(LocalPageInfo page)
 {
     /*return GetFullPathForPageDrafts(GetNamespacePartialPathForPageContent(NameTools.GetNamespace(page.FullName))
         + page.File);*/
     return GetFullPathForPageDrafts(page.File);
 }