1
0
Fork 0
mirror of https://github.com/vbatts/freezing-octo-hipster.git synced 2025-07-03 07:48:29 +00:00

go*: one go module for the repo, no more nested

Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
This commit is contained in:
Vincent Batts 2024-04-26 19:34:55 +00:00
parent a788e9ac95
commit 4ab3be9bc6
Signed by: vbatts
GPG key ID: E30EFAA812C6E5ED
632 changed files with 153930 additions and 133148 deletions

21
vendor/github.com/luksen/maildir/LICENSE.txt generated vendored Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Lukas Senger
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

9
vendor/github.com/luksen/maildir/README.mkdn generated vendored Normal file
View file

@ -0,0 +1,9 @@
The maildir package provides an interface to mailboxes in the Maildir format.
Documentation can be found online here:
https://pkg.go.dev/github.com/luksen/maildir
This is what I used as a reference:
- https://en.wikipedia.org/wiki/Maildir
- http://www.qmail.org/qmail-manual-html/man5/maildir.html
- http://cr.yp.to/proto/maildir.html

3
vendor/github.com/luksen/maildir/go.mod generated vendored Normal file
View file

@ -0,0 +1,3 @@
module github.com/luksen/maildir
go 1.15

520
vendor/github.com/luksen/maildir/maildir.go generated vendored Normal file
View file

@ -0,0 +1,520 @@
// The maildir package provides an interface to mailboxes in the Maildir format.
package maildir
import (
"bufio"
"bytes"
"crypto/rand"
"encoding/hex"
"fmt"
"io"
"net/mail"
"net/textproto"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"sync/atomic"
"time"
)
// The Separator separates a messages unique key from its flags in the filename.
// This should only be changed on operating systems where the colon isn't
// allowed in filenames.
var Separator rune = ':'
var id int64 = 10000
// CreateMode holds the permissions used when creating a directory.
const CreateMode = 0700
// A KeyError occurs when a key matches more or less than one message.
type KeyError struct {
Key string // the (invalid) key
N int // number of matches (!= 1)
}
func (e *KeyError) Error() string {
return "maildir: key " + e.Key + " matches " + strconv.Itoa(e.N) + " files."
}
// A FlagError occurs when a non-standard info section is encountered.
type FlagError struct {
Info string // the encountered info section
Experimental bool // info section starts with 1
}
func (e *FlagError) Error() string {
if e.Experimental {
return "maildir: experimental info section encountered: " + e.Info[2:]
}
return "maildir: bad info section encountered: " + e.Info
}
// A Dir represents a single directory in a Maildir mailbox.
type Dir string
// Unseen moves messages from new to cur and returns their keys.
// This means the messages are now known to the application. To find out whether
// a user has seen a message, use Flags().
func (d Dir) Unseen() ([]string, error) {
f, err := os.Open(filepath.Join(string(d), "new"))
if err != nil {
return nil, err
}
defer f.Close()
names, err := f.Readdirnames(0)
if err != nil {
return nil, err
}
var keys []string
for _, n := range names {
if n[0] != '.' {
split := strings.FieldsFunc(n, func(r rune) bool {
return r == Separator
})
key := split[0]
info := "2,"
// Messages in new shouldn't have an info section but
// we act as if, in case some other program didn't
// follow the spec.
if len(split) > 1 {
info = split[1]
}
keys = append(keys, key)
err = os.Rename(filepath.Join(string(d), "new", n),
filepath.Join(string(d), "cur", key+string(Separator)+info))
}
}
return keys, err
}
// UnseenCount returns the number of messages in new without looking at them.
func (d Dir) UnseenCount() (int, error) {
f, err := os.Open(filepath.Join(string(d), "new"))
if err != nil {
return 0, err
}
defer f.Close()
names, err := f.Readdirnames(0)
if err != nil {
return 0, err
}
c := 0
for _, n := range names {
if n[0] != '.' {
c += 1
}
}
return c, nil
}
// Keys returns a slice of valid keys to access messages by. This only returns
// keys for messages in cur. Use Unseen to access messages in new. All keys,
// whether returned here or by Unseen, point to messages in cur.
func (d Dir) Keys() ([]string, error) {
f, err := os.Open(filepath.Join(string(d), "cur"))
if err != nil {
return nil, err
}
defer f.Close()
names, err := f.Readdirnames(0)
if err != nil {
return nil, err
}
var keys []string
for _, n := range names {
if n[0] != '.' {
split := strings.FieldsFunc(n, func(r rune) bool {
return r == Separator
})
keys = append(keys, split[0])
}
}
return keys, nil
}
func fileExists(filename string) bool {
finfo, err := os.Stat(filename)
return err == nil && finfo.Mode().IsRegular()
}
var suffices []string = []string{
"",
"S",
"D",
"F",
"P",
"R",
"T",
"DF",
"DP",
"DR",
"DS",
"DT",
"FP",
"FR",
"FS",
"FT",
"PR",
"PS",
"PT",
"RS",
"RT",
"ST",
"DFP",
"DFR",
"DFS",
"DFT",
"DPR",
"DPS",
"DPT",
"DRS",
"DRT",
"DST",
"FPR",
"FPS",
"FPT",
"FRS",
"FRT",
"FST",
"PRS",
"PRT",
"PST",
"RST",
"DFPR",
"DFPS",
"DFPT",
"DFRS",
"DFRT",
"DFST",
"DPRS",
"DPRT",
"DPST",
"DRST",
"FPRS",
"FPRT",
"FPST",
"FRST",
"PRST",
"DFPRS",
"DFPRT",
"DFPST",
"DFRST",
"DPRST",
"FPRST",
"DFPRST"}
// quick check for existance of legal (per DJB) file names for a key
func (d Dir) quickFilename(key string) string {
// "cur" files must have :info suffix
filePrefix := filepath.Join(string(d), "cur", key+string(Separator)+"2,")
for _, suffix := range suffices {
if filename := filePrefix + suffix; fileExists(filename) {
return filename
}
}
return ""
}
// Filename returns the path to the file corresponding to the key.
func (d Dir) Filename(key string) (string, error) {
if matchedFile := d.quickFilename(key); matchedFile != "" {
return matchedFile, nil
}
dirPath := filepath.Join(string(d), "cur")
f, err := os.Open(dirPath)
if err != nil {
return "", err
}
defer f.Close()
names, err := f.Readdirnames(-1)
if err != nil {
return "", err
}
for _, name := range names {
if strings.HasPrefix(name, key) {
return filepath.Join(dirPath, name), nil
}
}
return "", &KeyError{key, 0}
}
// Header returns the corresponding mail header to a key.
func (d Dir) Header(key string) (header mail.Header, err error) {
filename, err := d.Filename(key)
if err != nil {
return
}
file, err := os.Open(filename)
if err != nil {
return
}
defer file.Close()
tp := textproto.NewReader(bufio.NewReader(file))
hdr, err := tp.ReadMIMEHeader()
if err != nil {
return
}
header = mail.Header(hdr)
return
}
// Message returns a Message by key.
func (d Dir) Message(key string) (*mail.Message, error) {
filename, err := d.Filename(key)
if err != nil {
return &mail.Message{}, err
}
r, err := os.Open(filename)
if err != nil {
return &mail.Message{}, err
}
defer r.Close()
buf := new(bytes.Buffer)
_, err = io.Copy(buf, r)
if err != nil {
return &mail.Message{}, err
}
msg, err := mail.ReadMessage(buf)
if err != nil {
return msg, err
}
return msg, nil
}
type runeSlice []rune
func (s runeSlice) Len() int { return len(s) }
func (s runeSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s runeSlice) Less(i, j int) bool { return s[i] < s[j] }
// Flags returns the flags for a message sorted in ascending order.
// See the documentation of SetFlags for details.
func (d Dir) Flags(key string) (string, error) {
filename, err := d.Filename(key)
if err != nil {
return "", err
}
split := strings.FieldsFunc(filename, func(r rune) bool {
return r == Separator
})
switch {
case len(split[1]) < 2,
split[1][1] != ',':
return "", &FlagError{split[1], false}
case split[1][0] == '1':
return "", &FlagError{split[1], true}
case split[1][0] != '2':
return "", &FlagError{split[1], false}
}
rs := runeSlice(split[1][2:])
sort.Sort(rs)
return string(rs), nil
}
// SetFlags appends an info section to the filename according to the given flags.
// This function removes duplicates and sorts the flags, but doesn't check
// whether they conform with the Maildir specification.
//
// The following flags are listed in the specification
// (http://cr.yp.to/proto/maildir.html):
//
// Flag "P" (passed): the user has resent/forwarded/bounced this message to someone else.
// Flag "R" (replied): the user has replied to this message.
// Flag "S" (seen): the user has viewed this message, though perhaps he didn't read all the way through it.
// Flag "T" (trashed): the user has moved this message to the trash; the trash will be emptied by a later user action.
// Flag "D" (draft): the user considers this message a draft; toggled at user discretion.
// Flag "F" (flagged): user-defined flag; toggled at user discretion.
//
// Using only these standard flags will improve message retrieval speed.
func (d Dir) SetFlags(key string, flags string) error {
info := "2,"
rs := runeSlice(flags)
sort.Sort(rs)
for _, r := range rs {
if []rune(info)[len(info)-1] != r {
info += string(r)
}
}
return d.SetInfo(key, info)
}
// Set the info part of the filename.
// Only use this if you plan on using a non-standard info part.
func (d Dir) SetInfo(key, info string) error {
filename, err := d.Filename(key)
if err != nil {
return err
}
err = os.Rename(filename, filepath.Join(string(d), "cur", key+
string(Separator)+info))
return err
}
// Key exposes the internal unique key generation. This function is deprecated.
func Key() (string, error) {
fmt.Println("maildir: Key() is deprecated without replacement. See https://github.com/luksen/maildir/issues/5 for details.")
return generateKey()
}
// generateKey generates a new unique key as described in the Maildir
// specification. For the third part of the key (delivery identifier) it uses
// an internal counter, the process id and a cryptographical random number to
// ensure uniqueness among messages delivered in the same second.
func generateKey() (string, error) {
var key string
key += strconv.FormatInt(time.Now().Unix(), 10)
key += "."
host, err := os.Hostname()
if err != err {
return "", err
}
host = strings.Replace(host, "/", "\057", -1)
host = strings.Replace(host, string(Separator), "\072", -1)
key += host
key += "."
key += strconv.FormatInt(int64(os.Getpid()), 10)
key += strconv.FormatInt(id, 10)
atomic.AddInt64(&id, 1)
bs := make([]byte, 10)
_, err = io.ReadFull(rand.Reader, bs)
if err != nil {
return "", err
}
key += hex.EncodeToString(bs)
return key, nil
}
// Create creates the directory structure for a Maildir.
// If the main directory already exists, it tries to create the subdirectories
// in there. If an error occurs while creating one of the subdirectories, this
// function may leave a partially created directory structure.
func (d Dir) Create() error {
err := os.Mkdir(string(d), os.ModeDir|CreateMode)
if err != nil && !os.IsExist(err) {
return err
}
err = os.Mkdir(filepath.Join(string(d), "tmp"), os.ModeDir|CreateMode)
if err != nil && !os.IsExist(err) {
return err
}
err = os.Mkdir(filepath.Join(string(d), "new"), os.ModeDir|CreateMode)
if err != nil && !os.IsExist(err) {
return err
}
err = os.Mkdir(filepath.Join(string(d), "cur"), os.ModeDir|CreateMode)
if err != nil && !os.IsExist(err) {
return err
}
return nil
}
// Delivery represents an ongoing message delivery to the mailbox.
// It implements the WriteCloser interface. On closing the underlying file is
// moved/relinked to new.
type Delivery struct {
file *os.File
d Dir
key string
}
// NewDelivery creates a new Delivery.
func (d Dir) NewDelivery() (*Delivery, error) {
key, err := generateKey()
if err != nil {
return nil, err
}
del := &Delivery{}
time.AfterFunc(24*time.Hour, func() { del.Abort() })
file, err := os.Create(filepath.Join(string(d), "tmp", key))
if err != nil {
return nil, err
}
del.file = file
del.d = d
del.key = key
return del, nil
}
func (d *Delivery) Write(p []byte) (int, error) {
return d.file.Write(p)
}
// Close closes the underlying file and moves it to new.
func (d *Delivery) Close() error {
err := d.file.Close()
if err != nil {
return err
}
err = os.Link(filepath.Join(string(d.d), "tmp", d.key),
filepath.Join(string(d.d), "new", d.key))
if err != nil {
return err
}
err = os.Remove(filepath.Join(string(d.d), "tmp", d.key))
if err != nil {
return err
}
return nil
}
// Abort closes the underlying file and removes it completely.
func (d *Delivery) Abort() error {
err := d.file.Close()
if err != nil {
return err
}
err = os.Remove(filepath.Join(string(d.d), "tmp", d.key))
if err != nil {
return err
}
return nil
}
// Move moves a message from this Maildir to another.
func (d Dir) Move(target Dir, key string) error {
path, err := d.Filename(key)
if err != nil {
return err
}
return os.Rename(path, filepath.Join(string(target), "cur", filepath.Base(path)))
}
// Purge removes the actual file behind this message.
func (d Dir) Purge(key string) error {
f, err := d.Filename(key)
if err != nil {
return err
}
return os.Remove(f)
}
// Clean removes old files from tmp and should be run periodically.
// This does not use access time but modification time for portability reasons.
func (d Dir) Clean() error {
f, err := os.Open(filepath.Join(string(d), "tmp"))
if err != nil {
return err
}
defer f.Close()
names, err := f.Readdirnames(0)
if err != nil {
return err
}
now := time.Now()
for _, n := range names {
fi, err := os.Stat(filepath.Join(string(d), "tmp", n))
if err != nil {
continue
}
if now.Sub(fi.ModTime()).Hours() > 36 {
err = os.Remove(filepath.Join(string(d), "tmp", n))
if err != nil {
return err
}
}
}
return nil
}