diff options
| author | Přemysl Janouch <p@janouch.name> | 2018-07-30 17:39:32 +0200 | 
|---|---|---|
| committer | Přemysl Janouch <p@janouch.name> | 2018-07-30 17:50:27 +0200 | 
| commit | c75299e1c376026ada795d7edf704e0bf5f0eb6b (patch) | |
| tree | 9fa00c198770ae12da3b06a80a9925de72141653 /hid | |
| parent | 24f1c4413a6e26aa05c642a462ce77d70d478e92 (diff) | |
| download | haven-c75299e1c376026ada795d7edf704e0bf5f0eb6b.tar.gz haven-c75299e1c376026ada795d7edf704e0bf5f0eb6b.tar.xz haven-c75299e1c376026ada795d7edf704e0bf5f0eb6b.zip | |
hid: port IRC 3.2 message tag parsing, unused
Diffstat (limited to 'hid')
| -rw-r--r-- | hid/main.go | 84 | 
1 files changed, 66 insertions, 18 deletions
| diff --git a/hid/main.go b/hid/main.go index 1c72fca..eec67d9 100644 --- a/hid/main.go +++ b/hid/main.go @@ -296,17 +296,72 @@ func ircFnmatch(pattern string, s string) bool {  	return matched  } -// TODO: We will need to add support for IRCv3 tags.  var reMsg = regexp.MustCompile( -	`^(?::([^! ]*)(?:!([^@]*)@([^ ]*))? +)?([^ ]+)(.*)?$`) +	`^(?:@[^ ]* +)(?::([^! ]*)(?:!([^@]*)@([^ ]*))? +)?([^ ]+)(.*)?$`)  var reArgs = regexp.MustCompile(`:.*| [^: ][^ ]*`)  type message struct { -	nick    string   // optional nickname -	user    string   // optional username -	host    string   // optional hostname or IP address -	command string   // command name -	params  []string // arguments +	tags    map[string]string // IRC 3.2 message tags +	nick    string            // optional nickname +	user    string            // optional username +	host    string            // optional hostname or IP address +	command string            // command name +	params  []string          // arguments +} + +func ircUnescapeMessageTag(value string) string { +	var buf []byte +	escape := false +	for i := 0; i < len(value); i++ { +		if escape { +			switch value[i] { +			case ':': +				buf = append(buf, ';') +			case 's': +				buf = append(buf, ' ') +			case 'r': +				buf = append(buf, '\r') +			case 'n': +				buf = append(buf, '\n') +			default: +				buf = append(buf, value[i]) +			} +			escape = false +		} else if value[i] == '\\' { +			escape = true +		} else { +			buf = append(buf, value[i]) +		} +	} +	return string(buf) +} + +func ircParseMessageTags(tags string, out map[string]string) { +	for _, tag := range splitString(tags, ";", true /* ignoreEmpty */) { +		if equal := strings.IndexByte(tag, '='); equal < 0 { +			out[tag] = "" +		} else { +			out[tag[:equal]] = ircUnescapeMessageTag(tag[equal+1:]) +		} +	} +} + +func ircParseMessage(line string) *message { +	m := reMsg.FindStringSubmatch(line) +	if m == nil { +		return nil +	} + +	msg := message{nil, m[2], m[3], m[4], m[5], nil} +	if m[1] != "" { +		msg.tags = make(map[string]string) +		ircParseMessageTags(m[1], msg.tags) +	} +	for _, x := range reArgs.FindAllString(m[6], -1) { +		msg.params = append(msg.params, x[1:]) +	} +	return &msg +  }  // Everything as per RFC 2812 @@ -2627,23 +2682,16 @@ func (c *client) onRead(data []byte, readErr error) {  			break  		} +		// XXX: And since it accepts LF, we miscalculate receivedBytes within.  		c.recvQ = c.recvQ[advance:]  		line := string(token)  		log.Printf("-> %s\n", line) -		m := reMsg.FindStringSubmatch(line) -		if m == nil { +		if msg := ircParseMessage(line); msg == nil {  			log.Println("error: invalid line") -			continue -		} - -		msg := message{m[1], m[2], m[3], m[4], nil} -		for _, x := range reArgs.FindAllString(m[5], -1) { -			msg.params = append(msg.params, x[1:]) +		} else { +			ircProcessMessage(c, msg, line)  		} - -		// XXX: And since it accepts LF, we miscalculate receivedBytes within. -		ircProcessMessage(c, &msg, line)  	}  	if readErr != nil { | 
