func HandleSendInstantMsg(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
if !cc.Authorize(accessSendPrivMsg) {
res = append(res, cc.NewErrReply(t, "You are not allowed to send private messages."))
- return res, err
+ return res, errors.New("user is not allowed to send private messages")
}
msg := t.GetField(FieldData)
reply.Fields = append(reply.Fields, NewField(FieldQuotingMsg, t.GetField(FieldQuotingMsg).Data))
}
- id, _ := byteToInt(ID.Data)
+ id, err := byteToInt(ID.Data)
+ if err != nil {
+ return res, errors.New("invalid client ID")
+ }
otherClient, ok := cc.Server.Clients[uint16(id)]
if !ok {
return res, errors.New("invalid client ID")
// Check if target user has "Refuse private messages" flag
flagBitmap := big.NewInt(int64(binary.BigEndian.Uint16(otherClient.Flags)))
- if flagBitmap.Bit(userFLagRefusePChat) == 1 {
+ if flagBitmap.Bit(UserFlagRefusePM) == 1 {
res = append(res,
*NewTransaction(
TranServerMsg,
return res, err
}
- res = append(res, cc.NewReply(t,
- NewField(FieldFileName, []byte(fw.name)),
+ encodedName, err := txtEncoder.String(fw.name)
+ if err != nil {
+ return res, fmt.Errorf("invalid filepath encoding: %w", err)
+ }
+
+ fields := []Field{
+ NewField(FieldFileName, []byte(encodedName)),
NewField(FieldFileTypeString, fw.ffo.FlatFileInformationFork.friendlyType()),
NewField(FieldFileCreatorString, fw.ffo.FlatFileInformationFork.friendlyCreator()),
- NewField(FieldFileComment, fw.ffo.FlatFileInformationFork.Comment),
NewField(FieldFileType, fw.ffo.FlatFileInformationFork.TypeSignature),
NewField(FieldFileCreateDate, fw.ffo.FlatFileInformationFork.CreateDate),
NewField(FieldFileModifyDate, fw.ffo.FlatFileInformationFork.ModifyDate),
- NewField(FieldFileSize, fw.totalSize()),
- ))
+ }
+
+ // Include the optional FileComment field if there is a comment.
+ if len(fw.ffo.FlatFileInformationFork.Comment) != 0 {
+ fields = append(fields, NewField(FieldFileComment, fw.ffo.FlatFileInformationFork.Comment))
+ }
+
+ // Include the FileSize field for files.
+ if !bytes.Equal(fw.ffo.FlatFileInformationFork.TypeSignature, []byte{0x66, 0x6c, 0x64, 0x72}) {
+ fields = append(fields, NewField(FieldFileSize, fw.totalSize()))
+ }
+
+ res = append(res, cc.NewReply(t, fields...))
return res, err
}
if err != nil {
return nil, err
}
- hlFile.name = string(fileNewName)
+ hlFile.name, err = txtDecoder.String(string(fileNewName))
+ if err != nil {
+ return res, fmt.Errorf("invalid filepath encoding: %w", err)
+ }
+
err = hlFile.move(fileDir)
if os.IsNotExist(err) {
res = append(res, cc.NewErrReply(t, "Cannot rename file "+string(fileName)+" because it does not exist or cannot be found."))
res = append(res, cc.NewErrReply(t, "Cannot delete file "+fileName+" because it does not exist or cannot be found."))
return res, err
}
- if err != nil {
- return res, err
- }
switch mode := fi.Mode(); {
case mode.IsDir():
if !cc.Authorize(accessMoveFolder) {
}
}
newFolderPath := path.Join(cc.Server.Config.FileRoot, subPath, folderName)
+ newFolderPath, err = txtDecoder.String(newFolderPath)
+ if err != nil {
+ return res, fmt.Errorf("invalid filepath encoding: %w", err)
+ }
// TODO: check path and folder name lengths
return []Transaction{cc.NewErrReply(t, msg)}, nil
}
- // TODO: check for disallowed characters to maintain compatibility for original client
-
if err := cc.Server.FS.Mkdir(newFolderPath, 0777); err != nil {
msg := fmt.Sprintf("Cannot create folder \"%s\" because an error occurred.", folderName)
return []Transaction{cc.NewErrReply(t, msg)}, nil
return res, err
}
- login := DecodeUserString(t.GetField(FieldUserLogin).Data)
+ login := decodeString(t.GetField(FieldUserLogin).Data)
userName := string(t.GetField(FieldUserName).Data)
newAccessLvl := t.GetField(FieldUserAccess).Data
flagBitmap := big.NewInt(int64(binary.BigEndian.Uint16(c.Flags)))
if c.Authorize(accessDisconUser) {
- flagBitmap.SetBit(flagBitmap, userFlagAdmin, 1)
+ flagBitmap.SetBit(flagBitmap, UserFlagAdmin, 1)
} else {
- flagBitmap.SetBit(flagBitmap, userFlagAdmin, 0)
+ flagBitmap.SetBit(flagBitmap, UserFlagAdmin, 0)
}
binary.BigEndian.PutUint16(c.Flags, uint16(flagBitmap.Int64()))
res = append(res, cc.NewReply(t,
NewField(FieldUserName, []byte(account.Name)),
- NewField(FieldUserLogin, negateString(t.GetField(FieldUserLogin).Data)),
+ NewField(FieldUserLogin, encodeString(t.GetField(FieldUserLogin).Data)),
NewField(FieldUserPassword, []byte(account.Password)),
NewField(FieldUserAccess, account.Access[:]),
))
}
if len(subFields) == 1 {
- login := DecodeUserString(getField(FieldData, &subFields).Data)
+ login := decodeString(getField(FieldData, &subFields).Data)
cc.logger.Infow("DeleteUser", "login", login)
if !cc.Authorize(accessDeleteUser) {
continue
}
- login := DecodeUserString(getField(FieldUserLogin, &subFields).Data)
+ login := decodeString(getField(FieldUserLogin, &subFields).Data)
// check if the login dataFile; if so, we know we are updating an existing user
if acc, ok := cc.Server.Accounts[login]; ok {
}
err = cc.Server.UpdateUser(
- DecodeUserString(getField(FieldData, &subFields).Data),
- DecodeUserString(getField(FieldUserLogin, &subFields).Data),
+ decodeString(getField(FieldData, &subFields).Data),
+ decodeString(getField(FieldUserLogin, &subFields).Data),
string(getField(FieldUserName, &subFields).Data),
acc.Password,
acc.Access,
return res, err
}
- login := DecodeUserString(t.GetField(FieldUserLogin).Data)
+ login := decodeString(t.GetField(FieldUserLogin).Data)
// If the account already dataFile, reply with an error
if _, ok := cc.Server.Accounts[login]; ok {
}
// TODO: Handle case where account doesn't exist; e.g. delete race condition
- login := DecodeUserString(t.GetField(FieldUserLogin).Data)
+ login := decodeString(t.GetField(FieldUserLogin).Data)
if err := cc.Server.DeleteUser(login); err != nil {
return res, err
// Check refuse private PM option
if optBitmap.Bit(refusePM) == 1 {
- flagBitmap.SetBit(flagBitmap, userFlagRefusePM, 1)
+ flagBitmap.SetBit(flagBitmap, UserFlagRefusePM, 1)
binary.BigEndian.PutUint16(cc.Flags, uint16(flagBitmap.Int64()))
}
// Check refuse private chat option
if optBitmap.Bit(refuseChat) == 1 {
- flagBitmap.SetBit(flagBitmap, userFLagRefusePChat, 1)
+ flagBitmap.SetBit(flagBitmap, UserFlagRefusePChat, 1)
binary.BigEndian.PutUint16(cc.Flags, uint16(flagBitmap.Int64()))
}
}
newsPost := fmt.Sprintf(newsTemplate+"\r", cc.UserName, time.Now().Format(newsDateTemplate), t.GetField(FieldData).Data)
- newsPost = strings.Replace(newsPost, "\n", "\r", -1)
+ newsPost = strings.ReplaceAll(newsPost, "\n", "\r")
// update news in memory
cc.Server.FlatNews = append([]byte(newsPost), cc.Server.FlatNews...)
banUntil := time.Now().Add(tempBanDuration)
cc.Server.banList[strings.Split(clientConn.RemoteAddr, ":")[0]] = &banUntil
- cc.Server.writeBanList()
case 2:
// send message: "You are permanently banned on this server"
cc.logger.Infow("Disconnect & ban " + string(clientConn.UserName))
))
cc.Server.banList[strings.Split(clientConn.RemoteAddr, ":")[0]] = nil
- cc.Server.writeBanList()
+ }
+
+ err := cc.Server.writeBanList()
+ if err != nil {
+ return res, err
}
}
optBitmap := big.NewInt(int64(binary.BigEndian.Uint16(options)))
flagBitmap := big.NewInt(int64(binary.BigEndian.Uint16(cc.Flags)))
- flagBitmap.SetBit(flagBitmap, userFlagRefusePM, optBitmap.Bit(refusePM))
+ flagBitmap.SetBit(flagBitmap, UserFlagRefusePM, optBitmap.Bit(refusePM))
binary.BigEndian.PutUint16(cc.Flags, uint16(flagBitmap.Int64()))
- flagBitmap.SetBit(flagBitmap, userFLagRefusePChat, optBitmap.Bit(refuseChat))
+ flagBitmap.SetBit(flagBitmap, UserFlagRefusePChat, optBitmap.Bit(refuseChat))
binary.BigEndian.PutUint16(cc.Flags, uint16(flagBitmap.Int64()))
// Check auto response
targetClient := cc.Server.Clients[binary.BigEndian.Uint16(targetID)]
flagBitmap := big.NewInt(int64(binary.BigEndian.Uint16(targetClient.Flags)))
- if flagBitmap.Bit(userFLagRefusePChat) == 1 {
+ if flagBitmap.Bit(UserFlagRefusePChat) == 1 {
res = append(res,
*NewTransaction(
TranServerMsg,