hunk.code_window: 			}
   		}
   		// Only report events to users who are in the channel for the event
   		if len(msg.ChannelId) > 0 {
   			allowed := webCon.HasPermissionsToChannel(msg.ChannelId)
   			if !allowed {
   				return false
  
hunk.labels: keep keep keep replace replace keep keep keep keep
hunk.after_edit: 		// Only report events to users who are in the channel for the event execept deleted events
   		if len(msg.ChannelId) > 0 && msg.Action != model.ACTION_CHANNEL_DELETED {
  
hunk.file_path: api/web_hub.go
hunk.type: replace
file: // Copyright 2013 The Gorilla Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  package handlers
  
  import (
  	"bufio"
  	"fmt"
  	"io"
  	"net"
  	"net/http"
  	"net/url"
  	"sort"
  	"strconv"
  	"strings"
  	"time"
  	"unicode/utf8"
  )
  
  // MethodHandler is an http.Handler that dispatches to a handler whose key in the
  // MethodHandler's map matches the name of the HTTP request's method, eg: GET
  //
  // If the request's method is OPTIONS and OPTIONS is not a key in the map then
  // the handler responds with a status of 200 and sets the Allow header to a
  // comma-separated list of available methods.
  //
  // If the request's method doesn't match any of its keys the handler responds
  // with a status of HTTP 405 "Method Not Allowed" and sets the Allow header to a
  // comma-separated list of available methods.
  type MethodHandler map[string]http.Handler
  
  func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  	if handler, ok := h[req.Method]; ok {
  		handler.ServeHTTP(w, req)
  	} else {
  		allow := []string{}
  		for k := range h {
  			allow = append(allow, k)
  		}
  		sort.Strings(allow)
  		w.Header().Set("Allow", strings.Join(allow, ", "))
  		if req.Method == "OPTIONS" {
  			w.WriteHeader(http.StatusOK)
  		} else {
  			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
  		}
  	}
  }
  
  // loggingHandler is the http.Handler implementation for LoggingHandlerTo and its
  // friends
  type loggingHandler struct {
  	writer  io.Writer
  	handler http.Handler
  }
  
  // combinedLoggingHandler is the http.Handler implementation for LoggingHandlerTo
  // and its friends
  type combinedLoggingHandler struct {
  	writer  io.Writer
  	handler http.Handler
  }
  
  func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  	t := time.Now()
  	logger := makeLogger(w)
  	url := *req.URL
  	h.handler.ServeHTTP(logger, req)
  	writeLog(h.writer, req, url, t, logger.Status(), logger.Size())
  }
  
  func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  	t := time.Now()
  	logger := makeLogger(w)
  	url := *req.URL
  	h.handler.ServeHTTP(logger, req)
  	writeCombinedLog(h.writer, req, url, t, logger.Status(), logger.Size())
  }
  
  func makeLogger(w http.ResponseWriter) loggingResponseWriter {
  	var logger loggingResponseWriter = &responseLogger{w: w}
  	if _, ok := w.(http.Hijacker); ok {
  		logger = &hijackLogger{responseLogger{w: w}}
  	}
  	h, ok1 := logger.(http.Hijacker)
  	c, ok2 := w.(http.CloseNotifier)
  	if ok1 && ok2 {
  		return hijackCloseNotifier{logger, h, c}
  	}
  	if ok2 {
  		return &closeNotifyWriter{logger, c}
  	}
  	return logger
  }
  
  type loggingResponseWriter interface {
  	http.ResponseWriter
  	http.Flusher
  	Status() int
  	Size() int
  }
  
  // responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP
  // status code and body size
  type responseLogger struct {
  	w      http.ResponseWriter
  	status int
  	size   int
  }
  
  func (l *responseLogger) Header() http.Header {
  	return l.w.Header()
  }
  
  func (l *responseLogger) Write(b []byte) (int, error) {
  	if l.status == 0 {
  		// The status will be StatusOK if WriteHeader has not been called yet
  		l.status = http.StatusOK
  	}
  	size, err := l.w.Write(b)
  	l.size += size
  	return size, err
  }
  
  func (l *responseLogger) WriteHeader(s int) {
  	l.w.WriteHeader(s)
  	l.status = s
  }
  
  func (l *responseLogger) Status() int {
  	return l.status
  }
  
  func (l *responseLogger) Size() int {
  	return l.size
  }
  
  func (l *responseLogger) Flush() {
  	f, ok := l.w.(http.Flusher)
  	if ok {
  		f.Flush()
  	}
  }
  
  type hijackLogger struct {
  	responseLogger
  }
  
  func (l *hijackLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
  	h := l.responseLogger.w.(http.Hijacker)
  	conn, rw, err := h.Hijack()
  	if err == nil && l.responseLogger.status == 0 {
  		// The status will be StatusSwitchingProtocols if there was no error and
  		// WriteHeader has not been called yet
  		l.responseLogger.status = http.StatusSwitchingProtocols
  	}
  	return conn, rw, err
  }
  
  type closeNotifyWriter struct {
  	loggingResponseWriter
  	http.CloseNotifier
  }
  
  type hijackCloseNotifier struct {
  	loggingResponseWriter
  	http.Hijacker
  	http.CloseNotifier
  }
  
  const lowerhex = "0123456789abcdef"
  
  func appendQuoted(buf []byte, s string) []byte {
  	var runeTmp [utf8.UTFMax]byte
  	for width := 0; len(s) > 0; s = s[width:] {
  		r := rune(s[0])
  		width = 1
  		if r >= utf8.RuneSelf {
  			r, width = utf8.DecodeRuneInString(s)
  		}
  		if width == 1 && r == utf8.RuneError {
  			buf = append(buf, `\x`...)
  			buf = append(buf, lowerhex[s[0]>>4])
  			buf = append(buf, lowerhex[s[0]&0xF])
  			continue
  		}
  		if r == rune('"') || r == '\\' { // always backslashed
  			buf = append(buf, '\\')
  			buf = append(buf, byte(r))
  			continue
  		}
  		if strconv.IsPrint(r) {
  			n := utf8.EncodeRune(runeTmp[:], r)
  			buf = append(buf, runeTmp[:n]...)
  			continue
  		}
  		switch r {
  		case '\a':
  			buf = append(buf, `\a`...)
  		case '\b':
  			buf = append(buf, `\b`...)
  		case '\f':
  			buf = append(buf, `\f`...)
  		case '\n':
  			buf = append(buf, `\n`...)
  		case '\r':
  			buf = append(buf, `\r`...)
  		case '\t':
  			buf = append(buf, `\t`...)
  		case '\v':
  			buf = append(buf, `\v`...)
  		default:
  			switch {
  			case r < ' ':
  				buf = append(buf, `\x`...)
  				buf = append(buf, lowerhex[s[0]>>4])
  				buf = append(buf, lowerhex[s[0]&0xF])
  			case r > utf8.MaxRune:
  				r = 0xFFFD
  				fallthrough
  			case r < 0x10000:
  				buf = append(buf, `\u`...)
  				for s := 12; s >= 0; s -= 4 {
  					buf = append(buf, lowerhex[r>>uint(s)&0xF])
  				}
  			default:
  				buf = append(buf, `\U`...)
  				for s := 28; s >= 0; s -= 4 {
  					buf = append(buf, lowerhex[r>>uint(s)&0xF])
  				}
  			}
  		}
  	}
  	return buf
  
  }
  
  // buildCommonLogLine builds a log entry for req in Apache Common Log Format.
  // ts is the timestamp with which the entry should be logged.
  // status and size are used to provide the response HTTP status and size.
  func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
  	username := "-"
  	if url.User != nil {
  		if name := url.User.Username(); name != "" {
  			username = name
  		}
  	}
  
  	host, _, err := net.SplitHostPort(req.RemoteAddr)
  
  	if err != nil {
  		host = req.RemoteAddr
  	}
  
  	uri := req.RequestURI
  
  	// Requests using the CONNECT method over HTTP/2.0 must use
  	// the authority field (aka r.Host) to identify the target.
  	// Refer: https://httpwg.github.io/specs/rfc7540.html#CONNECT
  	if req.ProtoMajor == 2 && req.Method == "CONNECT" {
  		uri = req.Host
  	}
  	if uri == "" {
  		uri = url.RequestURI()
  	}
  
  	buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
  	buf = append(buf, host...)
  	buf = append(buf, " - "...)
  	buf = append(buf, username...)
  	buf = append(buf, " ["...)
  	buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
  	buf = append(buf, `] "`...)
  	buf = append(buf, req.Method...)
  	buf = append(buf, " "...)
  	buf = appendQuoted(buf, uri)
  	buf = append(buf, " "...)
  	buf = append(buf, req.Proto...)
  	buf = append(buf, `" `...)
  	buf = append(buf, strconv.Itoa(status)...)
  	buf = append(buf, " "...)
  	buf = append(buf, strconv.Itoa(size)...)
  	return buf
  }
  
  // writeLog writes a log entry for req to w in Apache Common Log Format.
  // ts is the timestamp with which the entry should be logged.
  // status and size are used to provide the response HTTP status and size.
  func writeLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
  	buf := buildCommonLogLine(req, url, ts, status, size)
  	buf = append(buf, '\n')
  	w.Write(buf)
  }
  
  // writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
  // ts is the timestamp with which the entry should be logged.
  // status and size are used to provide the response HTTP status and size.
  func writeCombinedLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
  	buf := buildCommonLogLine(req, url, ts, status, size)
  	buf = append(buf, ` "`...)
  	buf = appendQuoted(buf, req.Referer())
  	buf = append(buf, `" "`...)
  	buf = appendQuoted(buf, req.UserAgent())
  	buf = append(buf, '"', '\n')
  	w.Write(buf)
  }
  
  // CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
  // Apache Combined Log Format.
  //
  // See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
  //
  // LoggingHandler always sets the ident field of the log to -
  func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
  	return combinedLoggingHandler{out, h}
  }
  
  // LoggingHandler return a http.Handler that wraps h and logs requests to out in
  // Apache Common Log Format (CLF).
  //
  // See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
  //
  // LoggingHandler always sets the ident field of the log to -
  //
  // Example:
  //
  //  r := mux.NewRouter()
  //  r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  //  	w.Write([]byte("This is a catch-all route"))
  //  })
  //  loggedRouter := handlers.LoggingHandler(os.Stdout, r)
  //  http.ListenAndServe(":1123", loggedRouter)
  //
  func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
  	return loggingHandler{out, h}
  }
  
  // isContentType validates the Content-Type header matches the supplied
  // contentType. That is, its type and subtype match.
  func isContentType(h http.Header, contentType string) bool {
  	ct := h.Get("Content-Type")
  	if i := strings.IndexRune(ct, ';'); i != -1 {
  		ct = ct[0:i]
  	}
  	return ct == contentType
  }
  
  // ContentTypeHandler wraps and returns a http.Handler, validating the request
  // content type is compatible with the contentTypes list. It writes a HTTP 415
  // error if that fails.
  //
  // Only PUT, POST, and PATCH requests are considered.
  func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  		if !(r.Method == "PUT" || r.Method == "POST" || r.Method == "PATCH") {
  			h.ServeHTTP(w, r)
  			return
  		}
  
  		for _, ct := range contentTypes {
  			if isContentType(r.Header, ct) {
  				h.ServeHTTP(w, r)
  				return
  			}
  		}
  		http.Error(w, fmt.Sprintf("Unsupported content type %q; expected one of %q", r.Header.Get("Content-Type"), contentTypes), http.StatusUnsupportedMediaType)
  	})
  }
  
  const (
  	// HTTPMethodOverrideHeader is a commonly used
  	// http header to override a request method.
  	HTTPMethodOverrideHeader = "X-HTTP-Method-Override"
  	// HTTPMethodOverrideFormKey is a commonly used
  	// HTML form key to override a request method.
  	HTTPMethodOverrideFormKey = "_method"
  )
  
  // HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for
  // the X-HTTP-Method-Override header or the _method form key, and overrides (if
  // valid) request.Method with its value.
  //
  // This is especially useful for HTTP clients that don't support many http verbs.
  // It isn't secure to override e.g a GET to a POST, so only POST requests are
  // considered.  Likewise, the override method can only be a "write" method: PUT,
  // PATCH or DELETE.
  //
  // Form method takes precedence over header method.
  func HTTPMethodOverrideHandler(h http.Handler) http.Handler {
  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  		if r.Method == "POST" {
  			om := r.FormValue(HTTPMethodOverrideFormKey)
  			if om == "" {
  				om = r.Header.Get(HTTPMethodOverrideHeader)
  			}
  			if om == "PUT" || om == "PATCH" || om == "DELETE" {
  				r.Method = om
  			}
  		}
  		h.ServeHTTP(w, r)
  	})
  }
  