// Code generated by Gosora's Router Generator. DO NOT EDIT. /* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ package main import ( "log" "strings" //"bytes" "strconv" "compress/gzip" "sync" "sync/atomic" "errors" "os" "net/http" "time" c "github.com/Azareal/Gosora/common" co "github.com/Azareal/Gosora/common/counters" "github.com/Azareal/Gosora/uutils" "github.com/Azareal/Gosora/routes" "github.com/Azareal/Gosora/routes/panel" ) var ErrNoRoute = errors.New("That route doesn't exist.") // TODO: What about the /uploads/ route? x.x var RouteMap = map[string]interface{}{ "routes.Error": routes.Error, "routes.Overview": routes.Overview, "routes.CustomPage": routes.CustomPage, "routes.ForumList": routes.ForumList, "routes.ViewForum": routes.ViewForum, "routes.ChangeTheme": routes.ChangeTheme, "routes.ShowAttachment": routes.ShowAttachment, "common.RouteWebsockets": c.RouteWebsockets, "routeAPIPhrases": routeAPIPhrases, "routes.APIMe": routes.APIMe, "routeJSAntispam": routeJSAntispam, "routeAPI": routeAPI, "routes.ReportSubmit": routes.ReportSubmit, "routes.TopicListMostViewed": routes.TopicListMostViewed, "routes.CreateTopic": routes.CreateTopic, "routes.TopicList": routes.TopicList, "panel.Forums": panel.Forums, "panel.ForumsCreateSubmit": panel.ForumsCreateSubmit, "panel.ForumsDelete": panel.ForumsDelete, "panel.ForumsDeleteSubmit": panel.ForumsDeleteSubmit, "panel.ForumsOrderSubmit": panel.ForumsOrderSubmit, "panel.ForumsEdit": panel.ForumsEdit, "panel.ForumsEditSubmit": panel.ForumsEditSubmit, "panel.ForumsEditPermsSubmit": panel.ForumsEditPermsSubmit, "panel.ForumsEditPermsAdvance": panel.ForumsEditPermsAdvance, "panel.ForumsEditPermsAdvanceSubmit": panel.ForumsEditPermsAdvanceSubmit, "panel.Settings": panel.Settings, "panel.SettingEdit": panel.SettingEdit, "panel.SettingEditSubmit": panel.SettingEditSubmit, "panel.WordFilters": panel.WordFilters, "panel.WordFiltersCreateSubmit": panel.WordFiltersCreateSubmit, "panel.WordFiltersEdit": panel.WordFiltersEdit, "panel.WordFiltersEditSubmit": panel.WordFiltersEditSubmit, "panel.WordFiltersDeleteSubmit": panel.WordFiltersDeleteSubmit, "panel.Pages": panel.Pages, "panel.PagesCreateSubmit": panel.PagesCreateSubmit, "panel.PagesEdit": panel.PagesEdit, "panel.PagesEditSubmit": panel.PagesEditSubmit, "panel.PagesDeleteSubmit": panel.PagesDeleteSubmit, "panel.Themes": panel.Themes, "panel.ThemesSetDefault": panel.ThemesSetDefault, "panel.ThemesMenus": panel.ThemesMenus, "panel.ThemesMenusEdit": panel.ThemesMenusEdit, "panel.ThemesMenuItemEdit": panel.ThemesMenuItemEdit, "panel.ThemesMenuItemEditSubmit": panel.ThemesMenuItemEditSubmit, "panel.ThemesMenuItemCreateSubmit": panel.ThemesMenuItemCreateSubmit, "panel.ThemesMenuItemDeleteSubmit": panel.ThemesMenuItemDeleteSubmit, "panel.ThemesMenuItemOrderSubmit": panel.ThemesMenuItemOrderSubmit, "panel.ThemesWidgets": panel.ThemesWidgets, "panel.ThemesWidgetsEditSubmit": panel.ThemesWidgetsEditSubmit, "panel.ThemesWidgetsCreateSubmit": panel.ThemesWidgetsCreateSubmit, "panel.ThemesWidgetsDeleteSubmit": panel.ThemesWidgetsDeleteSubmit, "panel.Plugins": panel.Plugins, "panel.PluginsActivate": panel.PluginsActivate, "panel.PluginsDeactivate": panel.PluginsDeactivate, "panel.PluginsInstall": panel.PluginsInstall, "panel.Users": panel.Users, "panel.UsersEdit": panel.UsersEdit, "panel.UsersEditSubmit": panel.UsersEditSubmit, "panel.UsersAvatarSubmit": panel.UsersAvatarSubmit, "panel.UsersAvatarRemoveSubmit": panel.UsersAvatarRemoveSubmit, "panel.AnalyticsViews": panel.AnalyticsViews, "panel.AnalyticsRoutes": panel.AnalyticsRoutes, "panel.AnalyticsRoutesPerf": panel.AnalyticsRoutesPerf, "panel.AnalyticsAgents": panel.AnalyticsAgents, "panel.AnalyticsSystems": panel.AnalyticsSystems, "panel.AnalyticsLanguages": panel.AnalyticsLanguages, "panel.AnalyticsReferrers": panel.AnalyticsReferrers, "panel.AnalyticsRouteViews": panel.AnalyticsRouteViews, "panel.AnalyticsAgentViews": panel.AnalyticsAgentViews, "panel.AnalyticsForumViews": panel.AnalyticsForumViews, "panel.AnalyticsSystemViews": panel.AnalyticsSystemViews, "panel.AnalyticsLanguageViews": panel.AnalyticsLanguageViews, "panel.AnalyticsReferrerViews": panel.AnalyticsReferrerViews, "panel.AnalyticsPosts": panel.AnalyticsPosts, "panel.AnalyticsMemory": panel.AnalyticsMemory, "panel.AnalyticsActiveMemory": panel.AnalyticsActiveMemory, "panel.AnalyticsTopics": panel.AnalyticsTopics, "panel.AnalyticsForums": panel.AnalyticsForums, "panel.AnalyticsPerf": panel.AnalyticsPerf, "panel.Groups": panel.Groups, "panel.GroupsEdit": panel.GroupsEdit, "panel.GroupsEditPromotions": panel.GroupsEditPromotions, "panel.GroupsPromotionsCreateSubmit": panel.GroupsPromotionsCreateSubmit, "panel.GroupsPromotionsDeleteSubmit": panel.GroupsPromotionsDeleteSubmit, "panel.GroupsEditPerms": panel.GroupsEditPerms, "panel.GroupsEditSubmit": panel.GroupsEditSubmit, "panel.GroupsEditPermsSubmit": panel.GroupsEditPermsSubmit, "panel.GroupsCreateSubmit": panel.GroupsCreateSubmit, "panel.Backups": panel.Backups, "panel.LogsRegs": panel.LogsRegs, "panel.LogsMod": panel.LogsMod, "panel.LogsAdmin": panel.LogsAdmin, "panel.Debug": panel.Debug, "panel.Dashboard": panel.Dashboard, "routes.AccountEdit": routes.AccountEdit, "routes.AccountEditPassword": routes.AccountEditPassword, "routes.AccountEditPasswordSubmit": routes.AccountEditPasswordSubmit, "routes.AccountEditAvatarSubmit": routes.AccountEditAvatarSubmit, "routes.AccountEditRevokeAvatarSubmit": routes.AccountEditRevokeAvatarSubmit, "routes.AccountEditUsernameSubmit": routes.AccountEditUsernameSubmit, "routes.AccountEditPrivacy": routes.AccountEditPrivacy, "routes.AccountEditPrivacySubmit": routes.AccountEditPrivacySubmit, "routes.AccountEditMFA": routes.AccountEditMFA, "routes.AccountEditMFASetup": routes.AccountEditMFASetup, "routes.AccountEditMFASetupSubmit": routes.AccountEditMFASetupSubmit, "routes.AccountEditMFADisableSubmit": routes.AccountEditMFADisableSubmit, "routes.AccountEditEmail": routes.AccountEditEmail, "routes.AccountEditEmailTokenSubmit": routes.AccountEditEmailTokenSubmit, "routes.AccountLogins": routes.AccountLogins, "routes.AccountBlocked": routes.AccountBlocked, "routes.LevelList": routes.LevelList, "routes.Convos": routes.Convos, "routes.ConvosCreate": routes.ConvosCreate, "routes.Convo": routes.Convo, "routes.ConvosCreateSubmit": routes.ConvosCreateSubmit, "routes.ConvosCreateReplySubmit": routes.ConvosCreateReplySubmit, "routes.ConvosDeleteReplySubmit": routes.ConvosDeleteReplySubmit, "routes.ConvosEditReplySubmit": routes.ConvosEditReplySubmit, "routes.RelationsBlockCreate": routes.RelationsBlockCreate, "routes.RelationsBlockCreateSubmit": routes.RelationsBlockCreateSubmit, "routes.RelationsBlockRemove": routes.RelationsBlockRemove, "routes.RelationsBlockRemoveSubmit": routes.RelationsBlockRemoveSubmit, "routes.ViewProfile": routes.ViewProfile, "routes.BanUserSubmit": routes.BanUserSubmit, "routes.UnbanUser": routes.UnbanUser, "routes.ActivateUser": routes.ActivateUser, "routes.IPSearch": routes.IPSearch, "routes.DeletePostsSubmit": routes.DeletePostsSubmit, "routes.CreateTopicSubmit": routes.CreateTopicSubmit, "routes.EditTopicSubmit": routes.EditTopicSubmit, "routes.DeleteTopicSubmit": routes.DeleteTopicSubmit, "routes.StickTopicSubmit": routes.StickTopicSubmit, "routes.UnstickTopicSubmit": routes.UnstickTopicSubmit, "routes.LockTopicSubmit": routes.LockTopicSubmit, "routes.UnlockTopicSubmit": routes.UnlockTopicSubmit, "routes.MoveTopicSubmit": routes.MoveTopicSubmit, "routes.LikeTopicSubmit": routes.LikeTopicSubmit, "routes.UnlikeTopicSubmit": routes.UnlikeTopicSubmit, "routes.AddAttachToTopicSubmit": routes.AddAttachToTopicSubmit, "routes.RemoveAttachFromTopicSubmit": routes.RemoveAttachFromTopicSubmit, "routes.ViewTopic": routes.ViewTopic, "routes.CreateReplySubmit": routes.CreateReplySubmit, "routes.ReplyEditSubmit": routes.ReplyEditSubmit, "routes.ReplyDeleteSubmit": routes.ReplyDeleteSubmit, "routes.ReplyLikeSubmit": routes.ReplyLikeSubmit, "routes.ReplyUnlikeSubmit": routes.ReplyUnlikeSubmit, "routes.AddAttachToReplySubmit": routes.AddAttachToReplySubmit, "routes.RemoveAttachFromReplySubmit": routes.RemoveAttachFromReplySubmit, "routes.ProfileReplyCreateSubmit": routes.ProfileReplyCreateSubmit, "routes.ProfileReplyEditSubmit": routes.ProfileReplyEditSubmit, "routes.ProfileReplyDeleteSubmit": routes.ProfileReplyDeleteSubmit, "routes.PollVote": routes.PollVote, "routes.PollResults": routes.PollResults, "routes.AccountLogin": routes.AccountLogin, "routes.AccountRegister": routes.AccountRegister, "routes.AccountLogout": routes.AccountLogout, "routes.AccountLoginSubmit": routes.AccountLoginSubmit, "routes.AccountLoginMFAVerify": routes.AccountLoginMFAVerify, "routes.AccountLoginMFAVerifySubmit": routes.AccountLoginMFAVerifySubmit, "routes.AccountRegisterSubmit": routes.AccountRegisterSubmit, "routes.AccountPasswordReset": routes.AccountPasswordReset, "routes.AccountPasswordResetSubmit": routes.AccountPasswordResetSubmit, "routes.AccountPasswordResetToken": routes.AccountPasswordResetToken, "routes.AccountPasswordResetTokenSubmit": routes.AccountPasswordResetTokenSubmit, "routes.DynamicRoute": routes.DynamicRoute, "routes.UploadedFile": routes.UploadedFile, "routes.StaticFile": routes.StaticFile, "routes.RobotsTxt": routes.RobotsTxt, "routes.SitemapXml": routes.SitemapXml, "routes.OpenSearchXml": routes.OpenSearchXml, "routes.Favicon": routes.Favicon, "routes.BadRoute": routes.BadRoute, "routes.HTTPSRedirect": routes.HTTPSRedirect, } // ! NEVER RELY ON THESE REMAINING THE SAME BETWEEN COMMITS var routeMapEnum = map[string]int{ "routes.Error": 0, "routes.Overview": 1, "routes.CustomPage": 2, "routes.ForumList": 3, "routes.ViewForum": 4, "routes.ChangeTheme": 5, "routes.ShowAttachment": 6, "common.RouteWebsockets": 7, "routeAPIPhrases": 8, "routes.APIMe": 9, "routeJSAntispam": 10, "routeAPI": 11, "routes.ReportSubmit": 12, "routes.TopicListMostViewed": 13, "routes.CreateTopic": 14, "routes.TopicList": 15, "panel.Forums": 16, "panel.ForumsCreateSubmit": 17, "panel.ForumsDelete": 18, "panel.ForumsDeleteSubmit": 19, "panel.ForumsOrderSubmit": 20, "panel.ForumsEdit": 21, "panel.ForumsEditSubmit": 22, "panel.ForumsEditPermsSubmit": 23, "panel.ForumsEditPermsAdvance": 24, "panel.ForumsEditPermsAdvanceSubmit": 25, "panel.Settings": 26, "panel.SettingEdit": 27, "panel.SettingEditSubmit": 28, "panel.WordFilters": 29, "panel.WordFiltersCreateSubmit": 30, "panel.WordFiltersEdit": 31, "panel.WordFiltersEditSubmit": 32, "panel.WordFiltersDeleteSubmit": 33, "panel.Pages": 34, "panel.PagesCreateSubmit": 35, "panel.PagesEdit": 36, "panel.PagesEditSubmit": 37, "panel.PagesDeleteSubmit": 38, "panel.Themes": 39, "panel.ThemesSetDefault": 40, "panel.ThemesMenus": 41, "panel.ThemesMenusEdit": 42, "panel.ThemesMenuItemEdit": 43, "panel.ThemesMenuItemEditSubmit": 44, "panel.ThemesMenuItemCreateSubmit": 45, "panel.ThemesMenuItemDeleteSubmit": 46, "panel.ThemesMenuItemOrderSubmit": 47, "panel.ThemesWidgets": 48, "panel.ThemesWidgetsEditSubmit": 49, "panel.ThemesWidgetsCreateSubmit": 50, "panel.ThemesWidgetsDeleteSubmit": 51, "panel.Plugins": 52, "panel.PluginsActivate": 53, "panel.PluginsDeactivate": 54, "panel.PluginsInstall": 55, "panel.Users": 56, "panel.UsersEdit": 57, "panel.UsersEditSubmit": 58, "panel.UsersAvatarSubmit": 59, "panel.UsersAvatarRemoveSubmit": 60, "panel.AnalyticsViews": 61, "panel.AnalyticsRoutes": 62, "panel.AnalyticsRoutesPerf": 63, "panel.AnalyticsAgents": 64, "panel.AnalyticsSystems": 65, "panel.AnalyticsLanguages": 66, "panel.AnalyticsReferrers": 67, "panel.AnalyticsRouteViews": 68, "panel.AnalyticsAgentViews": 69, "panel.AnalyticsForumViews": 70, "panel.AnalyticsSystemViews": 71, "panel.AnalyticsLanguageViews": 72, "panel.AnalyticsReferrerViews": 73, "panel.AnalyticsPosts": 74, "panel.AnalyticsMemory": 75, "panel.AnalyticsActiveMemory": 76, "panel.AnalyticsTopics": 77, "panel.AnalyticsForums": 78, "panel.AnalyticsPerf": 79, "panel.Groups": 80, "panel.GroupsEdit": 81, "panel.GroupsEditPromotions": 82, "panel.GroupsPromotionsCreateSubmit": 83, "panel.GroupsPromotionsDeleteSubmit": 84, "panel.GroupsEditPerms": 85, "panel.GroupsEditSubmit": 86, "panel.GroupsEditPermsSubmit": 87, "panel.GroupsCreateSubmit": 88, "panel.Backups": 89, "panel.LogsRegs": 90, "panel.LogsMod": 91, "panel.LogsAdmin": 92, "panel.Debug": 93, "panel.Dashboard": 94, "routes.AccountEdit": 95, "routes.AccountEditPassword": 96, "routes.AccountEditPasswordSubmit": 97, "routes.AccountEditAvatarSubmit": 98, "routes.AccountEditRevokeAvatarSubmit": 99, "routes.AccountEditUsernameSubmit": 100, "routes.AccountEditPrivacy": 101, "routes.AccountEditPrivacySubmit": 102, "routes.AccountEditMFA": 103, "routes.AccountEditMFASetup": 104, "routes.AccountEditMFASetupSubmit": 105, "routes.AccountEditMFADisableSubmit": 106, "routes.AccountEditEmail": 107, "routes.AccountEditEmailTokenSubmit": 108, "routes.AccountLogins": 109, "routes.AccountBlocked": 110, "routes.LevelList": 111, "routes.Convos": 112, "routes.ConvosCreate": 113, "routes.Convo": 114, "routes.ConvosCreateSubmit": 115, "routes.ConvosCreateReplySubmit": 116, "routes.ConvosDeleteReplySubmit": 117, "routes.ConvosEditReplySubmit": 118, "routes.RelationsBlockCreate": 119, "routes.RelationsBlockCreateSubmit": 120, "routes.RelationsBlockRemove": 121, "routes.RelationsBlockRemoveSubmit": 122, "routes.ViewProfile": 123, "routes.BanUserSubmit": 124, "routes.UnbanUser": 125, "routes.ActivateUser": 126, "routes.IPSearch": 127, "routes.DeletePostsSubmit": 128, "routes.CreateTopicSubmit": 129, "routes.EditTopicSubmit": 130, "routes.DeleteTopicSubmit": 131, "routes.StickTopicSubmit": 132, "routes.UnstickTopicSubmit": 133, "routes.LockTopicSubmit": 134, "routes.UnlockTopicSubmit": 135, "routes.MoveTopicSubmit": 136, "routes.LikeTopicSubmit": 137, "routes.UnlikeTopicSubmit": 138, "routes.AddAttachToTopicSubmit": 139, "routes.RemoveAttachFromTopicSubmit": 140, "routes.ViewTopic": 141, "routes.CreateReplySubmit": 142, "routes.ReplyEditSubmit": 143, "routes.ReplyDeleteSubmit": 144, "routes.ReplyLikeSubmit": 145, "routes.ReplyUnlikeSubmit": 146, "routes.AddAttachToReplySubmit": 147, "routes.RemoveAttachFromReplySubmit": 148, "routes.ProfileReplyCreateSubmit": 149, "routes.ProfileReplyEditSubmit": 150, "routes.ProfileReplyDeleteSubmit": 151, "routes.PollVote": 152, "routes.PollResults": 153, "routes.AccountLogin": 154, "routes.AccountRegister": 155, "routes.AccountLogout": 156, "routes.AccountLoginSubmit": 157, "routes.AccountLoginMFAVerify": 158, "routes.AccountLoginMFAVerifySubmit": 159, "routes.AccountRegisterSubmit": 160, "routes.AccountPasswordReset": 161, "routes.AccountPasswordResetSubmit": 162, "routes.AccountPasswordResetToken": 163, "routes.AccountPasswordResetTokenSubmit": 164, "routes.DynamicRoute": 165, "routes.UploadedFile": 166, "routes.StaticFile": 167, "routes.RobotsTxt": 168, "routes.SitemapXml": 169, "routes.OpenSearchXml": 170, "routes.Favicon": 171, "routes.BadRoute": 172, "routes.HTTPSRedirect": 173, } var reverseRouteMapEnum = map[int]string{ 0: "routes.Error", 1: "routes.Overview", 2: "routes.CustomPage", 3: "routes.ForumList", 4: "routes.ViewForum", 5: "routes.ChangeTheme", 6: "routes.ShowAttachment", 7: "common.RouteWebsockets", 8: "routeAPIPhrases", 9: "routes.APIMe", 10: "routeJSAntispam", 11: "routeAPI", 12: "routes.ReportSubmit", 13: "routes.TopicListMostViewed", 14: "routes.CreateTopic", 15: "routes.TopicList", 16: "panel.Forums", 17: "panel.ForumsCreateSubmit", 18: "panel.ForumsDelete", 19: "panel.ForumsDeleteSubmit", 20: "panel.ForumsOrderSubmit", 21: "panel.ForumsEdit", 22: "panel.ForumsEditSubmit", 23: "panel.ForumsEditPermsSubmit", 24: "panel.ForumsEditPermsAdvance", 25: "panel.ForumsEditPermsAdvanceSubmit", 26: "panel.Settings", 27: "panel.SettingEdit", 28: "panel.SettingEditSubmit", 29: "panel.WordFilters", 30: "panel.WordFiltersCreateSubmit", 31: "panel.WordFiltersEdit", 32: "panel.WordFiltersEditSubmit", 33: "panel.WordFiltersDeleteSubmit", 34: "panel.Pages", 35: "panel.PagesCreateSubmit", 36: "panel.PagesEdit", 37: "panel.PagesEditSubmit", 38: "panel.PagesDeleteSubmit", 39: "panel.Themes", 40: "panel.ThemesSetDefault", 41: "panel.ThemesMenus", 42: "panel.ThemesMenusEdit", 43: "panel.ThemesMenuItemEdit", 44: "panel.ThemesMenuItemEditSubmit", 45: "panel.ThemesMenuItemCreateSubmit", 46: "panel.ThemesMenuItemDeleteSubmit", 47: "panel.ThemesMenuItemOrderSubmit", 48: "panel.ThemesWidgets", 49: "panel.ThemesWidgetsEditSubmit", 50: "panel.ThemesWidgetsCreateSubmit", 51: "panel.ThemesWidgetsDeleteSubmit", 52: "panel.Plugins", 53: "panel.PluginsActivate", 54: "panel.PluginsDeactivate", 55: "panel.PluginsInstall", 56: "panel.Users", 57: "panel.UsersEdit", 58: "panel.UsersEditSubmit", 59: "panel.UsersAvatarSubmit", 60: "panel.UsersAvatarRemoveSubmit", 61: "panel.AnalyticsViews", 62: "panel.AnalyticsRoutes", 63: "panel.AnalyticsRoutesPerf", 64: "panel.AnalyticsAgents", 65: "panel.AnalyticsSystems", 66: "panel.AnalyticsLanguages", 67: "panel.AnalyticsReferrers", 68: "panel.AnalyticsRouteViews", 69: "panel.AnalyticsAgentViews", 70: "panel.AnalyticsForumViews", 71: "panel.AnalyticsSystemViews", 72: "panel.AnalyticsLanguageViews", 73: "panel.AnalyticsReferrerViews", 74: "panel.AnalyticsPosts", 75: "panel.AnalyticsMemory", 76: "panel.AnalyticsActiveMemory", 77: "panel.AnalyticsTopics", 78: "panel.AnalyticsForums", 79: "panel.AnalyticsPerf", 80: "panel.Groups", 81: "panel.GroupsEdit", 82: "panel.GroupsEditPromotions", 83: "panel.GroupsPromotionsCreateSubmit", 84: "panel.GroupsPromotionsDeleteSubmit", 85: "panel.GroupsEditPerms", 86: "panel.GroupsEditSubmit", 87: "panel.GroupsEditPermsSubmit", 88: "panel.GroupsCreateSubmit", 89: "panel.Backups", 90: "panel.LogsRegs", 91: "panel.LogsMod", 92: "panel.LogsAdmin", 93: "panel.Debug", 94: "panel.Dashboard", 95: "routes.AccountEdit", 96: "routes.AccountEditPassword", 97: "routes.AccountEditPasswordSubmit", 98: "routes.AccountEditAvatarSubmit", 99: "routes.AccountEditRevokeAvatarSubmit", 100: "routes.AccountEditUsernameSubmit", 101: "routes.AccountEditPrivacy", 102: "routes.AccountEditPrivacySubmit", 103: "routes.AccountEditMFA", 104: "routes.AccountEditMFASetup", 105: "routes.AccountEditMFASetupSubmit", 106: "routes.AccountEditMFADisableSubmit", 107: "routes.AccountEditEmail", 108: "routes.AccountEditEmailTokenSubmit", 109: "routes.AccountLogins", 110: "routes.AccountBlocked", 111: "routes.LevelList", 112: "routes.Convos", 113: "routes.ConvosCreate", 114: "routes.Convo", 115: "routes.ConvosCreateSubmit", 116: "routes.ConvosCreateReplySubmit", 117: "routes.ConvosDeleteReplySubmit", 118: "routes.ConvosEditReplySubmit", 119: "routes.RelationsBlockCreate", 120: "routes.RelationsBlockCreateSubmit", 121: "routes.RelationsBlockRemove", 122: "routes.RelationsBlockRemoveSubmit", 123: "routes.ViewProfile", 124: "routes.BanUserSubmit", 125: "routes.UnbanUser", 126: "routes.ActivateUser", 127: "routes.IPSearch", 128: "routes.DeletePostsSubmit", 129: "routes.CreateTopicSubmit", 130: "routes.EditTopicSubmit", 131: "routes.DeleteTopicSubmit", 132: "routes.StickTopicSubmit", 133: "routes.UnstickTopicSubmit", 134: "routes.LockTopicSubmit", 135: "routes.UnlockTopicSubmit", 136: "routes.MoveTopicSubmit", 137: "routes.LikeTopicSubmit", 138: "routes.UnlikeTopicSubmit", 139: "routes.AddAttachToTopicSubmit", 140: "routes.RemoveAttachFromTopicSubmit", 141: "routes.ViewTopic", 142: "routes.CreateReplySubmit", 143: "routes.ReplyEditSubmit", 144: "routes.ReplyDeleteSubmit", 145: "routes.ReplyLikeSubmit", 146: "routes.ReplyUnlikeSubmit", 147: "routes.AddAttachToReplySubmit", 148: "routes.RemoveAttachFromReplySubmit", 149: "routes.ProfileReplyCreateSubmit", 150: "routes.ProfileReplyEditSubmit", 151: "routes.ProfileReplyDeleteSubmit", 152: "routes.PollVote", 153: "routes.PollResults", 154: "routes.AccountLogin", 155: "routes.AccountRegister", 156: "routes.AccountLogout", 157: "routes.AccountLoginSubmit", 158: "routes.AccountLoginMFAVerify", 159: "routes.AccountLoginMFAVerifySubmit", 160: "routes.AccountRegisterSubmit", 161: "routes.AccountPasswordReset", 162: "routes.AccountPasswordResetSubmit", 163: "routes.AccountPasswordResetToken", 164: "routes.AccountPasswordResetTokenSubmit", 165: "routes.DynamicRoute", 166: "routes.UploadedFile", 167: "routes.StaticFile", 168: "routes.RobotsTxt", 169: "routes.SitemapXml", 170: "routes.OpenSearchXml", 171: "routes.Favicon", 172: "routes.BadRoute", 173: "routes.HTTPSRedirect", } var osMapEnum = map[string]int{ "unknown": 0, "windows": 1, "linux": 2, "mac": 3, "android": 4, "iphone": 5, } var reverseOSMapEnum = map[int]string{ 0: "unknown", 1: "windows", 2: "linux", 3: "mac", 4: "android", 5: "iphone", } var agentMapEnum = map[string]int{ "unknown": 0, "firefox": 1, "chrome": 2, "opera": 3, "safari": 4, "edge": 5, "internetexplorer": 6, "trident": 7, "androidchrome": 8, "mobilesafari": 9, "samsung": 10, "ucbrowser": 11, "googlebot": 12, "yandex": 13, "bing": 14, "slurp": 15, "exabot": 16, "mojeek": 17, "cliqz": 18, "datenbank": 19, "baidu": 20, "sogou": 21, "toutiao": 22, "haosou": 23, "duckduckgo": 24, "seznambot": 25, "discord": 26, "twitter": 27, "facebook": 28, "cloudflare": 29, "archive_org": 30, "uptimebot": 31, "slackbot": 32, "apple": 33, "discourse": 34, "alexa": 35, "lynx": 36, "blank": 37, "malformed": 38, "suspicious": 39, "semrush": 40, "dotbot": 41, "ahrefs": 42, "proximic": 43, "majestic": 44, "blexbot": 45, "aspiegel": 46, "mail_ru": 47, "zgrab": 48, "curl": 49, "python": 50, "go": 51, } var reverseAgentMapEnum = map[int]string{ 0: "unknown", 1: "firefox", 2: "chrome", 3: "opera", 4: "safari", 5: "edge", 6: "internetexplorer", 7: "trident", 8: "androidchrome", 9: "mobilesafari", 10: "samsung", 11: "ucbrowser", 12: "googlebot", 13: "yandex", 14: "bing", 15: "slurp", 16: "exabot", 17: "mojeek", 18: "cliqz", 19: "datenbank", 20: "baidu", 21: "sogou", 22: "toutiao", 23: "haosou", 24: "duckduckgo", 25: "seznambot", 26: "discord", 27: "twitter", 28: "facebook", 29: "cloudflare", 30: "archive_org", 31: "uptimebot", 32: "slackbot", 33: "apple", 34: "discourse", 35: "alexa", 36: "lynx", 37: "blank", 38: "malformed", 39: "suspicious", 40: "semrush", 41: "dotbot", 42: "ahrefs", 43: "proximic", 44: "majestic", 45: "blexbot", 46: "aspiegel", 47: "mail_ru", 48: "zgrab", 49: "curl", 50: "python", 51: "go", } var markToAgent = map[string]string{ "OPR": "opera", "Chrome": "chrome", "Firefox": "firefox", "Safari": "safari", "MSIE": "internetexplorer", "Trident": "trident", "Edge": "edge", "Lynx": "lynx", "SamsungBrowser": "samsung", "UCBrowser": "ucbrowser", "Google": "googlebot", "Googlebot": "googlebot", "yandex": "yandex", "DuckDuckBot": "duckduckgo", "DuckDuckGo": "duckduckgo", "Baiduspider": "baidu", "Sogou": "sogou", "ToutiaoSpider": "toutiao", "360Spider": "haosou", "bingbot": "bing", "BingPreview": "bing", "msnbot": "bing", "Slurp": "slurp", "Exabot": "exabot", "MojeekBot": "mojeek", "Cliqzbot": "cliqz", "netEstate": "datenbank", "SeznamBot": "seznambot", "CloudFlare": "cloudflare", "archive": "archive_org", "Uptimebot": "uptimebot", "Slackbot": "slackbot", "Slack": "slackbot", "Discordbot": "discord", "Twitterbot": "twitter", "facebookexternalhit": "facebook", "Facebot": "facebook", "Applebot": "apple", "Discourse": "discourse", "ia_archiver": "alexa", "SemrushBot": "semrush", "DotBot": "dotbot", "AhrefsBot": "ahrefs", "proximic": "proximic", "MJ12bot": "majestic", "BLEXBot": "blexbot", "AspiegelBot": "aspiegel", "RU_Bot": "mail_ru", "zgrab": "zgrab", "curl": "curl", "python": "python", "Go": "go", } var markToID = map[string]int{ "OPR": 3, "Chrome": 2, "Firefox": 1, "Safari": 4, "MSIE": 6, "Trident": 7, "Edge": 5, "Lynx": 36, "SamsungBrowser": 10, "UCBrowser": 11, "Google": 12, "Googlebot": 12, "yandex": 13, "DuckDuckBot": 24, "DuckDuckGo": 24, "Baiduspider": 20, "Sogou": 21, "ToutiaoSpider": 22, "360Spider": 23, "bingbot": 14, "BingPreview": 14, "msnbot": 14, "Slurp": 15, "Exabot": 16, "MojeekBot": 17, "Cliqzbot": 18, "netEstate": 19, "SeznamBot": 25, "CloudFlare": 29, "archive": 30, "Uptimebot": 31, "Slackbot": 32, "Slack": 32, "Discordbot": 26, "Twitterbot": 27, "facebookexternalhit": 28, "Facebot": 28, "Applebot": 33, "Discourse": 34, "ia_archiver": 35, "SemrushBot": 40, "DotBot": 41, "AhrefsBot": 42, "proximic": 43, "MJ12bot": 44, "BLEXBot": 45, "AspiegelBot": 46, "RU_Bot": 47, "zgrab": 48, "curl": 49, "python": 50, "Go": 51, } /*var agentRank = map[string]int{ "opera":9, "chrome":8, "safari":1, }*/ // TODO: Stop spilling these into the package scope? func init() { _ = time.Now() co.SetRouteMapEnum(routeMapEnum) co.SetReverseRouteMapEnum(reverseRouteMapEnum) co.SetAgentMapEnum(agentMapEnum) co.SetReverseAgentMapEnum(reverseAgentMapEnum) co.SetOSMapEnum(osMapEnum) co.SetReverseOSMapEnum(reverseOSMapEnum) c.Chrome = agentMapEnum["chrome"] c.Firefox = agentMapEnum["firefox"] ame := agentMapEnum c.SimpleBots = []int{ ame["semrush"], ame["ahrefs"], ame["python"], ame["go"], ame["curl"], } } type WriterIntercept struct { http.ResponseWriter } func NewWriterIntercept(w http.ResponseWriter) *WriterIntercept { return &WriterIntercept{w} } var wiMaxAge = "max-age=" + strconv.Itoa(int(c.Day)) func (wi *WriterIntercept) WriteHeader(code int) { if code == 200 { h := wi.ResponseWriter.Header() h.Set("Cache-Control", wiMaxAge) h.Set("Vary", "Accept-Encoding") } wi.ResponseWriter.WriteHeader(code) } // HTTPSRedirect is a connection handler which redirects all HTTP requests to HTTPS type HTTPSRedirect struct {} func (red *HTTPSRedirect) ServeHTTP(w http.ResponseWriter, req *http.Request) { w.Header().Set("Connection", "close") co.RouteViewCounter.Bump(173) dest := "https://" + req.Host + req.URL.String() http.Redirect(w, req, dest, http.StatusTemporaryRedirect) } type GenRouter struct { UploadHandler func(http.ResponseWriter, *http.Request) extraRoutes map[string]func(http.ResponseWriter, *http.Request, *c.User) c.RouteError requestLogger *log.Logger sync.RWMutex } func NewGenRouter(uploads http.Handler) (*GenRouter, error) { f, err := os.OpenFile("./logs/reqs-"+strconv.FormatInt(c.StartTime.Unix(),10)+".log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755) if err != nil { return nil, err } return &GenRouter{ UploadHandler: func(w http.ResponseWriter, req *http.Request) { writ := NewWriterIntercept(w) http.StripPrefix("/uploads/",uploads).ServeHTTP(writ,req) }, extraRoutes: make(map[string]func(http.ResponseWriter, *http.Request, *c.User) c.RouteError), requestLogger: log.New(f, "", log.LstdFlags), }, nil } func (r *GenRouter) handleError(err c.RouteError, w http.ResponseWriter, req *http.Request, u *c.User) { if err.Handled() { return } if err.Type() == "system" { c.InternalErrorJSQ(err, w, req, err.JSON()) return } c.LocalErrorJSQ(err.Error(), w, req, u, err.JSON()) } func (r *GenRouter) Handle(_ string, _ http.Handler) { } func (r *GenRouter) HandleFunc(pattern string, h func(http.ResponseWriter, *http.Request, *c.User) c.RouteError) { r.Lock() defer r.Unlock() r.extraRoutes[pattern] = h } func (r *GenRouter) RemoveFunc(pattern string) error { r.Lock() defer r.Unlock() _, ok := r.extraRoutes[pattern] if !ok { return ErrNoRoute } delete(r.extraRoutes, pattern) return nil } // TODO: Use strings builder? func (r *GenRouter) DumpRequest(req *http.Request, pre string) { var heads string for key, value := range req.Header { for _, vvalue := range value { heads += "Header '" + c.SanitiseSingleLine(key) + "': " + c.SanitiseSingleLine(vvalue) + "\n" } } r.requestLogger.Print(pre + "\nUA: " + c.SanitiseSingleLine(req.UserAgent()) + "\n" + "Method: " + c.SanitiseSingleLine(req.Method) + "\n" + heads + "Host: " + c.SanitiseSingleLine(req.Host) + "\n" + "URL.Path: " + c.SanitiseSingleLine(req.URL.Path) + "\n" + "URL.RawQuery: " + c.SanitiseSingleLine(req.URL.RawQuery) + "\n" + "Ref: " + c.SanitiseSingleLine(req.Referer()) + "\n" + "IP: " + req.RemoteAddr + "\n") } func (r *GenRouter) SuspiciousRequest(req *http.Request, pre string) { if pre != "" { pre += "\n" } r.DumpRequest(req,pre+"Suspicious Request") co.AgentViewCounter.Bump(39) } func isLocalHost(h string) bool { return h=="localhost" || h=="127.0.0.1" || h=="::1" } // TODO: Pass the default path or config struct to the router rather than accessing it via a package global // TODO: SetDefaultPath // TODO: GetDefaultPath func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { malformedRequest := func(typ int) { w.WriteHeader(200) // 400 w.Write([]byte("")) r.DumpRequest(req,"Malformed Request T"+strconv.Itoa(typ)) co.AgentViewCounter.Bump(38) } // Split the Host and Port string var shost, sport string if req.Host[0]=='[' { spl := strings.Split(req.Host,"]") if len(spl) > 2 { malformedRequest(0) return } shost = strings.TrimPrefix(spl[0],"[") sport = strings.TrimPrefix(spl[1],":") } else if strings.Contains(req.Host,":") { spl := strings.Split(req.Host,":") if len(spl) > 2 { malformedRequest(1) return } shost = spl[0] //if len(spl)==2 { sport = spl[1] //} } else { shost = req.Host } // TODO: Reject requests from non-local IPs, if the site host is set to localhost or a localhost IP if !c.Config.LoosePort && c.Site.PortInt != 80 && c.Site.PortInt != 443 && sport != c.Site.Port { malformedRequest(2) return } // Redirect www. and local IP requests to the right place if strings.HasPrefix(shost, "www.") || c.Site.LocalHost { if shost == "www." + c.Site.Host || (c.Site.LocalHost && shost != c.Site.Host && isLocalHost(shost)) { // TODO: Abstract the redirect logic? w.Header().Set("Connection", "close") var s string if c.Config.SslSchema { s = "s" } var p string if c.Site.PortInt != 80 && c.Site.PortInt != 443 { p = ":"+c.Site.Port } dest := "http"+s+"://" + c.Site.Host+p + req.URL.Path if len(req.URL.RawQuery) > 0 { dest += "?" + req.URL.RawQuery } http.Redirect(w, req, dest, http.StatusMovedPermanently) return } } // Deflect malformed requests if len(req.URL.Path) == 0 || req.URL.Path[0] != '/' || (!c.Config.LooseHost && shost != c.Site.Host) { malformedRequest(3) return } if c.Dev.FullReqLog { r.DumpRequest(req,"") } // TODO: Cover more suspicious strings and at a lower layer than this for _, ch := range req.URL.Path { //char if ch != '&' && !(ch > 44 && ch < 58) && ch != '=' && ch != '?' && !(ch > 64 && ch < 91) && ch != '\\' && ch != '_' && !(ch > 96 && ch < 123) { r.SuspiciousRequest(req,"Bad char '"+string(ch)+"' in path") break } } lp := strings.ToLower(req.URL.Path) // TODO: Flag any requests which has a dot with anything but a number after that // TODO: Use HasSuffix to avoid over-scanning? if strings.Contains(lp,"..")/* || strings.Contains(lp,"--")*/ || strings.Contains(lp,".php") || strings.Contains(lp,".asp") || strings.Contains(lp,".cgi") || strings.Contains(lp,".py") || strings.Contains(lp,".sql") || strings.Contains(lp,".action") { r.SuspiciousRequest(req,"Bad snippet in path") } // Indirect the default route onto a different one if req.URL.Path == "/" { req.URL.Path = c.Config.DefaultPath } //log.Print("URL.Path: ", req.URL.Path) prefix := req.URL.Path[0:strings.IndexByte(req.URL.Path[1:],'/') + 1] // TODO: Use the same hook table as downstream hTbl := c.GetHookTable() skip, ferr := hTbl.VhookSkippable("router_after_filters", w, req, prefix) if skip || ferr != nil { return } if prefix != "/ws" { h := w.Header() h.Set("X-Frame-Options", "deny") h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing h.Set("X-Content-Type-Options", "nosniff") if c.Config.RefNoRef || !c.Config.SslSchema { h.Set("Referrer-Policy","no-referrer") } else { h.Set("Referrer-Policy","strict-origin") } } if c.Dev.SuperDebug { r.DumpRequest(req,"before routes.StaticFile") } // Increment the request counter if !c.Config.DisableAnalytics { co.GlobalViewCounter.Bump() } if prefix == "/s" { //old prefix: /static if !c.Config.DisableAnalytics { co.RouteViewCounter.Bump(167) } routes.StaticFile(w, req) return } // TODO: Handle JS routes if atomic.LoadInt32(&c.IsDBDown) == 1 { c.DatabaseError(w, req) return } if c.Dev.SuperDebug { r.requestLogger.Print("before PreRoute") } /*if c.Dev.QuicPort != 0 { w.Header().Set("Alt-Svc", "quic=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=2592000; v=\"44,43,39\", h3-23=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=3600, h3-24=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=3600, h2=\":443\"; ma=3600") }*/ // Track the user agents. Unfortunately, everyone pretends to be Mozilla, so this'll be a little less efficient than I would like. // TODO: Add a setting to disable this? // TODO: Use a more efficient detector instead of smashing every possible combination in var agent int if !c.Config.DisableAnalytics { ua := strings.TrimSpace(strings.Replace(strings.TrimPrefix(req.UserAgent(),"Mozilla/5.0 ")," Safari/537.36","",-1)) // Noise, no one's going to be running this and it would require some sort of agent ranking system to determine which identifier should be prioritised over another if ua == "" { co.AgentViewCounter.Bump(37) if c.Dev.DebugMode { var pre string for _, char := range req.UserAgent() { pre += strconv.Itoa(int(char)) + " " } r.DumpRequest(req,"Blank UA: " + pre) } } else { // WIP UA Parser var items []string var buffer []byte var os int for _, it := range uutils.StringToBytes(ua) { if (it > 64 && it < 91) || (it > 96 && it < 123) || it == '_' { // TODO: Store an index and slice that instead? buffer = append(buffer, it) } else if it == ' ' || it == '(' || it == ')' || it == '-' || (it > 47 && it < 58) || it == ';' || it == ':' || it == '.' || it == '+' || it == '~' || it == '@' /*|| (it == ':' && bytes.Equal(buffer,[]byte("http")))*/ || it == ',' || it == '/' { if len(buffer) != 0 { if len(buffer) > 2 { // Use an unsafe zero copy conversion here just to use the switch, it's not safe for this string to escape from here, as it will get mutated, so do a regular string conversion in append switch(uutils.BytesToString(buffer)) { case "Windows": os = 1 case "Linux": os = 2 case "Mac": os = 3 case "iPhone": os = 5 case "Android": os = 4 case "like","compatible": // Skip these words default: items = append(items, string(buffer)) } } buffer = buffer[:0] } } else { // TODO: Test this items = items[:0] r.SuspiciousRequest(req,"Illegal char "+strconv.Itoa(int(it))+" in UA") r.requestLogger.Print("UA Buf: ", buffer) r.requestLogger.Print("UA Buf String: ", string(buffer)) break } } // Iterate over this in reverse as the real UA tends to be on the right side for i := len(items) - 1; i >= 0; i-- { //fAgent, ok := markToAgent[items[i]] fAgent, ok := markToID[items[i]] if ok { agent = fAgent if agent != 4 { break } } } if c.Dev.SuperDebug { r.requestLogger.Print("parsed agent: ", agent) r.requestLogger.Print("os: ", os) r.requestLogger.Printf("items: %+v\n",items) } // Special handling switch(agent) { case 2: if os == 4 { agent = 8 } case 4: if os == 5 { agent = 9 } case 7: // Hack to support IE11, change this after we start logging versions if strings.Contains(ua,"rv:11") { agent = 6 } case 48: r.SuspiciousRequest(req,"Vulnerability Scanner") } if agent == 0 { co.AgentViewCounter.Bump(0) if c.Dev.DebugMode { var pre string for _, char := range req.UserAgent() { pre += strconv.Itoa(int(char)) + " " } r.DumpRequest(req,"Blank UA: " + pre) } else { r.requestLogger.Print("unknown ua: ", c.SanitiseSingleLine(ua)) } } else { //co.AgentViewCounter.Bump(agentMapEnum[agent]) co.AgentViewCounter.Bump(agent) } co.OSViewCounter.Bump(os) } // TODO: Do we want to track missing language headers too? Maybe as it's own type, e.g. "noheader"? // TODO: Default to anything other than en, if anything else is present, to avoid over-representing it for multi-linguals? lang := req.Header.Get("Accept-Language") if lang != "" { // TODO: Reduce allocs here lLang := strings.Split(strings.TrimSpace(lang),"-") tLang := strings.Split(strings.Split(lLang[0],";")[0],",") c.DebugDetail("tLang:", tLang) var llLang string for _, seg := range tLang { if seg == "*" { continue } llLang = seg break } c.DebugDetail("llLang:", llLang) if !co.LangViewCounter.Bump(llLang) { r.DumpRequest(req,"Invalid ISO Code") } } else { co.LangViewCounter.Bump2(0) } if !c.Config.RefNoTrack { ref := req.Header.Get("Referer") // Check the 'referrer' header too? :P if ref != "" { // ? Optimise this a little? ref = strings.TrimPrefix(strings.TrimPrefix(ref,"http://"),"https://") ref = strings.Split(ref,"/")[0] portless := strings.Split(ref,":")[0] // TODO: Handle c.Site.Host in uppercase too? if portless != "localhost" && portless != "127.0.0.1" && portless != c.Site.Host { co.ReferrerTracker.Bump(ref) } } } } // Deal with the session stuff, etc. ucpy, ok := c.PreRoute(w, req) if !ok { return } user := &ucpy user.LastAgent = agent if c.Dev.SuperDebug { r.requestLogger.Print( "after PreRoute\n" + "routeMapEnum: ", routeMapEnum) } //log.Println("req: ", req) // Disable Gzip when SSL is disabled for security reasons? if prefix != "/ws" && strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { h := w.Header() h.Set("Content-Encoding", "gzip") gzw := c.GzipResponseWriter{Writer: gzip.NewWriter(w), ResponseWriter: w} defer func() { //h := w.Header() if h.Get("Content-Encoding") == "gzip" && h.Get("X-I") == "" { //log.Print("push gzip close") gzw.Writer.(*gzip.Writer).Close() } }() w = gzw } skip, ferr = hTbl.VhookSkippable("router_pre_route", w, req, user, prefix) if skip || ferr != nil { r.handleError(ferr,w,req,user) return } var extraData string if req.URL.Path[len(req.URL.Path) - 1] != '/' { extraData = req.URL.Path[strings.LastIndexByte(req.URL.Path,'/') + 1:] req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1] } ferr = r.routeSwitch(w, req, user, prefix, extraData) if ferr != nil { r.handleError(ferr,w,req,user) return } /*if !c.Config.DisableAnalytics { co.RouteViewCounter.Bump(id) }*/ hTbl.VhookNoRet("router_end", w, req, user, prefix, extraData) //c.StoppedServer("Profile end") } func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user *c.User, prefix, extraData string) /*(id int, orerr */c.RouteError/*)*/ { var err c.RouteError cn := uutils.Nanotime() switch(prefix) { case "/overview": h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.Overview(w,req,user,h) co.RouteViewCounter.Bump3(1, cn) case "/pages": h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.CustomPage(w,req,user,h,extraData) co.RouteViewCounter.Bump3(2, cn) case "/forums": h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.ForumList(w,req,user,h) co.RouteViewCounter.Bump3(3, cn) case "/forum": h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.ViewForum(w,req,user,h,extraData) co.RouteViewCounter.Bump3(4, cn) case "/theme": err = c.ParseForm(w,req,user) if err != nil { return err } err = routes.ChangeTheme(w,req,user) co.RouteViewCounter.Bump3(5, cn) case "/attachs": err = c.ParseForm(w,req,user) if err != nil { return err } gzw, ok := w.(c.GzipResponseWriter) if ok { w = gzw.ResponseWriter w.Header().Del("Content-Encoding") } err = routes.ShowAttachment(w,req,user,extraData) co.RouteViewCounter.Bump3(6, cn) case "/ws": req.URL.Path += extraData err = c.RouteWebsockets(w,req,user) case "/api": switch(req.URL.Path) { case "/api/phrases/": err = routeAPIPhrases(w,req,user) co.RouteViewCounter.Bump3(8, cn) case "/api/me/": err = routes.APIMe(w,req,user) co.RouteViewCounter.Bump3(9, cn) case "/api/watches/": err = routeJSAntispam(w,req,user) co.RouteViewCounter.Bump3(10, cn) default: err = routeAPI(w,req,user) co.RouteViewCounter.Bump3(11, cn) } case "/report": err = c.NoBanned(w,req,user) if err != nil { return err } switch(req.URL.Path) { case "/report/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ReportSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(12, cn) } case "/topics": switch(req.URL.Path) { case "/topics/most-viewed/": h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.TopicListMostViewed(w,req,user,h) co.RouteViewCounter.Bump3(13, cn) case "/topics/create/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.CreateTopic(w,req,user,h,extraData) co.RouteViewCounter.Bump3(14, cn) default: h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.TopicList(w,req,user, h) co.RouteViewCounter.Bump3(15, cn) } case "/panel": err = c.SuperModOnly(w,req,user) if err != nil { return err } switch(req.URL.Path) { case "/panel/forums/": err = panel.Forums(w,req,user) co.RouteViewCounter.Bump3(16, cn) case "/panel/forums/create/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ForumsCreateSubmit(w,req,user) co.RouteViewCounter.Bump3(17, cn) case "/panel/forums/delete/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ForumsDelete(w,req,user,extraData) co.RouteViewCounter.Bump3(18, cn) case "/panel/forums/delete/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ForumsDeleteSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(19, cn) case "/panel/forums/order/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ForumsOrderSubmit(w,req,user) co.RouteViewCounter.Bump3(20, cn) case "/panel/forums/edit/": err = panel.ForumsEdit(w,req,user,extraData) co.RouteViewCounter.Bump3(21, cn) case "/panel/forums/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ForumsEditSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(22, cn) case "/panel/forums/edit/perms/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ForumsEditPermsSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(23, cn) case "/panel/forums/edit/perms/": err = panel.ForumsEditPermsAdvance(w,req,user,extraData) co.RouteViewCounter.Bump3(24, cn) case "/panel/forums/edit/perms/adv/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ForumsEditPermsAdvanceSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(25, cn) case "/panel/settings/": err = panel.Settings(w,req,user) co.RouteViewCounter.Bump3(26, cn) case "/panel/settings/edit/": err = panel.SettingEdit(w,req,user,extraData) co.RouteViewCounter.Bump3(27, cn) case "/panel/settings/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.SettingEditSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(28, cn) case "/panel/settings/word-filters/": err = panel.WordFilters(w,req,user) co.RouteViewCounter.Bump3(29, cn) case "/panel/settings/word-filters/create/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.WordFiltersCreateSubmit(w,req,user) co.RouteViewCounter.Bump3(30, cn) case "/panel/settings/word-filters/edit/": err = panel.WordFiltersEdit(w,req,user,extraData) co.RouteViewCounter.Bump3(31, cn) case "/panel/settings/word-filters/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.WordFiltersEditSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(32, cn) case "/panel/settings/word-filters/delete/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.WordFiltersDeleteSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(33, cn) case "/panel/pages/": err = c.AdminOnly(w,req,user) if err != nil { return err } err = panel.Pages(w,req,user) co.RouteViewCounter.Bump3(34, cn) case "/panel/pages/create/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.AdminOnly(w,req,user) if err != nil { return err } err = panel.PagesCreateSubmit(w,req,user) co.RouteViewCounter.Bump3(35, cn) case "/panel/pages/edit/": err = c.AdminOnly(w,req,user) if err != nil { return err } err = panel.PagesEdit(w,req,user,extraData) co.RouteViewCounter.Bump3(36, cn) case "/panel/pages/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.AdminOnly(w,req,user) if err != nil { return err } err = panel.PagesEditSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(37, cn) case "/panel/pages/delete/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.AdminOnly(w,req,user) if err != nil { return err } err = panel.PagesDeleteSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(38, cn) case "/panel/themes/": err = panel.Themes(w,req,user) co.RouteViewCounter.Bump3(39, cn) case "/panel/themes/default/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ThemesSetDefault(w,req,user,extraData) co.RouteViewCounter.Bump3(40, cn) case "/panel/themes/menus/": err = panel.ThemesMenus(w,req,user) co.RouteViewCounter.Bump3(41, cn) case "/panel/themes/menus/edit/": err = panel.ThemesMenusEdit(w,req,user,extraData) co.RouteViewCounter.Bump3(42, cn) case "/panel/themes/menus/item/edit/": err = panel.ThemesMenuItemEdit(w,req,user,extraData) co.RouteViewCounter.Bump3(43, cn) case "/panel/themes/menus/item/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ThemesMenuItemEditSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(44, cn) case "/panel/themes/menus/item/create/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ThemesMenuItemCreateSubmit(w,req,user) co.RouteViewCounter.Bump3(45, cn) case "/panel/themes/menus/item/delete/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ThemesMenuItemDeleteSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(46, cn) case "/panel/themes/menus/item/order/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ThemesMenuItemOrderSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(47, cn) case "/panel/themes/widgets/": err = panel.ThemesWidgets(w,req,user) co.RouteViewCounter.Bump3(48, cn) case "/panel/themes/widgets/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ThemesWidgetsEditSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(49, cn) case "/panel/themes/widgets/create/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ThemesWidgetsCreateSubmit(w,req,user) co.RouteViewCounter.Bump3(50, cn) case "/panel/themes/widgets/delete/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.ThemesWidgetsDeleteSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(51, cn) case "/panel/plugins/": err = panel.Plugins(w,req,user) co.RouteViewCounter.Bump3(52, cn) case "/panel/plugins/activate/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.PluginsActivate(w,req,user,extraData) co.RouteViewCounter.Bump3(53, cn) case "/panel/plugins/deactivate/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.PluginsDeactivate(w,req,user,extraData) co.RouteViewCounter.Bump3(54, cn) case "/panel/plugins/install/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.PluginsInstall(w,req,user,extraData) co.RouteViewCounter.Bump3(55, cn) case "/panel/users/": err = panel.Users(w,req,user) co.RouteViewCounter.Bump3(56, cn) case "/panel/users/edit/": err = panel.UsersEdit(w,req,user,extraData) co.RouteViewCounter.Bump3(57, cn) case "/panel/users/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.UsersEditSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(58, cn) case "/panel/users/avatar/submit/": err = c.HandleUploadRoute(w,req,user,int(c.Config.MaxRequestSize)) if err != nil { return err } err = c.NoUploadSessionMismatch(w,req,user) if err != nil { return err } err = panel.UsersAvatarSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(59, cn) case "/panel/users/avatar/remove/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.UsersAvatarRemoveSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(60, cn) case "/panel/analytics/views/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsViews(w,req,user) co.RouteViewCounter.Bump3(61, cn) case "/panel/analytics/routes/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsRoutes(w,req,user) co.RouteViewCounter.Bump3(62, cn) case "/panel/analytics/routes-perf/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsRoutesPerf(w,req,user) co.RouteViewCounter.Bump3(63, cn) case "/panel/analytics/agents/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsAgents(w,req,user) co.RouteViewCounter.Bump3(64, cn) case "/panel/analytics/systems/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsSystems(w,req,user) co.RouteViewCounter.Bump3(65, cn) case "/panel/analytics/langs/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsLanguages(w,req,user) co.RouteViewCounter.Bump3(66, cn) case "/panel/analytics/referrers/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsReferrers(w,req,user) co.RouteViewCounter.Bump3(67, cn) case "/panel/analytics/route/": err = panel.AnalyticsRouteViews(w,req,user,extraData) co.RouteViewCounter.Bump3(68, cn) case "/panel/analytics/agent/": err = panel.AnalyticsAgentViews(w,req,user,extraData) co.RouteViewCounter.Bump3(69, cn) case "/panel/analytics/forum/": err = panel.AnalyticsForumViews(w,req,user,extraData) co.RouteViewCounter.Bump3(70, cn) case "/panel/analytics/system/": err = panel.AnalyticsSystemViews(w,req,user,extraData) co.RouteViewCounter.Bump3(71, cn) case "/panel/analytics/lang/": err = panel.AnalyticsLanguageViews(w,req,user,extraData) co.RouteViewCounter.Bump3(72, cn) case "/panel/analytics/referrer/": err = panel.AnalyticsReferrerViews(w,req,user,extraData) co.RouteViewCounter.Bump3(73, cn) case "/panel/analytics/posts/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsPosts(w,req,user) co.RouteViewCounter.Bump3(74, cn) case "/panel/analytics/memory/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsMemory(w,req,user) co.RouteViewCounter.Bump3(75, cn) case "/panel/analytics/active-memory/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsActiveMemory(w,req,user) co.RouteViewCounter.Bump3(76, cn) case "/panel/analytics/topics/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsTopics(w,req,user) co.RouteViewCounter.Bump3(77, cn) case "/panel/analytics/forums/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsForums(w,req,user) co.RouteViewCounter.Bump3(78, cn) case "/panel/analytics/perf/": err = c.ParseForm(w,req,user) if err != nil { return err } err = panel.AnalyticsPerf(w,req,user) co.RouteViewCounter.Bump3(79, cn) case "/panel/groups/": err = panel.Groups(w,req,user) co.RouteViewCounter.Bump3(80, cn) case "/panel/groups/edit/": err = panel.GroupsEdit(w,req,user,extraData) co.RouteViewCounter.Bump3(81, cn) case "/panel/groups/edit/promotions/": err = panel.GroupsEditPromotions(w,req,user,extraData) co.RouteViewCounter.Bump3(82, cn) case "/panel/groups/promotions/create/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.GroupsPromotionsCreateSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(83, cn) case "/panel/groups/promotions/delete/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.GroupsPromotionsDeleteSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(84, cn) case "/panel/groups/edit/perms/": err = panel.GroupsEditPerms(w,req,user,extraData) co.RouteViewCounter.Bump3(85, cn) case "/panel/groups/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.GroupsEditSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(86, cn) case "/panel/groups/edit/perms/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.GroupsEditPermsSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(87, cn) case "/panel/groups/create/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = panel.GroupsCreateSubmit(w,req,user) co.RouteViewCounter.Bump3(88, cn) case "/panel/backups/": err = c.SuperAdminOnly(w,req,user) if err != nil { return err } gzw, ok := w.(c.GzipResponseWriter) if ok { w = gzw.ResponseWriter w.Header().Del("Content-Encoding") } err = panel.Backups(w,req,user,extraData) co.RouteViewCounter.Bump3(89, cn) case "/panel/logs/regs/": err = panel.LogsRegs(w,req,user) co.RouteViewCounter.Bump3(90, cn) case "/panel/logs/mod/": err = panel.LogsMod(w,req,user) co.RouteViewCounter.Bump3(91, cn) case "/panel/logs/admin/": err = panel.LogsAdmin(w,req,user) co.RouteViewCounter.Bump3(92, cn) case "/panel/debug/": err = c.AdminOnly(w,req,user) if err != nil { return err } err = panel.Debug(w,req,user) co.RouteViewCounter.Bump3(93, cn) default: err = panel.Dashboard(w,req,user) co.RouteViewCounter.Bump3(94, cn) } case "/user": switch(req.URL.Path) { case "/user/edit/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountEdit(w,req,user,h) co.RouteViewCounter.Bump3(95, cn) case "/user/edit/password/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountEditPassword(w,req,user,h) co.RouteViewCounter.Bump3(96, cn) case "/user/edit/password/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.AccountEditPasswordSubmit(w,req,user) co.RouteViewCounter.Bump3(97, cn) case "/user/edit/avatar/submit/": err = c.MemberOnly(w,req,user) if err != nil { return err } err = c.HandleUploadRoute(w,req,user,int(c.Config.MaxRequestSize)) if err != nil { return err } err = c.NoUploadSessionMismatch(w,req,user) if err != nil { return err } err = routes.AccountEditAvatarSubmit(w,req,user) co.RouteViewCounter.Bump3(98, cn) case "/user/edit/avatar/revoke/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.AccountEditRevokeAvatarSubmit(w,req,user) co.RouteViewCounter.Bump3(99, cn) case "/user/edit/username/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.AccountEditUsernameSubmit(w,req,user) co.RouteViewCounter.Bump3(100, cn) case "/user/edit/privacy/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountEditPrivacy(w,req,user,h) co.RouteViewCounter.Bump3(101, cn) case "/user/edit/privacy/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.AccountEditPrivacySubmit(w,req,user) co.RouteViewCounter.Bump3(102, cn) case "/user/edit/mfa/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountEditMFA(w,req,user,h) co.RouteViewCounter.Bump3(103, cn) case "/user/edit/mfa/setup/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountEditMFASetup(w,req,user,h) co.RouteViewCounter.Bump3(104, cn) case "/user/edit/mfa/setup/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.AccountEditMFASetupSubmit(w,req,user) co.RouteViewCounter.Bump3(105, cn) case "/user/edit/mfa/disable/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.AccountEditMFADisableSubmit(w,req,user) co.RouteViewCounter.Bump3(106, cn) case "/user/edit/email/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountEditEmail(w,req,user,h) co.RouteViewCounter.Bump3(107, cn) case "/user/edit/token/": err = routes.AccountEditEmailTokenSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(108, cn) case "/user/edit/logins/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountLogins(w,req,user,h) co.RouteViewCounter.Bump3(109, cn) case "/user/edit/blocked/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountBlocked(w,req,user,h) co.RouteViewCounter.Bump3(110, cn) case "/user/levels/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.LevelList(w,req,user,h) co.RouteViewCounter.Bump3(111, cn) case "/user/convos/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.Convos(w,req,user,h) co.RouteViewCounter.Bump3(112, cn) case "/user/convos/create/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.ConvosCreate(w,req,user,h) co.RouteViewCounter.Bump3(113, cn) case "/user/convo/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.Convo(w,req,user,h,extraData) co.RouteViewCounter.Bump3(114, cn) case "/user/convos/create/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ConvosCreateSubmit(w,req,user) co.RouteViewCounter.Bump3(115, cn) case "/user/convo/create/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ConvosCreateReplySubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(116, cn) case "/user/convo/delete/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ConvosDeleteReplySubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(117, cn) case "/user/convo/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ConvosEditReplySubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(118, cn) case "/user/block/create/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.RelationsBlockCreate(w,req,user,h,extraData) co.RouteViewCounter.Bump3(119, cn) case "/user/block/create/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.RelationsBlockCreateSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(120, cn) case "/user/block/remove/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.RelationsBlockRemove(w,req,user,h,extraData) co.RouteViewCounter.Bump3(121, cn) case "/user/block/remove/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.RelationsBlockRemoveSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(122, cn) default: req.URL.Path += extraData h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.ViewProfile(w,req,user, h) co.RouteViewCounter.Bump3(123, cn) } case "/users": switch(req.URL.Path) { case "/users/ban/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.BanUserSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(124, cn) case "/users/unban/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.UnbanUser(w,req,user,extraData) co.RouteViewCounter.Bump3(125, cn) case "/users/activate/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ActivateUser(w,req,user,extraData) co.RouteViewCounter.Bump3(126, cn) case "/users/ips/": err = c.MemberOnly(w,req,user) if err != nil { return err } h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.IPSearch(w,req,user,h) co.RouteViewCounter.Bump3(127, cn) case "/users/delete-posts/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.DeletePostsSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(128, cn) } case "/topic": switch(req.URL.Path) { case "/topic/create/submit/": err = c.MemberOnly(w,req,user) if err != nil { return err } err = c.HandleUploadRoute(w,req,user,int(c.Config.MaxRequestSize)) if err != nil { return err } err = c.NoUploadSessionMismatch(w,req,user) if err != nil { return err } err = routes.CreateTopicSubmit(w,req,user) co.RouteViewCounter.Bump3(129, cn) case "/topic/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.EditTopicSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(130, cn) case "/topic/delete/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } req.URL.Path += extraData err = routes.DeleteTopicSubmit(w,req,user) co.RouteViewCounter.Bump3(131, cn) case "/topic/stick/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.StickTopicSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(132, cn) case "/topic/unstick/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.UnstickTopicSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(133, cn) case "/topic/lock/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } req.URL.Path += extraData err = routes.LockTopicSubmit(w,req,user) co.RouteViewCounter.Bump3(134, cn) case "/topic/unlock/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.UnlockTopicSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(135, cn) case "/topic/move/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.MoveTopicSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(136, cn) case "/topic/like/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.LikeTopicSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(137, cn) case "/topic/unlike/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.UnlikeTopicSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(138, cn) case "/topic/attach/add/submit/": err = c.MemberOnly(w,req,user) if err != nil { return err } err = c.HandleUploadRoute(w,req,user,int(c.Config.MaxRequestSize)) if err != nil { return err } err = c.NoUploadSessionMismatch(w,req,user) if err != nil { return err } err = routes.AddAttachToTopicSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(139, cn) case "/topic/attach/remove/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.RemoveAttachFromTopicSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(140, cn) default: h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.ViewTopic(w,req,user, h, extraData) co.RouteViewCounter.Bump3(141, cn) } case "/reply": switch(req.URL.Path) { case "/reply/create/": err = c.MemberOnly(w,req,user) if err != nil { return err } err = c.HandleUploadRoute(w,req,user,int(c.Config.MaxRequestSize)) if err != nil { return err } err = c.NoUploadSessionMismatch(w,req,user) if err != nil { return err } err = routes.CreateReplySubmit(w,req,user) co.RouteViewCounter.Bump3(142, cn) case "/reply/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ReplyEditSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(143, cn) case "/reply/delete/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ReplyDeleteSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(144, cn) case "/reply/like/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ReplyLikeSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(145, cn) case "/reply/unlike/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ReplyUnlikeSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(146, cn) case "/reply/attach/add/submit/": err = c.MemberOnly(w,req,user) if err != nil { return err } err = c.HandleUploadRoute(w,req,user,int(c.Config.MaxRequestSize)) if err != nil { return err } err = c.NoUploadSessionMismatch(w,req,user) if err != nil { return err } err = routes.AddAttachToReplySubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(147, cn) case "/reply/attach/remove/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.RemoveAttachFromReplySubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(148, cn) } case "/profile": switch(req.URL.Path) { case "/profile/reply/create/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ProfileReplyCreateSubmit(w,req,user) co.RouteViewCounter.Bump3(149, cn) case "/profile/reply/edit/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ProfileReplyEditSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(150, cn) case "/profile/reply/delete/submit/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.ProfileReplyDeleteSubmit(w,req,user,extraData) co.RouteViewCounter.Bump3(151, cn) } case "/poll": switch(req.URL.Path) { case "/poll/vote/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.PollVote(w,req,user,extraData) co.RouteViewCounter.Bump3(152, cn) case "/poll/results/": err = routes.PollResults(w,req,user,extraData) co.RouteViewCounter.Bump3(153, cn) } case "/accounts": switch(req.URL.Path) { case "/accounts/login/": h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountLogin(w,req,user,h) co.RouteViewCounter.Bump3(154, cn) case "/accounts/create/": h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountRegister(w,req,user,h) co.RouteViewCounter.Bump3(155, cn) case "/accounts/logout/": err = c.NoSessionMismatch(w,req,user) if err != nil { return err } err = c.MemberOnly(w,req,user) if err != nil { return err } err = routes.AccountLogout(w,req,user) co.RouteViewCounter.Bump3(156, cn) case "/accounts/login/submit/": err = c.ParseForm(w,req,user) if err != nil { return err } err = routes.AccountLoginSubmit(w,req,user) co.RouteViewCounter.Bump3(157, cn) case "/accounts/mfa_verify/": h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountLoginMFAVerify(w,req,user,h) co.RouteViewCounter.Bump3(158, cn) case "/accounts/mfa_verify/submit/": err = c.ParseForm(w,req,user) if err != nil { return err } err = routes.AccountLoginMFAVerifySubmit(w,req,user) co.RouteViewCounter.Bump3(159, cn) case "/accounts/create/submit/": err = c.ParseForm(w,req,user) if err != nil { return err } err = routes.AccountRegisterSubmit(w,req,user) co.RouteViewCounter.Bump3(160, cn) case "/accounts/password-reset/": h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountPasswordReset(w,req,user,h) co.RouteViewCounter.Bump3(161, cn) case "/accounts/password-reset/submit/": err = c.ParseForm(w,req,user) if err != nil { return err } err = routes.AccountPasswordResetSubmit(w,req,user) co.RouteViewCounter.Bump3(162, cn) case "/accounts/password-reset/token/": h, err := c.UserCheckNano(w,req,user,cn) if err != nil { return err } err = routes.AccountPasswordResetToken(w,req,user,h) co.RouteViewCounter.Bump3(163, cn) case "/accounts/password-reset/token/submit/": err = c.ParseForm(w,req,user) if err != nil { return err } err = routes.AccountPasswordResetTokenSubmit(w,req,user) co.RouteViewCounter.Bump3(164, cn) } /*case "/sitemaps": // TODO: Count these views req.URL.Path += extraData err = sitemapSwitch(w,req)*/ // ! Temporary fix for certain bots case "/static": w.Header().Set("Connection", "close") http.Redirect(w, req, "/s/"+extraData, http.StatusTemporaryRedirect) case "/uploads": if extraData == "" { co.RouteViewCounter.Bump3(166, cn) return c.NotFound(w,req,nil) } gzw, ok := w.(c.GzipResponseWriter) if ok { w = gzw.ResponseWriter h := w.Header() h.Del("Content-Encoding") } req.URL.Path += extraData // TODO: Find a way to propagate errors up from this? r.UploadHandler(w,req) // TODO: Count these views co.RouteViewCounter.Bump3(166, cn) return nil case "": // Stop the favicons, robots.txt file, etc. resolving to the topics list // TODO: Add support for favicons and robots.txt files switch(extraData) { case "robots.txt": co.RouteViewCounter.Bump3(168, cn) return routes.RobotsTxt(w,req) case "favicon.ico": gzw, ok := w.(c.GzipResponseWriter) if ok { w = gzw.ResponseWriter h := w.Header() h.Del("Content-Encoding") } req.URL.Path = "/s/favicon.ico" routes.StaticFile(w,req) co.RouteViewCounter.Bump3(171, cn) return nil case "opensearch.xml": co.RouteViewCounter.Bump3(170, cn) return routes.OpenSearchXml(w,req) /*case "sitemap.xml": co.RouteViewCounter.Bump3(169, cn) return routes.SitemapXml(w,req)*/ } co.RouteViewCounter.Bump(0) return c.NotFound(w,req,nil) default: // A fallback for dynamic routes, e.g. ones declared by plugins r.RLock() h, ok := r.extraRoutes[req.URL.Path] r.RUnlock() req.URL.Path += extraData if ok { // TODO: Be more specific about *which* dynamic route it is co.RouteViewCounter.Bump(165) return h(w,req,user) } co.RouteViewCounter.Bump3(172, cn) lp := strings.ToLower(req.URL.Path) if strings.Contains(lp,"admin") || strings.Contains(lp,"sql") || strings.Contains(lp,"manage") || strings.Contains(lp,"//") || strings.Contains(lp,"\\\\") || strings.Contains(lp,"wp") || strings.Contains(lp,"wordpress") || strings.Contains(lp,"config") || strings.Contains(lp,"setup") || strings.Contains(lp,"install") || strings.Contains(lp,"update") || strings.Contains(lp,"php") || strings.Contains(lp,"pl") || strings.Contains(lp,"wget") || strings.Contains(lp,"wp-") || strings.Contains(lp,"include") || strings.Contains(lp,"vendor") || strings.Contains(lp,"bin") || strings.Contains(lp,"system") || strings.Contains(lp,"eval") || strings.Contains(lp,"config") { r.SuspiciousRequest(req,"Bad Route") return c.MicroNotFound(w,req) } r.DumpRequest(req,"Bad Route") return c.NotFound(w,req,nil) } return err }