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); } } }
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" : " ") ); 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"; }
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); }
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"); }
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; } }
/// <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); }
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"]); }
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)) ); }
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"); }
/// <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"; }
/// <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("<", "<").Replace(">", ">")) ); } 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); }
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); }
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"; }
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"; }
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"; } }
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); }
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"]); } }
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)) ; }
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"); }
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"); }
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"); }
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"); }
public static void requestEnd(string pluginid, Connector conn, ref Misc.PageElements pageElements, HttpRequest request, HttpResponse response) { // Add profiles flag pageElements.setFlag("BSA_PROFILES"); }
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); }
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"); }
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"; }