func main() {
	if len(os.Args) != 2 {
		fmt.Fprintf(os.Stderr, "Usage: %s <log entries file>\n", os.Args[0])
		os.Exit(1)
	}
	fileName := os.Args[1]

	in, err := os.Open(fileName)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to open entries file: %s\n", err)
		os.Exit(1)
	}
	defer in.Close()

	entriesFile := certificatetransparency.EntriesFile{in}

	outputLock := new(sync.Mutex)

	//pinned_domains, _ := regexp.Compile("(.*[.])?mozilla[.](com|org|net)")
	//pinned_domains, _ := regexp.Compile("(.*[.])?twitter[.](com|net)")
	pinned_domains, _ := regexp.Compile("(.*[.])?google[.](com|net)")
	// Dump
	// - csv file of OCSP urls, one per line
	// - csv file of CRL sets, one per line
	// - CNs and subjectAltName for compatibility testing

	entriesFile.Map(func(ent *certificatetransparency.EntryAndPosition, err error) {
		if err != nil {
			return
		}

		cert, err := x509.ParseCertificate(ent.Entry.X509Cert)
		if err != nil {
			return
		}

		dump := false
		if pinned_domains.MatchString(cert.Subject.CommonName) {
			dump = true
		}
		for _, san := range cert.DNSNames {
			if pinned_domains.MatchString(san) {
				dump = true
			}
		}
		if dump {
			hasher := sha1.New()
			hasher.Write(cert.RawSubjectPublicKeyInfo)
			outputLock.Lock()
			fmt.Printf("CN:%s\n", cert.Subject.CommonName)
			fmt.Printf("ISSUER:%s\n", cert.Issuer.CommonName)
			for _, san := range cert.DNSNames {
				fmt.Printf("DNS:%s\n", san)
			}
			for _, san := range cert.CRLDistributionPoints {
				fmt.Printf("CRL:%s\n", san)
			}
			for _, san := range cert.OCSPServer {
				fmt.Printf("OCSP:%s\n", san)
			}
			pem.Encode(os.Stdout, &pem.Block{Type: "CERTIFICATE", Bytes: ent.Entry.X509Cert})
			fmt.Printf("SHA1:%s\n", base64.StdEncoding.EncodeToString(hasher.Sum(nil)))
			outputLock.Unlock()
		}
	})
}
func main() {
	if len(os.Args) != 2 {
		fmt.Fprintf(os.Stderr, "Usage: %s <log entries file>\n", os.Args[0])
		os.Exit(1)
	}
	fileName := os.Args[1]

	in, err := os.Open(fileName)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to open entries file: %s\n", err)
		os.Exit(1)
	}
	defer in.Close()

	entriesFile := certificatetransparency.EntriesFile{in}

	outputLock := new(sync.Mutex)

	// Dump
	// - csv file of OCSP urls, one per line
	// - csv file of CRL sets, one per line
	// - CNs and subjectAltName for compatibility testing

	entriesFile.Map(func(ent *certificatetransparency.EntryAndPosition, err error) {
		if err != nil {
			return
		}

		cert, err := x509.ParseCertificate(ent.Entry.X509Cert)
		if err != nil {
			return
		}

		dump := true
		for _, san := range cert.DNSNames {
			if strings.HasSuffix(san, ".corp") {
				dump = true
			}
		}
		if dump {
			outputLock.Lock()
			fmt.Printf("CN:%s\n", cert.Subject.CommonName)
			fmt.Printf("ISSUER:%s\n", cert.Issuer.CommonName)
			hasher := sha1.New()
			sha256hasher := sha256.New()
			hasher.Write(cert.RawSubjectPublicKeyInfo)
			sha256hasher.Write(cert.RawSubjectPublicKeyInfo)
			fmt.Printf("sha1/%s\n", base64.StdEncoding.EncodeToString(hasher.Sum(nil)))
			fmt.Printf("sha256/%s\n", base64.StdEncoding.EncodeToString(sha256hasher.Sum(nil)))
			for _, san := range cert.DNSNames {
				fmt.Printf("DNS:%s\n", san)
			}
			for _, san := range cert.CRLDistributionPoints {
				fmt.Printf("CRL:%s\n", san)
			}
			for _, san := range cert.OCSPServer {
				fmt.Printf("OCSP:%s\n", san)
			}
			outputLock.Unlock()
		}
	})
}
func main() {
	if len(os.Args) != 3 {
		fmt.Fprintf(os.Stderr, "Usage: %s <log nickname> <log entries file>\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Known logs:\n")
		fmt.Fprintf(os.Stderr, "\taviator\n")
		fmt.Fprintf(os.Stderr, "\tcertly\n")
		fmt.Fprintf(os.Stderr, "\tdigicert\n")
		fmt.Fprintf(os.Stderr, "\tizenpe\n")
		fmt.Fprintf(os.Stderr, "\tpilot\n")
		fmt.Fprintf(os.Stderr, "\trocketeer\n")
		fmt.Fprintf(os.Stderr, "\tsymantec\n")
		fmt.Fprintf(os.Stderr, "\tvenafi\n")
		os.Exit(1)
	}
	logName := os.Args[1]
	fileName := os.Args[2]

	var log *certificatetransparency.Log
	if logName == "pilot" {
		log = certificatetransparency.PilotLog
	} else if logName == "aviator" {
		log = certificatetransparency.AviatorLog
	} else if logName == "rocketeer" {
		log = certificatetransparency.RocketeerLog
	} else if logName == "symantec" {
		log = certificatetransparency.SymantecLog
	} else if logName == "izenpe" {
		log = certificatetransparency.IzenpeLog
	} else if logName == "certly" {
		log = certificatetransparency.CertlyLog
	} else if logName == "digicert" {
		log = certificatetransparency.DigiCertLog
	} else if logName == "venafi" {
		log = certificatetransparency.VenafiLog
	} else {
		fmt.Fprintf(os.Stderr, "Unknown log name '%s'\n", logName)
		os.Exit(1)
	}

	out, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0666)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to open entries file: %s\n", err)
		os.Exit(1)
	}
	defer out.Close()

	entriesFile := certificatetransparency.EntriesFile{out}
	fmt.Printf("Counting existing entries... ")
	count, err := entriesFile.Count()
	if err != nil {
		fmt.Fprintf(os.Stderr, "\nFailed to read entries file: %s\n", err)
		os.Exit(1)
	}
	fmt.Printf("%d\n", count)

	fmt.Printf("Fetching signed tree head... ")
	sth, err := log.GetSignedTreeHead()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}
	fmt.Printf("%d total entries at %s\n", sth.Size, sth.Time.Format(time.ANSIC))
	if count == sth.Size {
		fmt.Printf("Nothing to do\n")
		return
	}

	statusChan := make(chan certificatetransparency.OperationStatus, 1)
	wg := new(sync.WaitGroup)
	displayProgress(statusChan, wg)
	_, err = log.DownloadRange(out, statusChan, count, sth.Size)
	wg.Wait()

	clearLine()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error while downloading: %s\n", err)
		os.Exit(1)
	}

	fmt.Printf("Hashing tree\n")
	entriesFile.Seek(0, 0)
	statusChan = make(chan certificatetransparency.OperationStatus, 1)
	wg = new(sync.WaitGroup)
	displayProgress(statusChan, wg)
	treeHash, err := entriesFile.HashTree(statusChan, sth.Size)
	wg.Wait()

	clearLine()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error hashing tree: %s\n", err)
		os.Exit(1)
	}
	if !bytes.Equal(treeHash[:], sth.Hash) {
		fmt.Fprintf(os.Stderr, "Hashes do not match! Calculated: %x, STH contains %x\n", treeHash, sth.Hash)
		os.Exit(1)
	}
}