package main
//import "fmt"
import "sync"
import "bytes"
import "strings"
import "strconv"
import "regexp"
import "html/template"
type HeaderVars struct
{
NoticeList []string
Scripts []string
Stylesheets []string
Widgets PageWidgets
Site *Site
Settings map[string]interface{}
ExtData ExtData
}
// TO-DO: Add this to routes which don't use templates. E.g. Json APIs.
type HeaderLite struct
{
Site *Site
Settings SettingBox
}
type PageWidgets struct
{
LeftSidebar template.HTML
RightSidebar template.HTML
}
/*type UnsafeExtData struct
{
items map[string]interface{} // Key: pluginname
}*/
type ExtData struct
{
items map[string]interface{} // Key: pluginname
sync.RWMutex
}
type Page struct
{
Title string
CurrentUser User
Header HeaderVars
ItemList []interface{}
Something interface{}
}
type TopicPage struct
{
Title string
CurrentUser User
Header HeaderVars
ItemList []Reply
Topic TopicUser
Page int
LastPage int
ExtData ExtData
}
type TopicsPage struct
{
Title string
CurrentUser User
Header HeaderVars
ItemList []*TopicsRow
ExtData ExtData
}
type ForumPage struct
{
Title string
CurrentUser User
Header HeaderVars
ItemList []*TopicsRow
Forum Forum
Page int
LastPage int
ExtData ExtData
}
type ForumsPage struct
{
Title string
CurrentUser User
Header HeaderVars
ItemList []Forum
ExtData ExtData
}
type ProfilePage struct
{
Title string
CurrentUser User
Header HeaderVars
ItemList []Reply
ProfileOwner User
ExtData ExtData
}
type CreateTopicPage struct
{
Title string
CurrentUser User
Header HeaderVars
ItemList []Forum
FID int
ExtData ExtData
}
type PanelStats struct
{
Users int
Groups int
Forums int
Settings int
Themes int
Reports int
}
type PanelPage struct
{
Title string
CurrentUser User
Header HeaderVars
Stats PanelStats
ItemList []interface{}
Something interface{}
}
type GridElement struct
{
ID string
Body string
Order int // For future use
Class string
Background string
TextColour string
Note string
}
type PanelDashboardPage struct
{
Title string
CurrentUser User
Header HeaderVars
Stats PanelStats
GridItems []GridElement
ExtData ExtData
}
type PanelThemesPage struct
{
Title string
CurrentUser User
Header HeaderVars
Stats PanelStats
PrimaryThemes []Theme
VariantThemes []Theme
ExtData ExtData
}
type PanelUserPage struct
{
Title string
CurrentUser User
Header HeaderVars
Stats PanelStats
ItemList []User
PageList []int
Page int
LastPage int
ExtData ExtData
}
type PanelGroupPage struct
{
Title string
CurrentUser User
Header HeaderVars
Stats PanelStats
ItemList []GroupAdmin
PageList []int
Page int
LastPage int
ExtData ExtData
}
type PanelEditGroupPage struct
{
Title string
CurrentUser User
Header HeaderVars
Stats PanelStats
ID int
Name string
Tag string
Rank string
DisableRank bool
ExtData ExtData
}
type GroupForumPermPreset struct
{
Group Group
Preset string
}
type PanelEditForumPage struct
{
Title string
CurrentUser User
Header HeaderVars
Stats PanelStats
ID int
Name string
Desc string
Active bool
Preset string
Groups []GroupForumPermPreset
ExtData ExtData
}
type NameLangPair struct
{
Name string
LangStr string
}
type NameLangToggle struct
{
Name string
LangStr string
Toggle bool
}
type PanelEditGroupPermsPage struct
{
Title string
CurrentUser User
Header HeaderVars
Stats PanelStats
ID int
Name string
LocalPerms []NameLangToggle
GlobalPerms []NameLangToggle
ExtData ExtData
}
type Log struct {
Action template.HTML
IPAddress string
DoneAt string
}
type PanelLogsPage struct
{
Title string
CurrentUser User
Header HeaderVars
Stats PanelStats
Logs []Log
PageList []int
Page int
LastPage int
ExtData ExtData
}
type PanelDebugPage struct
{
Title string
CurrentUser User
Header HeaderVars
Stats PanelStats
Uptime string
OpenConns int
DBAdapter string
ExtData ExtData
}
type PageSimple struct
{
Title string
Something interface{}
}
type AreYouSure struct
{
URL string
Message string
}
var space_gap []byte = []byte(" ")
var http_prot_b []byte = []byte("http://")
var invalid_url []byte = []byte("[Invalid URL]")
var invalid_topic []byte = []byte("[Invalid Topic]")
var invalid_profile []byte = []byte("[Invalid Profile]")
var invalid_forum []byte = []byte("[Invalid Forum]")
var url_open []byte = []byte("")
var bytes_singlequote []byte = []byte("'")
var bytes_greaterthan []byte = []byte(">")
var url_mention []byte = []byte(" class='mention'")
var url_close []byte = []byte("")
var urlpattern string = `(?s)([ {1}])((http|https|ftp|mailto)*)(:{??)\/\/([\.a-zA-Z\/]+)([ {1}])`
var url_reg *regexp.Regexp
func init() {
url_reg = regexp.MustCompile(urlpattern)
}
func shortcode_to_unicode(msg string) string {
//re := regexp.MustCompile(":(.):")
msg = strings.Replace(msg,":grinning:","đ",-1)
msg = strings.Replace(msg,":grin:","đ",-1)
msg = strings.Replace(msg,":joy:","đ",-1)
msg = strings.Replace(msg,":rofl:","đ¤Ŗ",-1)
msg = strings.Replace(msg,":smiley:","đ",-1)
msg = strings.Replace(msg,":smile:","đ",-1)
msg = strings.Replace(msg,":sweat_smile:","đ
",-1)
msg = strings.Replace(msg,":laughing:","đ",-1)
msg = strings.Replace(msg,":satisfied:","đ",-1)
msg = strings.Replace(msg,":wink:","đ",-1)
msg = strings.Replace(msg,":blush:","đ",-1)
msg = strings.Replace(msg,":yum:","đ",-1)
msg = strings.Replace(msg,":sunglasses:","đ",-1)
msg = strings.Replace(msg,":heart_eyes:","đ",-1)
msg = strings.Replace(msg,":kissing_heart:","đ",-1)
msg = strings.Replace(msg,":kissing:","đ",-1)
msg = strings.Replace(msg,":kissing_smiling_eyes:","đ",-1)
msg = strings.Replace(msg,":kissing_closed_eyes:","đ",-1)
msg = strings.Replace(msg,":relaxed:","âēī¸",-1)
msg = strings.Replace(msg,":slight_smile:","đ",-1)
msg = strings.Replace(msg,":hugging:","đ¤",-1)
msg = strings.Replace(msg,":thinking:","đ¤",-1)
msg = strings.Replace(msg,":neutral_face:","đ",-1)
msg = strings.Replace(msg,":expressionless:","đ",-1)
msg = strings.Replace(msg,":no_mouth:","đļ",-1)
msg = strings.Replace(msg,":rolling_eyes:","đ",-1)
msg = strings.Replace(msg,":smirk:","đ",-1)
msg = strings.Replace(msg,":persevere:","đŖ",-1)
msg = strings.Replace(msg,":disappointed_relieved:","đĨ",-1)
msg = strings.Replace(msg,":open_mouth:","đŽ",-1)
msg = strings.Replace(msg,":zipper_mouth:","đ¤",-1)
msg = strings.Replace(msg,":hushed:","đ¯",-1)
msg = strings.Replace(msg,":sleepy:","đĒ",-1)
msg = strings.Replace(msg,":tired_face:","đĢ",-1)
msg = strings.Replace(msg,":sleeping:","đ´",-1)
msg = strings.Replace(msg,":relieved:","đ",-1)
msg = strings.Replace(msg,":nerd:","đ¤",-1)
msg = strings.Replace(msg,":stuck_out_tongue:","đ",-1)
msg = strings.Replace(msg,":worried:","đ",-1)
msg = strings.Replace(msg,":drooling_face:","đ¤¤",-1)
msg = strings.Replace(msg,":disappointed:","đ",-1)
msg = strings.Replace(msg,":astonished:","đ˛",-1)
msg = strings.Replace(msg,":slight_frown:","đ",-1)
msg = strings.Replace(msg,":skull_crossbones:","â ī¸",-1)
msg = strings.Replace(msg,":skull:","đ",-1)
msg = strings.Replace(msg,":point_up:","âī¸",-1)
msg = strings.Replace(msg,":v:","âī¸ī¸",-1)
msg = strings.Replace(msg,":writing_hand:","âī¸",-1)
msg = strings.Replace(msg,":heart:","â¤ī¸ī¸",-1)
msg = strings.Replace(msg,":heart_exclamation:","âŖī¸",-1)
msg = strings.Replace(msg,":hotsprings:","â¨ī¸",-1)
msg = strings.Replace(msg,":airplane:","âī¸ī¸",-1)
msg = strings.Replace(msg,":hourglass:","â",-1)
msg = strings.Replace(msg,":watch:","â",-1)
msg = strings.Replace(msg,":comet:","âī¸",-1)
msg = strings.Replace(msg,":snowflake:","âī¸",-1)
msg = strings.Replace(msg,":cloud:","âī¸",-1)
msg = strings.Replace(msg,":sunny:","âī¸",-1)
msg = strings.Replace(msg,":spades:","â ī¸",-1)
msg = strings.Replace(msg,":hearts:","âĨī¸ī¸",-1)
msg = strings.Replace(msg,":diamonds:","âĻī¸",-1)
msg = strings.Replace(msg,":clubs:","âŖī¸",-1)
msg = strings.Replace(msg,":phone:","âī¸",-1)
msg = strings.Replace(msg,":telephone:","âī¸",-1)
msg = strings.Replace(msg,":biohazard:","âŖī¸",-1)
msg = strings.Replace(msg,":radioactive:","âĸī¸",-1)
msg = strings.Replace(msg,":scissors:","âī¸",-1)
msg = strings.Replace(msg,":arrow_upper_right:","âī¸",-1)
msg = strings.Replace(msg,":arrow_right:","âĄī¸",-1)
msg = strings.Replace(msg,":arrow_lower_right:","âī¸",-1)
msg = strings.Replace(msg,":arrow_lower_left:","âī¸",-1)
msg = strings.Replace(msg,":arrow_upper_left:","âī¸",-1)
msg = strings.Replace(msg,":arrow_up_down:","âī¸",-1)
msg = strings.Replace(msg,":left_right_arrow:","âī¸",-1)
msg = strings.Replace(msg,":leftwards_arrow_with_hook:","âŠī¸",-1)
msg = strings.Replace(msg,":arrow_right_hook:","âĒī¸",-1)
msg = strings.Replace(msg,":arrow_forward:","âļī¸",-1)
msg = strings.Replace(msg,":arrow_backward:","âī¸",-1)
msg = strings.Replace(msg,":female:","âī¸",-1)
msg = strings.Replace(msg,":male:","âī¸",-1)
msg = strings.Replace(msg,":ballot_box_with_check:","âī¸",-1)
msg = strings.Replace(msg,":heavy_check_mark:","âī¸ī¸",-1)
msg = strings.Replace(msg,":heavy_multiplication_x:","âī¸",-1)
msg = strings.Replace(msg,":pisces:","â",-1)
msg = strings.Replace(msg,":aquarius:","â",-1)
msg = strings.Replace(msg,":capricorn:","â",-1)
msg = strings.Replace(msg,":sagittarius:","â",-1)
msg = strings.Replace(msg,":scorpius:","â",-1)
msg = strings.Replace(msg,":libra:","â",-1)
msg = strings.Replace(msg,":virgo:","â",-1)
msg = strings.Replace(msg,":leo:","â",-1)
msg = strings.Replace(msg,":cancer:","â",-1)
msg = strings.Replace(msg,":gemini:","â",-1)
msg = strings.Replace(msg,":taurus:","â",-1)
msg = strings.Replace(msg,":aries:","â",-1)
msg = strings.Replace(msg,":peace:","âŽī¸",-1)
msg = strings.Replace(msg,":eight_spoked_asterisk:","âŗī¸",-1)
msg = strings.Replace(msg,":eight_pointed_black_star:","â´ī¸",-1)
msg = strings.Replace(msg,":snowman2:","âī¸",-1)
msg = strings.Replace(msg,":umbrella2:","âī¸",-1)
msg = strings.Replace(msg,":pencil2:","âī¸",-1)
msg = strings.Replace(msg,":black_nib:","âī¸",-1)
msg = strings.Replace(msg,":email:","âī¸",-1)
msg = strings.Replace(msg,":envelope:","âī¸",-1)
msg = strings.Replace(msg,":keyboard:","â¨ī¸",-1)
msg = strings.Replace(msg,":white_small_square:","âĢī¸",-1)
msg = strings.Replace(msg,":black_small_square:","âĒī¸",-1)
msg = strings.Replace(msg,":secret:","ãī¸",-1)
msg = strings.Replace(msg,":congratulations:","ãī¸",-1)
msg = strings.Replace(msg,":m:","âī¸",-1)
msg = strings.Replace(msg,":tm:","âĸī¸ī¸",-1)
msg = strings.Replace(msg,":registered:","ÂŽī¸",-1)
msg = strings.Replace(msg,":copyright:","Šī¸",-1)
msg = strings.Replace(msg,":wavy_dash:","ã°ī¸",-1)
msg = strings.Replace(msg,":bangbang:","âŧī¸",-1)
msg = strings.Replace(msg,":sparkle:","âī¸",-1)
msg = strings.Replace(msg,":star_of_david:","âĄī¸",-1)
msg = strings.Replace(msg,":wheel_of_dharma:","â¸ī¸",-1)
msg = strings.Replace(msg,":yin_yang:","â¯ī¸",-1)
msg = strings.Replace(msg,":cross:","âī¸",-1)
msg = strings.Replace(msg,":orthodox_cross:","âĻī¸",-1)
msg = strings.Replace(msg,":star_and_crescent:","âĒī¸",-1)
msg = strings.Replace(msg,":frowning2:","âšī¸",-1)
msg = strings.Replace(msg,":information_source:","âšī¸",-1)
msg = strings.Replace(msg,":interrobang:","âī¸",-1)
return msg
}
func preparse_message(msg string) string {
if sshooks["preparse_preassign"] != nil {
msg = run_sshook("preparse_preassign", msg)
}
return shortcode_to_unicode(msg)
}
func parse_message(msg string/*, user User*/) string {
msg = strings.Replace(msg,":)","đ",-1)
msg = strings.Replace(msg,":(","đ",-1)
msg = strings.Replace(msg,":D","đ",-1)
msg = strings.Replace(msg,":P","đ",-1)
msg = strings.Replace(msg,":O","đ˛",-1)
msg = strings.Replace(msg,":p","đ",-1)
msg = strings.Replace(msg,":o","đ˛",-1)
//msg = url_reg.ReplaceAllString(msg,"$2$3//$4")
// Search for URLs, mentions and hashlinks in the messages...
//log.Print("Parser Loop!")
var msgbytes = []byte(msg)
var outbytes []byte
msgbytes = append(msgbytes,space_gap...)
//log.Print(`"`+string(msgbytes)+`"`)
lastItem := 0
i := 0
for ; len(msgbytes) > (i + 1); i++ {
//log.Print("Index:",i)
//log.Print("Index Item:",msgbytes[i])
//if msgbytes[i] == 10 {
// log.Print("NEWLINE")
//} else if msgbytes[i] == 32 {
// log.Print("SPACE")
//} else {
// log.Print("string(msgbytes[i])",string(msgbytes[i]))
//}
//log.Print("End Index")
if (i==0 && (msgbytes[0] > 32)) || ((msgbytes[i] < 33) && (msgbytes[i + 1] > 32)) {
//log.Print("IN")
//log.Print(msgbytes[i])
if (i != 0) || msgbytes[i] < 33 {
i++
}
if msgbytes[i]=='#' {
//log.Print("IN #")
if bytes.Equal(msgbytes[i+1:i+5],[]byte("tid-")) {
outbytes = append(outbytes,msgbytes[lastItem:i]...)
i += 5
start := i
tid, int_len := coerce_int_bytes(msgbytes[start:])
i += int_len
topic, err := topics.CascadeGet(tid)
if err != nil || !fstore.Exists(topic.ParentID) {
outbytes = append(outbytes,invalid_topic...)
lastItem = i
continue
}
outbytes = append(outbytes, url_open...)
var url_bit []byte = []byte(build_topic_url("",tid))
outbytes = append(outbytes, url_bit...)
outbytes = append(outbytes, url_open2...)
var tid_bit []byte = []byte("#tid-" + strconv.Itoa(tid))
outbytes = append(outbytes, tid_bit...)
outbytes = append(outbytes, url_close...)
lastItem = i
//log.Print("string(msgbytes)",string(msgbytes))
//log.Print(msgbytes)
//log.Print(msgbytes[lastItem - 1])
//log.Print(lastItem - 1)
//log.Print(msgbytes[lastItem])
//log.Print(lastItem)
} else if bytes.Equal(msgbytes[i+1:i+5],[]byte("rid-")) {
outbytes = append(outbytes,msgbytes[lastItem:i]...)
i += 5
start := i
rid, int_len := coerce_int_bytes(msgbytes[start:])
i += int_len
topic, err := get_topic_by_reply(rid)
if err != nil || !fstore.Exists(topic.ParentID) {
outbytes = append(outbytes,invalid_topic...)
lastItem = i
continue
}
outbytes = append(outbytes, url_open...)
var url_bit []byte = []byte(build_topic_url("",topic.ID))
outbytes = append(outbytes, url_bit...)
outbytes = append(outbytes, url_open2...)
var rid_bit []byte = []byte("#rid-" + strconv.Itoa(rid))
outbytes = append(outbytes, rid_bit...)
outbytes = append(outbytes, url_close...)
lastItem = i
} else if bytes.Equal(msgbytes[i+1:i+5],[]byte("fid-")) {
outbytes = append(outbytes,msgbytes[lastItem:i]...)
i += 5
start := i
fid, int_len := coerce_int_bytes(msgbytes[start:])
i += int_len
if !fstore.Exists(fid) {
outbytes = append(outbytes,invalid_forum...)
lastItem = i
continue
}
outbytes = append(outbytes, url_open...)
var url_bit []byte = []byte(build_forum_url("",fid))
outbytes = append(outbytes, url_bit...)
outbytes = append(outbytes, url_open2...)
var fid_bit []byte = []byte("#fid-" + strconv.Itoa(fid))
outbytes = append(outbytes, fid_bit...)
outbytes = append(outbytes, url_close...)
lastItem = i
} else {
// TO-DO: Forum Shortcode Link
}
} else if msgbytes[i]=='@' {
//log.Print("IN @")
outbytes = append(outbytes,msgbytes[lastItem:i]...)
i++
start := i
uid, int_len := coerce_int_bytes(msgbytes[start:])
i += int_len
menUser, err := users.CascadeGet(uid)
if err != nil {
outbytes = append(outbytes,invalid_profile...)
lastItem = i
continue
}
outbytes = append(outbytes, url_open...)
var url_bit []byte = []byte(menUser.Link)
outbytes = append(outbytes, url_bit...)
outbytes = append(outbytes, bytes_singlequote...)
outbytes = append(outbytes, url_mention...)
outbytes = append(outbytes, bytes_greaterthan...)
var uid_bit []byte = []byte("@" + menUser.Name)
outbytes = append(outbytes, uid_bit...)
outbytes = append(outbytes, url_close...)
lastItem = i
//log.Print(string(msgbytes))
//log.Print(msgbytes)
//log.Print(msgbytes[lastItem - 1])
//log.Print("lastItem - 1",lastItem - 1)
//log.Print("msgbytes[lastItem]",msgbytes[lastItem])
//log.Print("lastItem",lastItem)
} else if msgbytes[i]=='h' || msgbytes[i]=='f' || msgbytes[i]=='g' {
//log.Print("IN hfg")
if msgbytes[i + 1]=='t' && msgbytes[i + 2]=='t' && msgbytes[i + 3]=='p' {
if msgbytes[i + 4] == 's' && msgbytes[i + 5] == ':' && msgbytes[i + 6] == '/' && msgbytes[i + 7] == '/' {
// Do nothing
} else if msgbytes[i + 4] == ':' && msgbytes[i + 5] == '/' && msgbytes[i + 6] == '/' {
// Do nothing
} else {
continue
}
} else if msgbytes[i + 1] == 't' && msgbytes[i + 2] == 'p' && msgbytes[i + 3] == ':' && msgbytes[i + 4] == '/' && msgbytes[i + 5] == '/' {
// Do nothing
} else if msgbytes[i + 1] == 'i' && msgbytes[i + 2] == 't' && msgbytes[i + 3] == ':' && msgbytes[i + 4] == '/' && msgbytes[i + 5] == '/' {
// Do nothing
} else {
continue
}
outbytes = append(outbytes,msgbytes[lastItem:i]...)
url_len := partial_url_bytes_len(msgbytes[i:])
if msgbytes[i + url_len] != ' ' && msgbytes[i + url_len] != 10 {
outbytes = append(outbytes,invalid_url...)
i += url_len
continue
}
outbytes = append(outbytes, url_open...)
outbytes = append(outbytes, msgbytes[i:i + url_len]...)
outbytes = append(outbytes, url_open2...)
outbytes = append(outbytes, msgbytes[i:i + url_len]...)
outbytes = append(outbytes, url_close...)
i += url_len
lastItem = i
}
}
}
if lastItem != i && len(outbytes) != 0 {
//log.Print("lastItem:",msgbytes[lastItem])
//log.Print("lastItem index:")
//log.Print(lastItem)
//log.Print("i:")
//log.Print(i)
//log.Print("lastItem to end:")
//log.Print(msgbytes[lastItem:])
//log.Print("-----")
calclen := len(msgbytes) - 10
if calclen <= lastItem {
calclen = lastItem
}
outbytes = append(outbytes, msgbytes[lastItem:calclen]...)
msg = string(outbytes)
}
//log.Print(`"`+string(outbytes)+`"`)
//log.Print("msg",`"`+msg+`"`)
msg = strings.Replace(msg,"\n","
",-1)
if sshooks["parse_assign"] != nil {
msg = run_sshook("parse_assign", msg)
}
return msg
}
func regex_parse_message(msg string) string {
msg = strings.Replace(msg,":)","đ",-1)
msg = strings.Replace(msg,":D","đ",-1)
msg = strings.Replace(msg,":P","đ",-1)
msg = url_reg.ReplaceAllString(msg,"$2$3//$4")
msg = strings.Replace(msg,"\n","
",-1)
if sshooks["parse_assign"] != nil {
msg = run_sshook("parse_assign", msg)
}
return msg
}
// 6, 7, 8, 6, 7
// ftp://, http://, https:// git://, mailto: (not a URL, just here for length comparison purposes)
func validate_url_bytes(data []byte) bool {
datalen := len(data)
i := 0
if datalen >= 6 {
if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) {
i = 6
} else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) {
i = 7
} else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) {
i = 8
}
}
for ;datalen > i; i++ {
if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) {
return false
}
}
return true
}
func validated_url_bytes(data []byte) (url []byte) {
datalen := len(data)
i := 0
if datalen >= 6 {
if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) {
i = 6
} else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) {
i = 7
} else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) {
i = 8
}
}
for ;datalen > i; i++ {
if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) {
return invalid_url
}
}
url = append(url, data...)
return url
}
func partial_url_bytes(data []byte) (url []byte) {
datalen := len(data)
i := 0
end := datalen - 1
if datalen >= 6 {
if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) {
i = 6
} else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) {
i = 7
} else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) {
i = 8
}
}
for ;end >= i; i++ {
if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) {
end = i
}
}
url = append(url, data[0:end]...)
return url
}
func partial_url_bytes_len(data []byte) int {
datalen := len(data)
i := 0
if datalen >= 6 {
//log.Print(string(data[0:5]))
if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) {
i = 6
} else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) {
i = 7
} else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) {
i = 8
}
}
for ;datalen > i; i++ {
if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) {
//log.Print("Bad Character:",data[i])
return i
}
}
//log.Print("Data Length:",datalen)
return datalen
}
func parse_media_bytes(data []byte) (protocol []byte, url []byte) {
datalen := len(data)
i := 0
if datalen >= 6 {
if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) {
i = 6
protocol = data[0:2]
} else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) {
i = 7
protocol = []byte("http")
} else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) {
i = 8
protocol = []byte("https")
}
}
for ;datalen > i; i++ {
if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) {
return []byte(""), invalid_url
}
}
if len(protocol) == 0 {
protocol = []byte("http")
}
return protocol, data[i:]
}
func coerce_int_bytes(data []byte) (res int, length int) {
if !(data[0] > 47 && data[0] < 58) {
return 0, 1
}
i := 0
for ;len(data) > i; i++ {
if !(data[i] > 47 && data[i] < 58) {
conv, err := strconv.Atoi(string(data[0:i]))
if err != nil {
return 0, i
}
return conv, i
}
}
conv, err := strconv.Atoi(string(data))
if err != nil {
return 0, i
}
return conv, i
}
// TO-DO: Write tests for this
func paginate(count int, per_page int, maxPages int) []int {
if count < per_page {
return []int{1}
}
var page int
var out []int
for current := 0; current < count; current += per_page {
page++
out = append(out,page)
if len(out) >= maxPages {
break
}
}
return out
}
// TO-DO: Write tests for this
func page_offset(count int, page int, perPage int) (int, int, int) {
var offset int
lastPage := int(count / perPage) + 1
if page > 1 {
offset = (perPage * page) - perPage
} else if page == -1 {
page = lastPage
offset = (perPage * page) - perPage
} else {
page = 1
}
// We don't want the offset to overflow the slices, if everything's in memory
if offset >= (count - 1) {
offset = 0
}
return offset, page, lastPage
}