<commit_before>// Copyright 2016 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"strings"

	"github.com/dullgiulio/kuradns/cfg"
)

var errUnhandledURL = errors.New("unhandled URL")

func (s *server) handleHttpError(w http.ResponseWriter, r *http.Request, err error) {
	http.Error(w, "An error occurred; please refer to the logs for more information", 500)
	log.Printf("[error] http: %s %s %s: %s", r.RemoteAddr, r.Method, r.URL.Path, err)
}

func (s *server) handleSourceAdd(name, gentype string, conf *cfg.Config) error {
	src := newSource(name, conf)
	if err := src.initGenerator(); err != nil {
		return fmt.Errorf("cannot start generator: %s", err)
	}

	req := makeRequest(src, reqtypeAdd)

	if err := req.send(s.requests); err != nil {
		return fmt.Errorf("cannot process %s: %s", req.String(), err)
	}
	if err := <-req.resp; err != nil {
		return fmt.Errorf("cannot add source: %s", err)
	}
	return nil
}

func (s *server) handleSourceDelete(name string) error {
	src := newSource(name, nil)
	req := makeRequest(src, reqtypeDel)

	if err := req.send(s.requests); err != nil {
		return fmt.Errorf("cannot process %s: %s", req.String(), err)
	}
	if err := <-req.resp; err != nil {
		return fmt.Errorf("cannot remove source: %s", err)
	}
	return nil
}

func (s *server) handleSourceUpdate(name string) error {
	src := newSource(name, nil)
	req := makeRequest(src, reqtypeUp)

	if err := req.send(s.requests); err != nil {
		return fmt.Errorf("cannot process %s: %s", req.String(), err)
	}
	if err := <-req.resp; err != nil {
		return fmt.Errorf("cannot update source: %s", err)
	}
	return nil
}

func (s *server) handleDnsDump(w http.ResponseWriter, r *http.Request) error {
	w.Header().Set("Content-Type", "text/plain")
	wb := bufio.NewWriter(w)

	s.mux.RLock()
	defer s.mux.RUnlock()

	if err := s.repo.WriteTo(wb); err != nil {
		return err
	}

	return wb.Flush()
}

func (s *server) handleSourceList(w http.ResponseWriter, r *http.Request) error {
	w.Header().Set("Content-Type", "text/plain")
	wb := bufio.NewWriter(w)

	s.mux.RLock()
	defer s.mux.RUnlock()

	for _, src := range s.srcs {
		fmt.Fprintf(wb, "%s %s\n", src.name, src.conf.GetVal("source.type", "unknown"))
	}

	return wb.Flush()
}

// take last value in case of duplicates
func (s *server) configFromForm(cf *cfg.Config, form url.Values) error {
	for k, vs := range form {
		if strings.HasPrefix(k, "config.") || strings.HasPrefix(k, "source.") {
			cf.Put(k, vs[len(vs)-1])
		}
	}
	return nil
}

func (s *server) configFromJSON(cf *cfg.Config, r io.Reader) error {
	if err := cf.FromJSON(r); err != nil {
		return fmt.Errorf("cannot parse JSON: %s", err)
	}
	return nil
}

func (s *server) getFromConf(cf *cfg.Config, key string) (string, error) {
	if v, ok := cf.Get(key); ok {
		return v, nil
	}
	return "", fmt.Errorf("required parameter %s not found", key)
}

func (s *server) parseBodyData(w http.ResponseWriter, r *http.Request) (*cfg.Config, error) {
	cf := cfg.NewConfig()
	// JSON data as POST body
	if r.Header.Get("Content-Type") == "application/json" {<commit_msg>Do not accept empty source names<commit_after>// Copyright 2016 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"strings"

	"github.com/dullgiulio/kuradns/cfg"
)

var errUnhandledURL = errors.New("unhandled URL")

func (s *server) handleHttpError(w http.ResponseWriter, r *http.Request, err error) {
	http.Error(w, "An error occurred; please refer to the logs for more information", 500)
	log.Printf("[error] http: %s %s %s: %s", r.RemoteAddr, r.Method, r.URL.Path, err)
}

func (s *server) handleSourceAdd(name, gentype string, conf *cfg.Config) error {
	src := newSource(name, conf)
	if err := src.initGenerator(); err != nil {
		return fmt.Errorf("cannot start generator: %s", err)
	}

	req := makeRequest(src, reqtypeAdd)

	if err := req.send(s.requests); err != nil {
		return fmt.Errorf("cannot process %s: %s", req.String(), err)
	}
	if err := <-req.resp; err != nil {
		return fmt.Errorf("cannot add source: %s", err)
	}
	return nil
}

func (s *server) handleSourceDelete(name string) error {
	src := newSource(name, nil)
	req := makeRequest(src, reqtypeDel)

	if err := req.send(s.requests); err != nil {
		return fmt.Errorf("cannot process %s: %s", req.String(), err)
	}
	if err := <-req.resp; err != nil {
		return fmt.Errorf("cannot remove source: %s", err)
	}
	return nil
}

func (s *server) handleSourceUpdate(name string) error {
	src := newSource(name, nil)
	req := makeRequest(src, reqtypeUp)

	if err := req.send(s.requests); err != nil {
		return fmt.Errorf("cannot process %s: %s", req.String(), err)
	}
	if err := <-req.resp; err != nil {
		return fmt.Errorf("cannot update source: %s", err)
	}
	return nil
}

func (s *server) handleDnsDump(w http.ResponseWriter, r *http.Request) error {
	w.Header().Set("Content-Type", "text/plain")
	wb := bufio.NewWriter(w)

	s.mux.RLock()
	defer s.mux.RUnlock()

	if err := s.repo.WriteTo(wb); err != nil {
		return err
	}

	return wb.Flush()
}

func (s *server) handleSourceList(w http.ResponseWriter, r *http.Request) error {
	w.Header().Set("Content-Type", "text/plain")
	wb := bufio.NewWriter(w)

	s.mux.RLock()
	defer s.mux.RUnlock()

	for _, src := range s.srcs {
		fmt.Fprintf(wb, "%s %s\n", src.name, src.conf.GetVal("source.type", "unknown"))
	}

	return wb.Flush()
}

// take last value in case of duplicates
func (s *server) configFromForm(cf *cfg.Config, form url.Values) error {
	for k, vs := range form {
		if strings.HasPrefix(k, "config.") || strings.HasPrefix(k, "source.") {
			cf.Put(k, vs[len(vs)-1])
		}
	}
	return nil
}

func (s *server) configFromJSON(cf *cfg.Config, r io.Reader) error {
	if err := cf.FromJSON(r); err != nil {
		return fmt.Errorf("cannot parse JSON: %s", err)
	}
	return nil
}

func (s *server) getFromConf(cf *cfg.Config, key string) (string, error) {
	if v, ok := cf.Get(key); ok {
		if v == "" {
			return "", fmt.Errorf("required parameter %s is empty", key)
		}
		return v, nil
	}
	return "", fmt.Errorf("required parameter %s not found", key)
}

func (s *server) parseBodyData(w http.ResponseWriter, r *http.Request) (*cfg.Config, error) {
	cf := cfg.NewConfig()
	// JSON data as POST body
	if r.Header.Get("Content-Type") == "application/json" {
{'fraction_non_alphanumeric': 0.16982284667073916, 'fraction_numerical': 0.002443494196701283, 'mean_word_length': 3.92406015037594, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '25468', 'n_tokens_mistral': 2493, 'n_tokens_neox': 2396, 'n_words': 700}