diff --git a/common/token/token.go b/common/token/token.go new file mode 100644 index 000000000..73568bcbc --- /dev/null +++ b/common/token/token.go @@ -0,0 +1,13 @@ +package token + +import "math/rand" + +// Generate returns an alphanumeric token of specified length +func Generate(length int) string { + var chars = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") + b := make([]rune, length) + for i := range b { + b[i] = chars[rand.Intn(len(chars))] + } + return string(b) +} diff --git a/config.json b/config.json index 5e23789d8..fcf7d3c0f 100644 --- a/config.json +++ b/config.json @@ -3,13 +3,14 @@ "BinPath": "bin", "DisableSoftCrash": false, "FeaturedWeapons": 1, + "HideLoginNotice": true, + "LoginNotice": "
Welcome to Erupe SU9.1!
Erupe is experimental software, we are not liable for any
issues caused by installing the software!

■Report bugs on Discord!

■Test everything!

■Don't talk to softlocking NPCs!

■Fork the code on GitHub!

Thank you to all of the contributors,

this wouldn't exist without you.", + "PatchServerManifest": "", + "PatchServerFile": "", + "ScreenshotAPIURL": "", "DevMode": true, "DevModeOptions": { - "PatchServerManifest": "", - "PatchServerFile": "", "AutoCreateAccount": true, - "HideLoginNotice": false, - "LoginNotice": "
Welcome to Erupe SU9.1!
Erupe is experimental software, we are not liable for any
issues caused by installing the software!

■Report bugs on Discord!

■Test everything!

■Don't talk to softlocking NPCs!

■Fork the code on GitHub!

Thank you to all of the contributors,

this wouldn't exist without you.", "CleanDB": false, "MaxLauncherHR": false, "LogInboundMessages": false, diff --git a/config/config.go b/config/config.go index 8fde5293a..9c9b6b7db 100644 --- a/config/config.go +++ b/config/config.go @@ -12,11 +12,16 @@ import ( // Config holds the global server-wide config. type Config struct { - Host string `mapstructure:"Host"` - BinPath string `mapstructure:"BinPath"` - DisableSoftCrash bool // Disables the 'Press Return to exit' dialog allowing scripts to reboot the server automatically - FeaturedWeapons int // Number of Active Feature weapons to generate daily - DevMode bool + Host string `mapstructure:"Host"` + BinPath string `mapstructure:"BinPath"` + DisableSoftCrash bool // Disables the 'Press Return to exit' dialog allowing scripts to reboot the server automatically + FeaturedWeapons int // Number of Active Feature weapons to generate daily + HideLoginNotice bool // Hide the Erupe notice on login + LoginNotice string // MHFML string of the login notice displayed + PatchServerManifest string // Manifest patch server override + PatchServerFile string // File patch server override + ScreenshotAPIURL string // Destination for screenshots uploaded to BBS + DevMode bool DevModeOptions DevModeOptions Discord Discord @@ -32,24 +37,20 @@ type Config struct { // DevModeOptions holds various debug/temporary options for use while developing Erupe. type DevModeOptions struct { - PatchServerManifest string // Manifest patch server override - PatchServerFile string // File patch server override - AutoCreateAccount bool // Automatically create accounts if they don't exist - HideLoginNotice bool // Hide the Erupe notice on login - LoginNotice string // MHFML string of the login notice displayed - CleanDB bool // Automatically wipes the DB on server reset. - MaxLauncherHR bool // Sets the HR returned in the launcher to HR7 so that you can join non-beginner worlds. - LogInboundMessages bool // Log all messages sent to the server - LogOutboundMessages bool // Log all messages sent to the clients - MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled - DivaEvent int // Diva Defense event status - FestaEvent int // Hunter's Festa event status - TournamentEvent int // VS Tournament event status - MezFesEvent bool // MezFes status - MezFesAlt bool // Swaps out Volpakkun for Tokotoko - DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!) - DisableMailItems bool // Hack to prevent english versions of MHF from crashing - QuestDebugTools bool // Enable various quest debug logs + AutoCreateAccount bool // Automatically create accounts if they don't exist + CleanDB bool // Automatically wipes the DB on server reset. + MaxLauncherHR bool // Sets the HR returned in the launcher to HR7 so that you can join non-beginner worlds. + LogInboundMessages bool // Log all messages sent to the server + LogOutboundMessages bool // Log all messages sent to the clients + MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled + DivaEvent int // Diva Defense event status + FestaEvent int // Hunter's Festa event status + TournamentEvent int // VS Tournament event status + MezFesEvent bool // MezFes status + MezFesAlt bool // Swaps out Volpakkun for Tokotoko + DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!) + DisableMailItems bool // Hack to prevent english versions of MHF from crashing + QuestDebugTools bool // Enable various quest debug logs SaveDumps SaveDumpOptions } diff --git a/network/mhfpacket/msg_mhf_apply_bbs_article.go b/network/mhfpacket/msg_mhf_apply_bbs_article.go index df0218ce0..d2b9c803b 100644 --- a/network/mhfpacket/msg_mhf_apply_bbs_article.go +++ b/network/mhfpacket/msg_mhf_apply_bbs_article.go @@ -1,15 +1,24 @@ package mhfpacket -import ( - "errors" +import ( + "errors" + "erupe-ce/common/bfutil" + "erupe-ce/common/stringsupport" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfApplyBbsArticle represents the MSG_MHF_APPLY_BBS_ARTICLE -type MsgMhfApplyBbsArticle struct{} +type MsgMhfApplyBbsArticle struct { + AckHandle uint32 + Unk0 uint32 + Unk1 []byte + Name string + Title string + Description string +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfApplyBbsArticle) Opcode() network.PacketID { @@ -18,7 +27,13 @@ func (m *MsgMhfApplyBbsArticle) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfApplyBbsArticle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadBytes(16) + m.Name = stringsupport.SJISToUTF8(bfutil.UpToNull(bf.ReadBytes(32))) + m.Title = stringsupport.SJISToUTF8(bfutil.UpToNull(bf.ReadBytes(128))) + m.Description = stringsupport.SJISToUTF8(bfutil.UpToNull(bf.ReadBytes(256))) + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_get_bbs_sns_status.go b/network/mhfpacket/msg_mhf_get_bbs_sns_status.go index 07ab9e485..0c50f67e8 100644 --- a/network/mhfpacket/msg_mhf_get_bbs_sns_status.go +++ b/network/mhfpacket/msg_mhf_get_bbs_sns_status.go @@ -1,15 +1,18 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfGetBbsSnsStatus represents the MSG_MHF_GET_BBS_SNS_STATUS -type MsgMhfGetBbsSnsStatus struct{} +type MsgMhfGetBbsSnsStatus struct { + AckHandle uint32 + Unk []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetBbsSnsStatus) Opcode() network.PacketID { @@ -18,7 +21,9 @@ func (m *MsgMhfGetBbsSnsStatus) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetBbsSnsStatus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk = bf.ReadBytes(12) + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_get_bbs_user_status.go b/network/mhfpacket/msg_mhf_get_bbs_user_status.go index 69bcef671..9c44faa76 100644 --- a/network/mhfpacket/msg_mhf_get_bbs_user_status.go +++ b/network/mhfpacket/msg_mhf_get_bbs_user_status.go @@ -1,15 +1,18 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfGetBbsUserStatus represents the MSG_MHF_GET_BBS_USER_STATUS -type MsgMhfGetBbsUserStatus struct{} +type MsgMhfGetBbsUserStatus struct { + AckHandle uint32 + Unk []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetBbsUserStatus) Opcode() network.PacketID { @@ -18,7 +21,9 @@ func (m *MsgMhfGetBbsUserStatus) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetBbsUserStatus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk = bf.ReadBytes(12) + return nil } // Build builds a binary packet from the current data. diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 47d3d6b4c..b1af93beb 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -1495,10 +1495,6 @@ func handleMsgMhfInfoScenarioCounter(s *Session, p mhfpacket.MHFPacket) { doAckBufSucceed(s, pkt.AckHandle, resp.Data()) } -func handleMsgMhfGetBbsSnsStatus(s *Session, p mhfpacket.MHFPacket) {} - -func handleMsgMhfApplyBbsArticle(s *Session, p mhfpacket.MHFPacket) {} - func handleMsgMhfGetEtcPoints(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetEtcPoints) diff --git a/server/channelserver/handlers_bbs.go b/server/channelserver/handlers_bbs.go new file mode 100644 index 000000000..222a8eadc --- /dev/null +++ b/server/channelserver/handlers_bbs.go @@ -0,0 +1,41 @@ +package channelserver + +import ( + "erupe-ce/common/byteframe" + "erupe-ce/common/stringsupport" + "erupe-ce/common/token" + "erupe-ce/network/mhfpacket" +) + +func handleMsgMhfGetBbsUserStatus(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetBbsUserStatus) + bf := byteframe.NewByteFrame() + bf.WriteUint32(200) + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(0) + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfGetBbsSnsStatus(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetBbsSnsStatus) + bf := byteframe.NewByteFrame() + bf.WriteUint32(200) + bf.WriteUint32(401) + bf.WriteUint32(401) + bf.WriteUint32(0) + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfApplyBbsArticle(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfApplyBbsArticle) + bf := byteframe.NewByteFrame() + articleToken := token.Generate(40) + bf.WriteUint32(200) + bf.WriteUint32(80) + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteBytes(stringsupport.PaddedString(articleToken, 64, false)) + bf.WriteBytes(stringsupport.PaddedString(s.server.erupeConfig.ScreenshotAPIURL, 64, false)) + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} diff --git a/server/channelserver/handlers_users.go b/server/channelserver/handlers_users.go index c360b82a6..fc8b47a8d 100644 --- a/server/channelserver/handlers_users.go +++ b/server/channelserver/handlers_users.go @@ -54,5 +54,3 @@ func handleMsgSysGetUserBinary(s *Session, p mhfpacket.MHFPacket) { } func handleMsgSysNotifyUserBinary(s *Session, p mhfpacket.MHFPacket) {} - -func handleMsgMhfGetBbsUserStatus(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index 3966af8d6..9335de0c0 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -4,6 +4,7 @@ import ( "erupe-ce/common/byteframe" ps "erupe-ce/common/pascalstring" "erupe-ce/common/stringsupport" + "erupe-ce/common/token" "erupe-ce/server/channelserver" "fmt" "math/rand" @@ -18,15 +19,6 @@ func makeSignInFailureResp(respID RespID) []byte { return bf.Data() } -func randSeq(n int) string { - var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") - b := make([]rune, n) - for i := range b { - b[i] = letters[rand.Intn(len(letters))] - } - return string(b) -} - func (s *Session) makeSignInResp(uid int) []byte { returnExpiry := s.server.getReturnExpiry(uid) @@ -37,13 +29,13 @@ func (s *Session) makeSignInResp(uid int) []byte { } rand.Seed(time.Now().UnixNano()) - token := randSeq(16) - s.server.registerToken(uid, token) + sessToken := token.Generate(16) + s.server.registerToken(uid, sessToken) bf := byteframe.NewByteFrame() bf.WriteUint8(1) // resp_code - if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.PatchServerManifest != "" && s.server.erupeConfig.DevModeOptions.PatchServerFile != "" { + if s.server.erupeConfig.DevMode && s.server.erupeConfig.PatchServerManifest != "" && s.server.erupeConfig.PatchServerFile != "" { bf.WriteUint8(2) } else { bf.WriteUint8(0) @@ -51,12 +43,12 @@ func (s *Session) makeSignInResp(uid int) []byte { bf.WriteUint8(1) // entrance server count bf.WriteUint8(uint8(len(chars))) // character count bf.WriteUint32(0xFFFFFFFF) // login_token_number - bf.WriteBytes([]byte(token)) // login_token + bf.WriteBytes([]byte(sessToken)) // login_token bf.WriteUint32(uint32(time.Now().Unix())) // current time if s.server.erupeConfig.DevMode { - if s.server.erupeConfig.DevModeOptions.PatchServerManifest != "" && s.server.erupeConfig.DevModeOptions.PatchServerFile != "" { - ps.Uint8(bf, s.server.erupeConfig.DevModeOptions.PatchServerManifest, false) - ps.Uint8(bf, s.server.erupeConfig.DevModeOptions.PatchServerFile, false) + if s.server.erupeConfig.PatchServerManifest != "" && s.server.erupeConfig.PatchServerFile != "" { + ps.Uint8(bf, s.server.erupeConfig.PatchServerManifest, false) + ps.Uint8(bf, s.server.erupeConfig.PatchServerFile, false) } } ps.Uint8(bf, fmt.Sprintf("%s:%d", s.server.erupeConfig.Host, s.server.erupeConfig.Entrance.Port), false) @@ -111,11 +103,11 @@ func (s *Session) makeSignInResp(uid int) []byte { } } - if s.server.erupeConfig.DevModeOptions.HideLoginNotice { + if s.server.erupeConfig.HideLoginNotice { bf.WriteUint8(0) } else { bf.WriteUint8(1) // Notice count - noticeText := s.server.erupeConfig.DevModeOptions.LoginNotice + noticeText := s.server.erupeConfig.LoginNotice ps.Uint32(bf, noticeText, true) }