Skip to content
Snippets Groups Projects
Commit ab7689e4 authored by Bensong Liu's avatar Bensong Liu
Browse files

move git repo

parent ab717bc3
No related branches found
No related tags found
No related merge requests found
Showing
with 1389 additions and 0 deletions
.idea
.vscode
.DS_store
*.zip
# cs161-proj2
This is a repo for `$GOPATH/src/cs161\_proj2`.
DO NOT put documents or binary here. Use git submodule wisely.
## Proposed Design Doc (Subject to change)
> CS161 Project2 Design Doc ----Yinuo Zhang
- Section 1: Implementation
Storing client info: Each client structure contains all the keys and a filetable(explained later) for the client, and it is encrypted on the DS, this is our TCB if this is compromised, then we lost all the security.
To encrypt the client struct, we use Authenticated Encryption, first generate a symmetric key and a sign key based on the user password, which is high in entropy (as said in the document), this is done using HKFD. Then we encrypt the struct, which has been turned into byte array via json, and sign on the encryption using the sign key via HMAC function, this is believed to be secure as long as the underline hash function is secure. This way we both achieve confidentiality and integrity of our basic client info.
Storing client file: We do not rely on the username, for each file, we build a file structure list, each structure contains the UUID of the current piece of file(each piece receives its own random UUID) the symmetric key and signkey that is used specifically to encrypt and sign this piece of file, and the filename.
To encrypt each piece of file, we first we generate a UUID which is completely random using new_UUID function, then generate its symmetric and signkey using random generator, and then using Authenticated Encryption to encrypt this piece of file data, and store the resulting signature and encrypted data inside another shell structure in the DS, with the entry of its UUID. This ensures both confidentiality and integrity, and this also achieves IND-CPA since each piece is encrypted using its own random IV and own random keys, this also ensures forward-secrecy since when we rewrite any piece of the file, or even reload it, the keys and IVs are completely different and independent of previous ones.
To maintain the file info, we build a filetable in each user struct, which is a map between file name and the file structure list, this grants owner all info to decrypt, since we can rely on the security of user struct, the security of each file necessarily follows.
To append is easy, we encrypt this piece of file and get back its file structure, and we can just append it to the file structure list. The decryption for any file is just the combined data collected from each file structure in the list corresponds to that file name.
Sharing the file takes two steps, first build a file-transfer structure, which contains all UUIDS, all symmetric keys and sign keys from all file structures in the list corresponds to the file name, then randomly generate another symmetric key and sign key to encrypt this file-transfer structure using Authenticated Encryption just as above to ensure confidentiality and Integrity, then randomly generate a UUID to store this file-transfer structure in the DS in that entry, finally append the symmetric key, sign key and UUID altogether into a data array, encrypt this array using public key encryption (recipient’s PubKey) and DIgital signature (sender’s signKey) this again ensures confidentiality and integrity. Finally turn the encrypted data and signature into a string, which is our magic_string. Upon reception, the recipient can decrypt and check for integrity on the message, then use the decrypted data (which includes symmetric key, sign key, UUID) to do another symmetric key decryption and also checks for integrity for the file-transfer struct stored in the DS, then it just copies the value pairs this structure and add them to his own file structure list under the name of filename (invented by him/her self) The recipient never knows the filename of senders since we never encrypt or send this info.
To revoke, the user simply first loads the file data, then traverse the file structure list under that filename and delete every entry given by every UUID in every file structure, this will remove the encrypted data of every single piece of file entirely. Then to recreate it, just call StoreFile again with the previous loaded data, since each Storing will create completely new and independent random keys and UUIDs, this again ensures forward secrecy and makes our scheme IND_CPA. For the users previously shared with this file, since all entries are deleted, they cannot load any piece of file using their previous UUID, even in the worst case where the same content is again inserted into the same entry (with negligible probability) the user still cannot read that file since the keys to decrypt that file is also re-picked from random)
- Section 2: Attack Models
Attack on client info: since the client info is stored in DS, we cannot rely on obscurity by hiding the UUID of our client, since the attacker can always do a brute force search on the DS and check for every UUIDs, therefore, we encrypt and authenticate the client info so that the attacker cannot break the scheme even though the UUID is known to the attacker.
Attack on file info: again, we cannot use filename to generate UUIDs and keys, since filename is often low in entropy, the attacker can use a precomputed dictionary of keys to perform the attack. therefore, we need to generate completely random keys and UUIDs for each file piece. Since our file is always seperated into pieces of info, and each piece is encrypted with its own random keys and signatures and IVs, we thus gauarantee that even if one piece of the file is compromised, the attacker cannot use that info to decrypt other piece of the file. The attacker cannot even change any piece of the file, since even if one piece of file is changed, its own signature will not match, which will shutdown the entire decryption process. Therefore, we not only achieve integrity but also prevent the attacker from doing a piece-by-piece attack on the user files.
Attack on file sharing: We first encrypt a file transfer struct, which is a copy of the owner’s file structure list corresponds to certain file name, and store is just like a regular file (using the same authenticated encryption method) in the DS, therefore, any attack model breaking this scheme will also break the security of our previous discussed user file security, and a simple reduction shows that this file transfer struct is secure. The keys and UUIDs to find and decrypt this transfer struct is send via public key encryption and verified using a digital signature, so the attacker cannot decrypt the keys and UUIDs as long as the underlying public key encryption method is secure, the attacker also cannot forge signature so that the receiver can always verify the authenticity of the message string. Therefore, the file sharing system is secure also.
package proj2
// You MUST NOT change what you import. If you add ANY additional
// imports it will break the autograder, and we will be Very Upset.
import (
// You neet to add with
// go get github.com/nweaver/cs161-p2/userlib
"github.com/nweaver/cs161-p2/userlib"
// Life is much easier with json: You are
// going to want to use this so you can easily
// turn complex structures into strings etc...
"encoding/json"
// Likewise useful for debugging etc
"encoding/hex"
// UUIDs are generated right based on the crypto RNG
// so lets make life easier and use those too...
//
// You need to add with "go get github.com/google/uuid"
"github.com/google/uuid"
// Useful for debug messages, or string manipulation for datastore keys
"strings"
// Want to import errors
"errors"
// optional
// strconv
// if you are looking for fmt, we don't give you fmt, but you can use userlib.DebugMsg
// see someUsefulThings() below
)
// This serves two purposes: It shows you some useful primitives and
// it suppresses warnings for items not being imported
func someUsefulThings() {
// Creates a random UUID
f := uuid.New()
userlib.DebugMsg("UUID as string:%v", f.String())
// Example of writing over a byte of f
f[0] = 10
userlib.DebugMsg("UUID as string:%v", f.String())
// takes a sequence of bytes and renders as hex
h := hex.EncodeToString([]byte("fubar"))
userlib.DebugMsg("The hex: %v", h)
// Marshals data into a JSON representation
// Will actually work with go structures as well
d, _ := json.Marshal(f)
userlib.DebugMsg("The json data: %v", string(d))
var g uuid.UUID
json.Unmarshal(d, &g)
userlib.DebugMsg("Unmashaled data %v", g.String())
// This creates an error type
userlib.DebugMsg("Creation of error %v", errors.New(strings.ToTitle("This is an error")))
// And a random RSA key. In this case, ignoring the error
// return value
var pk userlib.PKEEncKey
var sk userlib.PKEDecKey
pk, sk, _ = userlib.PKEKeyGen()
userlib.DebugMsg("Key is %v, %v", pk, sk)
}
// Helper function: Takes the first 16 bytes and
// converts it into the UUID type
func bytesToUUID(data []byte) (ret uuid.UUID) {
for x := range ret {
ret[x] = data[x]
}
return
}
//the structure definition of a file key for one whole file
type FileKeys struct {
Filename string
SymmetricKey []byte
Signkey []byte
FileUUID uuid.UUID
}
// The structure definition for a file record
type File struct {
Filename string
FileUUID uuid.UUID
SymmetricKey []byte
Signkey []byte
FileSlice int
}
// The structure definition for a user record
type User struct {
Username string
Pubk userlib.PKEEncKey
Privk userlib.PKEDecKey
Signk userlib.DSSignKey
Vrfyk userlib.DSVerifyKey
Filemap map[string](FileKeys)
Password string
// You can add other fields here if you want...
// Note for JSON to marshal/unmarshal, the fields need to
// be public (start with a capital letter)
}
type EncPair struct {
Cipher []byte
Signature []byte
}
// This creates a user. It will only be called once for a user
// (unless the keystore and datastore are cleared during testing purposes)
// It should store a copy of the userdata, suitably encrypted, in the
// datastore and should store the user's public key in the keystore.
// The datastore may corrupt or completely erase the stored
// information, but nobody outside should be able to get at the stored
// User data: the name used in the datastore should not be guessable
// without also knowing the password and username.
// You are not allowed to use any global storage other than the
// keystore and the datastore functions in the userlib library.
// You can assume the user has a STRONG password
func InitUser(username string, password string) (userdataptr *User, err error) {
if(len(username)==0){ //invalid username
return nil, errors.New("Bad username")
}
var userdata User
userdata.Username = username
userdata.Password = password
userdata.Pubk, userdata.Privk, err = userlib.PKEKeyGen()
if err != nil {
return
}
userdata.Signk, userdata.Vrfyk, err = userlib.DSKeyGen()
if err != nil {
return
}
userdata.Filemap = make(map[string](FileKeys))
err = userlib.KeystoreSet(username+"Pubk", userdata.Pubk)
if err != nil {
return
}
err = userlib.KeystoreSet(username+"Vrfyk", userdata.Vrfyk)
if err != nil {
return
}
return UpdateUser(userdata)
}
func UpdateUser(userdata User) (userdataptr *User, err error) {
password := userdata.Password
namebyte := []byte(userdata.Username)
uuid_root_namespace, _ := uuid.FromBytes(make([]byte, 16))
user_UUID := uuid.NewMD5(uuid_root_namespace, namebyte)
encpairdata, _ := AEencUser(userdata, password)
userlib.DatastoreDelete(user_UUID)
userlib.DatastoreSet(user_UUID, encpairdata)
return &userdata, nil
}
func AEencUser(userdata User, password string) (encpairdata []byte, err error) {
data, _ := json.Marshal(userdata)
iv := userlib.RandomBytes(userlib.AESBlockSize)
passwordbyte := []byte(password)
passwordbyte = append(passwordbyte, passwordbyte...)
namebyte := []byte(userdata.Username)
if (len(passwordbyte)<=16){ //extend passwordbyte to 16 bytes
if(len(passwordbyte)==0){
passwordbyte = make([]byte, 16)
} else {
offset := 16/len(passwordbyte)
for i:=0; i<offset+1; i++ {
passwordbyte = append(passwordbyte, passwordbyte...)
}
passwordbyte = passwordbyte[:16]
}
}
symmetricKey, _ := userlib.HMACEval(passwordbyte[:16], namebyte)
symmetricKey = symmetricKey[:16]
encrypteddata := userlib.SymEnc(symmetricKey, iv, data)
signkey, _ := userlib.HMACEval(symmetricKey, namebyte)
signkey = signkey[:16]
signature, _ := userlib.HMACEval(signkey, data)
var pair EncPair
pair.Cipher = encrypteddata
pair.Signature = signature
encpairdata, _ = json.Marshal(pair)
return encpairdata, nil
}
func AEdpyUser(encpairdata []byte, username string, password string) (userdata User, err error) {
var encpair EncPair
json.Unmarshal(encpairdata, &encpair)
encrypteddata := encpair.Cipher
signature := encpair.Signature
passwordbyte := []byte(password)
passwordbyte = append(passwordbyte, passwordbyte...)
namebyte := []byte(username)
if (len(passwordbyte)<=16){ //extend passwordbyte to 16 bytes
if(len(passwordbyte)==0){
passwordbyte = make([]byte, 16)
} else {
offset := 16/len(passwordbyte)
for i:=0; i<offset+1; i++ {
passwordbyte = append(passwordbyte, passwordbyte...)
}
passwordbyte = passwordbyte[:16]
}
}
symmetricKey, _ := userlib.HMACEval(passwordbyte[:16], namebyte)
symmetricKey = symmetricKey[:16]
if(len(encrypteddata)<userlib.AESBlockSize){
return userdata, errors.New("size of data to small")
}
data := userlib.SymDec(symmetricKey, encrypteddata)
signkey, _ := userlib.HMACEval(symmetricKey, namebyte)
signkey = signkey[:16]
current_signature, _ := userlib.HMACEval(signkey, data)
ok := userlib.HMACEqual(current_signature, signature)
if (!ok) {
err = errors.New("UserData corrupted")
return userdata, err
}
json.Unmarshal(data, &userdata)
return userdata, nil
}
func AEencFile(data []byte) (encpairdata []byte, symmetricKey []byte, signkey []byte) {
iv := userlib.RandomBytes(userlib.AESBlockSize)
symmetricKey = userlib.RandomBytes(16)
encfiledata := userlib.SymEnc(symmetricKey, iv, data)
signkey = userlib.RandomBytes(16)
signature, _ := userlib.HMACEval(signkey, data)
var pair EncPair
pair.Cipher = encfiledata
pair.Signature = signature
encpairdata, _ = json.Marshal(pair)
return
}
func AEdpyFile(file File) (filedata []byte, err error) {
F_UUid := file.FileUUID
encpairdata, ok := userlib.DatastoreGet(F_UUid)
if (!ok) {
err = errors.New("No such piece of file found in DS")
return filedata, err
}
var encpair EncPair
json.Unmarshal(encpairdata, &encpair)
encrypteddata := encpair.Cipher
signature := encpair.Signature
if(len(encrypteddata)<userlib.AESBlockSize){
return filedata, errors.New("size of data to small")
}
data := userlib.SymDec(file.SymmetricKey, encrypteddata)
current_signature, _ := userlib.HMACEval(file.Signkey, data)
ok = userlib.HMACEqual(current_signature, signature)
if (!ok) {
err = errors.New("FileData corrupted")
return filedata, err
}
filedata = data
return filedata, nil
}
// This fetches the user information from the Datastore. It should
// fail with an error if the user/password is invalid, or if the user
// data was corrupted, or if the user can't be found.
func GetUser(username string, password string) (userdataptr *User, err error) {
var userdata User
userdataptr = &userdata
namebyte := []byte(username)
uuid_root_namespace, _ := uuid.FromBytes(make([]byte, 16))
user_UUID := uuid.NewMD5(uuid_root_namespace, namebyte)
if err != nil {
return nil, errors.New("fuck google uuid!")
}
encpairdata, ok := userlib.DatastoreGet(user_UUID)
if (!ok) {
err = errors.New("Not found in DS")
return nil, err
}
userdata, err = AEdpyUser(encpairdata, username, password)
return userdataptr, err
}
// This stores a file in the datastore.
//
// The name of the file should NOT be revealed to the datastore!
func (userdata *User) StoreFile(filename string, data []byte) {
if(len(filename)==0){
return
}
var currentuser User
currentuser = *userdata
encpairdata, symmetricKey, signkey := AEencFile(data)
new_UUID := uuid.New()
userlib.DatastoreSet(new_UUID, encpairdata)
var file File
file.Filename = filename
file.FileUUID = new_UUID
file.SymmetricKey = symmetricKey
file.Signkey = signkey
var filelist []File
filelist = append(filelist, file)
var newkeys FileKeys
transferstruct := ToTransferStruct(filelist)
transferdata, _ := json.Marshal(transferstruct)
encpairdata, symmetricKey, signkey = AEencFile(transferdata)
newkeys.SymmetricKey = symmetricKey
newkeys.Signkey = signkey
new_UUID = uuid.New() // TODO: Confirm that this logic is right.
newkeys.FileUUID = new_UUID
userlib.DatastoreSet(new_UUID, encpairdata)
(currentuser.Filemap)[filename] = newkeys
UpdateUser(currentuser)
return
}
// This adds on to an existing file.
//
// Append should be efficient, you shouldn't rewrite or reencrypt the
// existing file, but only whatever additional information and
// metadata you need.
func (userdata *User) AppendFile(filename string, data []byte) (err error) {
if(len(filename)==0){
return errors.New("Bad filename")
}
var currentuser User
currentuser = *userdata
filekeys, ok := (currentuser.Filemap)[filename]
if (!ok) {
err = errors.New("File Not found in DS for this user")
return err
}
symmetricKey := filekeys.SymmetricKey
signkey := filekeys.Signkey
new_UUID := filekeys.FileUUID
transferdata, err := AEdpyTransferFile(new_UUID, symmetricKey, signkey)
if (err != nil) {
return err
}
var filelist []File
var transferstruct FileTransfer
json.Unmarshal(transferdata, &transferstruct)
fileuuids := transferstruct.FileUUIDs
symmetrickeys := transferstruct.SymmetricKeys
signkeys := transferstruct.Signkeys
for i := 0; i < len(fileuuids); i++ {
var file File
file.Filename = filename
file.FileUUID = fileuuids[i]
file.SymmetricKey = symmetrickeys[i]
file.Signkey = signkeys[i]
filelist = append(filelist, file)
}
var encpairdata []byte
encpairdata, symmetricKey, signkey = AEencFile(data)
new_UUID = uuid.New()
userlib.DatastoreSet(new_UUID, encpairdata)
var file File
file.Filename = filename
file.FileUUID = new_UUID
file.SymmetricKey = symmetricKey
file.Signkey = signkey
filelist = append(filelist, file)
transferstruct = ToTransferStruct(filelist)
transferdata, _ = json.Marshal(transferstruct)
iv := userlib.RandomBytes(userlib.AESBlockSize)
encfiledata := userlib.SymEnc(filekeys.SymmetricKey, iv, transferdata)
signature, _ := userlib.HMACEval(filekeys.Signkey, transferdata)
var pair EncPair
pair.Cipher = encfiledata
pair.Signature = signature
encpairdata, _ = json.Marshal(pair)
userlib.DatastoreSet(filekeys.FileUUID, encpairdata)
UpdateUser(currentuser)
return nil
}
// This loads a file from the Datastore.
//
// It should give an error if the file is corrupted in any way.
func (userdata *User) LoadFile(filename string) (data []byte, err error) {
if(len(filename)==0){
return nil, errors.New("Bad filename")
}
var currentuser User
currentuser = *userdata
filekeys, ok := (currentuser.Filemap)[filename]
if (!ok) {
err = errors.New("File Not found in DS for this user")
return data, err
}
symmetricKey := filekeys.SymmetricKey
signkey := filekeys.Signkey
new_UUID := filekeys.FileUUID
transferdata, err := AEdpyTransferFile(new_UUID, symmetricKey, signkey)
if (err != nil) {
return data, err
}
var transferstruct FileTransfer
json.Unmarshal(transferdata, &transferstruct)
fileuuids := transferstruct.FileUUIDs
symmetrickeys := transferstruct.SymmetricKeys
signkeys := transferstruct.Signkeys
for i := 0; i < len(fileuuids); i++ {
var file File
file.Filename = filename
file.FileUUID = fileuuids[i]
file.SymmetricKey = symmetrickeys[i]
file.Signkey = signkeys[i]
var curr_filedata []byte
curr_filedata, err = AEdpyFile(file)
if (err != nil) {
return data, err
}
data = append(data, curr_filedata...)
}
return data, nil
}
// The structure definition for a file-transfer record
type FileTransfer struct {
FileUUIDs []uuid.UUID
SymmetricKeys []([]byte)
Signkeys []([]byte)
}
func ToTransferStruct(filelist []File) (transferstruct FileTransfer) {
for _, file := range filelist {
transferstruct.FileUUIDs = append(transferstruct.FileUUIDs, file.FileUUID)
transferstruct.SymmetricKeys = append(transferstruct.SymmetricKeys, file.SymmetricKey)
transferstruct.Signkeys = append(transferstruct.Signkeys, file.Signkey)
}
return transferstruct
}
// You may want to define what you actually want to pass as a
// sharingRecord to serialized/deserialize in the data store.
type sharingRecord struct {
}
func AEPubencKey(recipient_PubK userlib.PKEEncKey, user_SignK userlib.DSSignKey, data []byte) (encpairdata []byte, err error) {
encfiledata, err := userlib.PKEEnc(recipient_PubK, data)
if (err != nil) {
return encpairdata, err
}
signature, err := userlib.DSSign(user_SignK, encfiledata)
if (err != nil) {
return encpairdata, err
}
var pair EncPair
pair.Cipher = encfiledata
pair.Signature = signature
encpairdata, _ = json.Marshal(pair)
return encpairdata, nil
}
func AEPubdpyKey(recipient_PrivK userlib.PKEDecKey, user_VrfyK userlib.DSVerifyKey, encpairdata []byte) (filedata []byte, err error) {
var encpair EncPair
json.Unmarshal(encpairdata, &encpair)
encrypteddata := encpair.Cipher
signature := encpair.Signature
err = userlib.DSVerify(user_VrfyK, encrypteddata, signature)
if (err != nil) {
err = errors.New("Verfication for magic failed")
return filedata, err
}
filedata, err = userlib.PKEDec(recipient_PrivK, encrypteddata)
if (err != nil) {
return filedata, err
}
return filedata, nil
}
// This creates a sharing record, which is a key pointing to something
// in the datastore to share with the recipient.
// This enables the recipient to access the encrypted file as well
// for reading/appending.
// Note that neither the recipient NOR the datastore should gain any
// information about what the sender calls the file. Only the
// recipient can access the sharing record, and only the recipient
// should be able to know the sender.
func (userdata *User) ShareFile(filename string, recipient string) (
magic_string string, err error) {
if(len(filename)==0){
return magic_string, errors.New("Bad filename")
}
var currentuser User
currentuser = *userdata
recipient_PubK, ok := userlib.KeystoreGet(recipient + "Pubk")
if (!ok) {
err = errors.New("No such user")
return magic_string, err
}
filekeys, good := (currentuser.Filemap)[filename]
if (!good) {
err = errors.New("File Not found in DS for this user to Share")
return magic_string, err
}
var message []byte
uuid_byte, _ := json.Marshal(filekeys.FileUUID)
message = append(message, filekeys.SymmetricKey...)
message = append(message, filekeys.Signkey...)
message = append(message, uuid_byte...)
var encpairdata []byte
encpairdata, err = AEPubencKey(recipient_PubK, currentuser.Signk, message)
if (err != nil) {
return magic_string, err
}
magic_string = hex.EncodeToString(encpairdata)
return magic_string, nil
}
func AEdpyTransferFile(uuid uuid.UUID, symmetricKey []byte, signkey []byte) (filedata []byte, err error) {
encpairdata, ok := userlib.DatastoreGet(uuid)
if (!ok) {
err = errors.New("No such piece of transfer info found in DS")
return filedata, err
}
var encpair EncPair
json.Unmarshal(encpairdata, &encpair)
encrypteddata := encpair.Cipher
signature := encpair.Signature
if(len(encrypteddata)<userlib.AESBlockSize){
return filedata, errors.New("size of data to small")
}
data := userlib.SymDec(symmetricKey, encrypteddata)
current_signature, _ := userlib.HMACEval(signkey, data)
ok = userlib.HMACEqual(current_signature, signature)
if (!ok) {
err = errors.New("FileData corrupted")
return filedata, err
}
filedata = data
return filedata, nil
}
// Note recipient's filename can be different from the sender's filename.
// The recipient should not be able to discover the sender's view on
// what the filename even is! However, the recipient must ensure that
// it is authentically from the sender.
func (userdata *User) ReceiveFile(filename string, sender string,
magic_string string) (err error) {
if(len(filename)==0){
return errors.New("Bad filename to receive")
}
var currentuser User
currentuser = *userdata
encpairdata, err := hex.DecodeString(magic_string)
if (err != nil) {
return err
}
user_VrfyK, ok := userlib.KeystoreGet(sender + "Vrfyk")
if (!ok) {
err = errors.New("Sender is not found")
return err
}
var message []byte
message, err = AEPubdpyKey(currentuser.Privk, user_VrfyK, encpairdata)
if (err != nil) {
return err
}
symmetricKey := message[:16]
signkey := message[16:32]
uuid_byte := message[32:]
var new_UUID uuid.UUID
json.Unmarshal(uuid_byte, &new_UUID)
var filekeys FileKeys
filekeys.SymmetricKey = symmetricKey
filekeys.Signkey = signkey
filekeys.FileUUID = new_UUID
(currentuser.Filemap)[filename] = filekeys
UpdateUser(currentuser)
_, err = userdata.LoadFile(filename)
if(err!=nil){
return err
}
return nil
}
// Removes access for all others.
func (userdata *User) RevokeFile(filename string) (err error) {
var currentuser User
currentuser = *userdata
filekeys, ok := (currentuser.Filemap)[filename]
if (!ok) {
err = errors.New("File Not found in DS for this user")
return err
}
symmetricKey := filekeys.SymmetricKey
signkey := filekeys.Signkey
new_UUID := filekeys.FileUUID
transferdata, err := AEdpyTransferFile(new_UUID, symmetricKey, signkey)
if (err != nil) {
return err
}
var data []byte
var transferstruct FileTransfer
json.Unmarshal(transferdata, &transferstruct)
fileuuids := transferstruct.FileUUIDs
symmetrickeys := transferstruct.SymmetricKeys
signkeys := transferstruct.Signkeys
for i := 0; i < len(fileuuids); i++ {
var file File
file.Filename = filename
file.FileUUID = fileuuids[i]
file.SymmetricKey = symmetrickeys[i]
file.Signkey = signkeys[i]
var curr_filedata []byte
curr_filedata, err = AEdpyFile(file)
if (err != nil) {
return err
}
data = append(data, curr_filedata...)
userlib.DatastoreDelete(file.FileUUID)
}
userlib.DatastoreDelete(filekeys.FileUUID)
userdata.StoreFile(filename, data)
return nil
}
This diff is collapsed.
1:alice:fubar
1:bob:foobar
0:alice:fu
0::
0:a:fubar
0:bob:fubar
0: \n\toauisdhvfusdahfvsaodugfvhdasouifvhdsaoifhdsaoigvhadsoighasdoighohasdhgfoidsah:
0:bob\n:foobar
0:bob:foobar\r
0:bob:foobar
0:bob:\000foobar
0:bob:foobar doifvhbasdoigfbdsaouigbdsaoigfhbdsaoifhgsdahoifhgdsaoifhvsdoiadfhdsaoifhsadoifhsadoifh
0:bob:foobar
0:bob:foobar
0:bob:foobar中
0:bob中:foobar
0:bob :foobar
1:alice:fubar
1:bob:foobar
1:longlonglonglongUserTest:
1:longlonglonglong:
1:longlonglonglong :asovbaouigbouiedhbgouiasbhfvouisadhbgvoiawdhbvodsiagvhdslakgvhdsalkgvhdsaoligvhdsaoigfvhdsaoifvghdsaoivghhdsa
1:unicode用户名测试:同样是unicode的密码
0:alice:fuckyou
0::
0::fuckyoudoabfuoaidshgb
0::这是密码
1:file1.log:/b\nfuck again
0:file:/b\000sadoiuvbdafiuvbvbsdaiuvbdoiusavnsouvbernogvnarsogbasd
0::/b
0::/b1
1:file2.log:/b
1:file2.log:/b\n
1:file1.log:/b
1:file1.log:/bfuckyou\nfuck again
1:file2.log:/b\n
# new testcase
0:shit:
0:file1.log :
0:file1.log\n:
0:file1.lo:
0:file:
0:\t:
# testcase from StoreFile
1:dfoubvuodfagbaouedisgbfodaibndaosibvnfdsaoibvnfdsaojgvbdsaouigvbadsoigvbasdoigvbdsaoigvasdoighasoighadsoipgvhasdoigvhbdsaoigvhbasdoipgvhnasd:/b
1:file1.log:/bfuckyou
1:file2.log:/b
1:file3.log:/b这个文件是unicode的。\n他还有两行。
1:/usr/include/rlib/string.hpp:/b/*\n *\n * string.hpp string process utility.\n * Recolic Keghart <root@recolic.net>\n * MIT License\n *\n */\n\n#ifndef R_STRING_HPP\n#define R_STRING_HPP\n\n#include <rlib/require/cxx14>\n#include <rlib/class_decorator.hpp>\n#include <rlib/sys/os.hpp>\n\n#include <array>\n#include <vector>\n#include <string>\n#include <cstdarg>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <stdexcept>\n#include <sstream>\n#include <type_traits>\n\nnamespace rlib {\n // literals_format, format_string, stringformat\n namespace impl {\n#ifndef RLIB_MINGW_DISABLE_TLS\n//#if RLIB_CXX_STD < 2017\n// Intel C++ compiler has a pending bug for `thread_local inline` variable.\n thread_local extern stdstringstream to_string_by_sstream_ss; \n thread_local extern stdstringstream _format_string_helper_ss;\n//#else\n// thread_local inline stdstringstream to_string_by_sstream_ss; \n// thread_local inline stdstringstream _format_string_helper_ss;\n//#endif\n#endif\n template <typename VarT>\n stdstring to_string_by_sstream(VarT &thing) {\n#ifdef RLIB_MINGW_DISABLE_TLS // Fix intel C++ bug https//software.intel.com/en-us/forums/intel-c-compiler/topic/784136\n // Also fix mingw bug. But much slower!\n stdstringstream ss;\n#else\n auto &ss = to_string_by_sstream_ss;\n ss.str(stdstring());\n#endif\n ss << thing;\n return ss.str();\n }\n\n template<typename... Args>\n stdstring _format_string_helper(const stdstring &fmt, Args... args) {\n#ifdef RLIB_MINGW_DISABLE_TLS // Fix intel C++ bug https//software.intel.com/en-us/forums/intel-c-compiler/topic/784136\n stdstringstream ss;\n#else\n auto &ss = _format_string_helper_ss; // cached stringstream is much quicker.\n ss.str(stdstring());\n#endif\n size_t pos = 0, prev_pos = 0;\n stdarray<stdstring, sizeof...(args)> argsArr{to_string_by_sstream(args) ...};\n size_t current_used_arg = 0;\n bool discovered_escape_char = false;\n while((pos = fmt.find(\"{}\", pos)) != stdstringnpos) {\n if(pos != 0 && fmt[pos-1] == '\\\\') {\n // Invalid hit.\n discovered_escape_char = true;\n pos += 2;\n }\n else {\n stdstring cutted_tmp_str = fmt.substr(prev_pos, pos - prev_pos);\n if(discovered_escape_char) {\n // hand-written string replace. Replace `\\{}` to `{}`.\n size_t pos = 0;\n while((pos = cutted_tmp_str.find(\"\\\\{}\", pos)) != stdstringnpos) {\n cutted_tmp_str.erase(pos, 1);\n pos += 2;\n }\n }\n ss << cutted_tmp_str << argsArr[current_used_arg];\n pos += 2;\n prev_pos = pos;\n ++current_used_arg;\n }\n }\n ss << fmt.substr(prev_pos);\n return ss.str();\n }\n template<typename... Args>\n inline stdstring format_string(const stdstring &fmt, Args... args) {\n return _format_string_helper(fmt, args...);\n }\n template<>\n inline stdstring format_string<>(const stdstring &fmt) {\n return fmt;\n }\n \n /*\n template<class MetaFmtArr, typename... Args>\n constexpr stdstring format_string_meta(Args... args) {\n return (args + ...);\n }*/\n }\n\n // format_string_c, stringcformat\n namespace impl {\n inline char *_format_string_c_helper(const char *fmt, ...)\n {\n int n;\n int size = stdstrlen(fmt);\n char *p, *np;\n va_list ap;\n\n if ((p = (char *)malloc(size)) == NULL)\n throw stdruntime_error(\"malloc returns null.\");\n\n while (1) {\n va_start(ap, fmt);\n n = vsnprintf(p, size, fmt, ap);\n va_end(ap);\n\n if (n < 0)\n throw stdruntime_error(\"vsnprintf returns \" + stdto_string(n));\n if (n < size)\n return p;\n\n size = n + 1;\n\n if ((np = (char *)realloc (p, size)) == NULL) {\n free(p);\n throw stdruntime_error(\"make_message realloc failed.\");\n } else {\n p = np;\n }\n }\n }\n template<typename... Args>\n stdstring format_string_c(const stdstring &fmt, Args... args)\n {\n char *res = _format_string_c_helper(fmt.c_str(), args ...);\n stdstring s = res;\n free(res);\n return s;\n }\n }\n\n class string public stdstring {\n public\n using stdstringstring;\n string() stdstring() {}\n string(const stdstring &s) stdstring(s) {}\n string(stdstring &&s) stdstring(stdforward<stdstring>(s)) {}\n\n private\n template <typename T> struct as_helper {};\n template <typename T>\n T as(as_helper<T>) const {\n if(empty()) return T();\n return T(*this);\n }\n stdstring as(as_helper<stdstring>) const {\n return stdmove(*this);\n }\n rlibstring as(as_helper<rlibstring>) const {\n return stdmove(*this);\n }\n char as(as_helper<char>) const {\n if(size() > 1)\n throw stdinvalid_argument(\"Can not convert rlibstring to char size() > 1.\");\n return size() == 0 ? '\\0' *cbegin();\n }\n unsigned char as(as_helper<unsigned char>) const {\n return static_cast<unsigned char>(as<char>());\n }\n bool as(as_helper<bool>) const {\n if(*this == \"true\") {\n return true;\n }\n else if(*this == \"false\") {\n return false;\n }\n // Nothing is slower than throw(); Just test more cases...\n else if(*this == \"1\" || *this == \"True\" || *this == \"TRUE\") {\n return true;\n }\n else if(*this == \"0\" || *this == \"False\" || *this == \"FALSE\") {\n return false;\n }\n throw stdinvalid_argument(\"Can not convert rlibstring to bool. Not matching any template.\");\n }\n\n#define RLIB_IMPL_GEN_AS_NUMERIC(type, std_conv) \\\n type as(as_helper<type>) const { \\\n if(empty()) return 0; \\\n return stdstd_conv(*this); \\\n }\n\n RLIB_IMPL_GEN_AS_NUMERIC(int, stoi)\n RLIB_IMPL_GEN_AS_NUMERIC(long, stol)\n RLIB_IMPL_GEN_AS_NUMERIC(unsigned long, stoul)\n RLIB_IMPL_GEN_AS_NUMERIC(unsigned long long, stoull)\n RLIB_IMPL_GEN_AS_NUMERIC(long long, stoll)\n RLIB_IMPL_GEN_AS_NUMERIC(float, stof)\n RLIB_IMPL_GEN_AS_NUMERIC(double, stod)\n RLIB_IMPL_GEN_AS_NUMERIC(long double, stold)\n\n#define RLIB_IMPL_GEN_AS_ALIAS(new_type, old_type) \\\n new_type as(as_helper<new_type>) const { \\\n return static_cast<new_type>(as<old_type>()); \\\n }\n\n RLIB_IMPL_GEN_AS_ALIAS(unsigned int, unsigned long)\n RLIB_IMPL_GEN_AS_ALIAS(unsigned short, unsigned long)\n //RLIB_IMPL_GEN_AS_ALIAS(uint8_t, unsigned long)\n\n RLIB_IMPL_GEN_AS_ALIAS(short, int)\n //RLIB_IMPL_GEN_AS_ALIAS(int8_t, int)\n\n public\n template <typename T>\n T as() const {\n return stdforward<T>(as(as_helper<T>()));\n }\n\n stdvector<string> split(const char &divider = ' ') const {\n const string &toSplit = *this;\n stdvector<string> buf;\n size_t curr = 0, prev = 0;\n while((curr = toSplit.find(divider, curr)) != stdstringnpos) {\n buf.push_back(toSplit.substr(prev, curr - prev));\n ++curr; // skip divider\n prev = curr;\n }\n buf.push_back(toSplit.substr(prev));\n return buf;\n }\n stdvector<string> split(const stdstring &divider) const {\n const string &toSplit = *this;\n stdvector<string> buf;\n size_t curr = 0, prev = 0;\n while((curr = toSplit.find(divider, curr)) != stdstringnpos) {\n buf.push_back(toSplit.substr(prev, curr - prev));\n curr += divider.size(); // skip divider\n prev = curr;\n }\n buf.push_back(toSplit.substr(prev));\n return buf;\n }\n template <typename T>\n stdvector<T> split_as(const char &divider = ' ') const {\n const string &toSplit = *this;\n stdvector<T> buf;\n size_t curr = 0, prev = 0;\n while((curr = toSplit.find(divider, curr)) != stdstringnpos) {\n buf.push_back(string(toSplit.substr(prev, curr - prev)).as<T>());\n ++curr; // skip divider\n prev = curr;\n }\n buf.push_back(string(toSplit.substr(prev)).as<T>());\n return stdmove(buf);\n }\n template <typename T>\n stdvector<T> split_as(const stdstring &divider) const {\n const string &toSplit = *this;\n stdvector<T> buf;\n size_t curr = 0, prev = 0;\n while((curr = toSplit.find(divider, curr)) != stdstringnpos) {\n buf.push_back(string(toSplit.substr(prev, curr - prev)).as<T>());\n curr += divider.size(); // skip divider\n prev = curr;\n }\n buf.push_back(string(toSplit.substr(prev)).as<T>());\n return stdmove(buf);\n }\n\n template <class ForwardIterable>\n string &join(const ForwardIterable &buffer) {\n join(buffer.cbegin(), buffer.cend());\n return *this;\n }\n template <class ForwardIterator>\n string &join(ForwardIterator begin, ForwardIterator end) {\n const string &toJoin = *this;\n stdstring result;\n for(ForwardIterator iter = begin; iter != end; ++iter) {\n if(iter != begin)\n result += toJoin;\n result += *iter;\n }\n return operator=(stdmove(result));\n }\n\n string &strip() {\n strip(\" \\t\\r\\n\");\n return *this;\n }\n template <typename CharOrStringOrView>\n string &strip(const CharOrStringOrView &stripped) {\n size_t len = size();\n size_t begin = find_first_not_of(stripped);\n\n if(begin == stdstringnpos) {\n clear();\n return *this;\n }\n size_t end = find_last_not_of(stripped);\n\n erase(end + 1, len - end - 1);\n erase(0, begin);\n return *this;\n }\n\n string &replace(const stdstring &from, const stdstring &to) {\n size_t _;\n replace(from, to, _);\n return *this;\n }\n string &replace(const stdstring &from, const stdstring &to, size_t &out_times) {\n if(from.empty())\n return *this;\n size_t start_pos = 0;\n size_t times = 0;\n while((start_pos = find(from, start_pos)) != stdstringnpos)\n {\n ++times;\n this->stdstringreplace(start_pos, from.length(), to);\n start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'\n }\n out_times = times;\n return *this;\n }\n string &replace_once(const stdstring &from, const stdstring &to) {\n bool _;\n replace_once(from, to, _);\n return *this;\n }\n string &replace_once(const stdstring &from, const stdstring &to, bool &out_replaced) {\n size_t start_pos = find(from);\n if(start_pos == stdstringnpos) {\n out_replaced = false;\n }\n else {\n this->stdstringreplace(start_pos, from.length(), to);\n out_replaced = true;\n }\n return *this;\n }\n\n template <typename... Args>\n string &format(Args... args) {\n return operator=(stdmove(implformat_string(*this, args ...)));\n }\n template <typename... Args>\n string &cformat(Args... args) {\n return operator=(stdmove(implformat_string_c(*this, args ...)));\n }\n };\n\n namespace impl {\n struct formatter {\n formatter(const stdstring &fmt) fmt(fmt) {}\n formatter(stdstring &&fmt) fmt(fmt) {}\n template <typename... Args>\n stdstring operator ()(Args... args) {\n return stdmove(rlibimplformat_string(fmt, args ...));\n }\n\n stdstring fmt;\n };\n }\n\n namespace literals {\n inline implformatter operator \"\" _format (const char *str, size_t) {\n return implformatter(str);\n }\n inline rlibstring operator \"\" _rs (const char *str, size_t len) {\n return rlibstring(str, len);\n }\n }\n}\n\n#endif\n
0::/bfuckyou
1:.:/b
# NOTE: YOU MUST USE THE FOLLOWING COMMAND
./gen.py alice.StoreFile alice.StoreFile | sed 's/_.*:= //g'
1:dfoubvuodfagbaouedisgbfodaibndaosibvnfdsaoibvnfdsaojgvbdsaouigvbadsoigvbasdoigvbdsaoigvasdoighasoighadsoipgvhasdoigvhbdsaoigvhbasdoipgvhnasd:/b
1:file1.log:/bfuckyou
1:file2.log:/b
1:file3.log:/b这个文件是unicode的。\n他还有两行。
1:/usr/include/rlib/string.hpp:/b/*\n *\n * string.hpp string process utility.\n * Recolic Keghart <root@recolic.net>\n * MIT License\n *\n */\n\n#ifndef R_STRING_HPP\n#define R_STRING_HPP\n\n#include <rlib/require/cxx14>\n#include <rlib/class_decorator.hpp>\n#include <rlib/sys/os.hpp>\n\n#include <array>\n#include <vector>\n#include <string>\n#include <cstdarg>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <stdexcept>\n#include <sstream>\n#include <type_traits>\n\nnamespace rlib {\n // literals_format, format_string, stringformat\n namespace impl {\n#ifndef RLIB_MINGW_DISABLE_TLS\n//#if RLIB_CXX_STD < 2017\n// Intel C++ compiler has a pending bug for `thread_local inline` variable.\n thread_local extern stdstringstream to_string_by_sstream_ss; \n thread_local extern stdstringstream _format_string_helper_ss;\n//#else\n// thread_local inline stdstringstream to_string_by_sstream_ss; \n// thread_local inline stdstringstream _format_string_helper_ss;\n//#endif\n#endif\n template <typename VarT>\n stdstring to_string_by_sstream(VarT &thing) {\n#ifdef RLIB_MINGW_DISABLE_TLS // Fix intel C++ bug https//software.intel.com/en-us/forums/intel-c-compiler/topic/784136\n // Also fix mingw bug. But much slower!\n stdstringstream ss;\n#else\n auto &ss = to_string_by_sstream_ss;\n ss.str(stdstring());\n#endif\n ss << thing;\n return ss.str();\n }\n\n template<typename... Args>\n stdstring _format_string_helper(const stdstring &fmt, Args... args) {\n#ifdef RLIB_MINGW_DISABLE_TLS // Fix intel C++ bug https//software.intel.com/en-us/forums/intel-c-compiler/topic/784136\n stdstringstream ss;\n#else\n auto &ss = _format_string_helper_ss; // cached stringstream is much quicker.\n ss.str(stdstring());\n#endif\n size_t pos = 0, prev_pos = 0;\n stdarray<stdstring, sizeof...(args)> argsArr{to_string_by_sstream(args) ...};\n size_t current_used_arg = 0;\n bool discovered_escape_char = false;\n while((pos = fmt.find(\"{}\", pos)) != stdstringnpos) {\n if(pos != 0 && fmt[pos-1] == '\\\\') {\n // Invalid hit.\n discovered_escape_char = true;\n pos += 2;\n }\n else {\n stdstring cutted_tmp_str = fmt.substr(prev_pos, pos - prev_pos);\n if(discovered_escape_char) {\n // hand-written string replace. Replace `\\{}` to `{}`.\n size_t pos = 0;\n while((pos = cutted_tmp_str.find(\"\\\\{}\", pos)) != stdstringnpos) {\n cutted_tmp_str.erase(pos, 1);\n pos += 2;\n }\n }\n ss << cutted_tmp_str << argsArr[current_used_arg];\n pos += 2;\n prev_pos = pos;\n ++current_used_arg;\n }\n }\n ss << fmt.substr(prev_pos);\n return ss.str();\n }\n template<typename... Args>\n inline stdstring format_string(const stdstring &fmt, Args... args) {\n return _format_string_helper(fmt, args...);\n }\n template<>\n inline stdstring format_string<>(const stdstring &fmt) {\n return fmt;\n }\n \n /*\n template<class MetaFmtArr, typename... Args>\n constexpr stdstring format_string_meta(Args... args) {\n return (args + ...);\n }*/\n }\n\n // format_string_c, stringcformat\n namespace impl {\n inline char *_format_string_c_helper(const char *fmt, ...)\n {\n int n;\n int size = stdstrlen(fmt);\n char *p, *np;\n va_list ap;\n\n if ((p = (char *)malloc(size)) == NULL)\n throw stdruntime_error(\"malloc returns null.\");\n\n while (1) {\n va_start(ap, fmt);\n n = vsnprintf(p, size, fmt, ap);\n va_end(ap);\n\n if (n < 0)\n throw stdruntime_error(\"vsnprintf returns \" + stdto_string(n));\n if (n < size)\n return p;\n\n size = n + 1;\n\n if ((np = (char *)realloc (p, size)) == NULL) {\n free(p);\n throw stdruntime_error(\"make_message realloc failed.\");\n } else {\n p = np;\n }\n }\n }\n template<typename... Args>\n stdstring format_string_c(const stdstring &fmt, Args... args)\n {\n char *res = _format_string_c_helper(fmt.c_str(), args ...);\n stdstring s = res;\n free(res);\n return s;\n }\n }\n\n class string public stdstring {\n public\n using stdstringstring;\n string() stdstring() {}\n string(const stdstring &s) stdstring(s) {}\n string(stdstring &&s) stdstring(stdforward<stdstring>(s)) {}\n\n private\n template <typename T> struct as_helper {};\n template <typename T>\n T as(as_helper<T>) const {\n if(empty()) return T();\n return T(*this);\n }\n stdstring as(as_helper<stdstring>) const {\n return stdmove(*this);\n }\n rlibstring as(as_helper<rlibstring>) const {\n return stdmove(*this);\n }\n char as(as_helper<char>) const {\n if(size() > 1)\n throw stdinvalid_argument(\"Can not convert rlibstring to char size() > 1.\");\n return size() == 0 ? '\\0' *cbegin();\n }\n unsigned char as(as_helper<unsigned char>) const {\n return static_cast<unsigned char>(as<char>());\n }\n bool as(as_helper<bool>) const {\n if(*this == \"true\") {\n return true;\n }\n else if(*this == \"false\") {\n return false;\n }\n // Nothing is slower than throw(); Just test more cases...\n else if(*this == \"1\" || *this == \"True\" || *this == \"TRUE\") {\n return true;\n }\n else if(*this == \"0\" || *this == \"False\" || *this == \"FALSE\") {\n return false;\n }\n throw stdinvalid_argument(\"Can not convert rlibstring to bool. Not matching any template.\");\n }\n\n#define RLIB_IMPL_GEN_AS_NUMERIC(type, std_conv) \\\n type as(as_helper<type>) const { \\\n if(empty()) return 0; \\\n return stdstd_conv(*this); \\\n }\n\n RLIB_IMPL_GEN_AS_NUMERIC(int, stoi)\n RLIB_IMPL_GEN_AS_NUMERIC(long, stol)\n RLIB_IMPL_GEN_AS_NUMERIC(unsigned long, stoul)\n RLIB_IMPL_GEN_AS_NUMERIC(unsigned long long, stoull)\n RLIB_IMPL_GEN_AS_NUMERIC(long long, stoll)\n RLIB_IMPL_GEN_AS_NUMERIC(float, stof)\n RLIB_IMPL_GEN_AS_NUMERIC(double, stod)\n RLIB_IMPL_GEN_AS_NUMERIC(long double, stold)\n\n#define RLIB_IMPL_GEN_AS_ALIAS(new_type, old_type) \\\n new_type as(as_helper<new_type>) const { \\\n return static_cast<new_type>(as<old_type>()); \\\n }\n\n RLIB_IMPL_GEN_AS_ALIAS(unsigned int, unsigned long)\n RLIB_IMPL_GEN_AS_ALIAS(unsigned short, unsigned long)\n //RLIB_IMPL_GEN_AS_ALIAS(uint8_t, unsigned long)\n\n RLIB_IMPL_GEN_AS_ALIAS(short, int)\n //RLIB_IMPL_GEN_AS_ALIAS(int8_t, int)\n\n public\n template <typename T>\n T as() const {\n return stdforward<T>(as(as_helper<T>()));\n }\n\n stdvector<string> split(const char &divider = ' ') const {\n const string &toSplit = *this;\n stdvector<string> buf;\n size_t curr = 0, prev = 0;\n while((curr = toSplit.find(divider, curr)) != stdstringnpos) {\n buf.push_back(toSplit.substr(prev, curr - prev));\n ++curr; // skip divider\n prev = curr;\n }\n buf.push_back(toSplit.substr(prev));\n return buf;\n }\n stdvector<string> split(const stdstring &divider) const {\n const string &toSplit = *this;\n stdvector<string> buf;\n size_t curr = 0, prev = 0;\n while((curr = toSplit.find(divider, curr)) != stdstringnpos) {\n buf.push_back(toSplit.substr(prev, curr - prev));\n curr += divider.size(); // skip divider\n prev = curr;\n }\n buf.push_back(toSplit.substr(prev));\n return buf;\n }\n template <typename T>\n stdvector<T> split_as(const char &divider = ' ') const {\n const string &toSplit = *this;\n stdvector<T> buf;\n size_t curr = 0, prev = 0;\n while((curr = toSplit.find(divider, curr)) != stdstringnpos) {\n buf.push_back(string(toSplit.substr(prev, curr - prev)).as<T>());\n ++curr; // skip divider\n prev = curr;\n }\n buf.push_back(string(toSplit.substr(prev)).as<T>());\n return stdmove(buf);\n }\n template <typename T>\n stdvector<T> split_as(const stdstring &divider) const {\n const string &toSplit = *this;\n stdvector<T> buf;\n size_t curr = 0, prev = 0;\n while((curr = toSplit.find(divider, curr)) != stdstringnpos) {\n buf.push_back(string(toSplit.substr(prev, curr - prev)).as<T>());\n curr += divider.size(); // skip divider\n prev = curr;\n }\n buf.push_back(string(toSplit.substr(prev)).as<T>());\n return stdmove(buf);\n }\n\n template <class ForwardIterable>\n string &join(const ForwardIterable &buffer) {\n join(buffer.cbegin(), buffer.cend());\n return *this;\n }\n template <class ForwardIterator>\n string &join(ForwardIterator begin, ForwardIterator end) {\n const string &toJoin = *this;\n stdstring result;\n for(ForwardIterator iter = begin; iter != end; ++iter) {\n if(iter != begin)\n result += toJoin;\n result += *iter;\n }\n return operator=(stdmove(result));\n }\n\n string &strip() {\n strip(\" \\t\\r\\n\");\n return *this;\n }\n template <typename CharOrStringOrView>\n string &strip(const CharOrStringOrView &stripped) {\n size_t len = size();\n size_t begin = find_first_not_of(stripped);\n\n if(begin == stdstringnpos) {\n clear();\n return *this;\n }\n size_t end = find_last_not_of(stripped);\n\n erase(end + 1, len - end - 1);\n erase(0, begin);\n return *this;\n }\n\n string &replace(const stdstring &from, const stdstring &to) {\n size_t _;\n replace(from, to, _);\n return *this;\n }\n string &replace(const stdstring &from, const stdstring &to, size_t &out_times) {\n if(from.empty())\n return *this;\n size_t start_pos = 0;\n size_t times = 0;\n while((start_pos = find(from, start_pos)) != stdstringnpos)\n {\n ++times;\n this->stdstringreplace(start_pos, from.length(), to);\n start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'\n }\n out_times = times;\n return *this;\n }\n string &replace_once(const stdstring &from, const stdstring &to) {\n bool _;\n replace_once(from, to, _);\n return *this;\n }\n string &replace_once(const stdstring &from, const stdstring &to, bool &out_replaced) {\n size_t start_pos = find(from);\n if(start_pos == stdstringnpos) {\n out_replaced = false;\n }\n else {\n this->stdstringreplace(start_pos, from.length(), to);\n out_replaced = true;\n }\n return *this;\n }\n\n template <typename... Args>\n string &format(Args... args) {\n return operator=(stdmove(implformat_string(*this, args ...)));\n }\n template <typename... Args>\n string &cformat(Args... args) {\n return operator=(stdmove(implformat_string_c(*this, args ...)));\n }\n };\n\n namespace impl {\n struct formatter {\n formatter(const stdstring &fmt) fmt(fmt) {}\n formatter(stdstring &&fmt) fmt(fmt) {}\n template <typename... Args>\n stdstring operator ()(Args... args) {\n return stdmove(rlibimplformat_string(fmt, args ...));\n }\n\n stdstring fmt;\n };\n }\n\n namespace literals {\n inline implformatter operator \"\" _format (const char *str, size_t) {\n return implformatter(str);\n }\n inline rlibstring operator \"\" _rs (const char *str, size_t len) {\n return rlibstring(str, len);\n }\n }\n}\n\n#endif\n
0::/bfuckyou
1:.:/b
#!/usr/bin/fish
eval ./fuck_unused_var.py (seq 30 43) (seq 60 73) 1
#!/usr/bin/python3
import sys
shits = ["_py_gen_data" + i for i in sys.argv[1:]]
head = ['_' for i in shits]
print(', '.join(head) + ' = ' + ', '.join(shits))
#!/usr/bin/python3
import sys
funcname = sys.argv[1]
dataf = sys.argv[2]
with open(dataf) as f:
cont = f.read()
everything = []
t, f = [], []
try:
n = int(sys.argv[3])
except:
n = 0
for line in cont.split('\n'):
'1:user:password'
ar = line.split(':')
if len(ar) < 2:
continue
if ar[0] == '1':
everything = [ar] + everything
elif ar[0] == '0':
everything = everything + [ar]
for ar in everything:
errVarName = '_py_gen_err' + str(n)
tf, args = ar[0], ar[1:]
args = ['"{}"'.format(arg) for arg in args]
args = ['[]byte("{})'.format(quoted_arg[3:]) if quoted_arg[:3] == '"/b' else quoted_arg for quoted_arg in args]
should_ = 'success' if tf == '1' else 'fail'
print(' _, {} := {}({}) // Should {}.'.format(errVarName, funcname, ', '.join(args), should_))
n += 1
if tf == '1':
t.append(errVarName)
else:
f.append(errVarName)
if t != []:
print(' if {} != nil {{'.format(' != nil || '.join(t)))
print(' t.Error("Test {} failed.")'.format(funcname))
print(' }')
if f != []:
print(' if {} == nil {{'.format(' == nil || '.join(f)))
print(' t.Error("Test {} failed.")'.format(funcname))
print(' }')
#!/usr/bin/python3
import sys
funcname = sys.argv[1]
dataf = sys.argv[2]
with open(dataf) as f:
cont = f.read()
everything = []
t, f = [], []
try:
n = int(sys.argv[3])
except:
n = 0
try:
noReorder = sys.argv[4] == 'no-reorder'
except:
noReorder = False
for line in cont.split('\n'):
'1:user:password'
ar = line.split(':')
if len(ar) < 2:
continue
if ar[0] == '0' or noReorder:
everything = everything + [ar]
elif ar[0] == '1':
everything = [ar] + everything
for ar in everything:
dataVarNameHead = '_py_gen_data'
errVarName = '_py_gen_err' + str(n)
tf, args = ar[0], ar[1:]
args = [dataVarNameHead + arg[2:] if arg[:2] == '/v' else '"{}"'.format(arg) for arg in args]
args = ['[]byte("{})'.format(quoted_arg[3:]) if quoted_arg[:3] == '"/b' else quoted_arg for quoted_arg in args]
should_ = 'success' if tf == '1' else 'fail'
print(' {} := {}({}) // Should {}.'.format(errVarName, funcname, ', '.join(args), should_))
n += 1
if tf == '1':
t.append(errVarName)
else:
f.append(errVarName)
if t != []:
print(' if {} != nil {{'.format(' != nil || '.join(t)))
print(' t.Error("Test {} failed.")'.format(funcname))
print(' }')
if f != []:
print(' if {} == nil {{'.format(' == nil || '.join(f)))
print(' t.Error("Test {} failed.")'.format(funcname))
print(' }')
#!/usr/bin/python3
import sys
funcname = sys.argv[1]
dataf = sys.argv[2]
with open(dataf) as f:
cont = f.read()
everything = []
t, f = [], []
try:
n = int(sys.argv[3])
except:
n = 0
for line in cont.split('\n'):
'1:user:password'
ar = line.split(':')
if len(ar) < 2:
continue
if ar[0] == '1':
everything = [ar] + everything
elif ar[0] == '0':
everything = everything + [ar]
for ar in everything:
tf, args = ar[0], ar[1:]
errVarName = '_py_gen_err' + str(n)
dataVarName = '_py_gen_data' + str(n) if tf == '1' else '_'
args = ['"{}"'.format(arg) for arg in args]
args = ['[]byte("{})'.format(quoted_arg[3:]) if quoted_arg[:3] == '"/b' else quoted_arg for quoted_arg in args]
should_ = 'success' if tf == '1' else 'fail'
if funcname.find('Load') != -1:
print(' {}, {} := {}({}) // Should {}.'.format(dataVarName, errVarName, funcname, args[0], should_))
else:
print(' {}, {} := {}({}) // Should {}.'.format(dataVarName, errVarName, funcname, ', '.join(args), should_))
if tf == '1' and funcname.find('Load') != -1:
print(' if !reflect.DeepEqual({}, {}) {{'.format(dataVarName, args[1]))
print(' t.Error("Test {} failed. data does not match.")'.format(funcname))
print(' }')
n += 1
if tf == '1':
t.append(errVarName)
else:
f.append(errVarName)
if t != []:
print(' if {} != nil {{'.format(' != nil || '.join(t)))
print(' t.Error("Test {} failed.")'.format(funcname))
print(' }')
if f != []:
print(' if {} == nil {{'.format(' == nil || '.join(f)))
print(' t.Error("Test {} failed.")'.format(funcname))
print(' }')
test-writer's note:
alice ---file1.log---> bob
alice ---file2.log---> unicode用户名测试+bob
bob -----file1.log---> unicode用户名测试
unicode用户名测试 --file1.log--> longlonglonglong
1:file1.log:bob
1:file2.log:bob
0:file:bob
0:file1.log:
0::
# note: the file %empty should not be successfully stored.
0::bob
0:file1.log:bob\n
0:file1.log:bob
1:file1.log:bob
1:file1.log:bob
1:file2.log:unicode用户名测试
0:file2.log:unicode用户名测
1:file1.log:/bfuckyou\nfuck again\nfuckshit
1:file2.log:/b\n
../gen_Append_Receive_Revoke.py bob.ReceiveFile bob.ReceiveFile 100 no-reorder
1:file1.log:alice:/v2
0:file1.log:alice:/v2
1:file1.log:alice:/v4
0:file3.log:alice:/v2
0:file2.log:alice:/v0
0:file1.log:alice:/v3
1:file1.log:alice:/v3
test-writer's note:
alice ---file1.log---> bob
alice ---file2.log---> unicode用户名测试+bob
bob -----file1.log---> unicode用户名测试
unicode用户名测试 --file1.log--> longlonglonglong
1:file1.log:bob
1:file1.log:alice
1:file1.log:bob
1:file1.log:alice
1:file2.log:bob
1:file1.log:unicode用户名测试
1:file2.log:bob
1:file2.log:unicode用户名测试
1:file2.log:alice
1:file2.log:unicode用户名测试
1:file2.log:bob
1:file2.log:unicode用户名测试
1:file2.log:bob
1:file2.log:unicode用户名测试
0:.:longlonglonglong
0:file3.log:alice
# ../gen_Append_Receive_Revoke.py longlonglonglong.AppendFile longlonglonglong.AppendReceivedFile 0 no-reorder
0:file2.log:/btest
1:file1.log:/b
1:file1.log:/b\n
1:file1.log:/bfuckshit
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment