Beispiel #1
0
func processConnData(conn *textproto.Conn) response {
	res := response{Data: make([]string, 0)}
	for {
		line, err := conn.ReadLine()
		if err != nil {
			res.Err = err
			break
		}
		if line == "OK" {
			break
		}
		match := mpdErrorRegexp.FindStringSubmatch(line)
		if match != nil {
			ack, err := strconv.ParseUint(match[1], 0, 0)
			if err != nil {
				res.Err = err
				break
			}
			cln, err := strconv.ParseUint(match[2], 0, 0)
			if err != nil {
				res.Err = err
				break
			}
			res.MPDErr = &MPDError{uint(ack), uint(cln), match[3], match[4]}
			break
		}
		res.Data = append(res.Data, line)
	}
	return res
}
Beispiel #2
0
func handleAuthInfo(args []string, s *session, c *textproto.Conn) error {
	if len(args) < 2 {
		return SyntaxError
	}
	if strings.ToLower(args[0]) != "user" {
		return SyntaxError
	}

	if s.backend.Authorized() {
		return c.PrintfLine("250 authenticated")
	}

	c.PrintfLine("350 Continue")
	a, err := c.ReadLine()
	parts := strings.SplitN(a, " ", 3)
	if strings.ToLower(parts[0]) != "authinfo" || strings.ToLower(parts[1]) != "pass" {
		return SyntaxError
	}
	b, err := s.backend.Authenticate(args[1], parts[2])
	if err == nil {
		c.PrintfLine("250 authenticated")
		if b != nil {
			s.backend = b
		}
	}
	return err
}
Beispiel #3
0
func collectLines(c *textproto.Conn) ([]string, error) {
	var ex error
	var line string
	var msg []string
	var ended bool

	line, ex = c.ReadLine()

	if ex != nil {
		return nil, ex
	}

	if !validLine(line) {
		return nil, ErrShortResponse
	}

	msg = append(msg, line)

	ended = line[3] != '-'

	for ex == nil && !ended {
		line, ex = c.ReadLine()

		if ex != nil {
			return nil, ex
		}

		msg = append(msg, line)
		ended = line[3] != '-'
	}

	return msg, nil
}
Beispiel #4
0
func read(c *textproto.Conn) (string, error) {
	s, err := c.ReadLine()
	if err == io.EOF {
		return s, err
	}

	if err != nil {
		panic(err)
	}

	return s, err
}
func NewCommandRequest(c *textproto.Conn) (*CommandRequest, error) {
	verb, err := c.ReadLine()
	if err != nil {
		return nil, err
	}

	headers, err := c.ReadMIMEHeader()
	if err != nil {
		return nil, err
	}

	// read body here

	return &CommandRequest{
		Method:  verb,
		Headers: headers,
		//Body: body,
	}, nil
}
Beispiel #6
0
func (s *server) readRequest(p *textproto.Conn) (*request, error) {
	line, err := p.ReadLine()
	if err == io.EOF {
		return nil, err
	}
	if err != nil {
		log.Printf("reading request failed: %v\n", err)
		return nil, err
	}
	args := parseArgs(line)
	if len(args) == 0 {
		return &request{typ: simple, args: args}, nil
	}
	switch args[0] {
	case "command_list_ok_begin":
		var cmdList [][]string
		for {
			line, err := p.ReadLine()
			if err == io.EOF {
				return nil, err
			}
			if err != nil {
				log.Printf("reading request failed: %v\n", err)
				return nil, err
			}
			args = parseArgs(line)
			if len(args) > 0 && args[0] == "command_list_end" {
				break
			}
			cmdList = append(cmdList, args)
		}
		return &request{typ: commandListOk, cmdList: cmdList}, nil

	case "idle":
		return &request{typ: idle, args: args}, nil

	case "noidle":
		return &request{typ: noIdle, args: args}, nil
	}
	return &request{typ: simple, args: args}, nil
}
Beispiel #7
0
func MyreadCodeLine(r *textproto.Conn, expectCode int) (code int, continued bool, message string, err error) {
	var line string
	//fmt.Print("read ")
	line, err = r.ReadLine()
	if err != nil {
		return
	}
	//fmt.Println(line)
	// for (    Used disk quota 0 Kbytes, available 1000000 Kbytes)
	if strings.HasPrefix(line, "  ") {
		line, _ = r.ReadLine()
		if err != nil {
			return
		}

		//fmt.Printf("1: %s\n", line)
		line, err = r.ReadLine()
		if err != nil {
			return
		}
		//fmt.Printf("2: %s\n", line)
	}

	code, continued, message, err = parseCodeLine(line, expectCode)
	return
}
Beispiel #8
0
// run the mainloop for this connection
// stream if true means they support streaming mode
// reader if true means they support reader mode
func (self nntpConnection) runConnection(daemon NNTPDaemon, inbound, stream, reader bool, preferMode string, conn *textproto.Conn) {

	var err error
	var line string
	var success bool

	for err == nil {
		if self.mode == "" {
			if inbound {
				// no mode and inbound
				line, err = conn.ReadLine()
				log.Println(self.name, line)
				parts := strings.Split(line, " ")
				cmd := parts[0]
				if cmd == "CAPABILITIES" {
					// write capabilities
					conn.PrintfLine("101 i support to the following:")
					dw := conn.DotWriter()
					caps := []string{"VERSION 2", "READER", "STREAMING", "IMPLEMENTATION srndv2"}
					for _, cap := range caps {
						io.WriteString(dw, cap)
						io.WriteString(dw, "\n")
					}
					dw.Close()
					log.Println(self.name, "sent Capabilities")
				} else if cmd == "MODE" {
					if len(parts) == 2 {
						if parts[1] == "READER" {
							// set reader mode
							self.mode = "READER"
							// posting is not permitted with reader mode
							conn.PrintfLine("201 Posting not permitted")
						} else if parts[1] == "STREAM" {
							// set streaming mode
							conn.PrintfLine("203 Stream it brah")
							self.mode = "STREAM"
							log.Println(self.name, "streaming enabled")
							go self.startStreaming(daemon, reader, conn)
						}
					}
				} else {
					// handle a it as a command, we don't have a mode set
					parts := strings.Split(line, " ")
					var code64 int64
					code64, err = strconv.ParseInt(parts[0], 10, 32)
					if err == nil {
						err = self.handleLine(daemon, int(code64), line[4:], conn)
					} else {
						err = self.handleLine(daemon, 0, line, conn)
					}
				}
			} else { // no mode and outbound
				if preferMode == "stream" {
					// try outbound streaming
					if stream {
						success, err = self.modeSwitch("STREAM", conn)
						self.mode = "STREAM"
						if success {
							// start outbound streaming in background
							go self.startStreaming(daemon, reader, conn)
						}
					}
				} else if reader {
					// try reader mode
					success, err = self.modeSwitch("READER", conn)
					if success {
						self.mode = "READER"
						self.startReader(daemon, conn)
					}
				}
				if success {
					log.Println(self.name, "mode set to", self.mode)
				} else {
					// bullshit
					// we can't do anything so we quit
					log.Println(self.name, "can't stream or read, wtf?")
					conn.PrintfLine("QUIT")
					conn.Close()
					return
				}
			}
		} else {
			// we have our mode set
			line, err = conn.ReadLine()
			if err == nil {
				parts := strings.Split(line, " ")
				var code64 int64
				code64, err = strconv.ParseInt(parts[0], 10, 32)
				if err == nil {
					err = self.handleLine(daemon, int(code64), line[4:], conn)
				} else {
					err = self.handleLine(daemon, 0, line, conn)
				}
			}
		}
	}
	log.Println(self.name, "got error", err)
	if !inbound {
		// send quit on outbound
		conn.PrintfLine("QUIT")
	}
	conn.Close()
}
Beispiel #9
0
// run the mainloop for this connection
// stream if true means they support streaming mode
// reader if true means they support reader mode
func (self *nntpConnection) runConnection(daemon *NNTPDaemon, inbound, stream, reader, use_tls bool, preferMode string, nconn net.Conn, conf *FeedConfig) {
	self.addr = nconn.RemoteAddr()
	var err error
	var line string
	var success bool
	var conn *textproto.Conn

	if (conf != nil && !conf.tls_off) && use_tls && daemon.CanTLS() && !inbound {
		log.Println(self.name, "STARTTLS with", self.hostname)
		_conn, state, err := SendStartTLS(nconn, daemon.GetTLSConfig(self.hostname))
		if err == nil {
			// we upgraded
			conn = _conn
			self.authenticated = state.HandshakeComplete
			log.Println(self.name, "tls auth", self.authenticated)
		} else {
			log.Println(self.name, err)
			// we didn't upgrade, fall back
			conn = textproto.NewConn(nconn)
		}
	} else {
		// we are authenticated if we are don't need tls
		conn = textproto.NewConn(nconn)
	}
	if !inbound {
		if preferMode == "stream" {
			// try outbound streaming
			if stream {
				success, err = self.modeSwitch("STREAM", conn)
				if success {
					self.mode = "STREAM"
					// start outbound streaming in background
					go self.startStreaming(daemon, reader, conn)
				}
			}
		} else if reader {
			// try reader mode
			success, err = self.modeSwitch("READER", conn)
			if success {
				self.mode = "READER"
				self.startReader(daemon, conn)
				return
			}
		}
		if success {
			log.Println(self.name, "mode set to", self.mode)
		} else {
			// bullshit
			// we can't do anything so we quit
			log.Println(self.name, "can't stream or read, wtf?")
			conn.PrintfLine("QUIT")
			conn.Close()
			return
		}
	}

	for err == nil {
		line, err = conn.ReadLine()
		if self.mode == "" {
			if inbound {
				if len(line) == 0 {
					conn.Close()
					return
				} else if line == "QUIT" {
					conn.PrintfLine("205 bai")
					conn.Close()
					return
				}
				parts := strings.Split(line, " ")
				cmd := parts[0]
				if cmd == "STARTTLS" {
					_conn, state, err := HandleStartTLS(nconn, daemon.GetOurTLSConfig())
					if err == nil {
						// we are now tls
						conn = _conn
						self.tls_state = state
						self.authenticated = state.HandshakeComplete
						log.Println(self.name, "TLS initiated", self.authenticated)
					} else {
						log.Println("STARTTLS failed:", err)
					}
				} else if cmd == "CAPABILITIES" {
					// write capabilities
					conn.PrintfLine("101 i support to the following:")
					dw := conn.DotWriter()
					caps := []string{"VERSION 2", "READER", "STREAMING", "IMPLEMENTATION srndv2", "POST", "IHAVE", "AUTHINFO"}
					if daemon.CanTLS() {
						caps = append(caps, "STARTTLS")
					}
					for _, cap := range caps {
						io.WriteString(dw, cap)
						io.WriteString(dw, "\n")
					}
					dw.Close()
					log.Println(self.name, "sent Capabilities")
				} else if cmd == "MODE" {
					if len(parts) == 2 {
						mode := strings.ToUpper(parts[1])
						if mode == "READER" {
							// set reader mode
							self.mode = "READER"
							// we'll allow posting for reader
							conn.PrintfLine("200 Posting is Permitted awee yeh")
						} else if mode == "STREAM" {
							if !self.authenticated {
								conn.PrintfLine("483 Streaming Denied")
							} else {
								// set streaming mode
								conn.PrintfLine("203 Stream it brah")
								self.mode = "STREAM"
								log.Println(self.name, "streaming enabled")
								go self.startStreaming(daemon, reader, conn)
							}
						}
					}
				} else {
					// handle a it as a command, we don't have a mode set
					parts := strings.Split(line, " ")
					cmd := parts[0]
					if cmd == "STARTTLS" {
						_conn, state, err := HandleStartTLS(nconn, daemon.GetOurTLSConfig())
						if err == nil {
							// we are now tls
							conn = _conn
							self.tls_state = state
							self.authenticated = state.HandshakeComplete
							log.Println("TLS initiated")
						} else {
							log.Println("STARTTLS failed:", err)
							nconn.Close()
							return
						}
					}
					var code64 int64
					code64, err = strconv.ParseInt(parts[0], 10, 32)
					if err == nil {
						err = self.handleLine(daemon, int(code64), line[4:], conn)
					} else {
						err = self.handleLine(daemon, 0, line, conn)
					}
				}
			}
		} else {
			if err == nil {
				parts := strings.Split(line, " ")
				var code64 int64
				code64, err = strconv.ParseInt(parts[0], 10, 32)
				if err == nil {
					err = self.handleLine(daemon, int(code64), line[4:], conn)
				} else {
					err = self.handleLine(daemon, 0, line, conn)
				}
			}
		}
	}
	if err != io.EOF {
		log.Println(self.name, "got error", err)
		if !inbound && conn != nil {
			// send quit on outbound
			conn.PrintfLine("QUIT")
		}
	}
	nconn.Close()
}