예제 #1
0
 public static void requestEnd(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     bool cookiesEnabled = request.Cookies["cookie-control"] != null;
     // Add styling and toggle button
     Misc.Plugins.addHeaderCSS(pageElements["URL"] + "/Content/CSS/CookieControl.css", ref pageElements);
     Misc.Plugins.addHeaderJS(pageElements["URL"] + "/Content/JS/CookieControl.js", ref pageElements);
     // Add toggle button
     pageElements.appendToKey("BODY_FOOTER", Core.templates["cookiecontrol"]["toggle"]);
     // Add warning banner
     if (!cookiesEnabled)
         pageElements.appendToKey("BODY_HEADER", Core.templates["cookiecontrol"]["banner"]);
     else
     {
         // Check if cookies have been enabled, if so return - no need to remove cookies
         pageElements.setFlag("COOKIES_ON");
         return;
     }
     // Clear all the response cookies - these may have been added programmatically
     response.Cookies.Clear();
     // Add each cookie, sent in the request, in the response - to expire
     HttpCookie cookie;
     for (int i = 0; i < request.Cookies.Count; i++)
     {
         cookie = request.Cookies[i];
         if (cookie.Name != "ASP.NET_SessionId")
         {
             cookie.Expires = DateTime.Now.AddDays(-2);
             response.Cookies.Add(cookie);
         }
     }
 }
예제 #2
0
 public static void pageArticles_Pending(ref StringBuilder content, string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     // Check the user has publishing permissions
     if (!HttpContext.Current.User.Identity.IsAuthenticated || !conn.Query_Scalar("SELECT ug.access_media_publish FROM bsa_users AS u LEFT OUTER JOIN bsa_user_groups AS ug ON ug.groupid=u.groupid WHERE u.userid='" + Utils.Escape(HttpContext.Current.User.Identity.Name) + "'").ToString().Equals("1"))
         return;
     // Get the current page
     int page;
     if (!int.TryParse(request.QueryString["pg"], out page) || page < 1) page = 1;
     // Build a list of pending articles
     StringBuilder articlesPending = new StringBuilder();
     int pendingPerPage = Core.settings[SETTINGS_KEY].getInt(SETTINGS_PENDING_PER_PAGE);
     Result pending = conn.Query_Read("SELECT a.articleid, a.title, u.username, a.userid, a.datetime, a.allow_html FROM articles AS a LEFT OUTER JOIN bsa_users AS u ON u.userid=a.userid WHERE a.published='0' ORDER BY a.datetime ASC LIMIT " + ((page * pendingPerPage) - pendingPerPage) + "," + pendingPerPage);
     if (pending.Rows.Count > 0)
         foreach (ResultRow article in pending)
             articlesPending.Append(
                 Core.templates["articles"]["articles_pending_row"]
                 .Replace("<ARTICLEID>", HttpUtility.HtmlEncode(article["articleid"]))
                 .Replace("<TITLE>", HttpUtility.HtmlEncode(article["title"]))
                 .Replace("<USERNAME>", HttpUtility.HtmlEncode(article["username"]))
                 .Replace("<USERID>", HttpUtility.HtmlEncode(article["userid"]))
                 .Replace("<CREATED>", HttpUtility.HtmlEncode(article["datetime"]))
                 .Replace("<WARNINGS>", article["allow_html"].Equals("1") ? "HTML" : "&nbsp;")
                 );
     else
         articlesPending.Append("No pending articles.");
     // Append navigation
     articlesPending.Append(
         Core.templates["articles"]["pending_nav"]
         .Replace("<PAGE_PREVIOUS>", (page > 1 ? page - 1 : 1).ToString())
         .Replace("<PAGE>", page.ToString())
         .Replace("<PAGE_NEXT>", (page < int.MaxValue ? page + 1 : int.MaxValue).ToString())
         );
     // Set navigation flags
     if (page > 1) pageElements.setFlag("ARTICLE_PAGE_PREVIOUS");
     if (page < int.MaxValue && pending.Rows.Count == pendingPerPage) pageElements.setFlag("ARTICLE_PAGE_NEXT");
     // Output the page
     Misc.Plugins.addHeaderCSS(pageElements["URL"] + "/Content/CSS/Article.css", ref pageElements);
     content.Append(Core.templates["articles"]["articles_pending"]
         .Replace("<PENDING>", articlesPending.ToString())
         );
     pageElements["TITLE"] = "Articles - Pending";
 }
예제 #3
0
 public static void pageDownload_View(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response, bool admin, ResultRow file)
 {
     // Get downloads
     ResultRow downloads = conn.Query_Read("SELECT (SELECT COUNT('') FROM downloads WHERE downloadid='" + Utils.Escape(file["downloadid"]) + "') AS downloads_total, (SELECT COUNT('') FROM (SELECT ip_addr FROM downloads WHERE downloadid='" + Utils.Escape(file["downloadid"]) + "' GROUP BY ip_addr) AS a) AS downloads_unique")[0];
     // Render page
     pageElements["CONTENT"] = Core.templates["downloads"]["download_get"]
         .Replace("%DOWNLOADID%", file["downloadid"])
         .Replace("%NAV%", getNavBar(file["physical_path"].LastIndexOf('/') == -1 ? string.Empty : file["physical_path"].Substring(0, file["physical_path"].LastIndexOf('/'))))
         .Replace("%EXTENSION%", HttpUtility.HtmlEncode(file["extension"]))
         .Replace("%FILESIZE%", HttpUtility.HtmlEncode(file["file_size"].Length > 0 ? Misc.Plugins.getBytesString(float.Parse(file["file_size"])) : "unknown bytes"))
         .Replace("%DESCRIPTION%", file["description"].Length > 0 ? HttpUtility.HtmlEncode(file["description"]) : "(no description)")
         .Replace("%ICONID%", HttpUtility.HtmlEncode(file["iconid"]))
         .Replace("%DOWNLOADS_TOTAL%", downloads["downloads_total"])
         .Replace("%DOWNLOADS_UNIQUE%", downloads["downloads_unique"])
         .Replace("%DIRECT_LINK%", "http://" + request.Url.Host + (request.Url.Port != 80 ? ":" + request.Url.Port : string.Empty) + "/download/" + file["downloadid"] + "." + file["extension"])
         ;
     pageElements["TITLE"] = "Download - " + HttpUtility.HtmlEncode(file["title"]);
     // Admin flag
     if (admin) pageElements.setFlag("DOWNLOADS_ADMIN");
     // Add CSS
     Misc.Plugins.addHeaderCSS(pageElements["URL"] + "/Content/CSS/Downloads.css", ref pageElements);
 }
예제 #4
0
 public static void pageProfile_Upload(string pluginid, ref ResultRow profileData, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     string error = null;
     HttpPostedFile image = request.Files["profile_picture"];
     if(image != null)
     {
         int maxSize = Core.settings[SETTINGS_KEY].getInt(SETTINGS_KEY_PICTURE_MAX_SIZE);
         if (image.ContentLength > maxSize)
             error = "Picture cannot exceed " + maxSize + " bytes (" + Misc.Plugins.getBytesString(maxSize) + ") !";
         else if (image.ContentType != "image/gif" && image.ContentType != "image/jpeg" && image.ContentType != "image/png" && image.ContentType != "image/jpg")
             error = "Invalid file format!";
         else
         {
             // Compress the image
             double maxWidth = Core.settings[SETTINGS_KEY].getDouble(SETTINGS_KEY_PICTURE_MAX_WIDTH);
             double maxHeight = Core.settings[SETTINGS_KEY].getDouble(SETTINGS_KEY_PICTURE_MAX_HEIGHT);
             Stream bStream = image.InputStream;
             Image pp = Image.FromStream(bStream);
             // Work-out the size of the new image
             int width;
             int height;
             if (pp.Width > maxWidth)
             {
                 width = (int)maxWidth;
                 height = (int)((maxWidth / (double)pp.Width) * pp.Height);
             }
             else
             {
                 height = (int)maxHeight;
                 width = (int)((maxHeight / (double)pp.Height) * pp.Width);
             }
             Bitmap compressedImage = new Bitmap(width, height);
             // Draw the uploaded image
             Graphics g = Graphics.FromImage(compressedImage);
             g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
             g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
             g.DrawImage(pp, 0, 0, width, height);
             g.Dispose();
             // Save the image as a byte-array
             MemoryStream ms = new MemoryStream();
             compressedImage.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
             byte[] data = ms.ToArray();
             ms.Dispose();
             ms = null;
             // Dispose image
             compressedImage.Dispose();
             compressedImage = null;
             pp.Dispose();
             pp = null;
             bStream.Dispose();
             bStream = null;
             // Save the byte-array to the database
             Dictionary<string, object> queryParams = new Dictionary<string, object>();
             queryParams.Add("profile_picture", data);
             queryParams.Add("profileid", profileData["profileid"]);
             // Save the byte-array to the database
             conn.Query_Execute_Parameters("UPDATE bsa_profiles SET profile_picture=@profile_picture WHERE profileid=@profileid", queryParams);
             // Redirect to profile
             conn.Disconnect();
             response.Redirect(pageElements["URL"] + "/profile?userid=" + profileData["userid"], true);
         }
     }
     pageElements["PROFILE_CONTENT"] = Core.templates["bsa_profiles"]["profile_upload"]
         .Replace("<USERID>", HttpUtility.HtmlEncode(profileData["userid"]))
         .Replace("<ERROR>", error != null ? Core.templates[pageElements["TEMPLATE"]]["error"].Replace("<ERROR>", HttpUtility.HtmlEncode(error)) : string.Empty);
     pageElements.setFlag("PROFILE_UPLOAD");
 }
예제 #5
0
        public static void pageHistory(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
        {
            switch (request.QueryString["2"])
            {
                default:
                    // Today
                    if (request.QueryString["image"] != null)
                    {
                        // Output a graph for todays, unless otherwise specified, data
                        int graphWidth = 800;
                        int graphHeight = 500;
                        if (request.QueryString["width"] != null && int.TryParse(request.QueryString["width"], out graphWidth) && graphWidth < 10)
                            graphWidth = 800;
                        if (request.QueryString["height"] != null && int.TryParse(request.QueryString["height"], out graphHeight) && graphHeight < 10)
                            graphHeight = 500;
                        int graphPaddingLeft = 45;
                        int graphPaddingBottom = 65;
                        int graphPaddingTop = 10;
                        int graphPaddingRight = 20;
                        Bitmap graph = new Bitmap(graphWidth, graphHeight);
                        Graphics g = Graphics.FromImage(graph);
                        g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                        g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

                        Pen penBlack = new Pen(new SolidBrush(Color.Black)); // Used for drawing gridlines
                        Pen penDataWatts = new Pen(new SolidBrush(Color.Red)); // Used for drawing the watts
                        Font fontGridlines = new Font("Times New Roman", 8.0f, FontStyle.Regular); // Used for drawing text for gridlines
                        Font fontLabels = new Font("Times New Roman", 12.0f, FontStyle.Regular);
                        SolidBrush brushGridlinesText = new SolidBrush(Color.Black);

                        // Draw border
                        g.DrawRectangle(new Pen(new SolidBrush(Color.Gray)), 0, 0, graphWidth -1, graphHeight - 1);

                        // Draw Y line
                        g.DrawLine(penBlack, graphPaddingLeft, graphPaddingTop, graphPaddingLeft, graphHeight - graphPaddingBottom);
                        // Draw X line
                        g.DrawLine(penBlack, graphPaddingLeft, graphHeight - graphPaddingBottom, graphWidth - graphPaddingRight, graphHeight - graphPaddingBottom);

                        // Get the max value
                        int year = -1, month = -1, day = -1;
                        string rawYear = request.QueryString["year"];
                        string rawMonth = request.QueryString["month"];
                        string rawDay = request.QueryString["day"];
                        if (rawYear != null && int.TryParse(rawYear, out year) && year != -1 && year < 2000)
                            year = -1;
                        if (rawMonth != null && int.TryParse(rawMonth, out month) && month != -1 && month < 1 && month > 12)
                            month = -1;
                        if (rawDay != null && int.TryParse(rawDay, out day) && day != -1 && day < 1 && day > 31)
                            day = -1;
                        Result maxVal = conn.Query_Read("SELECT MAX(watts) AS watts FROM cc128_readings WHERE DATE(datetime) = " + (year != -1 && month != -1 && day != -1 ? "'" + year + "-" + month + "-" + day + "'" : "CURDATE()"));
                        if (maxVal.Rows.Count != 1 || maxVal[0]["watts"].Length == 0)
                        {
                            g.FillRectangle(new SolidBrush(Color.Red), 0, 0, graphWidth, graphHeight);
                            g.DrawString("No data available...check the CC128 is operational!\r\n\r\nIs it on COM1?\r\nDid you unplug it?\r\nIs there an issue with the database or server?", new Font("Times New Roman", 20.0f, FontStyle.Regular), new SolidBrush(Color.White), 5, 5);
                        }
                        else
                        {
                            int maxValue = int.Parse(maxVal[0]["watts"]);
                            // Calculate the area for plotting
                            double plotWidth = graphWidth - (graphPaddingLeft + graphPaddingRight);
                            double plotHeight = graphHeight - (graphPaddingTop + graphPaddingBottom);
                            double numberOfYGridLines = 10;
                            // Calculate the gap between watts/time from 0 to maxvalue within plot area
                            double steppingY = plotHeight / numberOfYGridLines;//plotHeight / (double)maxValue * (maxValue * 0.05); // Watts
                            double steppingX = plotWidth / 24; // Time - pretty much 24 hours (CEIL: 23.999999->24)

                            // Shared variables
                            int txtX, txtY;
                            SizeF txtSize;
                            string txt;

                            // Draw watt label
                            txtSize = g.MeasureString("Watts", fontLabels);
                            txtX = -(int)(txtSize.Width / 2);
                            txtY = graphHeight / 2;
                            g.TranslateTransform(txtX + (txtSize.Width / 2), txtY + (txtSize.Height / 2));
                            g.RotateTransform(270);
                            g.DrawString("Watts", fontLabels, brushGridlinesText, 0, 0);
                            g.ResetTransform();

                            // Draw watt grid lines
                            for (double i = 0; i <= plotHeight; i += steppingY)
                            {

                                g.DrawLine(penBlack, graphPaddingLeft - 4, (graphPaddingTop + (int)plotHeight) - (int)i, graphWidth - graphPaddingRight, (graphPaddingTop + (int)plotHeight) - (int)i);

                                txt = Math.Round(i > 0 ? maxValue * (i / plotHeight) : 0, 0).ToString();
                                txtSize = g.MeasureString(txt.ToString(), fontGridlines);
                                txtX = (graphPaddingLeft - 4) - (int)txtSize.Width;
                                txtY = ((graphPaddingTop + (int)plotHeight) - (int)i) - (int)(txtSize.Height / 2);

                                g.DrawString(txt, fontGridlines, brushGridlinesText, txtX, txtY);
                            }

                            // Draw time label
                            txtSize = g.MeasureString("Time", fontLabels);
                            g.DrawString("Time", fontLabels, brushGridlinesText, (graphWidth / 2) - (txtSize.Width / 2), graphHeight - txtSize.Height);

                            // Draw time grid lines
                            for (double i = 0; i <= plotWidth; i += steppingX)
                            {
                                g.DrawLine(penBlack, graphPaddingLeft + (int)i, graphPaddingTop, graphPaddingLeft + (int)i, graphHeight - (graphPaddingBottom - 4));

                                txt = i == 24 ? "23:59" : Math.Round(i > 0 ? (i / plotWidth) * 24 : 0, 0).ToString("0#") + ":00";
                                txtSize = g.MeasureString(txt, fontGridlines);
                                txtX = graphPaddingLeft + (int)i;
                                txtY = graphHeight - (graphPaddingBottom - 4);

                                g.TranslateTransform(txtX + (txtSize.Width / 2), txtY + (txtSize.Height / 2));
                                g.RotateTransform(270);
                                g.DrawString(txt, fontGridlines, brushGridlinesText, -txtSize.Width, -txtSize.Height);
                                g.ResetTransform();
                            }

                            // Plot data
                            int lastX = 0;
                            int lasty = 0;
                            int newX, newY;
                            double seconds;
                            DateTime secondsStart = year != -1 && month != -1 && day != -1 ? DateTime.Parse(year + "-" + month + "-" + day) : DateTime.Today;
                            foreach (ResultRow reading in conn.Query_Read("SELECT watts, datetime FROM cc128_readings WHERE DATE(datetime) = " + (year != -1 && month != -1 && day != -1 ? "'" + year + "-" + month + "-" + day + "'" : "CURDATE()")))
                            {
                                seconds = DateTime.Parse(reading["datetime"]).Subtract(secondsStart).TotalSeconds; // 86400 seconds in a day
                                newX = (int)((seconds / 86400) * plotWidth);
                                newY = (int)(((double)int.Parse(reading["watts"]) / (double)maxValue) * plotHeight);
                                g.DrawLine(penDataWatts, graphPaddingLeft + (lastX != 0 ? lastX : newX - 1), (int)(graphPaddingTop + plotHeight) - (lasty != 0 ? lasty : newY), graphPaddingLeft + newX, (int)(graphPaddingTop + plotHeight) - newY);
                                lastX = newX;
                                lasty = newY;
                            }
                        }
                        g.Dispose();
                        response.ContentType = "image/png";
                        graph.Save(response.OutputStream, System.Drawing.Imaging.ImageFormat.Png);
                        response.End();
                    }
                    else
                    {
                        StringBuilder itemsDay = new StringBuilder();
                        for (int i = 1; i <= 32; i++)
                            itemsDay.Append("<option").Append(i == DateTime.Now.Day ? " selected=\"selected\">" : ">").Append(i).Append("</option>");
                        StringBuilder itemsMonth = new StringBuilder();
                        for (int i = 1; i <= 12; i++)
                            itemsMonth.Append("<option value=\"").Append(i).Append("\"").Append(i == DateTime.Now.Month ? " selected=\"selected\">" : ">").Append(DateTime.Parse("2000-" + i + "-01").ToString("MMMM")).Append("</option>");
                        StringBuilder itemsYear = new StringBuilder();
                        for (int i = DateTime.Now.AddYears(-5).Year; i <= DateTime.Now.Year; i++)
                            itemsYear.Append("<option").Append(i == DateTime.Now.Year ? " selected=\"selected\">" : ">").Append(i).Append("</option>");
                        // Output the content to display an image (above) of todays data
                        pageElements["CC128_CONTENT"] = Core.templates["cc128"]["history_today"]
                            .Replace("%ITEMS_DAY%", itemsDay.ToString())
                            .Replace("%ITEMS_MONTH%", itemsMonth.ToString())
                            .Replace("%ITEMS_YEAR%", itemsYear.ToString())
                            ;
                        pageElements["CC128_TITLE"] = "History - Today";
                        pageElements.setFlag("CC128_H_TODAY");
                    }
                    break;
                case "month":
                    // Month
                    string monthCurr = DateTime.Now.Year + "-" + DateTime.Now.Month + "-01";
                    // Get the max value for the month
                    Result monthMaxVal = conn.Query_Read("SELECT AVG(watts) AS watts FROM cc128_readings WHERE datetime >= '" + Utils.Escape(monthCurr) + "' ORDER BY watts DESC LIMIT 1");
                    if (monthMaxVal.Rows.Count != 1 || monthMaxVal[0]["watts"].Length == 0)
                        pageElements["CC128_CONTENT"] = "<p>No data available.</p>";
                    else
                    {
                        double maxValue = double.Parse(monthMaxVal[0]["watts"]);
                        // Process every day
                        StringBuilder monthBars = new StringBuilder();
                        double percent;
                        foreach (ResultRow day in conn.Query_Read("SELECT AVG(watts) AS watts, DAY(datetime) AS day FROM cc128_readings WHERE datetime >= '" + Utils.Escape(monthCurr) + "' GROUP BY DATE(datetime)"))
                        {
                            percent = Math.Floor(100 * (double.Parse(day["watts"]) / maxValue));
                            monthBars.Append(
                                Core.templates["cc128"]["history_bar"]
                                .Replace("%TITLE%", int.Parse(day["day"]).ToString("0#") + " - " + day["watts"] + " watts average")
                                .Replace("%PERCENT%", (percent > 100 ? 100 : percent).ToString())
                                );
                        }
                        pageElements["CC128_CONTENT"] = Core.templates["cc128"]["history_month"]
                        .Replace("%ITEMS%", monthBars.ToString())
                        ;
                    }
                    pageElements["CC128_TITLE"] = "History - This Month";
                    pageElements.setFlag("CC128_H_MONTH");
                    break;
                case "year":
                    // Year
                    // Get the max value for the month
                    Result yearMaxVal = conn.Query_Read("SELECT AVG(watts) AS watts FROM cc128_readings WHERE YEAR(datetime) = YEAR(NOW()) GROUP BY MONTH(datetime) ORDER BY watts DESC LIMIT 1");
                    if (yearMaxVal.Rows.Count != 1)
                        pageElements["CC128_CONTENT"] = "<p>No data available.</p>";
                    else
                    {
                        double maxValue = double.Parse(yearMaxVal[0]["watts"]);
                        // Process every day
                        StringBuilder yearBars = new StringBuilder();
                        double percent;
                        foreach (ResultRow day in conn.Query_Read("SELECT AVG(watts) AS watts, MONTH(DATETIME) AS month  FROM cc128_readings WHERE YEAR(datetime) = YEAR(NOW()) GROUP BY MONTH(datetime)"))
                        {
                            percent = Math.Floor(100 * (double.Parse(day["watts"]) / maxValue));
                            yearBars.Append(
                                Core.templates["cc128"]["history_bar"]
                                .Replace("%TITLE%", DateTime.Parse(DateTime.Now.Year + "-" + day["month"] + "-01").ToString("MMMM") + " - " + day["watts"] + " watts average")
                                .Replace("%PERCENT%", (percent > 100 ? 100 : percent).ToString())
                                );
                        }
                        pageElements["CC128_CONTENT"] = Core.templates["cc128"]["history_month"]
                        .Replace("%ITEMS%", yearBars.ToString())
                        ;
                    }
                    pageElements["CC128_TITLE"] = "History - This Year";
                    pageElements.setFlag("CC128_H_YEAR");
                    break;
                case "all":
                    // All
                    Result general = conn.Query_Read("SELECT COUNT('') AS total, AVG(watts) AS average FROM cc128_readings");
                    Result allMax = conn.Query_Read("SELECT MAX(watts) AS watts, datetime FROM cc128_readings GROUP BY datetime ORDER BY watts DESC LIMIT 1");
                    Result allMin = conn.Query_Read("SELECT MIN(NULLIF(watts, 0)) AS watts, datetime FROM cc128_readings GROUP BY datetime ORDER BY watts ASC LIMIT 1"); // Thank-you to http://stackoverflow.com/questions/2099720/mysql-find-min-but-not-zero for pro-tip <3
                    pageElements["CC128_CONTENT"] = Core.templates["cc128"]["history_all"]
                        .Replace("%TOTAL%", HttpUtility.HtmlEncode(general.Rows.Count == 1 ? general[0]["total"] : "Unavailable"))
                        .Replace("%MAX_WATTS%", HttpUtility.HtmlEncode(allMax.Rows.Count == 1 ? allMax[0]["watts"] : "Unavailable"))
                        .Replace("%MAX_DATE%", HttpUtility.HtmlEncode(allMax.Rows.Count == 1 ? allMax[0]["datetime"] : "Unavailable"))
                        .Replace("%MIN_WATTS%", HttpUtility.HtmlEncode(allMin.Rows.Count == 1 ? allMin[0]["watts"] : "Unavailable"))
                        .Replace("%MIN_DATE%", HttpUtility.HtmlEncode(allMin.Rows.Count == 1 ? allMin[0]["datetime"] : "Unavailable"))
                        .Replace("%AVERAGE%", HttpUtility.HtmlEncode(general.Rows.Count == 1 ? general[0]["average"] : "Unavailable"))
                        ;
                    pageElements["CC128_TITLE"] = "History - All";
                    break;
            }
        }
예제 #6
0
 /// <summary>
 /// Used to authenticate existing users.
 /// </summary>
 /// <param name="pluginid"></param>
 /// <param name="conn"></param>
 /// <param name="pageElements"></param>
 /// <param name="request"></param>
 /// <param name="response"></param>
 private static void pageLogin(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     const string incorrectUserPassword = "******";
     string error = null;
     string referral = request.Form["referral"];
     // Check for login
     if (request.Form["username"] != null && request.Form["password"] != null)
     {
         bool persist = request.Form["persist"] != null;
         string username = request.Form["username"];
         string password = request.Form["password"];
         // Validate
         if (!Common.Validation.validCaptcha(request.Form["captcha"]))
             error = "Invalid captcha code!";
         else if (username.Length < USERNAME_MIN || username.Length > USERNAME_MAX)
             error = incorrectUserPassword;
         else if (password.Length < PASSWORD_MIN || password.Length > PASSWORD_MAX)
             error = incorrectUserPassword;
         else
         {
             int maxLoginPeriod = int.Parse(Core.settings[SETTINGS_CATEGORY][SETTINGS_MAX_LOGIN_PERIOD]);
             int maxLoginAttempts = int.Parse(Core.settings[SETTINGS_CATEGORY][SETTINGS_MAX_LOGIN_ATTEMPTS]);
             // Check the IP has not tried to authenticate in the past
             if (conn.Query_Count("SELECT COUNT('') FROM bsa_failed_logins WHERE ip='" + Utils.Escape(request.UserHostAddress) + "' AND datetime >= '" + Utils.Escape(DateTime.Now.AddMinutes(-maxLoginPeriod).ToString("yyyy-MM-dd HH:mm:ss")) + "'") >= maxLoginAttempts)
                 error = "You've exceeded the maximum login-attempts, try again in " + maxLoginPeriod + " minutes...";
             else
             {
                 // Set anti-injection flag
                 pageElements.setFlag(FLAG_PASSWORD_ACCESSED);
                 // Authenticate
                 Result res = conn.Query_Read("SELECT u.userid, u.password, g.access_login, COUNT(b.banid) AS active_bans FROM bsa_users AS u LEFT OUTER JOIN bsa_user_groups AS g ON g.groupid=u.groupid LEFT OUTER JOIN bsa_user_bans AS b ON (b.userid=u.userid AND ((b.unban_date IS NULL) OR (b.unban_date > NOW()) )) WHERE u.username='******'");
                 if (res.Rows.Count != 1 || res[0]["password"] != generateHash(password, salt1, salt2))
                 {
                     // Incorrect login - log as an attempt
                     // -- Check if the user exists, if so we'll log it into the user_log table
                     res = conn.Query_Read("SELECT userid FROM bsa_users WHERE username LIKE '" + username.Replace("%", "") + "'");
                     conn.Query_Execute("INSERT INTO bsa_failed_logins (ip, attempted_username, datetime) VALUES('" + Utils.Escape(request.UserHostAddress) + "', '" + Utils.Escape(username) + "', NOW());");
                     // Log event
                     if(res.Rows.Count == 1)
                         logEvent(res[0]["userid"], LogEvents.Login_Incorrect, request.UserHostAddress + " - " + request.UserAgent, conn);
                     // Inform the user
                     error = incorrectUserPassword;
                 }
                 else if (!res[0]["access_login"].Equals("1"))
                     error = "Your account is not allowed to login; your account is either awaiting activation or you've been banned.";
                 else if (int.Parse(res[0]["active_bans"]) > 0)
                 {
                     Result currentBan = conn.Query_Read("SELECT reason, unban_date FROM bsa_user_bans WHERE userid='" + Utils.Escape(res[0]["userid"]) + "' ORDER BY unban_date DESC");
                     if (currentBan.Rows.Count == 0)
                         error = "You are currently banned.";
                     else
                         error = "Your account is currently banned until '" + (currentBan[0]["unban_date"].Length > 0 ? HttpUtility.HtmlEncode(currentBan[0]["unban_date"]) : "the end of time (permanent)") + "' for the reason '" + HttpUtility.HtmlEncode(currentBan[0]["reason"]) + "'!";
                 }
                 else
                 {
                     // Authenticate the user
                     FormsAuthentication.SetAuthCookie(res[0]["userid"], persist);
                     // Log the event
                     logEvent(res[0]["userid"], LogEvents.Login_Authenticated, request.UserHostAddress + " - " + request.UserAgent, conn);
                     // Check if a ref-url exists, if so redirect to it
                     conn.Disconnect();
                     if (referral != null && referral.Length > 0)
                         response.Redirect(referral);
                     else
                         response.Redirect(pageElements["URL"]);
                 }
             }
         }
     }
     // Display page
     pageElements["TITLE"] = "Login";
     pageElements["CONTENT"] = Core.templates["basic_site_auth"]["login"]
         .Replace("%REFERRAL%", HttpUtility.HtmlEncode(referral != null ? referral : request.UrlReferrer != null ? request.UrlReferrer.AbsoluteUri : pageElements["URL"] + "/home"))
         .Replace("%USERNAME%", request.Form["username"] ?? string.Empty)
         .Replace("%PERSIST%", request.Form["persist"] != null ? "checked" : string.Empty)
         .Replace("%ERROR%", error != null ? Core.templates[pageElements["TEMPLATE"]]["error"].Replace("<ERROR>", error) : string.Empty);
     // Add CSS file
     Misc.Plugins.addHeaderCSS("/Content/CSS/BasicSiteAuth.css", ref pageElements);
 }
예제 #7
0
 public static void pageProfile_Profile(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     // Decide which user to display
     string userid = null;
     if (request.QueryString["userid"] != null) // Load via userid
     {
         // Ensure the userid is valid
         if (conn.Query_Count("SELECT COUNT('') FROM bsa_users WHERE userid='" + Utils.Escape(request.QueryString["userid"]) + "'") != 1)
             return;
         userid = request.QueryString["userid"];
     }
     else if (request.QueryString["username"] != null) // Load via username
     {
         // Fetch the userid, if not found we'll 404 the request by returning
         Result usernameToUserid = conn.Query_Read("SELECT userid FROM bsa_users WHERE username LIKE '" + Utils.Escape(request.QueryString["username"].Replace("%", "")) + "'");
         if (usernameToUserid.Rows.Count != 1) return;
         userid = usernameToUserid[0]["userid"];
     }
     else if (HttpContext.Current.User.Identity.IsAuthenticated) // Load the current logged-in user
         userid = HttpContext.Current.User.Identity.Name;
     else // No user specified, user is not authenticated - tell them to register
         response.Redirect(pageElements["URL"] + "/register", true);
     // By this point the userid should be valid and exist, hence we just need to grab the profile data
     string rawProfileDataQuery = "SELECT p.*, u.username, u.registered, g.title AS group_title, g.access_admin FROM bsa_profiles AS p LEFT OUTER JOIN bsa_users AS u ON u.userid=p.userid LEFT OUTER JOIN bsa_user_groups AS g ON g.groupid=u.groupid WHERE p.userid='" + Utils.Escape(userid) + "'";
     Result rawProfileData = conn.Query_Read(rawProfileDataQuery);
     if (rawProfileData.Rows.Count == 0) // Profile doesn't exist, create it
     {
         conn.Query_Execute("INSERT INTO bsa_profiles (userid) VALUES('" + Utils.Escape(userid) + "')");
         rawProfileData = conn.Query_Read(rawProfileDataQuery);
         if (rawProfileData.Rows.Count == 0) return; // Something is wrong...
     }
     ResultRow profileData = rawProfileData[0];
     // Check if admin or the owner of the profile - if so, we'll set the PROFILE_OWNER FLAG
     bool owner = false;
     if (HttpContext.Current.User.Identity.IsAuthenticated && (profileData["userid"] == HttpContext.Current.User.Identity.Name))
     {
         pageElements.setFlag("PROFILE_OWNER");
         owner = true;
     }
     // Check the user is allowed to access the profile - if it's disabled, only the owner or an admin can access it
     if (!owner && !profileData["disabled"].Equals("0"))
         return;
     // Check which page the user wants to access
     switch (request.QueryString["1"])
     {
         default:
             // -- About page is default
             pageProfile_About(pluginid, ref profileData, conn, ref pageElements, request, response);
             break;
         case "settings":
             pageProfile_Settings(pluginid, ref rawProfileDataQuery, ref profileData, conn, ref pageElements, request, response);
             break;
         case "upload":
             pageProfile_Upload(pluginid, ref profileData, conn, ref pageElements, request, response);
             break;
     }
     if (pageElements["PROFILE_CONTENT"] == null) return; // No content set, 404..
     // Build frame
     DateTime registered = profileData["registered"].Length > 0 ? DateTime.Parse(profileData["registered"]) : DateTime.MinValue;
     pageElements["CONTENT"] =
         Core.templates["bsa_profiles"]["profile_frame"]
         .Replace("<USERID>", HttpUtility.HtmlEncode(profileData["userid"]))
         .Replace("<PANE_BG_COLOUR>", profileData["colour_background"])
         .Replace("<PANE_TEXT_COLOUR>", profileData["colour_text"])
         .Replace("<BACKGROUND>", (profileData["background_url"].Length > 0 ? "url('" + HttpUtility.HtmlEncode(profileData["background_url"]) + "') " : string.Empty) + (profileData["background_colour"].Length > 0 ? "#" + profileData["background_colour"] : string.Empty))
         .Replace("<USERNAME>", HttpUtility.HtmlEncode(profileData["username"]))
         .Replace("<GROUP>", HttpUtility.HtmlEncode(profileData["group_title"]))
         .Replace("<REGISTERED>", HttpUtility.HtmlEncode(registered.ToString("dd MMMM yyyy")))
         .Replace("<REGISTERED_DAYS>", HttpUtility.HtmlEncode(Misc.Plugins.getTimeString(registered)))
         .Replace("<COUNTRY_FLAG>", profileData["country_code"].Length > 0 ? profileData["country_code"] : "unknown")
         .Replace("<COUNTRY_TITLE>", Common.Country.getCountryTitle(profileData["country_code"], conn) ?? "Unknown")
         .Replace("<GENDER_CODE>", profileData["gender"])
         .Replace("<GENDER>", profileData["gender"] == "1" ? "Male" : profileData["gender"] == "2" ? "Female" : "Not specified.")
         .Replace("<OCCUPATION>", profileData["occupation"].Length > 0 ? HttpUtility.HtmlEncode(profileData["occupation"]) : "Not specified.");
     ;
     pageElements["TITLE"] = "Profile - " + HttpUtility.HtmlEncode(profileData["username"]);
 }
예제 #8
0
        public static void pageArticle_View_Comments(ref string pluginid, ref Connector conn, ref Misc.PageElements pageElements, ref HttpRequest request, ref HttpResponse response, ref bool permCreate, ref bool permDelete, ref bool permPublish, ref bool owner, ref StringBuilder content, ref ResultRow article)
        {
            bool allowComments = article["allow_comments_thread"].Equals("1");
            if (!allowComments)
                content.Append(Core.templates["articles"]["comments_disabled"]);

            // -- Check for a new comment posted by the user
            string commentError = null;
            string commentBody = request.Form["comment_body"];
            string commentCaptcha = request.Form["comment_captcha"];
            if (commentBody != null && commentCaptcha != null)
            {
                if (!Common.Validation.validCaptcha(commentCaptcha))
                    commentError = "Incorrect captcha verification code!";
                else if (commentBody.Length < Core.settings[SETTINGS_KEY].getInt(SETTINGS_COMMENTS_LENGTH_MIN) || commentBody.Length > Core.settings[SETTINGS_KEY].getInt(SETTINGS_COMMENTS_LENGTH_MAX))
                    commentError = "Your comment must be " + Core.settings[SETTINGS_KEY][SETTINGS_COMMENTS_LENGTH_MIN] + " to  " + Core.settings[SETTINGS_KEY][SETTINGS_COMMENTS_LENGTH_MAX] + " in length!";
                else if (commentBody.Replace(" ", string.Empty).Length == 0)
                    commentError = "Comment cannot be empty/contain just spaces!";
                else if (conn.Query_Count("SELECT COUNT('') FROM articles_thread_comments WHERE userid='" + Utils.Escape(HttpContext.Current.User.Identity.Name) + "' AND datetime >= DATE_SUB(NOW(), INTERVAL 1 HOUR)") >= Core.settings[SETTINGS_KEY].getInt(SETTINGS_COMMENTS_MAX_PER_HOUR))
                    commentError = "You've already posted the maximum of " + Core.settings[SETTINGS_KEY][SETTINGS_COMMENTS_MAX_PER_HOUR] + " comments per an hour - try again later!";
                else
                {
                    // Insert the post
                    conn.Query_Execute("INSERT INTO articles_thread_comments (threadid, userid, message, datetime) VALUES('" + Utils.Escape(article["threadid"]) + "', '" + Utils.Escape(HttpContext.Current.User.Identity.Name) + "', '" + Utils.Escape(commentBody) + "', NOW())");
                    // Reset comment body
                    commentBody = null;
                }
            }
            // -- Check if to delete a comment
            string dcom = request.QueryString["dcom"];
            if (dcom != null && HttpContext.Current.User.Identity.IsAuthenticated && Misc.Plugins.isNumeric(dcom))
            {
                bool canDelete = permDelete;
                if (!canDelete)
                {
                    // -- User cannot delete all comments, check if they're the owner
                    Result dcomData = conn.Query_Read("SELECT userid FROM articles_thread_comments WHERE commentid='" + Utils.Escape(dcom) + "'");
                    if (dcomData.Rows.Count == 1 && dcomData[0]["userid"] == HttpContext.Current.User.Identity.Name)
                        canDelete = true;
                }
                if (!canDelete) return;
                else
                    conn.Query_Execute("DELETE FROM articles_thread_comments WHERE commentid='" + Utils.Escape(dcom) + "'");
            }
            // Build comments body
            string commentsPageRaw = request.QueryString["apg"];
            // -- Get the page
            int commentsPage;
            if (!int.TryParse(commentsPageRaw, out commentsPage) || commentsPage < 1) commentsPage = 1;
            // -- Get the comments data associated with that page
            int commentsPerPage = Core.settings[SETTINGS_KEY].getInt(SETTINGS_COMMENTS_PER_PAGE);
            Result commentsData = conn.Query_Read("SELECT atc.*, u.username FROM articles_thread_comments AS atc LEFT OUTER JOIN bsa_users AS u ON u.userid=atc.userid WHERE threadid='" + Utils.Escape(article["threadid"]) + "' ORDER BY datetime DESC LIMIT " + ((commentsPerPage * commentsPage) - commentsPerPage) + "," + commentsPerPage);
            // -- Build the data
            if (commentsData.Rows.Count == 0)
                content.Append(Core.templates["articles"]["comments_empty"]);
            else
                foreach (ResultRow comment in commentsData)
                {
                    content.Append(
                        (HttpContext.Current.User.Identity.IsAuthenticated && (permDelete || HttpContext.Current.User.Identity.Name == comment["userid"]) ? Core.templates["articles"]["comment_delete"] : Core.templates["articles"]["comment"])
                        .Replace("<USERID>", comment["userid"])
                        .Replace("<ARTICLEID>", article["articleid"])
                        .Replace("<COMMENTID>", comment["commentid"])
                        .Replace("<USERNAME>", HttpUtility.HtmlEncode(comment["username"]))
                        .Replace("<DATETIME>", HttpUtility.HtmlEncode(comment["datetime"]))
                        .Replace("<BODY>", HttpUtility.HtmlEncode(comment["message"]))
                        );
                }
            // Set navigator
            content.Append(
                Core.templates["articles"]["page_nav"]
                .Replace("<SUBPAGE>", "comments")
                .Replace("<PAGE>", commentsPage.ToString())
                .Replace("<PAGE_PREVIOUS>", (commentsPage > 1 ? commentsPage - 1 : 1).ToString())
                .Replace("<PAGE_NEXT>", (commentsPage < int.MaxValue ? commentsPage + 1 : int.MaxValue).ToString())
                );
            // -- Set flags for the previous and next buttons - very simple solution but highly efficient
            if (commentsPage > 1)
                pageElements.setFlag("ARTICLE_PAGE_PREVIOUS");
            if (commentsData.Rows.Count == commentsPerPage)
                pageElements.setFlag("ARTICLE_PAGE_NEXT");
            // Set the postbox
            if (HttpContext.Current.User.Identity.IsAuthenticated && allowComments)
                content.Append(
                        Core.templates["articles"]["comments_postbox"]
                    .Replace("<ERROR>", commentError != null ? Core.templates[pageElements["TEMPLATE"]]["error"].Replace("<ERROR>", commentError) : string.Empty)
                    .Replace("<COMMENT_BODY>", HttpUtility.HtmlEncode(commentBody))
                    );
        }
예제 #9
0
 public static void pageArticle_View_History(ref string pluginid, ref Connector conn, ref Misc.PageElements pageElements, ref HttpRequest request, ref HttpResponse response, ref bool permCreate, ref bool permDelete, ref bool permPublish, ref bool owner, ref StringBuilder content, ref ResultRow article)
 {
     // Setup the page being viewed
     int page;
     string rawPage = request.QueryString["apg"];
     if (rawPage == null || !int.TryParse(rawPage, out page) || page < 1) page = 1;
     // Append header
     content.Append(
         Core.templates["articles"]["history_header"]
         );
     // Grab the current selected article
     string currentArticleID = (conn.Query_Scalar("SELECT articleid_current FROM articles_thread WHERE threadid='" + Utils.Escape(article["threadid"]) + "'") ?? string.Empty).ToString();
     // Append each article revision
     int historyPerPage = Core.settings[SETTINGS_KEY].getInt(SETTINGS_HISTORY_PER_PAGE);
     Result articles = conn.Query_Read("SELECT a.*, u.username, u2.username AS author FROM articles AS a LEFT OUTER JOIN bsa_users AS u ON u.userid=a.moderator_userid LEFT OUTER JOIN bsa_users AS u2 ON u2.userid=a.userid WHERE a.threadid='" + Utils.Escape(article["threadid"]) + "' ORDER BY a.articleid DESC LIMIT " + ((historyPerPage * page) - historyPerPage) + "," + historyPerPage);
     foreach (ResultRow a in articles)
     {
         content.Append(
             Core.templates["articles"]["history_row"]
             .Replace("<ARTICLEID>", HttpUtility.HtmlEncode(a["articleid"]))
             .Replace("<SELECTED>", a["articleid"] == currentArticleID ? "SELECTED" : string.Empty)
             .Replace("<TITLE>", HttpUtility.HtmlEncode(a["title"]))
             .Replace("<PUBLISHED>", a["published"].Equals("1") ? "Published by " + HttpUtility.HtmlEncode(a["username"]) : "Pending publication.")
             .Replace("<DATETIME>", a["datetime"].Length > 0 ? a["datetime"] : "Unknown")
             .Replace("<DATETIME_SHORT>", a["datetime"].Length > 0 ? Misc.Plugins.getTimeString(DateTime.Parse(a["datetime"])) : "Unknown")
             .Replace("<CREATOR_USERID>", HttpUtility.HtmlEncode(a["userid"]))
             .Replace("<CREATOR>", HttpUtility.HtmlEncode(a["author"]))
             );
     }
     // Append navigator
     content.Append(
         Core.templates["articles"]["page_nav"]
         .Replace("<SUBPAGE>", "history")
         .Replace("<PAGE>", page.ToString())
         .Replace("<PAGE_PREVIOUS>", (page > 1 ? page - 1 : 1).ToString())
         .Replace("<PAGE_NEXT>", (page < int.MaxValue ? page + 1 : int.MaxValue).ToString())
         );
     // Set navigator flags
     if (page > 1)
         pageElements.setFlag("ARTICLE_PAGE_PREVIOUS");
     if (page < int.MaxValue && articles.Rows.Count == historyPerPage)
         pageElements.setFlag("ARTICLE_PAGE_NEXT");
 }
예제 #10
0
        /// <summary>
        /// Used to create/modify an article.
        /// </summary>
        /// <param name="pluginid"></param>
        /// <param name="conn"></param>
        /// <param name="pageElements"></param>
        /// <param name="request"></param>
        /// <param name="response"></param>
        public static void pageArticle_Editor(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
        {
            // Check the user is logged-in, else redirect to the login page
            if (!HttpContext.Current.User.Identity.IsAuthenticated)
                response.Redirect(pageElements["URL"] + "/login", true);

            // Load the users permissions and check they're able to create articles
            Result perms = conn.Query_Read("SELECT ug.access_media_create, ug.access_media_publish, ug.access_media_edit, ug.access_admin FROM bsa_users AS u LEFT OUTER JOIN bsa_user_groups AS ug ON ug.groupid=u.groupid WHERE u.userid='" + Utils.Escape(HttpContext.Current.User.Identity.Name) + "'");
            if (perms.Rows.Count != 1 || !perms[0]["access_media_create"].Equals("1")) return;
            bool permAdmin = perms[0]["access_admin"].Equals("1");
            bool permEdit = perms[0]["access_media_edit"].Equals("1");
            bool permPublish = perms[0]["access_media_publish"].Equals("1");

            string error = null;
            Result preData = null;
            ResultRow preDataRow = null;
            // Check if we're modifying an existing article, if so we'll load the data
            string articleid = request.QueryString["articleid"];
            if (articleid != null && Misc.Plugins.isNumeric(articleid))
            {
                // Attempt to load the pre-existing article's data
                preData = conn.Query_Read("SELECT a.*, at.relative_url, at.pdf_name, GROUP_CONCAT(at2.keyword SEPARATOR ',') AS tags FROM articles AS a LEFT OUTER JOIN articles_tags AS at2 ON (EXISTS (SELECT tagid FROM articles_tags_article WHERE tagid=at2.tagid AND articleid='" + Utils.Escape(articleid) + "')) LEFT OUTER JOIN articles_thread AS at ON at.threadid=a.threadid WHERE articleid='" + Utils.Escape(articleid) + "'");
                if (preData.Rows.Count != 1) preData = null;
                else
                    preDataRow = preData[0];
            }
            // Check for postback
            string title = request.Form["title"];
            string body = request.Form["body"];
            string relativeUrl = request.Form["relative_url"] ?? request.QueryString["relative_url"];
            string tags = request.Form["tags"];
            bool allowHTML = request.Form["allow_html"] != null;
            bool allowComments = request.Form["allow_comments"] != null;
            bool showPane = request.Form["show_pane"] != null;
            bool inheritThumbnail = request.Form["inherit_thumbnail"] != null;
            bool updateExisting = request.Form["update_existing"] != null;
            HttpPostedFile thumbnail = request.Files["thumbnail"];
            if (title != null && body != null && relativeUrl != null && tags != null)
            {
                // Validate
                if (title.Length < Core.settings[SETTINGS_KEY].getInt(SETTINGS_TITLE_MIN) || title.Length > Core.settings[SETTINGS_KEY].getInt(SETTINGS_TITLE_MAX))
                    error = "Title must be " + Core.settings[SETTINGS_KEY][SETTINGS_TITLE_MIN] + " to " + Core.settings[SETTINGS_KEY][SETTINGS_TITLE_MAX] + " characters in length!";
                else if (body.Length < Core.settings[SETTINGS_KEY].getInt(SETTINGS_BODY_MIN) || body.Length > Core.settings[SETTINGS_KEY].getInt(SETTINGS_BODY_MAX))
                    error = "Body must be " + Core.settings[SETTINGS_KEY][SETTINGS_BODY_MIN] + " to " + Core.settings[SETTINGS_KEY][SETTINGS_BODY_MAX] + " characters in length!";
                else if (body.Replace(" ", string.Empty).Length == 0)
                    error = "Body cannot be empty/contain just spaces!";
                else if (thumbnail != null && thumbnail.ContentLength > 0 && thumbnail.ContentLength > Core.settings[SETTINGS_KEY].getInt(SETTINGS_THUMBNAIL_MAXSIZE))
                    error = "Thumbnail cannot exceed " + Core.settings[SETTINGS_KEY][SETTINGS_THUMBNAIL_MAXSIZE] + " bytes (" + Misc.Plugins.getBytesString(Core.settings[SETTINGS_KEY].getInt(SETTINGS_THUMBNAIL_MAXSIZE)) + ")!";
                else if (thumbnail != null && thumbnail.ContentLength > 0 && !Core.settings[SETTINGS_KEY].getCommaArrayContains(SETTINGS_IMAGE_TYPES, thumbnail.ContentType))
                    error = "Invalid thumbnail image format - ensure you uploaded an image!";
                else if ((error = validRelativeUrl(relativeUrl, Core.settings[SETTINGS_KEY].getInt(SETTINGS_RELATIVE_URL_MAXCHUNKS), Core.settings[SETTINGS_KEY].getInt(SETTINGS_RELATIVE_URL_CHUNK_MIN), Core.settings[SETTINGS_KEY].getInt(SETTINGS_RELATIVE_URL_CHUNK_MAX))) != null)
                    ;
                else
                {
                    // Verify the user has not exceeded post limits for today - unless they're admin, we'll just skip the checks
                    ResultRow postLimits = permAdmin ? null : conn.Query_Read("SELECT (SELECT COUNT('') FROM articles WHERE userid='" + Utils.Escape(HttpContext.Current.User.Identity.Name) + "' AND datetime >= DATE_SUB(NOW(), INTERVAL 1 HOUR)) AS articles_hour, (SELECT COUNT('') FROM articles WHERE userid='" + Utils.Escape(HttpContext.Current.User.Identity.Name) + "' AND datetime >= DATE_SUB(NOW(), INTERVAL 1 DAY)) AS articles_day")[0];
                    if (postLimits != null && int.Parse(postLimits["articles_hour"]) >= Core.settings[SETTINGS_KEY].getInt(SETTINGS_ARTICLES_EDIT_PER_HOUR))
                        error = "You've already posted the maximum amount of articles allowed within an hour, please try again later!";
                    else if (postLimits != null && int.Parse(postLimits["articles_day"]) >= Core.settings[SETTINGS_KEY].getInt(SETTINGS_ARTICLES_EDIT_PER_DAY))
                        error = "You've already posted the maximum amount of articles allowed today, please try again later!";
                    else
                    {
                        // Verify tags
                        ArticleTags parsedTags = getTags(tags, Core.settings[SETTINGS_KEY].getInt(SETTINGS_TAGS_TITLE_MIN), Core.settings[SETTINGS_KEY].getInt(SETTINGS_TAGS_TITLE_MAX), Core.settings[SETTINGS_KEY].getInt(SETTINGS_TAGS_MAX));
                        if (parsedTags.error != null) error = parsedTags.error;
                        else
                        {
                            // Check if we're inserting, else perhaps inheriting, a thumbnail
                            string thumbnailid = null;
                            if (thumbnail != null && thumbnail.ContentLength > 0)
                            {
                                byte[] imageData = compressImageData(thumbnail.InputStream, Core.settings[SETTINGS_KEY].getInt(SETTINGS_THUMBNAIL_MAXWIDTH), Core.settings[SETTINGS_KEY].getInt(SETTINGS_THUMBNAIL_MAXHEIGHT));
                                if (imageData != null)
                                {
                                    // Success - insert thumbnail and get thumbnailid
                                    Dictionary<string, object> thumbParams = new Dictionary<string, object>();
                                    thumbParams.Add("thumb", imageData);
                                    thumbnailid = conn.Query_Scalar_Parameters("INSERT INTO articles_thumbnails (data) VALUES(@thumb); SELECT LAST_INSERT_ID();", thumbParams).ToString();
                                }
                                else
                                    error = "Failed to process thumbnail image, please try again or report this to the site administrator!";
                            }
                            else if (inheritThumbnail && preDataRow != null && preDataRow["thumbnailid"].Length != 0)
                            {
                                // Grab pre-existing thumbnailid
                                thumbnailid = preDataRow["thumbnailid"];
                            }
                            // Ensure no thumbnail processing errors occur, else do not continue
                            if (error == null)
                            {
                                // Format the body formatting for caching
                                StringBuilder cached = new StringBuilder(body);
                                articleViewRebuildCache(conn, ref cached, allowHTML, ref pageElements);

                                // Posted data is valid, check if the thread exists - else create it
                                bool updateArticle = false; // If the article is being modified and it has not been published and it's owned by the same user -> update it (user may make a small change)
                                string threadid;
                                Result threadCheck = conn.Query_Read("SELECT threadid FROM articles_thread WHERE relative_url='" + Utils.Escape(relativeUrl) + "'");
                                if (threadCheck.Rows.Count == 1)
                                {
                                    // -- Thread exists
                                    threadid = threadCheck[0]["threadid"];
                                    // -- Check if to update the article if the articleid has been specified
                                    if (articleid != null)
                                    {
                                        Result updateCheck = conn.Query_Read("SELECT userid, published FROM articles WHERE articleid='" + Utils.Escape(articleid) + "' AND threadid='" + Utils.Escape(threadid) + "'");
                                        // If the article is unpublished *or* update-existing is true, set the update flag to true
                                        bool ucPublished = updateCheck[0]["published"].Equals("1");
                                        if (updateCheck.Rows.Count == 1 && ((updateCheck[0]["userid"] == HttpContext.Current.User.Identity.Name && !ucPublished) || (updateExisting && (permAdmin || permEdit))))
                                            updateArticle = true;
                                    }
                                }
                                else
                                    // -- Create thread
                                    threadid = conn.Query_Scalar("INSERT INTO articles_thread (relative_url) VALUES('" + Utils.Escape(relativeUrl) + "'); SELECT LAST_INSERT_ID();").ToString();

                                // Check if to insert or update the article
                                if (updateArticle)
                                {
                                    StringBuilder query = new StringBuilder();
                                    // Update the article
                                    query
                                        .Append("UPDATE articles SET title='").Append(Utils.Escape(title))
                                        .Append("', thumbnailid=").Append(thumbnailid != null ? "'" + Utils.Escape(thumbnailid) + "'" : "NULL")
                                        .Append(", body='").Append(Utils.Escape(body))
                                        .Append("', body_cached='").Append(Utils.Escape(cached.ToString()))
                                        .Append("', allow_comments='").Append(allowComments ? "1" : "0")
                                        .Append("', allow_html='").Append(allowHTML ? "1" : "0")
                                        .Append("', show_pane='").Append(showPane ? "1" : "0").Append("' WHERE articleid='").Append(Utils.Escape(articleid)).Append("';");
                                    // Delete the previous tags
                                    query.Append("DELETE FROM articles_tags_article WHERE articleid='" + Utils.Escape(articleid) + "';");
                                    // Delete the previous images associated with the article
                                    query.Append("DELETE FROM articles_images_links WHERE articleid='" + Utils.Escape(articleid) + "'");
                                    // -- Execute query
                                    conn.Query_Execute(query.ToString());
                                }
                                else
                                {
                                    // Insert article and link to the thread
                                    StringBuilder query = new StringBuilder();
                                    query
                                        .Append("INSERT INTO articles (threadid, title, userid, body, body_cached, moderator_userid, published, allow_comments, allow_html, show_pane, thumbnailid, datetime) VALUES('")
                                        .Append(Utils.Escape(threadid))
                                        .Append("', '").Append(Utils.Escape(title))
                                        .Append("', '").Append(Utils.Escape(HttpContext.Current.User.Identity.Name))
                                        .Append("', '").Append(Utils.Escape(body))
                                        .Append("', '").Append(Utils.Escape(cached.ToString()))
                                        .Append("', ").Append(permPublish ? "'" + Utils.Escape(HttpContext.Current.User.Identity.Name) + "'" : "NULL")
                                        .Append(", '").Append(permPublish ? "1" : "0")
                                        .Append("', '").Append(allowComments ? "1" : "0")
                                        .Append("', '").Append(allowHTML ? "1" : "0")
                                        .Append("', '").Append(showPane ? "1" : "0")
                                        .Append("', ").Append(thumbnailid != null ? "'" + Utils.Escape(thumbnailid) + "'" : "NULL")
                                        .Append(", NOW()); SELECT LAST_INSERT_ID();");
                                    articleid = conn.Query_Scalar(query.ToString()).ToString();
                                    // If this was automatically published, set it as the current article for the thread
                                    if (permPublish)
                                        conn.Query_Execute("UPDATE articles_thread SET articleid_current='" + Utils.Escape(articleid) + "' WHERE relative_url='" + Utils.Escape(relativeUrl) + "'");
                                }
                                // Add/update pdf
                                pdfRebuild(pluginid, articleid, title, preData != null ? preDataRow["pdf_name"] : string.Empty, threadid, request);
                                // Add the new tags and delete any tags not used by any other articles, as well as cleanup unused thumbnails
                                StringBuilder finalQuery = new StringBuilder();
                                if (parsedTags.tags.Count > 0)
                                {
                                    StringBuilder tagsInsertQuery = new StringBuilder();
                                    StringBuilder tagsArticleQuery = new StringBuilder();
                                    foreach (string tag in parsedTags.tags)
                                    {
                                        // -- Attempt to insert the tags - if they exist, they wont be inserted
                                        tagsInsertQuery.Append("('" + Utils.Escape(tag) + "'),");
                                        tagsArticleQuery.Append("((SELECT tagid FROM articles_tags WHERE keyword='" + Utils.Escape(tag) + "'), '" + Utils.Escape(articleid) + "'),");
                                    }
                                    // -- Build final query
                                    finalQuery.Append("INSERT IGNORE INTO articles_tags (keyword) VALUES")
                                        .Append(tagsInsertQuery.Remove(tagsInsertQuery.Length - 1, 1).ToString())
                                        .Append("; INSERT IGNORE INTO articles_tags_article (tagid, articleid) VALUES")
                                        .Append(tagsArticleQuery.Remove(tagsArticleQuery.Length - 1, 1).ToString())
                                        .Append(";");
                                }
                                // Add any linked imagery
                                // -- Find the unique valid image IDs
                                List<string> images = new List<string>();
                                foreach (Match m in Regex.Matches(body, REGEX_IMAGE_STORE, RegexOptions.Multiline))
                                    if (!images.Contains(m.Groups[1].Value))
                                        images.Add(m.Groups[1].Value);
                                foreach (Match m in Regex.Matches(body, REGEX_IMAGE_STORE_CUSTOM_W, RegexOptions.Multiline))
                                    if (!images.Contains(m.Groups[3].Value))
                                        images.Add(m.Groups[3].Value);
                                foreach (Match m in Regex.Matches(body, REGEX_IMAGE_STORE_CUSTOM_WH, RegexOptions.Multiline))
                                    if (!images.Contains(m.Groups[3].Value))
                                        images.Add(m.Groups[3].Value);
                                if (images.Count != 0)
                                {
                                    // -- Insert all the valid IDs which exist in the actual articles_images table
                                    finalQuery.Append("INSERT IGNORE INTO articles_images_links (articleid, imageid) SELECT '" + Utils.Escape(articleid) + "' AS articleid, imageid FROM articles_images WHERE imageid IN (");
                                    foreach (string s in images)
                                        finalQuery.Append("'").Append(Utils.Escape(s)).Append("',");
                                    finalQuery.Remove(finalQuery.Length - 1, 1).Append(");");
                                }
                                // -- This will delete any tags in the main table no longer used in the articles tags table
                                finalQuery.Append(QUERY_TAGS_CLEANUP);
                                // -- This will delete any unused thumbnail images
                                finalQuery.Append(QUERY_THUMBNAIL_CLEANUP);
                                // -- This will log the event
                                finalQuery.Append(insertEvent(updateArticle ? RecentChanges_EventType.Edited : RecentChanges_EventType.Created, HttpContext.Current.User.Identity.Name, articleid, threadid));
                                // -- Execute final query
                                conn.Query_Execute(finalQuery.ToString());
                                // Redirect to the new article
                                conn.Disconnect();
                                response.Redirect(pageElements["URL"] + "/article/" + articleid, true);
                            }
                        }
                    }
                }
            }
            // Display form
            pageElements["CONTENT"] = Core.templates["articles"]["editor"]
                .Replace("<ERROR>", error != null ? Core.templates[pageElements["TEMPLATE"]]["error"].Replace("<ERROR>", HttpUtility.HtmlEncode(error)) : string.Empty)
                .Replace("<PARAMS>", preData != null ? "articleid=" + HttpUtility.UrlEncode(preData[0]["articleid"]) : string.Empty)
                .Replace("<TITLE>", HttpUtility.HtmlEncode(title ?? (preDataRow != null ? preDataRow["title"] : string.Empty)))
                .Replace("<RELATIVE_PATH>", HttpUtility.HtmlEncode(relativeUrl ?? (preDataRow != null ? preDataRow["relative_url"] : string.Empty)))
                .Replace("<TAGS>", HttpUtility.HtmlEncode(tags ?? (preDataRow != null ? preDataRow["tags"] : string.Empty)))
                .Replace("<ALLOW_HTML>", allowHTML || (title == null && preDataRow != null && preDataRow["allow_html"].Equals("1")) ? "checked" : string.Empty)
                .Replace("<ALLOW_COMMENTS>", allowComments || (title == null && preDataRow != null && preDataRow["allow_comments"].Equals("1")) ? "checked" : string.Empty)
                .Replace("<SHOW_PANE>", showPane || (title == null && preDataRow != null && preDataRow["show_pane"].Equals("1")) ? "checked" : string.Empty)
                .Replace("<INHERIT>", inheritThumbnail || (title == null && preDataRow != null && preDataRow["thumbnailid"].Length > 0) ? "checked" : string.Empty)
                .Replace("<UPDATE_EXISTING>", updateExisting || (title == null && preDataRow != null) ? "checked" : string.Empty)
                .Replace("<BODY>", HttpUtility.HtmlEncode(body ?? (preDataRow != null ? preDataRow["body"] : string.Empty)))
                ;
            // Set flags
            // -- Update existing checkbox
            if ((permAdmin || permEdit) && preData != null)
                pageElements.setFlag("UPDATE_EXISTING");
            // Finalize page
            Misc.Plugins.addHeaderJS(pageElements["URL"] + "/Content/JS/Article.js", ref pageElements);
            Misc.Plugins.addHeaderCSS(pageElements["URL"] + "/Content/CSS/Article.css", ref pageElements);
            Misc.Plugins.addHeaderCSS(pageElements["URL"] + "/Content/CSS/Common.css", ref pageElements);
            // Add includes
            Common.formatProvider_formatIncludes(request, response, conn, ref pageElements, true, true);
            pageElements["TITLE"] = "Articles - Editor";
        }
예제 #11
0
        /// <summary>
        /// Used to view an article.
        /// </summary>
        /// <param name="pluginid"></param>
        /// <param name="conn"></param>
        /// <param name="pageElements"></param>
        /// <param name="request"></param>
        /// <param name="response"></param>
        public static void pageArticle_View(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
        {
            // Retrieve the article ID
            string articleid;
            if (request.QueryString["page"] == "article")
                articleid = request.QueryString["1"];
            else
            {
                // Build the relative URL
                StringBuilder relativeUrl = new StringBuilder();
                relativeUrl.Append(request.QueryString["page"]).Append("/"); // The querystring "pg" should never be null, however no null exception will occur with stringbuilder anyhow
                string chunk;
                int relativeUrlMaxChunks = Core.settings[SETTINGS_KEY].getInt(SETTINGS_RELATIVE_URL_MAXCHUNKS);
                int relativeUrlChunkMax = Core.settings[SETTINGS_KEY].getInt(SETTINGS_RELATIVE_URL_CHUNK_MAX);
                int relativeUrlChunkMin = Core.settings[SETTINGS_KEY].getInt(SETTINGS_RELATIVE_URL_CHUNK_MIN);
                for (int i = 1; i <= relativeUrlMaxChunks; i++)
                {
                    chunk = request.QueryString[i.ToString()];
                    if (chunk != null)
                    {
                        if (chunk.Length < relativeUrlChunkMin || chunk.Length > relativeUrlChunkMax)
                            return; // Invalid request - hence 404...
                        else
                            relativeUrl.Append(chunk).Append("/");
                    }
                    else
                        break;
                }
                // Check if we've grabbed anything
                if (relativeUrl.Length == 0)
                    return; // No URL captured - 404...
                else
                    relativeUrl.Remove(relativeUrl.Length - 1, 1); // Remove tailing slash
                // Grab the article ID from the database
                articleid = (conn.Query_Scalar("SELECT articleid_current FROM articles_thread WHERE relative_url='" + Utils.Escape(relativeUrl.ToString()) + "'") ?? string.Empty).ToString();
            }
            // Check we have an articleid that is not null and greater than zero, else 404
            if (articleid == null || articleid.Length == 0) return;
            // Load the article's data
            Result articleRaw = conn.Query_Read("SELECT (SELECT COUNT('') FROM articles_thread_permissions WHERE threadid=at.threadid LIMIT 1) AS perms_enabled, (SELECT COUNT('') FROM articles WHERE threadid=a.threadid AND articleid <= a.articleid ORDER BY articleid ASC) AS revision, (SELECT ac.allow_comments FROM articles_thread AS act LEFT OUTER JOIN articles AS ac ON ac.articleid=act.articleid_current WHERE act.threadid=at.threadid) AS allow_comments_thread, a.articleid, a.threadid, a.title, a.userid, a.body, a.body_cached, a.moderator_userid, a.published, a.allow_comments, a.allow_html, a.show_pane, a.datetime, at.relative_url, at.articleid_current, at.pdf_name, u.username FROM (articles AS a, articles_thread AS at) LEFT OUTER JOIN bsa_users AS u ON u.userid=a.userid WHERE a.articleid='" + Utils.Escape(articleid) + "' AND at.threadid=a.threadid");
            if (articleRaw.Rows.Count != 1)
                return; // 404 - no data found - the article is corrupt (thread and article not linked) or the article does not exist
            ResultRow article = articleRaw[0];
            // Load the users permissions
            bool published = article["published"].Equals("1");
            bool permCreate;
            bool permDelete;
            bool permPublish;
            bool owner;
            // Grab the user's permissions and check they're allowed to access the thread - with overriding for PDF generator via access-code
            // -- Check for override
            string pdfc = request.QueryString["pdfc"];
            bool pdfOverride = pdfc != null && pdfc.Length == 16 && pdfAccessCodes.ContainsKey(pdfc) && pdfAccessCodes[pdfc] == article["articleid"];
            // -- Check actual permissions
            bool threadRequiresPermissions = !pdfOverride && article["perms_enabled"] != "0";
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                Result permsRaw = conn.Query_Read("SELECT " + (threadRequiresPermissions ? "(SELECT COUNT('') FROM articles_thread_permissions WHERE threadid='" + Utils.Escape(article["threadid"]) + "' AND groupid=g.groupid) AS role_exists," : string.Empty) + " g.access_media_create, g.access_media_delete, g.access_media_publish FROM bsa_users AS u LEFT OUTER JOIN bsa_user_groups AS g ON g.groupid=u.groupid WHERE u.userid='" + Utils.Escape(HttpContext.Current.User.Identity.Name) + "'");
                if(permsRaw.Rows.Count != 1) return; // Something has gone wrong
                ResultRow perms = permsRaw[0];
                permPublish = perms["access_media_publish"].Equals("1");
                // Check if the user has permission to view the thread; if the user has publish permissions, they are automatically allowed to view the thread
                if (!permPublish && threadRequiresPermissions && perms["role_exists"] == "0")
                {
                    pageArticle_View_AccessDenied(conn, pageElements);
                    return;
                }
                permCreate = perms["access_media_create"].Equals("1");
                permDelete = perms["access_media_delete"].Equals("1");
                owner = article["userid"] == HttpContext.Current.User.Identity.Name;
            }
            else if (threadRequiresPermissions)
            {
                pageArticle_View_AccessDenied(conn, pageElements);
                return;
            }
            else
            {
                permCreate = false;
                permDelete = false;
                permPublish = false;
                owner = false;
            }

            // Create stringbuilder for assembling the article
            StringBuilder content = new StringBuilder();
            // Check the article is published *or* the user is admin/owner of the article
            if (!published && (!HttpContext.Current.User.Identity.IsAuthenticated || (!owner && !permPublish)))
                return;
            // Append the main body of the article
            content.Append(Core.templates["articles"]["article"]);

            // Render the body based on the current page
            bool subpage = request.QueryString["page"] == "article" && request.QueryString["2"] != null;
            StringBuilder subpageContent = new StringBuilder();
            if (subpage)
            {
                // -- Sub-page
                switch (request.QueryString["2"])
                {
                    case "publish":
                        if (!permPublish) return; // Check the user has sufficient permission
                        pageArticle_View_Publish(ref pluginid, ref conn, ref pageElements, ref request, ref response, ref permCreate, ref permDelete, ref permPublish, ref owner, ref subpageContent, ref article);
                        break;
                    case "delete":
                        // An owner of an unpublished article can delete it
                        if (!permDelete && !(owner && !published)) return; // Check the user has sufficient permission
                        pageArticle_View_Delete(ref pluginid, ref conn, ref pageElements, ref request, ref response, ref permCreate, ref permDelete, ref permPublish, ref owner, ref subpageContent, ref article);
                        break;
                    case "history":
                        pageArticle_View_History(ref pluginid, ref conn, ref pageElements, ref request, ref response, ref permCreate, ref permDelete, ref permPublish, ref owner, ref subpageContent, ref article);
                        break;
                    case "comments":
                        pageArticle_View_Comments(ref pluginid, ref conn, ref pageElements, ref request, ref response, ref permCreate, ref permDelete, ref permPublish, ref owner, ref subpageContent, ref article);
                        break;
                    case "set":
                        if (!permPublish || !published) return;
                        pageArticle_View_Set(ref pluginid, ref conn, ref pageElements, ref request, ref response, ref permCreate, ref permDelete, ref permPublish, ref owner, ref subpageContent, ref article);
                        break;
                    case "rebuild":
                        pageArticle_View_Rebuild(ref pluginid, ref conn, ref pageElements, ref request, ref response, ref permCreate, ref permDelete, ref permPublish, ref owner, ref subpageContent, ref article);
                        break;
                    case "permissions":
                        if (!permPublish) return;
                        pageArticle_View_Permissions(ref pluginid, ref conn, ref pageElements, ref request, ref response, ref permCreate, ref permDelete, ref permPublish, ref owner, ref subpageContent, ref article);
                        break;
                    case "pdf":
                        pageArticle_View_Pdf(ref pluginid, ref conn, ref pageElements, ref request, ref response, ref article);
                        break;
                    default:
                        return; // 404 - unknown sub-page
                }
                content.Replace("<BODY>", subpageContent.ToString());
            }
            else
            {
                if (!published && article["allow_html"].Equals("1"))
                {
                    // Wrap content in HTML protection container (against e.g. malicious uploads)
                    subpageContent.Append(
                        Core.templates["articles"]["article_html_protect"]
                        .Replace("<DATA>", article["body_cached"].Replace("<", "&lt;").Replace(">", "&gt;"))
                        );
                }
                else
                    subpageContent.Append(article["body_cached"]);
                // Insert article dependencies
                Common.formatProvider_formatIncludes(request, response, conn, ref pageElements, true, true);
                // Generate tags
                StringBuilder tags = new StringBuilder();
                StringBuilder metaTags = new StringBuilder("<meta name=\"keywords\" content=\"");
                foreach (ResultRow tag in conn.Query_Read("SELECT at.keyword FROM articles_tags_article AS ata LEFT OUTER JOIN articles_tags AS at ON at.tagid=ata.tagid WHERE ata.articleid='" + Utils.Escape(article["articleid"]) + "'"))
                {
                    // Append tag for the bottom of the article
                    tags.Append(
                        Core.templates["articles"]["article_tag"].Replace("<TITLE_ENCODED>", HttpUtility.HtmlEncode(tag["keyword"])).Replace("<TITLE>", HttpUtility.HtmlEncode(tag["keyword"]))
                        );
                    // Append tag for meta
                    metaTags.Append(HttpUtility.HtmlEncode(tag["keyword"])).Append(",");
                }
                metaTags.Remove(metaTags.Length - 1, 1);
                // -- Append meta keywords
                pageElements["HEADER"] += metaTags.Append("\">").ToString();
                // -- Append meta author
                pageElements["HEADER"] += "<meta name=\"author\" content=\"" + article["username"] + "\" />";
                // Set the article's body
                content.Replace("<BODY>", subpageContent.ToString())
                    .Append(
                        Core.templates["articles"]["article_footer"]
                            .Replace("<TAGS>", tags.Length == 0 ? "(none)" : tags.ToString()))
                            .Replace("<DATE>", article["datetime"].Length > 0 ? Misc.Plugins.getTimeString(DateTime.Parse(article["datetime"])) : "unknown")
                            .Replace("<FULL_DATE>", article["datetime"].Length > 0 ? DateTime.Parse(article["datetime"]).ToString("dd/MM/yyyy HH:mm:ss") : "unknown")
                            .Replace("<REVISION>", HttpUtility.HtmlEncode(article["revision"]))
                    ;
            }

            // Add pane
            content
                .Replace("<ARTICLEID>", HttpUtility.HtmlEncode(article["articleid"]))
                .Replace("<THREADID>", HttpUtility.HtmlEncode(article["threadid"]))
                .Replace("<COMMENTS>", conn.Query_Count("SELECT COUNT('') FROM articles_thread_comments WHERE threadid='" + Utils.Escape(article["threadid"]) + "'").ToString())
                .Replace("<PDF_NAME>", HttpUtility.HtmlEncode(article["pdf_name"]))
                ;

            bool pdf = request.QueryString["pdf"] != null;

            // Set flag for showing pane - this can be overriden if a querystring force_pane is specified
            if (article["show_pane"].Equals("1") || !published || request.QueryString["force_pane"] != null || subpage)
                pageElements.setFlag("ARTICLE_SHOW_PANE");

            // Set published flag
            if (published)
                pageElements.setFlag("ARTICLE_PUBLISHED");

            // Set download as PDF flag
            if (Core.settings[SETTINGS_KEY].getBool(SETTINGS_PDF_ENABLED) && article["pdf_name"].Length > 0)
                pageElements.setFlag("ARTICLE_PDF_DOWNLOAD");

            //Set current article flag
            if (article["articleid_current"] == article["articleid"])
                pageElements.setFlag("ARTICLE_CURRENT");

            // Check if to use the PDF template
            if (pdf)
            {
                pageElements["TEMPLATE"] = "articles_pdf";
                pageElements.setFlag("ARTICLE_PDF_MODE");
            }

            // Set permission flags
            if (permCreate)
                pageElements.setFlag("ARTICLE_PERM_CREATE");
            if (permDelete)
                pageElements.setFlag("ARTICLE_PERM_DELETE");
            if (permPublish)
                pageElements.setFlag("ARTICLE_PERM_PUBLISH");

            pageElements["TITLE"] = HttpUtility.HtmlEncode(article["title"]);
            pageElements["CONTENT"] = content.ToString();
            Misc.Plugins.addHeaderCSS(pageElements["URL"] + "/Content/CSS/Article.css", ref pageElements);
            Misc.Plugins.addHeaderJS(pageElements["URL"] + "/Content/JS/Article.js", ref pageElements);
        }
예제 #12
0
        public static void pageArticles_Tag(ref StringBuilder content, string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
        {
            string tag = request.QueryString["2"];
            int browseArticlesPage = Core.settings[SETTINGS_KEY].getInt(SETTINGS_BROWSE_ARTICLES_PAGE);
            // Viewing articles by tag
            int page;
            if (request.QueryString["bpg"] == null || !int.TryParse(request.QueryString["bpg"], out page) || page < 1) page = 1;
            string sort = request.QueryString["sort"];
            // Security
            tag = tag.Replace("%", string.Empty);

            content.Append(Core.templates["articles"]["browse_header"].Replace("<TITLE>", "Tag `" + HttpUtility.HtmlEncode(tag) + "`"));
            // Add sorting
            content.Append(
                Core.templates["articles"]["browse_sorting"]
                .Replace("<URL>", "articles/tag/" + HttpUtility.HtmlEncode(tag) + "?bpg=" + page)
                );
            // Display all the articles belonging to a tag
            Result rawArticles = conn.Query_Read("SELECT ata.articleid, a.title, a.datetime, ath.relative_url FROM articles_tags_article AS ata, articles_tags AS at, articles AS a, articles_thread AS ath WHERE a.articleid=ath.articleid_current AND ata.articleid=a.articleid AND ata.tagid=at.tagid AND at.keyword LIKE '" + Utils.Escape(tag) + "' ORDER BY " + (sort == "t_a" ? "a.title ASC" : sort == "t_d" ? "a.title DESC" : sort == "d_a" ? "a.datetime ASC" : "a.datetime DESC") + " LIMIT " + ((browseArticlesPage * page) - browseArticlesPage) + "," + browseArticlesPage);
            if (rawArticles.Rows.Count != 0)
                foreach (ResultRow article in rawArticles)
                    content.Append(
                        Core.templates["articles"]["browse_article"]
                        .Replace("<RELATIVE_URL>", article["relative_url"])
                        .Replace("<ARTICLEID>", HttpUtility.UrlEncode(article["articleid"]))
                        .Replace("<TITLE>", HttpUtility.HtmlEncode(article["title"]))
                        .Replace("<DATETIME>", HttpUtility.HtmlEncode(article["datetime"]))
                        .Replace("<DATETIME_SHORT>", HttpUtility.HtmlEncode(article["datetime"].Length > 0 ? Misc.Plugins.getTimeString(DateTime.Parse(article["datetime"])) : "Unknown"))
                        );
            else
                content.Append("None.");
            // Add page navigation
            content.Append(
                Core.templates["articles"]["browse_nav"]
                .Replace("<TAG>", HttpUtility.UrlEncode(tag))
                .Replace("<URL>", "articles/tag/<TAG>?sort=" + HttpUtility.UrlEncode(sort))
                .Replace("<PAGE>", page.ToString())
                .Replace("<PAGE_PREVIOUS>", (page > 1 ? page - 1 : 1).ToString())
                .Replace("<PAGE_NEXT>", (page < int.MaxValue ? page + 1 : int.MaxValue).ToString())
                );
            // Set navigation flags
            if (page > 1) pageElements.setFlag("ARTICLES_PAGE_PREVIOUS");
            if (page < int.MaxValue && rawArticles.Rows.Count == browseArticlesPage) pageElements.setFlag("ARTICLES_PAGE_NEXT");
            pageElements["TITLE"] = "Articles - Tag - " + HttpUtility.HtmlEncode(tag);
        }
예제 #13
0
 public static void pageArticles_Search(ref StringBuilder content, string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     string search = request.QueryString["keywords"];
     int browseArticlesPage = Core.settings[SETTINGS_KEY].getInt(SETTINGS_BROWSE_ARTICLES_PAGE);
     int page;
     if (request.QueryString["bpg"] == null || !int.TryParse(request.QueryString["bpg"], out page) || page < 1) page = 1;
     // Viewing articles by search
     content.Append(Core.templates["articles"]["browse_header"].Replace("<TITLE>", "Search Results for `" + HttpUtility.HtmlEncode(search) + "`"));
     string escapedKeywords = Utils.Escape(search.Replace("%", string.Empty));
     Result results = conn.Query_Read("SELECT a.articleid, a.title, a.datetime, at.relative_url FROM articles_thread AS at LEFT OUTER JOIN articles AS a ON a.articleid=at.articleid_current WHERE at.relative_url LIKE '" + escapedKeywords + "' OR a.title LIKE '%" + escapedKeywords + "%' OR a.body LIKE '%" + escapedKeywords + "%' LIMIT " + ((browseArticlesPage * page) - browseArticlesPage) + "," + browseArticlesPage);
     if (results.Rows.Count != 0)
         foreach (ResultRow foundItem in results)
             content.Append(
                 Core.templates["articles"]["browse_article"]
                 .Replace("<RELATIVE_URL>", foundItem["relative_url"])
                 .Replace("<ARTICLEID>", HttpUtility.UrlEncode(foundItem["articleid"]))
                 .Replace("<TITLE>", HttpUtility.HtmlEncode(foundItem["title"]))
                 .Replace("<DATETIME>", HttpUtility.HtmlEncode(foundItem["datetime"]))
                 .Replace("<DATETIME_SHORT>", HttpUtility.HtmlEncode(foundItem["datetime"].Length > 0 ? Misc.Plugins.getTimeString(DateTime.Parse(foundItem["datetime"])) : "Unknown"))
                 );
     else
         content.Append("None.");
     // Add page navigation
     content.Append(
         Core.templates["articles"]["browse_nav"]
         .Replace("<URL>", "articles/search?keywords=" + HttpUtility.HtmlEncode(search))
         .Replace("<PAGE>", page.ToString())
         .Replace("<PAGE_PREVIOUS>", (page > 1 ? page - 1 : 1).ToString())
         .Replace("<PAGE_NEXT>", (page < int.MaxValue ? page + 1 : int.MaxValue).ToString())
         );
     // Set navigation flags
     if (page > 1) pageElements.setFlag("ARTICLES_PAGE_PREVIOUS");
     if (page < int.MaxValue && results.Rows.Count == browseArticlesPage) pageElements.setFlag("ARTICLES_PAGE_NEXT");
     pageElements["TITLE"] = "Articles - Search";
 }
예제 #14
0
 public static void pageArticles_RecentChanges(ref StringBuilder content, string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response, bool accessAdmin)
 {
     // Grab the page
     int page;
     if (request.QueryString["bpg"] == null || !int.TryParse(request.QueryString["bpg"], out page) || page < 1) page = 1;
     if (accessAdmin)
     {
         // Check for any admin options
         if (request.QueryString["2"] == "wipe" && Common.AntiCSRF.isValidTokenCookie(request, response))
         {
             // Wipe all log entries and reload the page
             conn.Query_Execute("DELETE FROM articles_log_events");
             conn.Disconnect();
             response.Redirect(pageElements["URL"] + "/articles/recent_changes");
         }
         // Append options pane
         content.Append(
             Core.templates["articles"]["change_options"]
         );
         // Set anti-csrf protection
         Common.AntiCSRF.setCookieToken(response);
     }
     // Begin building each log event
     int changesPerPage = Core.settings[SETTINGS_KEY].getInt(SETTINGS_CHANGES_PER_PAGE);
     RecentChanges_EventType type;
     DateTime eventDate;
     int year, month, day;
     year = month = day = 0;
     Result logData = conn.Query_Read("SELECT ale.*, at.relative_url, a.title, u.username FROM articles_log_events AS ale LEFT OUTER JOIN articles AS a ON a.articleid=ale.articleid LEFT OUTER JOIN articles_thread AS at ON at.threadid=ale.threadid LEFT OUTER JOIN bsa_users AS u ON u.userid=ale.userid ORDER BY datetime DESC LIMIT " + ((changesPerPage * page) - changesPerPage) + "," + changesPerPage);
     if (logData.Rows.Count != 0)
     {
         string logHtml;
         foreach (ResultRow logEvent in logData)
         {
             eventDate = DateTime.Parse(logEvent["datetime"]);
             // Check if to change the datetime
             if (eventDate.Day != day || eventDate.Month != month || eventDate.Year != year)
             {
                 day = eventDate.Day;
                 month = eventDate.Month;
                 year = eventDate.Year;
                 // Output date header
                 content.Append(
                     Core.templates["articles"]["change_date"]
                     .Replace("<TITLE>", eventDate.ToString("dd MMMM yyyy, dddd"))
                     );
             }
             // Append item
             type = (RecentChanges_EventType)Enum.Parse(typeof(RecentChanges_EventType), logEvent["event_type"]);
             switch (type)
             {
                 case RecentChanges_EventType.Created:
                     logHtml = Core.templates["articles"]["change_created"];
                     break;
                 case RecentChanges_EventType.Deleted:
                     logHtml = Core.templates["articles"]["change_deleted"];
                     break;
                 case RecentChanges_EventType.DeletedThread:
                     logHtml = Core.templates["articles"]["change_deletedthread"];
                     break;
                 case RecentChanges_EventType.Edited:
                     logHtml = Core.templates["articles"]["change_edited"];
                     break;
                 case RecentChanges_EventType.Published:
                     logHtml = Core.templates["articles"]["change_published"];
                     break;
                 case RecentChanges_EventType.SetAsSelected:
                     logHtml = Core.templates["articles"]["change_selected"];
                     break;
                 case RecentChanges_EventType.RebuiltArticleCache:
                     logHtml = Core.templates["articles"]["change_rebuild_cache"];
                     break;
                 default:
                     logHtml = null;
                     break;
             }
             // Replace text and append
             if (logHtml != null)
             {
                 content.Append(
                             logHtml
                             .Replace("<ARTICLEID>", HttpUtility.HtmlEncode(logEvent["articleid"]))
                             .Replace("<THREADID>", HttpUtility.HtmlEncode(logEvent["threadid"]))
                             .Replace("<RELATIVE_URL>", logEvent["relative_url"].Length > 0 ? HttpUtility.UrlEncode(logEvent["relative_url"]) : "(unknown)")
                             .Replace("<USERID>", HttpUtility.HtmlEncode(logEvent["userid"]))
                             .Replace("<USERNAME>", HttpUtility.HtmlEncode(logEvent["username"]))
                             .Replace("<DATETIME>", HttpUtility.HtmlEncode(logEvent["datetime"]))
                             .Replace("<TIME>", HttpUtility.HtmlEncode(Misc.Plugins.getTimeString(eventDate)))
                             .Replace("<TITLE>", HttpUtility.HtmlEncode(logEvent["title"]))
                             );
             }
         }
     }
     else
         content.Append("No recent changes have occurred or the log has been wiped.");
     // Append navigation
     content.Append(
         Core.templates["articles"]["browse_nav"]
         .Replace("<URL>", "articles/recent_changes")
         .Replace("<PAGE>", page.ToString())
         .Replace("<PAGE_PREVIOUS>", (page > 1 ? page - 1 : 1).ToString())
         .Replace("<PAGE_NEXT>", (page < int.MaxValue ? page + 1 : int.MaxValue).ToString())
         );
     // Set navigation flags
     if (page > 1) pageElements.setFlag("ARTICLES_PAGE_PREVIOUS");
     if (page < int.MaxValue && logData.Rows.Count == changesPerPage) pageElements.setFlag("ARTICLES_PAGE_NEXT");
     // Output the page
     pageElements["TITLE"] = "Articles - Recent Changes";
 }
예제 #15
0
 public static void pageUsers(Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     if (request.QueryString["2"] != null)
     {
         // Editing a user
         string error = null;
         bool updatedAccount = false;
         // Set SQL injection protection flag (to disable flag)
         pageElements.setFlag(Plugins.BasicSiteAuth.FLAG_PASSWORD_ACCESSED);
         // Grab the user's info, bans and available user groups
         Result user = conn.Query_Read("SELECT * FROM bsa_users WHERE userid='" + Utils.Escape(request.QueryString["2"]) + "'");
         if (user.Rows.Count != 1) return;
         Result bans = conn.Query_Read("SELECT b.*, u.username FROM bsa_user_bans AS b LEFT OUTER JOIN bsa_users AS u ON u.userid=b.banner_userid ORDER BY datetime DESC");
         Result userGroups = conn.Query_Read("SELECT groupid, title FROM bsa_user_groups ORDER BY access_login ASC, access_changeaccount ASC, access_media_create ASC, access_media_edit ASC, access_media_delete ASC, access_media_publish ASC, access_admin ASC, title ASC");
         string dban = request.QueryString["dban"];
         // Check for deleting a ban
         if (dban != null)
         {
             conn.Query_Execute("DELETE FROM bsa_user_bans WHERE banid='" + Utils.Escape(dban) + "'");
             conn.Disconnect();
             response.Redirect(pageElements["ADMIN_URL"] + "/" + user[0]["userid"], true);
         }
         // Check for postback of banning the user
         string ban = request.QueryString["ban"];
         string banCustom = request.QueryString["ban_custom"];
         string banReason = request.QueryString["ban_reason"];
         if (ban != null || banCustom != null)
         {
             int banAmount = 0;
             if (ban != null)
             {
                 if (ban.Equals("Permanent"))
                     banAmount = 0;
                 else if (ban.Equals("1 Month"))
                     banAmount = 2628000;
                 else if (ban.Equals("1 Week"))
                     banAmount = 604800;
                 else if (ban.Equals("3 Days"))
                     banAmount = 259200;
                 else if (ban.Equals("1 Day"))
                     banAmount = 86400;
                 else
                     error = "Invalid ban period!";
             }
             else
             {
                 if (banCustom != null && !int.TryParse(banCustom, out banAmount))
                     error = "Invalid ban period, not numeric!";
                 else if (banAmount < 0)
                     error = "Ban period cannot be less than zero!";
             }
             if(error == null)
             {
                 // Get the time at which the user will be unbanned
                 DateTime dt = DateTime.Now.AddSeconds(-banAmount);
                 // Insert the record
                 conn.Query_Execute("INSERT INTO bsa_user_bans (userid, reason, unban_date, datetime, banner_userid) VALUES('" + Utils.Escape(user[0]["userid"]) + "', '" + Utils.Escape(banReason) + "', " + (banAmount == 0 ? "NULL" : "'" + Utils.Escape(dt.ToString("yyyy-MM-dd HH:mm:ss")) + "'") + ", NOW(), '" + Utils.Escape(HttpContext.Current.User.Identity.Name) + "')");
                 // Refresh the page
                 conn.Disconnect();
                 response.Redirect(pageElements["ADMIN_URL"] + "/" + user[0]["userid"], true);
             }
         }
         // Check for postback of editing the user
         string username = request.Form["username"];
         string password = request.Form["password"];
         string email = request.Form["email"];
         string secretQuestion = request.Form["secret_question"];
         string secretAnswer = request.Form["secret_answer"];
         string groupid = request.Form["groupid"];
         if (username != null && password != null && email != null && secretQuestion != null && secretAnswer != null && groupid != null)
         {
             if (username.Length < Plugins.BasicSiteAuth.USERNAME_MIN || username.Length > Plugins.BasicSiteAuth.USERNAME_MAX)
                 error = "Username must be " + Plugins.BasicSiteAuth.USERNAME_MIN + " to " + Plugins.BasicSiteAuth.USERNAME_MAX + " characters in length!";
             else if ((error = Plugins.BasicSiteAuth.validUsernameChars(username)) != null)
                 ;
             else if (!Plugins.BasicSiteAuth.validEmail(email))
                 error = "Invalid e-mail!";
             else if (password.Length != 0 && (password.Length < Plugins.BasicSiteAuth.PASSWORD_MIN || password.Length > Plugins.BasicSiteAuth.PASSWORD_MAX))
                 error = "Password must be " + Plugins.BasicSiteAuth.PASSWORD_MIN + " to " + Plugins.BasicSiteAuth.PASSWORD_MAX + " characters in length!";
             else if (secretQuestion.Length < Plugins.BasicSiteAuth.SECRET_QUESTION_MIN || secretQuestion.Length > Plugins.BasicSiteAuth.SECRET_QUESTION_MAX)
                 error = "Secret question must be " + Plugins.BasicSiteAuth.SECRET_QUESTION_MIN + " to " + Plugins.BasicSiteAuth.SECRET_QUESTION_MAX + " characters in length!";
             else if (secretAnswer.Length < Plugins.BasicSiteAuth.SECRET_ANSWER_MIN || secretAnswer.Length > Plugins.BasicSiteAuth.SECRET_ANSWER_MAX)
                 error = "Secret answer must be " + Plugins.BasicSiteAuth.SECRET_ANSWER_MIN + " to " + Plugins.BasicSiteAuth.SECRET_ANSWER_MAX + " characters in length!";
             else
             {
                 // Ensure the groupid is valid
                 bool groupFound = false;
                 foreach (ResultRow group in userGroups) if (group["groupid"] == groupid) groupFound = true;
                 if (!groupFound)
                     error = "Invalid group!";
                 else
                 {
                     // Attempt to update the user's details
                     try
                     {
                         conn.Query_Execute("UPDATE bsa_users SET username='******', email='" + Utils.Escape(email) + "', " + (password.Length > 0 ? "password='******', " : string.Empty) + "secret_question='" + Utils.Escape(secretQuestion) + "', secret_answer='" + Utils.Escape(secretAnswer) + "', groupid='" + Utils.Escape(groupid) + "' WHERE userid='" + Utils.Escape(user[0]["userid"]) + "'");
                         updatedAccount = true;
                     }
                     catch (DuplicateEntryException ex)
                     {
                         if (ex.Column == "email")
                             error = "E-mail already in-use by another user!";
                         else if (ex.Column == "username")
                             error = "Username already in-use by another user!";
                         else
                             error = "Value for " + ex.Column + " is already in-use by another user!";
                     }
                     catch (Exception ex)
                     {
                         error = "Failed to update user settings - " + ex.Message;
                     }
                 }
             }
         }
         // Build user groups
         StringBuilder groups = new StringBuilder();
         foreach (ResultRow group in userGroups)
             groups.Append("<option value=\"").Append(group["groupid"]).Append("\"").Append(group["groupid"] == groupid || groupid == null && group["groupid"] == user[0]["groupid"] ? " selected=\"selected\"" : string.Empty).Append(">" + HttpUtility.HtmlEncode(group["title"]) +"</option>");
         // Build bans
         StringBuilder bansHistory = new StringBuilder();
         if (bans.Rows.Count == 0)
             bansHistory.Append("<p>No bans.</p>");
         else
             foreach (ResultRow banItem in bans)
                 bansHistory.Append(
                     Core.templates["basic_site_auth"]["admin_users_edit_ban"]
                     .Replace("%BANID%", HttpUtility.HtmlEncode(banItem["banid"]))
                     .Replace("%DATETIME%", HttpUtility.HtmlEncode(Misc.Plugins.getTimeString(DateTime.Parse(banItem["datetime"]))))
                     .Replace("%UNBAN_DATE%", HttpUtility.HtmlEncode(banItem["unban_date"].Length > 0 ? banItem["unban_date"] : "never"))
                     .Replace("%USERNAME%", HttpUtility.HtmlEncode(banItem["username"]))
                     .Replace("%REASON%", HttpUtility.HtmlEncode(banItem["reason"]))
                     );
         // Display edit form
         pageElements["ADMIN_CONTENT"] = Core.templates["basic_site_auth"]["admin_users_edit"]
             .Replace("%USERNAME%", HttpUtility.HtmlEncode(username ?? user[0]["username"]))
             .Replace("%EMAIL%", HttpUtility.HtmlEncode(email ?? user[0]["email"]))
             .Replace("%SECRET_QUESTION%", HttpUtility.HtmlEncode(secretQuestion ?? user[0]["secret_question"]))
             .Replace("%SECRET_ANSWER%", HttpUtility.HtmlEncode(secretAnswer ?? user[0]["secret_answer"]))
             .Replace("%GROUPID%", groups.ToString())
             .Replace("%BAN_REASON%", HttpUtility.HtmlEncode(banReason))
             .Replace("%BAN_CUSTOM%", HttpUtility.HtmlEncode(ban))
             .Replace("%BANS%", bansHistory.ToString())
             .Replace("%ERROR%", error != null ? Core.templates[pageElements["TEMPLATE"]]["error"].Replace("<ERROR>", HttpUtility.HtmlEncode(error)) : updatedAccount ? Core.templates[pageElements["TEMPLATE"]]["success"].Replace("<SUCCESS>", "Successfully updated account settings!") : string.Empty)
             .Replace("%USERID%", user[0]["userid"])
             ;
         pageElements["ADMIN_TITLE"] = "Authentication - Users - Editing '" + HttpUtility.HtmlEncode(user[0]["username"]) + "'";
     }
     else
     {
         string error = null;
         // Check for postback
         string username = request.Form["username"];
         if(username != null)
         {
             if (username.Length < Plugins.BasicSiteAuth.USERNAME_MIN || username.Length > Plugins.BasicSiteAuth.USERNAME_MAX || Plugins.BasicSiteAuth.validUsernameChars(username) != null)
                 error = "Invalid username!";
             else
             {
                 // Fetch the userid
                 Result userid = conn.Query_Read("SELECT userid FROM bsa_users WHERE username LIKE '" + Utils.Escape(username.Replace("%", "")) + "'");
                 if (userid.Rows.Count != 1) error = "User not found!";
                 else
                 {
                     conn.Disconnect();
                     response.Redirect(pageElements["ADMIN_URL"] + "/" + userid[0]["userid"], true);
                 }
             }
         }
         // Display user-search form
         pageElements["ADMIN_CONTENT"] = Core.templates["basic_site_auth"]["admin_users"]
             .Replace("%ERROR%", error != null ? Core.templates[pageElements["TEMPLATE"]]["error"].Replace("<ERROR>", HttpUtility.HtmlEncode(error)) : string.Empty)
             .Replace("%USERNAME%", HttpUtility.HtmlEncode(username));
         pageElements["ADMIN_TITLE"] = "Authentication - Users";
     }
 }
예제 #16
0
 public static void pageHome(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     int page;
     if (request.QueryString["pg"] == null || !int.TryParse(request.QueryString["pg"], out page) || page < 1) page = 1;
     const int newsPostsPerPage = 3;
     // Build list of posts
     StringBuilder content = new StringBuilder();
     Result articles = conn.Query_Read("SELECT a.articleid, a.title, a.body_cached, at.relative_url, u.username, a.datetime, a.userid FROM articles AS a LEFT OUTER JOIN bsa_users AS u ON u.userid=a.userid LEFT OUTER JOIN articles_thread AS at ON at.threadid=a.threadid WHERE a.articleid IN (SELECT articleid_current FROM articles_thread) AND a.articleid IN (SELECT ata.articleid FROM articles_tags_article AS ata, articles_tags AS at WHERE ata.tagid=at.tagid AND at.keyword='homepage') ORDER BY a.datetime DESC LIMIT " + ((page * newsPostsPerPage) - newsPostsPerPage) + "," + newsPostsPerPage);
     if (articles.Rows.Count > 0)
         foreach (ResultRow article in articles)
             content.Append(
                 Core.templates["articles"]["home_item"]
                 .Replace("<TITLE>", HttpUtility.HtmlEncode(article["title"]))
                 .Replace("<BODY>", article["body_cached"])
                 .Replace("<DATETIME>", article["datetime"].Length > 0 ? HttpUtility.HtmlEncode(Misc.Plugins.getTimeString(DateTime.Parse(article["datetime"]))) : "unknown")
                 .Replace("<URL>", HttpUtility.HtmlEncode(article["relative_url"].Length > 0 ? pageElements["URL"] + "/" + article["relative_url"] : pageElements["URL"] + "/article/" + article["articleid"]))
                 .Replace("<USERID>", HttpUtility.HtmlEncode(article["userid"]))
                 .Replace("<USERNAME>", HttpUtility.HtmlEncode(article["username"]))
                 );
     else
         content.Append("No more news articles available!");
     // Set page nav flags
     if (page > 1) pageElements.setFlag("PAGE_PREVIOUS");
     if (page < int.MaxValue && articles.Rows.Count == newsPostsPerPage) pageElements.setFlag("PAGE_NEXT");
     // Render page
     pageElements["CONTENT"] = Core.templates["articles"]["home"]
         .Replace("<PAGE>", page.ToString())
         .Replace("<PAGE_PREVIOUS>", (page > 1 ? page - 1 : 1).ToString())
         .Replace("<PAGE_NEXT>", (page < int.MaxValue ? page + 1 : int.MaxValue).ToString())
         .Replace("<ITEMS>", content.ToString())
         ;
     pageElements["TITLE"] = "News";
     // Add includes
     // -- Article
     Misc.Plugins.addHeaderCSS(pageElements["URL"] + "/Content/CSS/Article.css", ref pageElements);
     // -- Format provider
     Common.formatProvider_formatIncludes(request, response, conn, ref pageElements, true, true);
 }
예제 #17
0
 public static void requestEnd(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     // Check no query has been injected
     const string REGEX_ANTI_INJECTION_TEST = @"(([a-zA-Z0-9]+).(password|\*)(?:.+)(bsa_users AS (\2(?:.+)|\2$)))|((.+[^.])(password|\*)(?:.+)FROM(?:.+)bsa_users)";
     if (!pageElements.containsFlag(FLAG_PASSWORD_ACCESSED))
     {
         foreach (string query in conn.Logging_Queries())
             if (query.Contains("bsa_users") && query.Contains("password") && Regex.IsMatch(query, REGEX_ANTI_INJECTION_TEST, RegexOptions.Multiline | RegexOptions.IgnoreCase))
             {
                 // Uh oh...injection occurred...SHUT DOWN EVERYTHING.
                 AdminPanel.addAlert(conn, "Following query has been detected as an injection:\n" + query);
                 conn.Disconnect();
                 response.Write("Your request has been terminated due to a security concern; please try again or contact the site administrator!");
                 response.End();
             }
     }
     // Check the users session is still valid
     if (HttpContext.Current.User.Identity.IsAuthenticated)
     {
         // Set base flag(s)
         pageElements.setFlag("AUTHENTICATED");
         // Select username and check for bans
         Result data = conn.Query_Read("SELECT u.userid, u.username, COUNT(b.banid) AS active_bans, g.title, g.access_login FROM bsa_users AS u LEFT OUTER JOIN bsa_user_bans AS b ON (b.userid=u.userid AND ((b.unban_date IS NULL) OR (b.unban_date > NOW()) )) LEFT OUTER JOIN bsa_user_groups AS g ON g.groupid=u.groupid WHERE u.userid='" + Utils.Escape(HttpContext.Current.User.Identity.Name) + "'");
         if (data.Rows.Count != 1 || int.Parse(data[0]["active_bans"]) > 0 || !data[0]["access_login"].Equals("1"))
         {
             // Dispose the current session - now invalid
             FormsAuthentication.SignOut();
             HttpContext.Current.Session.Abandon();
             // Redirect to logout page to inform the user -- this will cause a 404 but also ensure the session has been disposed because it's invalid
             response.Redirect(pageElements["URL"] + "/logout/banned", true);
         }
         else
         {
             pageElements["USERNAME"] = data[0]["username"];
             pageElements["USERID"] = data[0]["userid"];
         }
         // Set group flag
         pageElements.setFlag("GROUP_" + data[0]["title"]);
     }
 }
예제 #18
0
 public static void pageArticles(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     // Grab permissions
     bool permPublish;
     bool permCreate;
     bool permDelete;
     bool adminAccess;
     if (HttpContext.Current.User.Identity.IsAuthenticated)
     {
         Result permissions = conn.Query_Read("SELECT access_media_create, access_media_publish, access_media_delete, access_admin FROM bsa_users AS u LEFT OUTER JOIN bsa_user_groups AS ug ON ug.groupid=u.groupid WHERE userid='" + Utils.Escape(HttpContext.Current.User.Identity.Name) + "'");
         if (permissions.Rows.Count == 1)
         {
             permPublish = permissions[0]["access_media_publish"].Equals("1");
             permCreate = permissions[0]["access_media_create"].Equals("1");
             permDelete = permissions[0]["access_media_delete"].Equals("1");
             adminAccess = permissions[0]["access_admin"].Equals("1");
         }
         else
             permPublish = permCreate = permDelete = adminAccess = false;
     }
     else
         permPublish = permCreate = permDelete = adminAccess = false;
     // Load settings
     int browseArticlesSection = Core.settings[SETTINGS_KEY].getInt(SETTINGS_BROWSE_ARTICLES_SECTION);
     int browseArticlesPage = Core.settings[SETTINGS_KEY].getInt(SETTINGS_BROWSE_ARTICLES_PAGE);
     // Begin building the content
     StringBuilder content = new StringBuilder();
     string subpg = request.QueryString["1"];
     string tag = request.QueryString["2"];
     string search = request.QueryString["keywords"];
     // Invoke the sub-page for content
     switch (subpg)
     {
         case null:
             pageArticles_Browse(ref content, pluginid, conn, ref pageElements, request, response);
             break;
         case "images":
             pageArticles_Images(ref content, pluginid, conn, ref pageElements, request, response, permCreate, permDelete, permPublish);
             break;
         case "recent_changes":
             pageArticles_RecentChanges(ref content, pluginid, conn, ref pageElements, request, response, adminAccess);
             break;
         case "search":
             if(search == null || search.Length < 1 || search.Length > 40) return;
             pageArticles_Search(ref content, pluginid, conn, ref pageElements, request, response);
             break;
         case "tag":
             if(tag.Length < Core.settings[SETTINGS_KEY].getInt(SETTINGS_TAGS_TITLE_MIN) || tag.Length > Core.settings[SETTINGS_KEY].getInt(SETTINGS_TAGS_TITLE_MAX))
                 return;
             pageArticles_Tag(ref content, pluginid, conn, ref pageElements, request, response);
             break;
         case "stats":
             pageArticles_Stats(ref content, pluginid, conn, ref pageElements, request, response);
             break;
         case "pending":
             pageArticles_Pending(ref content, pluginid, conn, ref pageElements, request, response);
             break;
         case "delete":
             pageArticles_Delete(ref content, pluginid, conn, ref pageElements, request, response);
             break;
         case "index":
             pageArticles_Index(ref content, pluginid, conn, ref pageElements, request, response);
             break;
         case "rebuild_cache":
             pageArticles_RebuildCache(ref content, pluginid, conn, ref pageElements, request, response);
             break;
         default:
             return;
     }
     // Check content has been set, else 404
     if (content.Length == 0) return;
     // Build tag categories
     StringBuilder tagCategories = new StringBuilder();
     Result rawCategories = conn.Query_Read("SELECT DISTINCT at.keyword, COUNT(ata.tagid) AS articles FROM articles_thread AS ath LEFT OUTER JOIN articles_tags_article AS ata On ata.articleid=ath.articleid_current LEFT OUTER JOIN articles_tags AS at ON at.tagid=ata.tagid GROUP BY at.keyword ORDER BY COUNT(ata.tagid) DESC, at.keyword ASC LIMIT " + Core.settings[SETTINGS_KEY].getInt(SETTINGS_BROWSE_TAG_CATEGORIES));
     bool appendedTags = false;
     if (rawCategories.Rows.Count != 0)
         foreach (ResultRow tagCategory in rawCategories)
         {
             if (tagCategory["keyword"].Length > 0)
             {
                 tagCategories.Append(
                     Core.templates["articles"]["browse_tag"]
                     .Replace("<TITLE>", HttpUtility.HtmlEncode(tagCategory["keyword"]))
                     .Replace("<ARTICLES>", HttpUtility.HtmlEncode(tagCategory["articles"]))
                     );
                 appendedTags = true;
             }
         }
     if(!appendedTags)
         tagCategories.Append("No categories/tags exist!");
     // Set flags
     if (permPublish)
         pageElements.setFlag("ARTICLES_PUBLISH");
     if(Core.settings[SETTINGS_KEY].getInt(SETTINGS_STATS_POLLING) > 0)
         pageElements.setFlag("ARTICLES_STATS");
     if (permCreate)
         pageElements.setFlag("ARTICLES_CREATE");
     if (adminAccess)
         pageElements.setFlag("ARTICLES_ADMIN");
     // Add CSS
     Misc.Plugins.addHeaderCSS(pageElements["URL"] + "/Content/CSS/Article.css", ref pageElements);
     // Output page
     pageElements["CONTENT"] = Core.templates["articles"]["browse"]
         .Replace("<CONTENT>", content.ToString())
         .Replace("<TAGS>", tagCategories.ToString())
         .Replace("<SEARCH>", HttpUtility.HtmlEncode(search))
         ;
 }
예제 #19
0
 public static void pageProfile_About(string pluginid, ref ResultRow profileData, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     // Build contact details
     StringBuilder contact = new StringBuilder();
     // -- Github
     if (profileData["contact_github"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "https://github.com/" + HttpUtility.HtmlEncode(profileData["contact_github"]))
             .Replace("<IMAGE>", "https://github.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_github"])));
     // -- Website
     if (profileData["contact_website"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://" + HttpUtility.HtmlEncode(profileData["contact_website"]))
             .Replace("<IMAGE>", pageElements["ADMIN_URL"] + "/Content/Images/bsa_profiles/website.png")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_website"])));
     // -- Email
     if (profileData["contact_email"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "mailto:" + HttpUtility.HtmlEncode(profileData["contact_email"]))
             .Replace("<IMAGE>", pageElements["ADMIN_URL"] + "/Content/Images/bsa_profiles/website.png")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_email"])));
     // -- Facebook
     if(profileData["contact_facebook"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://www.facebook.com/" + HttpUtility.HtmlEncode(profileData["contact_facebook"]))
             .Replace("<IMAGE>", "http://facebook.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_facebook"])));
     // -- G+
     if (profileData["contact_googleplus"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "https://plus.google.com/" + HttpUtility.HtmlEncode(profileData["contact_googleplus"]))
             .Replace("<IMAGE>", "http://plus.google.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_googleplus"])));
     // -- Reddit
     if (profileData["contact_reddit"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://www.reddit.com/user/" + HttpUtility.UrlEncode(profileData["contact_reddit"]))
             .Replace("<IMAGE>", "http://www.reddit.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_reddit"])));
     // -- Steam
     if (profileData["contact_steam"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://steamcommunity.com/id/" + HttpUtility.HtmlEncode(profileData["contact_steam"]))
             .Replace("<IMAGE>", "http://steamcommunity.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_steam"])));
     // -- WLM
     if (profileData["contact_wlm"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://spaces.live.com/profile.aspx?mem=" + HttpUtility.HtmlEncode(profileData["contact_wlm"]))
             .Replace("<IMAGE>", "http://windows.microsoft.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_wlm"])));
     // -- Skype
     if (profileData["contact_skype"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://myskype.info/" + HttpUtility.HtmlEncode(profileData["contact_skype"]))
             .Replace("<IMAGE>", "http://www.skypeassets.com/i/images/icons/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_skype"])));
     // -- YouTube
     if (profileData["contact_youtube"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://www.youtube.com/user/" + HttpUtility.HtmlEncode(profileData["contact_youtube"]))
             .Replace("<IMAGE>", "http://www.youtube.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_youtube"])));
     // -- SoundCloud
     if (profileData["contact_soundcloud"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://soundcloud.com/" + HttpUtility.HtmlEncode(profileData["contact_soundcloud"]))
             .Replace("<IMAGE>", "http://soundcloud.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_soundcloud"])));
     // -- Xbox
     if (profileData["contact_xbox"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://www.xboxlc.com/profile/" + HttpUtility.HtmlEncode(profileData["contact_xbox"]))
             .Replace("<IMAGE>", "http://www.xbox.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_xbox"])));
     // -- PSN
     if (profileData["contact_psn"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://profiles.us.playstation.com/playstation/psn/visit/profiles/" + HttpUtility.HtmlEncode(profileData["contact_psn"]))
             .Replace("<IMAGE>", "http://us.playstation.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_psn"])));
     // -- Flickr
     if (profileData["contact_flickr"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://www.flickr.com/photos/" + HttpUtility.HtmlEncode(profileData["contact_flickr"]))
             .Replace("<IMAGE>", "http://l.yimg.com/g/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_flickr"])));
     // -- Twitter
     if (profileData["contact_twitter"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://twitter.com/" + HttpUtility.HtmlEncode(profileData["contact_twitter"]))
             .Replace("<IMAGE>", "http://www.twitter.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_twitter"])));
     // -- Xfire
     if (profileData["contact_xfire"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://www.xfire.com/profile/" + HttpUtility.HtmlEncode(profileData["contact_xfire"]))
             .Replace("<IMAGE>", "http://xfire.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_xfire"])));
     // -- Deviantart
     if (profileData["contact_deviantart"].Length > 0)
         contact.Append(Core.templates["bsa_profiles"]["profile_about_contact"]
             .Replace("<URL>", "http://" + HttpUtility.HtmlEncode(profileData["contact_deviantart"]) + ".deviantart.com/")
             .Replace("<IMAGE>", "http://deviantart.com/favicon.ico")
             .Replace("<TITLE>", HttpUtility.HtmlEncode(profileData["contact_deviantart"])));
     // Set nutshell
     StringBuilder nutshell = new StringBuilder(HttpUtility.HtmlEncode(profileData["nutshell"]));
     if(nutshell.Length == 0)
         nutshell.Append("User has not specified a nutshell.");
     else
         Common.formatProvider_format(ref nutshell, request, response, conn, ref pageElements, true, true);
     // Set content
     pageElements["PROFILE_CONTENT"] = Core.templates["bsa_profiles"]["profile_about"]
         .Replace("<NUTSHELL>", nutshell.ToString())
         .Replace("<CONTACT>", contact.Length == 0 ? "User has not specified any contact details." : contact.ToString())
         ;
     pageElements.setFlag("PROFILE_ABOUT");
 }
예제 #20
0
 public static void pageArticles_Images_Browse(ref StringBuilder content, string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response, bool permCreate)
 {
     // Process request parameters
     int page;
     if (request.QueryString["bpg"] == null || !int.TryParse(request.QueryString["bpg"], out page) || page < 1) page = 1;
     string search = request.QueryString["search"];
     string alphabet = request.QueryString["a"];
     if (search != null && (search.Length < 1 || search.Length > 25)) search = null;
     if(alphabet != null && (alphabet.Length != 1 || !(alphabet[0] >= 97 && alphabet[0] <= 122))) alphabet = null;
     int imagesPerPage = 9;
     // Build list of images
     StringBuilder images = new StringBuilder();
     StringBuilder query = new StringBuilder("SELECT i.imageid, i.title FROM articles_images AS i");
     if(search != null || alphabet != null)
     {
         query.Append(" WHERE ");
         if(search != null)
             query.Append("i.title LIKE '%").Append(Utils.Escape(search.Replace("%", string.Empty))).Append("%'");
         if(search != null && alphabet != null)
             query.Append(" AND ");
         if(alphabet != null)
             query.Append("i.title LIKE '").Append(Utils.Escape(alphabet)).Append("%'");
     }
     query.Append(" ORDER BY i.title ASC, i.datetime ASC LIMIT ").Append((imagesPerPage * page) - imagesPerPage).Append(", ").Append(imagesPerPage);
     Result data = conn.Query_Read(query.ToString());
     StringBuilder results = new StringBuilder();
     if (data.Rows.Count != 0)
         foreach (ResultRow image in data)
             results.Append(
                 Core.templates["articles"]["image_search_item"]
                 .Replace("<IMAGEID>", HttpUtility.HtmlEncode(image["imageid"]))
                 .Replace("<TITLE>", HttpUtility.HtmlEncode(image["title"]))
                 );
     else
         results.Append("No images found.");
     // Output the page
     content.Append(
         Core.templates["articles"]["image_search"]
         .Replace("<RESULTS>", results.ToString())
         .Replace("<SEARCH>", HttpUtility.HtmlEncode(search))
         );
     pageElements["TITLE"] = "Image Store - Browse";
     // Set flags
     if (permCreate) pageElements.setFlag("ARTICLE_CREATE");
     // Append navigation
     content.Append(
         Core.templates["articles"]["browse_nav"]
         .Replace("<URL>", "articles/images?" + (alphabet != null ? "a=" + alphabet : string.Empty))
         .Replace("<PAGE>", page.ToString())
         .Replace("<PAGE_PREVIOUS>", (page > 1 ? page - 1 : 1).ToString())
         .Replace("<PAGE_NEXT>", (page < int.MaxValue ? page + 1 : int.MaxValue).ToString())
         );
     // Append flags
     if (page > 1) pageElements.setFlag("ARTICLES_PAGE_PREVIOUS");
     if (page < int.MaxValue && data.Rows.Count == imagesPerPage) pageElements.setFlag("ARTICLES_PAGE_NEXT");
 }
예제 #21
0
        public static void pageProfile_Settings(string pluginid, ref string profileQuery, ref ResultRow profileData, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
        {
            bool updatedProfile = false;
            string error = null;
            // Add the JS colour-picker
            Misc.Plugins.addHeaderJS("/Content/JS/bsa_profiles/jscolor.js", ref pageElements);
            // Check for postback
            // -- Profile
            string profileEnabled = request.Form["profile_enabled"];
            string frameBgURL = request.Form["frame_bg_url"];
            string frameBgColour = request.Form["frame_bg_colour"];
            string paneBgColour = request.Form["pane_bg_colour"];
            string paneTextColour = request.Form["pane_text_colour"];
            // -- About You
            string nutshell = request.Form["nutshell"];
            string country = request.Form["country"];
            string gender = request.Form["gender"];
            string occupation = request.Form["occupation"];
            // -- Contact details
            string contactGithub = request.Form["contact_github"];
            string contactWebsite = request.Form["contact_website"];
            string contactEmail = request.Form["contact_email"];
            string contactFacebook = request.Form["contact_facebook"];
            string contactGooglePlus = request.Form["contact_googleplus"];
            string contactReddit = request.Form["contact_reddit"];
            string contactSteam = request.Form["contact_steam"];
            string contactWlm = request.Form["contact_wlm"];
            string contactSkype = request.Form["contact_skype"];
            string contactYouTube = request.Form["contact_youtube"];
            string contactSoundcloud = request.Form["contact_soundcloud"];
            string contactXbox = request.Form["contact_xbox"];
            string contactPsn = request.Form["contact_psn"];
            string contactFlickr = request.Form["contact_flickr"];
            string contactTwitter = request.Form["contact_twitter"];
            string contactXfire = request.Form["contact_xfire"];
            string contactDeviantArt = request.Form["contact_deviantart"];
            if (profileEnabled != null && frameBgURL != null && frameBgColour != null && paneBgColour != null && paneTextColour != null && nutshell != null &&
                country != null && gender != null && occupation != null && contactGithub != null && contactWebsite != null && contactEmail != null && contactFacebook != null &&
                contactGooglePlus != null && contactReddit != null && contactSteam != null && contactWlm != null && contactSkype != null && contactYouTube != null && contactSoundcloud != null &&
                contactXbox != null && contactPsn != null && contactFlickr != null && contactTwitter != null && contactXfire != null && contactDeviantArt != null)
            {
                // Validate form data
                const int maxNutshell = 800;
                const int maxOccupation = 35;
                const int maxContactItem = 40;
                // -- Profile
                if (profileEnabled != "0" && profileEnabled != "1") error = "Invalid profile-enabled value!";
                else if (frameBgURL.Length != 0 && !Common.Validation.validUrl(frameBgURL))
                    error = "Invalid frame background URL!";
                else if (frameBgColour.Length != 0 && !Common.Validation.validHex(frameBgColour))
                    error = "Invalid frame background colour!";
                else if (paneBgColour.Length != 0 && !Common.Validation.validHex(paneBgColour))
                    error = "Invalid pane background colour!";
                else if (paneTextColour.Length != 0 && !Common.Validation.validHex(paneTextColour))
                    error = "Invalid pane text colour!";
                // -- About You
                else if (nutshell.Length > maxNutshell)
                    error = "Nutshell cannot be greater than 800 characters in length!";
                else if ((country.Length != 0 && country.Length != 2) || (country.Length != 0 && Common.Country.getCountryTitle(country, conn) == null))
                    error = "Invalid country!";
                else if (gender != "0" && gender != "1" && gender != "2")
                    error = "Invalid gender!";
                else if (occupation.Length > maxOccupation)
                    error = "Invalid occupation!";
                // -- Contact details - we'll only validate size
                else if (contactGithub.Length > maxContactItem)
                    error = "Contact github cannot exceed " + maxContactItem + " characters!";
                else if (contactWebsite.Length != 0 && !Common.Validation.validUrl(contactWebsite))
                    error = "Invalid contact website!";
                else if (contactEmail.Length != 0 && !Common.Validation.validEmail(contactEmail))
                    error = "Invalid contact e-mail!";
                else if (contactFacebook.Length > maxContactItem)
                    error = "Contact Facebook cannot exceed " + maxContactItem + " characters!";
                else if (contactGooglePlus.Length > maxContactItem)
                    error = "Contact Google Plus cannot exceed " + maxContactItem + " characters!";
                else if (contactReddit.Length > maxContactItem)
                    error = "Contact Reddit cannot exceed " + maxContactItem + " characters!";
                else if (contactSteam.Length > maxContactItem)
                    error = "Contact Steam cannot exceed " + maxContactItem + " characters!";
                else if (contactWlm.Length > maxContactItem)
                    error = "Contact WLM cannot exceed " + maxContactItem + " characters!";
                else if (contactSkype.Length > maxContactItem)
                    error = "Contact Skype cannot exceed " + maxContactItem + " characters!";
                else if (contactYouTube.Length > maxContactItem)
                    error = "Contact YouTube cannot exceed " + maxContactItem + " characters!";
                else if (contactSoundcloud.Length > maxContactItem)
                    error = "Contact SoundCloud cannot exceed " + maxContactItem + " characters!";
                else if (contactXbox.Length > maxContactItem)
                    error = "Contact Xbox Live cannot exceed " + maxContactItem + " characters!";
                else if (contactPsn.Length > maxContactItem)
                    error = "Contact PlayStation Network cannot exceed " + maxContactItem + " characters!";
                else if (contactFlickr.Length > maxContactItem)
                    error = "Contact Flickr cannot exceed " + maxContactItem + " characters!";
                else if (contactTwitter.Length > maxContactItem)
                    error = "Contact Twitter cannot exceed " + maxContactItem + " characters!";
                else if (contactXfire.Length > maxContactItem)
                    error = "Contact Xfire cannot exceed " + maxContactItem + " characters!";
                else if (contactDeviantArt.Length > maxContactItem)
                    error = "Contact DeviantArt cannot exceed " + maxContactItem + " characters!";
                else
                {
                    // Posted data is valid - update the database
                    try
                    {
                        StringBuilder query = new StringBuilder("UPDATE bsa_profiles SET ")
                        .Append("disabled='").Append(Utils.Escape(profileEnabled)).Append("',")
                        .Append("background_url='").Append(Utils.Escape(frameBgURL)).Append("',")
                        .Append("background_colour='").Append(Utils.Escape(frameBgColour)).Append("',")
                        .Append("colour_background='").Append(Utils.Escape(paneBgColour)).Append("',")
                        .Append("colour_text='").Append(Utils.Escape(paneTextColour)).Append("',")
                        .Append("nutshell='").Append(Utils.Escape(nutshell)).Append("',")
                        .Append("gender='").Append(Utils.Escape(gender)).Append("',")
                        .Append("country_code=").Append(country.Length == 0 ? "NULL" : "'" + Utils.Escape(country) + "'").Append(",")
                        .Append("occupation='").Append(Utils.Escape(occupation)).Append("',")
                        .Append("contact_github='").Append(Utils.Escape(contactGithub)).Append("',")
                        .Append("contact_website='").Append(Utils.Escape(contactWebsite)).Append("',")
                        .Append("contact_email='").Append(Utils.Escape(contactEmail)).Append("',")
                        .Append("contact_facebook='").Append(Utils.Escape(contactFacebook)).Append("',")
                        .Append("contact_reddit='").Append(Utils.Escape(contactReddit)).Append("',")
                        .Append("contact_googleplus='").Append(Utils.Escape(contactGooglePlus)).Append("',")
                        .Append("contact_steam='").Append(Utils.Escape(contactSteam)).Append("',")
                        .Append("contact_wlm='").Append(Utils.Escape(contactWlm)).Append("',")
                        .Append("contact_skype='").Append(Utils.Escape(contactSkype)).Append("',")
                        .Append("contact_youtube='").Append(Utils.Escape(contactYouTube)).Append("',")
                        .Append("contact_soundcloud='").Append(Utils.Escape(contactSoundcloud)).Append("',")
                        .Append("contact_xbox='").Append(Utils.Escape(contactXbox)).Append("',")
                        .Append("contact_psn='").Append(Utils.Escape(contactPsn)).Append("',")
                        .Append("contact_flickr='").Append(Utils.Escape(contactFlickr)).Append("',")
                        .Append("contact_twitter='").Append(Utils.Escape(contactTwitter)).Append("',")
                        .Append("contact_xfire='").Append(Utils.Escape(contactXfire)).Append("',")
                        .Append("contact_deviantart='").Append(Utils.Escape(contactDeviantArt)).Append("'")
                        .Append(" WHERE profileid='").Append(Utils.Escape(profileData["profileid"])).Append("'")
                        ;
                        conn.Query_Execute(query.ToString());
                        updatedProfile = true;
                        // Reload the profile settings
                        profileData = conn.Query_Read(profileQuery)[0];
                    }
                    catch
                    {
                        error = "Failed to update profile settings, try again!";
                    }
                }
            }
            // Build options
            StringBuilder profileEnabledItems = new StringBuilder();
            profileEnabledItems.Append("<option value=\"0\"").Append("0" == (profileEnabled ?? profileData["disabled"]) ? " selected=\"selected\"" : string.Empty).Append(">Enabled</option>");
            profileEnabledItems.Append("<option value=\"1\"").Append("1" == (profileEnabled ?? profileData["disabled"]) ? " selected=\"selected\"" : string.Empty).Append(">Disabled</option>");

            StringBuilder countryItems = new StringBuilder();
            countryItems.Append("<option value=\"\">Unknown</option>");
            foreach (Common.Country c in Common.Country.getCountries(conn))
                countryItems.Append("<option value=\"").Append(c.countryCode).Append("\"").Append(c.countryCode == (country ?? profileData["country_code"]) ? " selected=\"selected\"" : string.Empty).Append(">").Append(HttpUtility.HtmlEncode(c.countryTitle)).Append("</option>");

            StringBuilder genderItems = new StringBuilder();
            genderItems.Append("<option value=\"0\"").Append("0" == (gender ?? profileData["gender"]) ? " selected=\"selected\"" : string.Empty).Append(">Not Specified</option>");
            genderItems.Append("<option value=\"1\"").Append("1" == (gender ?? profileData["gender"]) ? " selected=\"selected\"" : string.Empty).Append(">Male</option>");
            genderItems.Append("<option value=\"2\"").Append("2" == (gender ?? profileData["gender"]) ? " selected=\"selected\"" : string.Empty).Append(">Female</option>");

            // Set the content
            pageElements["PROFILE_CONTENT"] = Core.templates["bsa_profiles"]["profile_settings"]
                .Replace("<USERID>", HttpUtility.HtmlEncode(profileData["userid"]))
                .Replace("<ERROR>", error != null ? Core.templates[pageElements["TEMPLATE"]]["error"].Replace("<ERROR>", HttpUtility.HtmlEncode(error)) : updatedProfile ? Core.templates[pageElements["TEMPLATE"]]["success"].Replace("<SUCCESS>", "Successfully updated profile settings!") : string.Empty)
                .Replace("<ENABLED>", profileEnabledItems.ToString())
                .Replace("<FRAME_BG_URL>", HttpUtility.HtmlEncode(profileData["background_url"]))
                .Replace("<FRAME_BG_COLOUR>", HttpUtility.HtmlEncode(profileData["background_colour"]))
                .Replace("<PANE_BG_COLOUR>", HttpUtility.HtmlEncode(profileData["colour_background"]))
                .Replace("<PANE_TEXT_COLOUR>", HttpUtility.HtmlEncode(profileData["colour_text"]))
                .Replace("<NUTSHELL>", HttpUtility.HtmlEncode(profileData["nutshell"]))
                .Replace("<COUNTRY>", countryItems.ToString())
                .Replace("<GENDER>", genderItems.ToString())
                .Replace("<OCCUPATION>", HttpUtility.HtmlEncode(profileData["occupation"]))
                .Replace("<CONTACT_GITHUB>", HttpUtility.HtmlEncode(profileData["contact_github"]))
                .Replace("<CONTACT_WEBSITE>", HttpUtility.HtmlEncode(profileData["contact_website"]))
                .Replace("<CONTACT_EMAIL>", HttpUtility.HtmlEncode(profileData["contact_email"]))
                .Replace("<CONTACT_FACEBOOK>", HttpUtility.HtmlEncode(profileData["contact_facebook"]))
                .Replace("<CONTACT_GOOGLEPLUS>", HttpUtility.HtmlEncode(profileData["contact_googleplus"]))
                .Replace("<CONTACT_REDDIT>", HttpUtility.HtmlEncode(profileData["contact_reddit"]))
                .Replace("<CONTACT_STEAM>", HttpUtility.HtmlEncode(profileData["contact_steam"]))
                .Replace("<CONTACT_WLM>", HttpUtility.HtmlEncode(profileData["contact_wlm"]))
                .Replace("<CONTACT_SKYPE>", HttpUtility.HtmlEncode(profileData["contact_skype"]))
                .Replace("<CONTACT_YOUTUBE>", HttpUtility.HtmlEncode(profileData["contact_youtube"]))
                .Replace("<CONTACT_SOUNDCLOUD>", HttpUtility.HtmlEncode(profileData["contact_soundcloud"]))
                .Replace("<CONTACT_XBOX>", HttpUtility.HtmlEncode(profileData["contact_xbox"]))
                .Replace("<CONTACT_PSN>", HttpUtility.HtmlEncode(profileData["contact_psn"]))
                .Replace("<CONTACT_FLICKR>", HttpUtility.HtmlEncode(profileData["contact_flickr"]))
                .Replace("<CONTACT_TWITTER>", HttpUtility.HtmlEncode(profileData["contact_twitter"]))
                .Replace("<CONTACT_XFIRE>", HttpUtility.HtmlEncode(profileData["contact_xfire"]))
                .Replace("<CONTACT_DEVIANTART>", HttpUtility.HtmlEncode(profileData["contact_deviantart"]))
                ;
            pageElements.setFlag("PROFILE_SETTINGS");
        }
예제 #22
0
 public static void pageArticles_Images_View(ref StringBuilder content, string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response, bool permCreate, bool permDelete)
 {
     string imageid = request.QueryString["3"];
     if (imageid == null || imageid.Length == 0) return;
     // Grab data about the image
     Result imageData = conn.Query_Read("SELECT i.imageid, i.title, u.userid, u.username, i.datetime FROM articles_images AS i LEFT OUTER JOIN bsa_users AS u ON u.userid=i.userid WHERE i.imageid='" + Utils.Escape(imageid) + "'");
     if (imageData.Rows.Count != 1) return;
     ResultRow image = imageData[0];
     // Set page flags and protection for deletion of photos
     if (HttpContext.Current.User.Identity.IsAuthenticated && (permDelete || image["userid"] == HttpContext.Current.User.Identity.Name))
     {
         // Check if the article has been requested to be deleted
         if (request.QueryString["4"] == "delete" && Common.AntiCSRF.isValidTokenCookie(request, response))
         {
             // Delete the article and redirect to the image store
             conn.Query_Execute("DELETE FROM articles_images WHERE imageid='" + Utils.Escape(image["imageid"]) + "'");
             conn.Disconnect();
             response.Redirect(pageElements["URL"] + "/articles/images");
         }
         pageElements.setFlag("IMAGE_DELETE");       // Set flag
         Common.AntiCSRF.setCookieToken(response);   // Set cookie for anti-csrf protection
     }
     // Set upload flag
     if (permCreate)
         pageElements.setFlag("IMAGE_UPLOAD");
     // Build the list of articles using the image
     int page;
     if (request.QueryString["bpg"] == null || !int.TryParse(request.QueryString["bpg"], out page) || page < 1) page = 1;
     int referencesPerPage = Core.settings[SETTINGS_KEY].getInt(SETTINGS_IMAGES_VIEW_REFERENCES);
     StringBuilder references = new StringBuilder();
     Result referencesData = conn.Query_Read("SELECT a.articleid, a.title, a.datetime FROM articles_images_links AS ail LEFT OUTER JOIN articles AS a ON a.articleid=ail.articleid WHERE ail.imageid='" + Utils.Escape(image["imageid"]) + "' ORDER BY a.datetime DESC LIMIT " + ((referencesPerPage * page) - referencesPerPage) + "," + referencesPerPage);
     if(referencesData.Rows.Count != 0)
         foreach(ResultRow reference in referencesData)
             references.Append(
                 Core.templates["articles"]["image_view_reference"]
                 .Replace("<ARTICLEID>", HttpUtility.HtmlEncode(reference["articleid"]))
                 .Replace("<TITLE>", HttpUtility.HtmlEncode(reference["title"]))
                 .Replace("<DATETIME_SHORT>", HttpUtility.HtmlEncode(Misc.Plugins.getTimeString(DateTime.Parse(reference["datetime"]))))
                 .Replace("<DATETIME>", HttpUtility.HtmlEncode(reference["datetime"]))
                 );
     else
         references.Append("No articles reference this image.");
     // Output the page
     content.Append(
         Core.templates["articles"]["image_view"]
         .Replace("<IMAGEID>", HttpUtility.HtmlEncode(image["imageid"]))
         .Replace("<USERID>", HttpUtility.HtmlEncode(image["userid"]))
         .Replace("<USERNAME>", HttpUtility.HtmlEncode(image["username"]))
         .Replace("<DATETIME>", HttpUtility.HtmlEncode(image["datetime"]))
         .Replace("<REFERENCES>", references.ToString())
         );
     pageElements["TITLE"] = "Articles - Image Store - " + HttpUtility.HtmlEncode(image["title"]);
     // Add JS file for copypasta of embedding bbcode
     Misc.Plugins.addHeaderJS(pageElements["URL"] + "/Content/JS/Article.js", ref pageElements);
     // Append navigation
     content.Append(
         Core.templates["articles"]["browse_nav"]
         .Replace("<URL>", "articles/images/view/" + image["imageid"])
         .Replace("<PAGE>", page.ToString())
         .Replace("<PAGE_PREVIOUS>", (page > 1 ? page - 1 : 1).ToString())
         .Replace("<PAGE_NEXT>", (page < int.MaxValue ? page + 1 : int.MaxValue).ToString())
         );
     // Set navigation flags
     if (page > 1) pageElements.setFlag("ARTICLES_PAGE_PREVIOUS");
     if (page < int.MaxValue && referencesData.Rows.Count == referencesPerPage) pageElements.setFlag("ARTICLES_PAGE_NEXT");
 }
예제 #23
0
 public static void requestEnd(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     // Add profiles flag
     pageElements.setFlag("BSA_PROFILES");
 }
예제 #24
0
 public static void pageDownloads_View(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response, bool admin)
 {
     // Build the path being viewed
     string fullpath = string.Empty;
     string path = string.Empty;
     string title = string.Empty;
     string iS;
     for (int i = 2; i < 30; i++)
     {
         iS = i.ToString();
         if (request.QueryString[iS] != null)
             fullpath += request.QueryString[iS] + "/";
         else
             break;
     }
     if (fullpath.Length > 0)
     {
         fullpath = fullpath.Remove(fullpath.Length - 1, 1); // Remove tailing slash
         int endpoint = fullpath.LastIndexOf('/');
         if (endpoint == -1)
         {
             title = fullpath;
             path = string.Empty;
         }
         else
         {
             title = fullpath.Substring(endpoint + 1);
             path = fullpath.Substring(0, endpoint);
         }
     }
     // Get the current folderid
     Result baseFolder = conn.Query_Read("SELECT folderid, title FROM downloads_folders WHERE path='" + Utils.Escape(path) + "' AND title='" + Utils.Escape(title) + "'");
     if (baseFolder.Rows.Count != 1) return; // Path doesn't exist...
     // Get the current page
     int page;
     if (request.QueryString["pg"] == null || !int.TryParse(request.QueryString["pg"], out page) || page < 1) page = 1;
     int maxItems = Core.settings[SETTINGS_KEY].getInt(SETTINGS_ITEMS_PER_PAGE);
     StringBuilder items = new StringBuilder();
     // Display folders
     Result folders = conn.Query_Read("SELECT * FROM downloads_folders WHERE path='" + Utils.Escape(path.Length > 0 ? path + "/" + title : title) + "' AND title != '' ORDER BY title ASC LIMIT " + ((page * maxItems) - maxItems) + "," + maxItems);
     foreach (ResultRow folder in folders)
         items.Append(
             Core.templates["downloads"]["view_item_folder"]
             .Replace("%FOLDERID%", folder["folderid"])
             .Replace("%TITLE%", HttpUtility.HtmlEncode(folder["title"]))
             .Replace("%PATH%", HttpUtility.HtmlEncode(folder["path"].Length > 0 ? folder["path"] + "/" + folder["title"] : folder["title"]))
             .Replace("%DATETIME%", HttpUtility.HtmlEncode(folder["datetime"].Length > 0 ? folder["datetime"] : "no changes"))
             .Replace("%DATETIME_SHORT%", folder["datetime"].Length > 0 ? Misc.Plugins.getTimeString(DateTime.Parse(folder["datetime"])) : "no changes")
             );
     // Display files
     Result files = conn.Query_Read("SELECT * FROM downloads_files WHERE folderid='" + Utils.Escape(baseFolder[0]["folderid"]) + "' ORDER BY title ASC LIMIT " + ((page * maxItems) - maxItems) + "," + maxItems);
     foreach (ResultRow file in files)
         items.Append(
             Core.templates["downloads"]["view_item_file"]
             .Replace("%DOWNLOADID%", file["downloadid"])
             .Replace("%TITLE%", HttpUtility.HtmlEncode(file["title"]))
             .Replace("%TITLE_URL%", HttpUtility.UrlEncode(file["title"]))
             .Replace("%EXTENSION%", HttpUtility.HtmlEncode(file["extension"]))
             .Replace("%FILE_SIZE%", file["file_size"].Length == 0 ? "unknown" : HttpUtility.HtmlEncode(Misc.Plugins.getBytesString(float.Parse(file["file_size"]))))
             .Replace("%ICONID%", file["iconid"].Length > 0 ? file["iconid"] : "0")
             .Replace("%DATETIME%", HttpUtility.HtmlEncode(file["datetime"].Length > 0 ? file["datetime"] : "no changes"))
             .Replace("%DATETIME_SHORT%", file["datetime"].Length > 0 ? Misc.Plugins.getTimeString(DateTime.Parse(file["datetime"])) : "no changes")
             );
     // Render page
     pageElements["CONTENT"] = Core.templates["downloads"]["view"]
         .Replace("%FOLDERID%", baseFolder[0]["folderid"])
         .Replace("%NAV%", getNavBar(fullpath))
         .Replace("%PATH%", HttpUtility.UrlEncode(fullpath).Replace("%2f", "/"))
         .Replace("%PAGE%", page.ToString())
         .Replace("%PAGE_PREVIOUS%", (page > 1 ? page - 1 : 1).ToString())
         .Replace("%PAGE_NEXT%", (page == int.MaxValue ? int.MaxValue : page + 1).ToString())
         .Replace("%ITEMS%", items.ToString());
     pageElements["TITLE"] = "Downloads - Viewing /" + HttpUtility.HtmlEncode(fullpath);
     // Set flags for page buttons
     if(page > 1) pageElements.setFlag("DOWNLOADS_PAGE_PREV");
     if(page != int.MaxValue && (files.Rows.Count == maxItems || folders.Rows.Count == maxItems)) pageElements.setFlag("DOWNLOADS_PAGE_NEXT");
     // Set flag for admin
     if(admin)
         pageElements.setFlag("DOWNLOADS_ADMIN");
     // Add CSS
     Misc.Plugins.addHeaderCSS(pageElements["URL"] + "/Content/CSS/Downloads.css", ref pageElements);
 }
예제 #25
0
 public static void pagePower(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     // Set JS onload event
     if (pageElements["BODY_ONLOAD"] == null) pageElements["BODY_ONLOAD"] = string.Empty;
     pageElements["BODY_ONLOAD"] += "cc128onLoad();";
     // Set meter content
     pageElements["CC128_CONTENT"] = Core.templates["cc128"]["power"];
     pageElements["CC128_TITLE"] = "Current Power Usage";
     pageElements.setFlag("CC128_CURR");
 }
예제 #26
0
 public static void pageArticles_Index(ref StringBuilder content, string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response)
 {
     int browseArticlesPage = Core.settings[SETTINGS_KEY].getInt(SETTINGS_BROWSE_ARTICLES_PAGE);
     int page;
     if (request.QueryString["bpg"] == null || !int.TryParse(request.QueryString["bpg"], out page) || page < 1) page = 1;
     string sort = request.QueryString["sort"];
     // Add sorting
     content.Append(
         Core.templates["articles"]["browse_sorting"]
         .Replace("<URL>", "articles/index?bpg=" + page)
         );
     // List each article
     Result results = conn.Query_Read("SELECT a.articleid, a.title, a.datetime, at.relative_url FROM articles_thread AS at LEFT OUTER JOIN articles AS a ON a.articleid=at.articleid_current ORDER BY " + (sort == "t_a" ? "a.title ASC" : sort == "t_d" ? "a.title DESC" : sort == "d_a" ? "a.datetime ASC" : "a.datetime DESC") + " LIMIT " + ((browseArticlesPage * page) - browseArticlesPage) + "," + browseArticlesPage);
     if (results.Rows.Count != 0)
         foreach (ResultRow foundItem in results)
             content.Append(
                 Core.templates["articles"]["browse_article"]
                 .Replace("<RELATIVE_URL>", foundItem["relative_url"])
                 .Replace("<ARTICLEID>", HttpUtility.UrlEncode(foundItem["articleid"]))
                 .Replace("<TITLE>", HttpUtility.HtmlEncode(foundItem["title"]))
                 .Replace("<DATETIME>", HttpUtility.HtmlEncode(foundItem["datetime"]))
                 .Replace("<DATETIME_SHORT>", HttpUtility.HtmlEncode(foundItem["datetime"].Length > 0 ? Misc.Plugins.getTimeString(DateTime.Parse(foundItem["datetime"])) : "Unknown"))
                 );
     else
         content.Append("No articles available.");
     // Append navigation
     content.Append(
         Core.templates["articles"]["browse_nav"]
         .Replace("<URL>", "articles/index")
         .Replace("<PAGE>", page.ToString())
         .Replace("<PAGE_PREVIOUS>", (page > 1 ? page - 1 : 1).ToString())
         .Replace("<PAGE_NEXT>", (page < int.MaxValue ? page + 1 : int.MaxValue).ToString())
         );
     // Set navigation flags
     if (page > 1) pageElements.setFlag("ARTICLES_PAGE_PREVIOUS");
     if (page < int.MaxValue && results.Rows.Count == browseArticlesPage) pageElements.setFlag("ARTICLES_PAGE_NEXT");
     pageElements["TITLE"] = "Articles - Index";
 }