github.com/Ptt-official-app/go-bbs@v0.12.0/pttbbs/passwd.go (about)

     1  // Copyright 2020 Pichu Chen, The PTT APP Authors
     2  
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package pttbbs
    16  
    17  import (
    18  	"github.com/Ptt-official-app/go-bbs/crypt"
    19  
    20  	"encoding/binary"
    21  	"fmt"
    22  	"io"
    23  	"log"
    24  	"os"
    25  	"strings"
    26  	"time"
    27  )
    28  
    29  const (
    30  	PosOfPasswdVersion      = 0
    31  	PosOfPasswdUserID       = PosOfPasswdVersion + 4
    32  	PosOfPasswdRealName     = PosOfPasswdUserID + IDLength + 1
    33  	PosOfPasswdNickname     = PosOfPasswdRealName + RealNameSize
    34  	PosOfPasswdPassword     = PosOfPasswdNickname + NicknameSize
    35  	PosOfPasswdUserFlag     = 1 + PosOfPasswdPassword + PasswordLength
    36  	PosOfPasswdUserLevel    = 4 + PosOfPasswdUserFlag + 4
    37  	PosOfPasswdNumLoginDays = PosOfPasswdUserLevel + 4
    38  	PosOfPasswdNumPosts     = PosOfPasswdNumLoginDays + 4
    39  	PosOfPasswdFirstLogin   = PosOfPasswdNumPosts + 4
    40  	PosOfPasswdLastLogin    = PosOfPasswdFirstLogin + 4
    41  	PosOfPasswdLastHost     = PosOfPasswdLastLogin + 4
    42  	PosOfPasswdMoney        = PosOfPasswdLastHost + IPV4Length + 1
    43  	PosOfPasswdEmail        = 4 + PosOfPasswdMoney + 4
    44  	PosOfPasswdAddress      = PosOfPasswdEmail + EmailSize
    45  	PosOfPasswdJustify      = PosOfPasswdAddress + AddressSize
    46  	PosOfPasswdOver18       = 3 + PosOfPasswdJustify + RegistrationLength + 1
    47  	PosOfPasswdPagerUIType  = PosOfPasswdOver18 + 1
    48  	PosOfPasswdPager        = PosOfPasswdPagerUIType + 1
    49  	PosOfPasswdInvisible    = PosOfPasswdPager + 1
    50  	PosOfPasswdExMailBox    = 2 + PosOfPasswdInvisible + 1
    51  
    52  	PosOfPasswdCareer        = 4 + PosOfPasswdExMailBox + 4
    53  	PosOfPasswdRole          = 20 + 4 + 44 + PosOfPasswdCareer + CareerSize
    54  	PosOfPasswdLastSeen      = PosOfPasswdRole + 4
    55  	PosOfPasswdTimeSetAngel  = PosOfPasswdLastSeen + 4
    56  	PosOfPasswdTimePlayAngel = PosOfPasswdTimeSetAngel + 4
    57  
    58  	PosOfPasswdLastSong  = PosOfPasswdTimePlayAngel + 4
    59  	PosOfPasswdLoginView = PosOfPasswdLastSong + 4
    60  
    61  	PosOfPasswdLawCounter = 1 + 1 + PosOfPasswdLoginView + 4
    62  	PosOfPasswdFiveWin    = PosOfPasswdLawCounter + 2
    63  	PosOfPasswdFiveLose   = PosOfPasswdFiveWin + 2
    64  	PosOfPasswdFiveTie    = PosOfPasswdFiveLose + 2
    65  	PosOfPasswdChcWin     = PosOfPasswdFiveTie + 2
    66  	PosOfPasswdChcLose    = PosOfPasswdChcWin + 2
    67  	PosOfPasswdChcTie     = PosOfPasswdChcLose + 2
    68  	PosOfPasswdConn6Win   = PosOfPasswdChcTie + 2
    69  	PosOfPasswdConn6Lose  = PosOfPasswdConn6Win + 2
    70  	PosOfPasswdConn6Tie   = PosOfPasswdConn6Lose + 2
    71  	PosOfPasswdGoWin      = 2 + PosOfPasswdConn6Tie + 2
    72  	PosOfPasswdGoLose     = PosOfPasswdGoWin + 2
    73  	PosOfPasswdGoTie      = PosOfPasswdGoLose + 2
    74  	PosOfPasswdDarkWin    = PosOfPasswdGoTie + 2
    75  	PosOfPasswdDarkLose   = PosOfPasswdDarkWin + 2
    76  	PosOfPasswdUaVersion  = PosOfPasswdDarkLose + 2
    77  
    78  	PosOfPasswdSignature = PosOfPasswdUaVersion + 1
    79  	PosOfPasswdBadPost   = 1 + PosOfPasswdSignature + 1
    80  	PosOfPasswdDarkTie   = PosOfPasswdBadPost + 1
    81  	PosOfPasswdMyAngel   = PosOfPasswdDarkTie + 2
    82  
    83  	PosOfPasswdChessEloRating    = 1 + PosOfPasswdMyAngel + IDLength + 1
    84  	PosOfPasswdWithMe            = PosOfPasswdChessEloRating + 2
    85  	PosOfPasswdTimeRemoveBadPost = PosOfPasswdWithMe + 4
    86  	PosOfPasswdTimeViolateLaw    = PosOfPasswdTimeRemoveBadPost + 4
    87  )
    88  
    89  // https://github.com/ptt/pttbbs/blob/master/include/pttstruct.h
    90  
    91  type GameScore struct {
    92  	Win  uint16
    93  	Lose uint16
    94  	Tie  uint16
    95  }
    96  
    97  type Userec struct {
    98  	Version  uint32 // Magic Number
    99  	userID   string // 使用者帳號,或稱使用者 ID
   100  	realName string // 真實姓名
   101  	nickname string // 暱稱
   102  	password string // 密碼,預設為 crypt, 不同版本實作可能不同
   103  
   104  	userFlag     uint32 // 習慣
   105  	UserLevel    uint32 // 權限
   106  	numLoginDays uint32
   107  	numPosts     uint32
   108  	firstLogin   time.Time
   109  	lastLogin    time.Time
   110  	lastHost     string
   111  	money        int32
   112  
   113  	Email   string
   114  	Address string
   115  	Justify string
   116  
   117  	Over18      bool
   118  	PagerUIType uint8
   119  	Pager       uint8
   120  	Invisible   bool
   121  
   122  	ExMailBox uint32
   123  
   124  	Career        string
   125  	Role          uint32
   126  	LastSeen      time.Time
   127  	TimeSetAngel  time.Time
   128  	TimePlayAngel time.Time
   129  
   130  	LastSong  time.Time
   131  	LoginView uint32
   132  
   133  	ViolateLaw   uint16
   134  	Five         GameScore
   135  	ChineseChess GameScore
   136  	Conn6        GameScore
   137  	GoChess      GameScore
   138  	DarkChess    GameScore
   139  	UaVersion    uint8 // User Agreement Version
   140  
   141  	Signature         uint8
   142  	BadPost           uint8
   143  	MyAngel           string
   144  	ChessEloRating    uint16
   145  	WithMe            uint32
   146  	TimeRemoveBadPost time.Time
   147  	TimeViolateLaw    time.Time
   148  }
   149  
   150  func (u *Userec) HashedPassword() string {
   151  	return u.password
   152  }
   153  
   154  // VerifyPassword will check user's password is OK. it will return null
   155  // when OK and error when there are something wrong
   156  func (u *Userec) VerifyPassword(password string) error {
   157  	res, err := crypt.Fcrypt([]byte(password), []byte(u.password[:2]))
   158  	if err != nil {
   159  		return err
   160  	}
   161  	str := strings.Trim(string(res), "\x00")
   162  	// log.Println("res", str, err, []byte(str), []byte(u.Password))
   163  
   164  	if str != u.password {
   165  		return fmt.Errorf("password incorrect")
   166  	}
   167  	return nil
   168  }
   169  
   170  func (u *Userec) UserID() string { return u.userID }
   171  
   172  // Nickname return a string for user's nickname, this string may change
   173  // depend on user's mood, return empty string if this bbs system do not support
   174  func (u *Userec) Nickname() string { return u.nickname }
   175  
   176  // RealName return a string for user's real name, this string may not be changed
   177  // return empty string if this bbs system do not support
   178  func (u *Userec) RealName() string { return u.realName }
   179  
   180  // NumLoginDays return how many days this have been login since account created.
   181  func (u *Userec) NumLoginDays() int { return int(u.numLoginDays) }
   182  
   183  // NumPosts return how many posts this user has posted.
   184  func (u *Userec) NumPosts() int { return int(u.numPosts) }
   185  
   186  // Money return the money this user have.
   187  func (u *Userec) Money() int { return int(u.money) }
   188  
   189  func (u *Userec) LastLogin() time.Time {
   190  	return u.lastLogin
   191  }
   192  
   193  func (u *Userec) LastHost() string {
   194  	return u.lastHost
   195  }
   196  
   197  // UserFlag return user setting.
   198  // uint32, see https://github.com/ptt/pttbbs/blob/master/include/uflags.h
   199  func (u *Userec) UserFlag() uint32 {
   200  	return u.userFlag
   201  }
   202  
   203  func OpenUserecFile(filename string) ([]*Userec, error) {
   204  	file, err := os.Open(filename)
   205  	if err != nil {
   206  		log.Println(err)
   207  		return nil, err
   208  	}
   209  
   210  	ret := []*Userec{}
   211  
   212  	for {
   213  		buf := make([]byte, 512)
   214  		_, err := file.Read(buf)
   215  		// log.Println(len, buf, err)
   216  		if err == io.EOF {
   217  			break
   218  		}
   219  
   220  		f, err := UnmarshalUserec(buf)
   221  		if err != nil {
   222  			return nil, err
   223  		}
   224  		ret = append(ret, f)
   225  		// log.Println(f.Filename)
   226  
   227  	}
   228  
   229  	return ret, nil
   230  
   231  }
   232  
   233  func UnmarshalUserec(data []byte) (*Userec, error) {
   234  	user := &Userec{}
   235  	user.Version = binary.LittleEndian.Uint32(data[PosOfPasswdVersion : PosOfPasswdVersion+4])
   236  	user.userID = newStringFormCString(data[PosOfPasswdUserID : PosOfPasswdUserID+IDLength+1])
   237  	user.realName = newStringFormBig5UAOCString(data[PosOfPasswdRealName : PosOfPasswdRealName+RealNameSize])
   238  	user.nickname = newStringFormBig5UAOCString(data[PosOfPasswdNickname : PosOfPasswdNickname+NicknameSize])
   239  	user.password = newStringFormCString(data[PosOfPasswdPassword : PosOfPasswdPassword+PasswordLength])
   240  
   241  	user.userFlag = binary.LittleEndian.Uint32(data[PosOfPasswdUserFlag : PosOfPasswdUserFlag+4])
   242  	user.UserLevel = binary.LittleEndian.Uint32(data[PosOfPasswdUserLevel : PosOfPasswdUserLevel+4])
   243  	user.numLoginDays = binary.LittleEndian.Uint32(data[PosOfPasswdNumLoginDays : PosOfPasswdNumLoginDays+4])
   244  	user.numPosts = binary.LittleEndian.Uint32(data[PosOfPasswdNumPosts : PosOfPasswdNumPosts+4])
   245  	user.firstLogin = time.Unix(int64(binary.LittleEndian.Uint32(data[PosOfPasswdFirstLogin:PosOfPasswdFirstLogin+4])), 0)
   246  	user.lastLogin = time.Unix(int64(binary.LittleEndian.Uint32(data[PosOfPasswdLastLogin:PosOfPasswdLastLogin+4])), 0)
   247  	user.lastHost = newStringFormCString(data[PosOfPasswdLastHost : PosOfPasswdLastHost+IPV4Length+1])
   248  
   249  	user.money = int32(binary.LittleEndian.Uint32(data[PosOfPasswdMoney : PosOfPasswdMoney+4]))
   250  
   251  	user.Email = newStringFormBig5UAOCString(data[PosOfPasswdEmail : PosOfPasswdEmail+EmailSize])
   252  	user.Address = newStringFormBig5UAOCString(data[PosOfPasswdAddress : PosOfPasswdAddress+AddressSize])
   253  	user.Justify = newStringFormBig5UAOCString(data[PosOfPasswdJustify : PosOfPasswdJustify+RegistrationLength+1])
   254  
   255  	user.Over18 = data[PosOfPasswdOver18] != 0
   256  	user.PagerUIType = data[PosOfPasswdPagerUIType]
   257  	user.Pager = data[PosOfPasswdPager]
   258  	user.Invisible = data[PosOfPasswdInvisible] != 0
   259  
   260  	user.ExMailBox = binary.LittleEndian.Uint32(data[PosOfPasswdExMailBox : PosOfPasswdExMailBox+4])
   261  
   262  	user.Career = newStringFormBig5UAOCString(data[PosOfPasswdCareer : PosOfPasswdCareer+CareerSize])
   263  	user.Role = binary.LittleEndian.Uint32(data[PosOfPasswdRole : PosOfPasswdRole+4])
   264  	user.LastSeen = time.Unix(int64(binary.LittleEndian.Uint32(data[PosOfPasswdLastSeen:PosOfPasswdLastSeen+4])), 0)
   265  	user.TimeSetAngel = time.Unix(int64(binary.LittleEndian.Uint32(data[PosOfPasswdTimeSetAngel:PosOfPasswdTimeSetAngel+4])), 0)
   266  	user.TimePlayAngel = time.Unix(int64(binary.LittleEndian.Uint32(data[PosOfPasswdTimePlayAngel:PosOfPasswdTimePlayAngel+4])), 0)
   267  
   268  	user.LastSong = time.Unix(int64(binary.LittleEndian.Uint32(data[PosOfPasswdLastSong:PosOfPasswdLastSong+4])), 0)
   269  	user.LoginView = binary.LittleEndian.Uint32(data[PosOfPasswdLoginView : PosOfPasswdLoginView+4])
   270  	user.ViolateLaw = binary.LittleEndian.Uint16(data[PosOfPasswdLawCounter : PosOfPasswdLawCounter+2])
   271  
   272  	user.Five.Win = binary.LittleEndian.Uint16(data[PosOfPasswdFiveWin : PosOfPasswdFiveWin+2])
   273  	user.Five.Lose = binary.LittleEndian.Uint16(data[PosOfPasswdFiveLose : PosOfPasswdFiveLose+2])
   274  	user.Five.Tie = binary.LittleEndian.Uint16(data[PosOfPasswdFiveTie : PosOfPasswdFiveTie+2])
   275  
   276  	user.ChineseChess.Win = binary.LittleEndian.Uint16(data[PosOfPasswdChcWin : PosOfPasswdChcWin+2])
   277  	user.ChineseChess.Lose = binary.LittleEndian.Uint16(data[PosOfPasswdChcLose : PosOfPasswdChcLose+2])
   278  	user.ChineseChess.Tie = binary.LittleEndian.Uint16(data[PosOfPasswdChcTie : PosOfPasswdChcTie+2])
   279  
   280  	user.Conn6.Win = binary.LittleEndian.Uint16(data[PosOfPasswdConn6Win : PosOfPasswdConn6Win+2])
   281  	user.Conn6.Lose = binary.LittleEndian.Uint16(data[PosOfPasswdConn6Lose : PosOfPasswdConn6Lose+2])
   282  	user.Conn6.Tie = binary.LittleEndian.Uint16(data[PosOfPasswdConn6Tie : PosOfPasswdConn6Tie+2])
   283  
   284  	user.GoChess.Win = binary.LittleEndian.Uint16(data[PosOfPasswdGoWin : PosOfPasswdGoWin+2])
   285  	user.GoChess.Lose = binary.LittleEndian.Uint16(data[PosOfPasswdGoLose : PosOfPasswdGoLose+2])
   286  	user.GoChess.Tie = binary.LittleEndian.Uint16(data[PosOfPasswdGoTie : PosOfPasswdGoTie+2])
   287  
   288  	user.DarkChess.Win = binary.LittleEndian.Uint16(data[PosOfPasswdDarkWin : PosOfPasswdDarkWin+2])
   289  	user.DarkChess.Lose = binary.LittleEndian.Uint16(data[PosOfPasswdDarkLose : PosOfPasswdDarkLose+2])
   290  	user.UaVersion = data[PosOfPasswdUaVersion]
   291  
   292  	user.Signature = data[PosOfPasswdSignature]
   293  	user.BadPost = data[PosOfPasswdBadPost]
   294  	user.DarkChess.Tie = binary.LittleEndian.Uint16(data[PosOfPasswdDarkTie : PosOfPasswdDarkTie+2])
   295  	user.MyAngel = newStringFormCString(data[PosOfPasswdMyAngel : PosOfPasswdMyAngel+IDLength+1+1])
   296  
   297  	user.ChessEloRating = binary.LittleEndian.Uint16(data[PosOfPasswdChessEloRating : PosOfPasswdChessEloRating+2])
   298  	user.WithMe = binary.LittleEndian.Uint32(data[PosOfPasswdWithMe : PosOfPasswdWithMe+4])
   299  	user.TimeRemoveBadPost = time.Unix(int64(binary.LittleEndian.Uint32(data[PosOfPasswdTimeRemoveBadPost:PosOfPasswdTimeRemoveBadPost+4])), 0)
   300  	user.TimeViolateLaw = time.Unix(int64(binary.LittleEndian.Uint32(data[PosOfPasswdTimeViolateLaw:PosOfPasswdTimeViolateLaw+4])), 0)
   301  
   302  	return user, nil
   303  }
   304  
   305  func (u *Userec) MarshalBinary() ([]byte, error) {
   306  	ret := make([]byte, 512)
   307  
   308  	binary.LittleEndian.PutUint32(ret[PosOfPasswdVersion:PosOfPasswdVersion+4], u.Version)
   309  	copy(ret[PosOfPasswdUserID:PosOfPasswdUserID+IDLength+1], utf8ToBig5UAOString(u.userID))
   310  	copy(ret[PosOfPasswdRealName:PosOfPasswdRealName+RealNameSize], utf8ToBig5UAOString(u.realName))
   311  	copy(ret[PosOfPasswdNickname:PosOfPasswdNickname+NicknameSize], utf8ToBig5UAOString(u.nickname))
   312  	copy(ret[PosOfPasswdPassword:PosOfPasswdPassword+PasswordLength], utf8ToBig5UAOString(u.password))
   313  
   314  	binary.LittleEndian.PutUint32(ret[PosOfPasswdUserFlag:PosOfPasswdUserFlag+4], u.userFlag)
   315  	binary.LittleEndian.PutUint32(ret[PosOfPasswdUserLevel:PosOfPasswdUserLevel+4], u.UserLevel)
   316  	binary.LittleEndian.PutUint32(ret[PosOfPasswdNumLoginDays:PosOfPasswdNumLoginDays+4], u.numLoginDays)
   317  	binary.LittleEndian.PutUint32(ret[PosOfPasswdNumPosts:PosOfPasswdNumPosts+4], u.numPosts)
   318  	binary.LittleEndian.PutUint32(ret[PosOfPasswdFirstLogin:PosOfPasswdFirstLogin+4], uint32(u.firstLogin.Unix()))
   319  	binary.LittleEndian.PutUint32(ret[PosOfPasswdLastLogin:PosOfPasswdLastLogin+4], uint32(u.lastLogin.Unix()))
   320  	copy(ret[PosOfPasswdLastHost:PosOfPasswdLastHost+IPV4Length+1], utf8ToBig5UAOString(u.lastHost))
   321  	binary.LittleEndian.PutUint32(ret[PosOfPasswdMoney:PosOfPasswdMoney+4], uint32(u.money))
   322  
   323  	copy(ret[PosOfPasswdEmail:PosOfPasswdEmail+EmailSize], utf8ToBig5UAOString(u.Email))
   324  	copy(ret[PosOfPasswdAddress:PosOfPasswdAddress+AddressSize], utf8ToBig5UAOString(u.Address))
   325  	copy(ret[PosOfPasswdJustify:PosOfPasswdJustify+RegistrationLength], utf8ToBig5UAOString(u.Justify))
   326  
   327  	if u.Over18 {
   328  		ret[PosOfPasswdOver18] = 1
   329  	} else {
   330  		ret[PosOfPasswdOver18] = 0
   331  	}
   332  
   333  	ret[PosOfPasswdPagerUIType] = u.PagerUIType
   334  	ret[PosOfPasswdPager] = u.Pager
   335  
   336  	if u.Invisible {
   337  		ret[PosOfPasswdInvisible] = 1
   338  	} else {
   339  		ret[PosOfPasswdInvisible] = 0
   340  	}
   341  
   342  	binary.LittleEndian.PutUint32(ret[PosOfPasswdExMailBox:PosOfPasswdExMailBox+4], u.ExMailBox)
   343  
   344  	copy(ret[PosOfPasswdCareer:PosOfPasswdCareer+CareerSize], utf8ToBig5UAOString(u.Career))
   345  
   346  	binary.LittleEndian.PutUint32(ret[PosOfPasswdLastSeen:PosOfPasswdLastSeen+4], uint32(u.LastSeen.Unix()))
   347  	binary.LittleEndian.PutUint32(ret[PosOfPasswdTimeSetAngel:PosOfPasswdTimeSetAngel+4], uint32(u.TimeSetAngel.Unix()))
   348  	binary.LittleEndian.PutUint32(ret[PosOfPasswdTimePlayAngel:PosOfPasswdTimePlayAngel+4], uint32(u.TimePlayAngel.Unix()))
   349  
   350  	binary.LittleEndian.PutUint32(ret[PosOfPasswdLastSong:PosOfPasswdLastSong+4], uint32(u.LastSong.Unix()))
   351  	binary.LittleEndian.PutUint32(ret[PosOfPasswdLoginView:PosOfPasswdLoginView+4], u.LoginView)
   352  	binary.LittleEndian.PutUint16(ret[PosOfPasswdLawCounter:PosOfPasswdLawCounter+2], u.ViolateLaw)
   353  
   354  	binary.LittleEndian.PutUint16(ret[PosOfPasswdFiveWin:PosOfPasswdFiveWin+2], u.Five.Win)
   355  	binary.LittleEndian.PutUint16(ret[PosOfPasswdFiveLose:PosOfPasswdFiveLose+2], u.Five.Lose)
   356  	binary.LittleEndian.PutUint16(ret[PosOfPasswdFiveTie:PosOfPasswdFiveTie+2], u.Five.Tie)
   357  
   358  	binary.LittleEndian.PutUint16(ret[PosOfPasswdChcWin:PosOfPasswdChcWin+2], u.ChineseChess.Win)
   359  	binary.LittleEndian.PutUint16(ret[PosOfPasswdChcLose:PosOfPasswdChcLose+2], u.ChineseChess.Lose)
   360  	binary.LittleEndian.PutUint16(ret[PosOfPasswdChcTie:PosOfPasswdChcTie+2], u.ChineseChess.Tie)
   361  
   362  	binary.LittleEndian.PutUint16(ret[PosOfPasswdConn6Win:PosOfPasswdConn6Win+2], u.Conn6.Win)
   363  	binary.LittleEndian.PutUint16(ret[PosOfPasswdConn6Lose:PosOfPasswdConn6Lose+2], u.Conn6.Lose)
   364  	binary.LittleEndian.PutUint16(ret[PosOfPasswdConn6Tie:PosOfPasswdConn6Tie+2], u.Conn6.Tie)
   365  
   366  	binary.LittleEndian.PutUint16(ret[PosOfPasswdGoWin:PosOfPasswdGoWin+2], u.GoChess.Win)
   367  	binary.LittleEndian.PutUint16(ret[PosOfPasswdGoLose:PosOfPasswdGoLose+2], u.GoChess.Lose)
   368  	binary.LittleEndian.PutUint16(ret[PosOfPasswdGoTie:PosOfPasswdGoTie+2], u.GoChess.Tie)
   369  
   370  	binary.LittleEndian.PutUint16(ret[PosOfPasswdDarkWin:PosOfPasswdDarkWin+2], u.DarkChess.Win)
   371  	binary.LittleEndian.PutUint16(ret[PosOfPasswdDarkLose:PosOfPasswdDarkLose+2], u.DarkChess.Lose)
   372  	ret[PosOfPasswdUaVersion] = u.UaVersion
   373  
   374  	ret[PosOfPasswdSignature] = u.Signature
   375  	ret[PosOfPasswdBadPost] = u.BadPost
   376  	binary.LittleEndian.PutUint16(ret[PosOfPasswdDarkTie:PosOfPasswdDarkTie+2], u.DarkChess.Tie)
   377  	copy(ret[PosOfPasswdMyAngel:PosOfPasswdMyAngel+IDLength+1+1], utf8ToBig5UAOString(u.MyAngel))
   378  
   379  	binary.LittleEndian.PutUint16(ret[PosOfPasswdChessEloRating:PosOfPasswdChessEloRating+2], u.ChessEloRating)
   380  	binary.LittleEndian.PutUint32(ret[PosOfPasswdWithMe:PosOfPasswdWithMe+4], u.WithMe)
   381  	binary.LittleEndian.PutUint32(ret[PosOfPasswdTimeRemoveBadPost:PosOfPasswdTimeRemoveBadPost+4], uint32(u.TimeRemoveBadPost.Unix()))
   382  	binary.LittleEndian.PutUint32(ret[PosOfPasswdTimeViolateLaw:PosOfPasswdTimeViolateLaw+4], uint32(u.TimeViolateLaw.Unix()))
   383  
   384  	return ret, nil
   385  }