-
Notifications
You must be signed in to change notification settings - Fork 1
/
main1.go
128 lines (92 loc) · 2.76 KB
/
main1.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package main
import (
"database/sql"
"flag"
"fmt"
_ "github.com/mattn/go-sqlite3"
"io/ioutil"
"os"
"path/filepath"
"strings"
)
func main() {
//read input dir name and name of output file
var input string
var output string
{
flag.StringVar(&input, "input", "", "directory that contains pst files")
flag.StringVar(&output, "output", "", "file that contains all emails and attachments, use sql to query")
flag.Parse()
fmt.Println("input folder= " + input)
fmt.Println("output file= " + output)
if len(input) == 0 || len(output) == 0 {
fmt.Println("\ninvalid in/out specified... Exiting")
os.Exit(1)
}
}
os.Remove(output)
db, err := sql.Open("sqlite3", output)
check(err)
defer db.Close()
sqlStmt := `create table email (path text, content text);
delete from email;
create table attachment (path text, content blob, email_id integer);
delete from attachment;
`
indexStmt := ` CREATE INDEX index_attachment_email_id ON attachment (email_id );
CREATE INDEX index_attachment_path ON attachment (path );
CREATE INDEX index_email_path ON email (path );
`
_, err = db.Exec(sqlStmt)
check(err)
tx, err := db.Begin()
check(err)
stmtEmail, err := tx.Prepare("insert into email(path, content) values(?, ?)")
check(err)
//setting email_id with latest email rowid we do get advantage
//not running update query later
//assuming file system will give us files in order - link right email and attachment
stmtAtt, err := tx.Prepare("insert into attachment(path, content, email_id) values(?, ?, (select max(rowid) from email))")
check(err)
defer stmtEmail.Close()
defer stmtAtt.Close()
//TODO file path shouldn't contain reduntant info. No "/home/..."
//TODO all logic goes to visit closure. Is it ok?
//TODO Add logic to parse email file and create more columns in database
visit := func(p string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
//very lazy way to create with primary key
//by removing slashes and whitespaces from file path
clearName := strings.Replace(p[len(input)+1:], "/", "_", -1)
clearName = strings.Replace(clearName, " ", "", -1)
//this is naive check, but is acceptable for now
if strings.Contains(info.Name(), "-") {
fmt.Println(" ", p, "attachment")
file, err := ioutil.ReadFile(p)
check(err)
_, err = stmtAtt.Exec(clearName, file)
check(err)
} else {
fmt.Println(" ", p, "email")
file, err := ioutil.ReadFile(p)
check(err)
_, err = stmtEmail.Exec(clearName, string(file))
check(err)
}
}
return nil
}
err = filepath.Walk(input, visit)
check(err)
tx.Commit()
_, err = db.Exec(indexStmt)
check(err)
}
func check(e error) {
if e != nil {
panic(e)
}
}