func write(args string) { tokens := strings.SplitN(args, " ", 2) path := tokens[0] if len(tokens) != 2 { println("A source filename is required") return } filename := tokens[1] file, err := os.Open(filename) if err != nil { println("Could not read file " + filename) return } url, err := determinURL(path) if err != nil { println(path + " is not a valid path") return } req := fosp.NewRequest(fosp.WRITE, url) req.Body = file if _, err := connection.SendRequest(req); err == nil { println("Write succeeded") } else { println("Write failed: " + err.Error()) } }
func read(args string) { tokens := strings.SplitN(args, " ", 2) path := tokens[0] if len(tokens) != 2 { println("A destination filename is required") return } filename := tokens[1] file, err := os.Create(filename) defer file.Close() if err != nil { println("Could not create file " + filename) } url, err := determinURL(path) if err != nil { println(path + " is not a valid path") return } req := fosp.NewRequest(fosp.READ, url) if resp, err := connection.SendRequest(req); err == nil && resp.Status == fosp.SUCCEEDED { if _, err = io.Copy(file, resp.Body); err == nil { println("Read succeeded") } else { println("Error when saving file " + err.Error()) } } else { if err != nil { println("Read failed: " + err.Error()) } else { println("Read failed, received FAILED response") } } }
func auth(args string) { parts := strings.Split(args, " ") if len(parts) != 2 { println("Not enough arguments for authenticate") } authenticationId := parts[0] password := parts[1] content := map[string]map[string]string{ "sasl": map[string]string{ "mechanism": "PLAIN", "initial-response": strings.Join([]string{"", authenticationId, password}, "\x00"), }, } encoded, err := json.Marshal(content) if err != nil { println("Error while building request " + err.Error()) return } req := fosp.NewRequest(fosp.AUTH, nil) req.Body = bytes.NewBuffer(encoded) if resp, err := connection.SendRequest(req); err == nil && resp.Status == fosp.SUCCEEDED { state.User = parts[0] state.Password = parts[0] state.Cwd = state.User buildPrompt() println("Authentication succeeded") } else { println("Authentication failed") } }
func del(args string) { url, err := determinURL(args) if err != nil { println(args + " is not a valid path") return } req := fosp.NewRequest(fosp.DELETE, url) if _, err := connection.SendRequest(req); err == nil { println("Delete succeeded") } else { println("Delete failed: " + err.Error()) } }
func list(args string) { url, err := determinURL(args) if err != nil { println(args + " is not a valid path") return } req := fosp.NewRequest(fosp.LIST, url) if resp, err := connection.SendRequest(req); err == nil { bytes, _ := ioutil.ReadAll(resp.Body) println(prettyJSON(bytes)) } else { println("Select failed: " + err.Error()) } }
func patch(args string) { tokens := strings.SplitN(args, " ", 2) path := tokens[0] content := "" if len(tokens) == 2 { content = tokens[1] } url, err := determinURL(path) if err != nil { println(path + " is not a valid path") return } req := fosp.NewRequest(fosp.PATCH, url) if content != "" { req.Body = bytes.NewBufferString(content) } if _, err := connection.SendRequest(req); err == nil { println("Patch succeeded") } else { println("Patch failed: " + err.Error()) } }
func parseMessage(in io.Reader) (msg fosp.Message, seq uint64, err error) { var ( firstLine []byte rawurl string isPrefix bool readerErr error fragments [][]byte code int msgURL *url.URL reader *bufio.Reader ok bool ) err = errors.New("Failed to parse message, unknown error") if reader, ok = in.(*bufio.Reader); !ok { reader = bufio.NewReader(in) } if firstLine, isPrefix, readerErr = reader.ReadLine(); isPrefix { err = errors.New("First line of message is too long") return } else if readerErr != nil && readerErr != io.EOF { err = newNestedError("Reader error", readerErr) return } if fragments = bytes.Split(firstLine, []byte(" ")); len(fragments) < 2 { err = errors.New("First line does not consist of at least 2 parts") return } identifier := string(fragments[0]) switch identifier { case fosp.OPTIONS, fosp.AUTH, fosp.GET, fosp.LIST, fosp.CREATE, fosp.PATCH, fosp.DELETE, fosp.READ, fosp.WRITE: if len(fragments) != 3 { err = errors.New("Request line does not consist of 3 parts") return } rawurl = string(fragments[1]) if rawurl != "*" { rawurl = "fosp://" + string(fragments[1]) if msgURL, err = url.Parse(rawurl); err != nil { err = errors.New("Invalid request URL") return } msgURL.Path = path.Clean(msgURL.Path) if msgURL.Path == "." { msgURL.Path = "/" } } if seq, err = strconv.ParseUint(string(fragments[2]), 10, 64); err != nil || seq < 1 { err = newNestedError("The request sequence number is not valid", err) return } req := fosp.NewRequest(identifier, msgURL) if req.Header, err = textproto.NewReader(reader).ReadMIMEHeader(); err != nil && err != io.EOF { err = newNestedError("The request header is not valid", err) return } req.Body = reader return req, seq, nil case fosp.SUCCEEDED, fosp.FAILED: if len(fragments) != 3 { err = errors.New("Response line does not consist of 3 parts") return } if code, err = strconv.Atoi(string(fragments[1])); err != nil { err = newNestedError("Status code is invalid", err) return } if seq, err = strconv.ParseUint(string(fragments[2]), 10, 64); err != nil || seq < 1 { err = newNestedError("The response sequence number is not valid", err) if seq < 1 { err = errors.New("The sequence number is 0") } return } resp := fosp.NewResponse(identifier, uint(code)) if resp.Header, err = textproto.NewReader(reader).ReadMIMEHeader(); err != nil && err != io.EOF { err = newNestedError("The response header is not valid", err) return } resp.Body = reader return resp, seq, nil case fosp.CREATED, fosp.UPDATED, fosp.DELETED: if len(fragments) != 2 { err = errors.New("Notification line does not consist of 2 parts") return } rawurl = string(fragments[1]) if rawurl != "*" { rawurl = "fosp://" + string(fragments[1]) if msgURL, err = url.Parse(rawurl); err != nil { err = errors.New("Invalid request URL") return } msgURL.Path = path.Clean(msgURL.Path) if msgURL.Path == "." { msgURL.Path = "/" } } evt := fosp.NewNotification(identifier, msgURL) if evt.Header, err = textproto.NewReader(reader).ReadMIMEHeader(); err != nil && err != io.EOF { err = newNestedError("The notification header is not valid", err) return } evt.Body = reader return evt, seq, nil default: err = errors.New("Unrecognized identifier " + identifier) return } }